1importScripts('https://www.gstatic.com/firebasejs/11.4.0/firebase-app-compat.js'); 2importScripts('https://www.gstatic.com/firebasejs/11.4.0/firebase-messaging-compat.js'); 3 4// Initialize Firebase 5const firebaseConfig = { 6 apiKey: "AIzaSyA5Ap4dvZK8in2NBpl-0ei-BbLjRMICC0s", 7 authDomain: "ecstatic-bounty-314812.firebaseapp.com", 8 projectId: "ecstatic-bounty-314812", 9 storageBucket: "ecstatic-bounty-314812.appspot.com", 10 messagingSenderId: "399981119913", 11 appId: "1:399981119913:web:2b4b5c63af0fd63a741cb8", 12 measurementId: "G-RLFKKS9Y50" 13}; 14 15firebase.initializeApp(firebaseConfig); 16const messaging = firebase.messaging(); 17 18self.addEventListener('push', async (event) => { 19 const payload = event.data?.json() || {}; 20 21 const allClients = await clients.matchAll({ 22 type: 'window', 23 includeUncontrolled: true 24 }); 25 26 const appIsInForeground = allClients.some((client) => client.focused); 27 28 if (appIsInForeground) { 29 console.log('[SW] App is in foreground â skipping push notification.'); 30 return; 31 } 32 33 const title = payload.data?.title || 'Notification'; 34 const body = payload.data?.body || ''; 35 const icon = '/default-icon.png'; 36 const image = payload.data?.image; 37 const link = payload.data?.link || '/'; 38 let extraData = {}; 39 40 try { 41 if (typeof payload.data?.data === 'string') { 42 extraData = JSON.parse(payload.data); 43 } else if (typeof payload.data?.data === 'object') { 44 extraData = payload.data.data; 45 } 46 } catch (err) { 47 console.warn('[SW] Failed to parse extraData:', err); 48 } 49 50 const options = { 51 body, 52 icon, 53 image, 54 data: { 55 link, 56 ...extraData 57 } 58 }; 59 60 event.waitUntil( 61 self.registration.showNotification(title, options) 62 ); 63}); 64 65self.addEventListener('notificationclick', (event) => { 66 event.notification.close(); 67 68 const link = event.notification.data?.link || '/'; 69 const targetUrl = new URL(link, self.location.origin).toString(); 70 71 event.waitUntil( 72 clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => { 73 for (const client of clientList) { 74 if (client.url === targetUrl && 'focus' in client) { 75 return client.focus(); 76 } 77 } 78 return clients.openWindow(targetUrl); 79 }) 80 ); 81}); 82 83self.addEventListener('message', (event) => { 84 if (event.data?.type === 'SKIP_WAITING') { 85 self.skipWaiting(); 86 } 87 88 if (event.data?.type === 'foreground-notification') { 89 const payload = event.data.payload; 90 91 self.registration.showNotification(payload.title, { 92 body: payload.body, 93 icon: payload.icon, 94 image: payload.image, 95 data: { 96 link: payload.link, 97 ...payload.data 98 } 99 }); 100 } 101}); 102 103// SW install/activate logic 104self.addEventListener("install", (event) => { 105 console.log("Service Worker installing..."); 106 self.skipWaiting(); 107}); 108 109self.addEventListener("activate", (event) => { 110 console.log("Service Worker activated..."); 111 event.waitUntil( 112 caches.keys().then((cacheNames) => { 113 return Promise.all( 114 cacheNames.map((cacheName) => caches.delete(cacheName)) 115 ); 116 }).then(() => self.clients.claim()) 117 ); 118});
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.