1/* v=4 â push + installability (no network intercept) */ 2const NOTIFICATION_ICON = '/icons/icon-192.png?v=3'; 3 4self.addEventListener('install', () => self.skipWaiting()); 5self.addEventListener('activate', (event) => { 6 event.waitUntil( 7 caches.keys().then((names) => Promise.all(names.map((n) => caches.delete(n)))) 8 .then(() => self.clients.claim()) 9 ); 10}); 11 12/* Empty fetch listener â needed for installability on older Chrome. Does not intercept. */ 13self.addEventListener('fetch', () => {}); 14 15self.addEventListener('push', (event) => { 16 const fallback = { 17 title: 'New sale', 18 body: 'A paid pack just came in.', 19 }; 20 event.waitUntil( 21 (async () => { 22 let data = fallback; 23 try { 24 if (event.data) data = { ...fallback, ...event.data.json() }; 25 } catch (e) { 26 console.error('[SW] Push parse error:', e); 27 } 28 await self.registration.showNotification(data.title || fallback.title, { 29 body: data.body || fallback.body, 30 icon: data.icon || NOTIFICATION_ICON, 31 badge: data.badge || NOTIFICATION_ICON, 32 tag: data.tag || `aislutbot-sale-${Date.now()}`, 33 data: data.data || { url: '/admin' }, 34 vibrate: [200, 100, 200], 35 requireInteraction: true, 36 renotify: true, 37 }); 38 })() 39 ); 40}); 41 42self.addEventListener('notificationclick', (event) => { 43 event.notification.close(); 44 const url = event.notification.data?.url || '/admin'; 45 event.waitUntil( 46 self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clients) => { 47 for (const client of clients) {
48 if (client.url.includes(url) && 'focus' in client) return client.focus(); 49 } 50 return self.clients.openWindow(url); 51 }) 52 ); 53});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.