/// /// /// /// self.addEventListener('install', (event) => { self.skipWaiting(); }); self.addEventListener('activate', (event) => { event.waitUntil(self.clients.claim()); }); // ###### Handle unread badge: const conversationReadStatus = { // Format: // conversationId: { lastRead: Optional(Datetime), lastMessage: Datetime } }; function countUnreadChannels() { return Object.values(conversationReadStatus) .map(({ lastRead, lastMessage }) => { return !lastRead || lastRead < lastMessage ? 1 : 0; }) .reduce((total, current) => total + current, 0); } self.addEventListener('push', (event) => { // Let's show a notification right away so Safari doesn't tell Apple to be // mad at us: event.waitUntil( self.registration.showNotification('Test notification', { actions: [], body: event.data.text(), }), ); const data = event.data?.json(); // Now we can do slower things that might fail: conversationReadStatus[data.conversationId] ||= { lastRead: null, lastMessage: null }; conversationReadStatus[data.conversationId].lastMessage = new Date(); event.waitUntil( (async () => { if (navigator.setAppBadge) { navigator.setAppBadge(countUnreadChannels()); } })(), ); }); // The client has to tell us when it has read a conversation: self.addEventListener('message', (event) => { const data = event.data; switch (data.type) { case 'CONVERSATION_READ': conversationReadStatus[data.conversationId] ||= { lastRead: null, lastMessage: null }; if (data.at) { conversationReadStatus[data.conversationId].lastRead = new Date(data.at.ts); } else { conversationReadStatus[data.conversationId].lastRead = new Date(); } event.waitUntil( (async () => { if (navigator.setAppBadge) { navigator.setAppBadge(countUnreadChannels()); } })(), ); break; default: break; } });