1// QuikkredAgent Service Worker 2// Push notifications + network-first fetch (no aggressive caching) 3 4const SW_VERSION = '1.0.0'; 5 6// Push notification handler 7self.addEventListener('push', (event) => { 8 let data = { title: 'Quikkred', body: 'You have a new notification', url: '/' }; 9 10 try { 11 if (event.data) { 12 const payload = event.data.json(); 13 data = { 14 title: payload.title || data.title, 15 body: payload.body || data.body, 16 url: payload.url || payload.data?.url || data.url, 17 }; 18 } 19 } catch { 20 // Use defaults 21 } 22 23 const options = { 24 body: data.body, 25 icon: '/logo-256.png', 26 badge: '/favicon.ico', 27 vibrate: [200, 100, 200], 28 tag: 'quikkred-notification', 29 renotify: true, 30 data: { url: data.url }, 31 actions: [ 32 { action: 'open', title: 'Open' }, 33 { action: 'dismiss', title: 'Dismiss' }, 34 ], 35 }; 36 37 event.waitUntil(self.registration.showNotification(data.title, options)); 38}); 39 40// Notification click handler 41self.addEventListener('notificationclick', (event) => { 42 event.notification.close(); 43 44 if (event.action === 'dismiss') return; 45 46 const url = event.notification.data?.url || '/'; 47 48 event.waitUntil( 49 clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => { 50 // Focus existing window if available 51 for (const client of clientList) { 52 if (client.url.includes(self.location.origin) && 'focus' in client) { 53 client.focus(); 54 client.postMessage({ type: 'NOTIFICATION_CLICK', url }); 55 return; 56 } 57 } 58 // Open new window 59 return clients.openWindow(url); 60 }) 61 ); 62}); 63 64// Fetch handler â network-first, no aggressive caching (avoid Next.js conflicts) 65self.addEventListener('fetch', (event) => { 66 // Only handle same-origin navigation requests 67 if (event.request.mode !== 'navigate') return; 68 69 event.respondWith( 70 fetch(event.request).catch(() => { 71 // Offline fallback â just let the browser handle it 72 return caches.match('/') || new Response('Offline', { status: 503 }); 73 }) 74 ); 75}); 76 77// Install â skip waiting 78self.addEventListener('install', () => { 79 self.skipWaiting(); 80}); 81 82// Activate â claim clients 83self.addEventListener('activate', (event) => { 84 event.waitUntil(self.clients.claim()); 85});
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.