const isClientFocused = () => { return self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((windowClients) => { return windowClients.map((client) => client.focused).indexOf(true) !== -1; }); }; const processNotification = (payload, actionsSupported) => { switch (payload.type) { case 'incomingMessages': const { message, from, onClickUrl } = payload; return self.registration.getNotifications().then((notifications) => { return notifications.length > 0 ? notifications.map((notification) => { return notification.data.from === from && notification })[0] : undefined; }).then((currentNotification) => { let notificationTitle = 'TV8 new message.'; const options = { requireInteraction: false, icon: './static/favicon_32x32.png', data: { from, onClickUrl, actionsSupported, messageCount: 1 } }; if (currentNotification) { // We have an open notification, let's do something with it. const newMessageCount = currentNotification.data.messageCount + 1; options.body = `You have ${newMessageCount} new messages from ${from}.`; options.data.messageCount = newMessageCount; // Remember to close the old notification. currentNotification.close(); } else { options.body = `${from}: ${message}`; } return self.registration.showNotification(notificationTitle, options); }); default: return; } }; const openWindow = (event) => { const urlToOpen = event.notification.data.onClickUrl; return self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((windowClients) => { let matchingClient = null; for (let i = 0; i < windowClients.length; i++) { const windowClient = windowClients[i]; if (windowClient.url === urlToOpen) { matchingClient = windowClient; break; } } event.notification.close(); if (matchingClient) { return matchingClient.focus(); } else { return self.clients.openWindow(urlToOpen); } }); }; self.addEventListener('push', (event) => { const notificationPayload = event.data.json(); const promiseChain = isClientFocused().then((clientIsFocused) => { if (clientIsFocused) { return; } // Client isn't focused, we need to show a notification. return processNotification(notificationPayload, 'actions' in Notification.prototype); }); event.waitUntil(promiseChain); }); self.addEventListener('notificationclick', (event) => { if (!event.action && event.notification.data.actionsSupported) { // Was a normal notification click event.waitUntil(openWindow(event)); return; } switch (event.action) { default: break; } }); self.addEventListener('install', () => { self.skipWaiting(); });