1const CACHE_NAME = "rtnc-v1"; 2const urlsToCache = ["/", "/icon/icon-192.png", "/icon/icon-512.png"]; 3 4self.addEventListener("install", (event) => { 5 event.waitUntil( 6 caches 7 .open(CACHE_NAME) 8 .then((cache) => cache.addAll(urlsToCache)) 9 .then(() => self.skipWaiting()), 10 ); 11}); 12 13self.addEventListener("fetch", (event) => { 14 // Only handle GET requests - POST/PUT/DELETE cannot be cached 15 if (event.request.method !== "GET") return; 16 17 let url; 18 try { 19 url = new URL(event.request.url); 20 } catch { 21 return; 22 } 23 24 // Never intercept cross-origin requests 25 if (url.origin !== self.location.origin) return; 26 27 // Never intercept auth paths 28 if (url.pathname.startsWith("/auth")) return; 29 30 // Handle navigation requests - fall back to cached root when offline 31 if (event.request.mode === "navigate") { 32 event.respondWith(fetch(event.request).catch(() => caches.match("/"))); 33 return; 34 } 35 36 // Network-first for other same-origin GET requests 37 event.respondWith( 38 fetch(event.request) 39 .then((response) => { 40 if (!response.ok) return response; 41 const responseToCache = response.clone(); 42 caches.open(CACHE_NAME).then((cache) => cache.put(event.request, responseToCache)); 43 return response; 44 }) 45 .catch(() => caches.match(event.request)), 46 ); 47}); 48 49self.addEventListener("activate", (event) => { 50 event.waitUntil( 51 caches 52 .keys() 53 .then((cacheNames) => 54 Promise.all( 55 cacheNames.map((cacheName) => { 56 if (cacheName !== CACHE_NAME) return caches.delete(cacheName); 57 }), 58 ), 59 ) 60 .then(() => self.clients.claim()), 61 ); 62}); 63 64// Handle push notifications - only show if app is not in focus 65self.addEventListener("push", (event) => { 66 const data = event.data?.json() ?? {}; 67 68 event.waitUntil( 69 clients.matchAll({ type: "window", includeUncontrolled: true }).then((clientList) => { 70 const isAppInFocus = clientList.some((client) => client.focused); 71 if (!isAppInFocus) { 72 return self.registration.showNotification(data.title, data.options); 73 } 74 }), 75 ); 76}); 77 78// Handle notification clicks - opens/focuses the app 79self.addEventListener("notificationclick", (event) => { 80 event.notification.close(); 81 82 event.waitUntil( 83 clients.matchAll({ type: "window" }).then((clientList) => { 84 for (const client of clientList) { 85 if ("focus" in client) return client.focus(); 86 } 87 if (clients.openWindow) return clients.openWindow("/"); 88 }), 89 ); 90});
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.