const VERSION = "dhikr-v4"; const SHELL = [ "./", "./index.html", "./manifest.webmanifest", "./icon-192.png", "./icon-512.png", "./icon-maskable-512.png", "./apple-touch-icon.png" ]; self.addEventListener("install", (e) => { e.waitUntil( caches.open(VERSION).then((c) => c.addAll(SHELL)).then(() => self.skipWaiting()) ); }); self.addEventListener("activate", (e) => { e.waitUntil( caches.keys() .then((keys) => Promise.all(keys.filter((k) => k !== VERSION).map((k) => caches.delete(k)))) .then(() => self.clients.claim()) ); }); self.addEventListener("fetch", (e) => { const url = new URL(e.request.url); // Google Fonts: stale-while-revalidate so typography survives offline if (url.hostname === "fonts.googleapis.com" || url.hostname === "fonts.gstatic.com") { e.respondWith( caches.open(VERSION).then(async (cache) => { const cached = await cache.match(e.request); const network = fetch(e.request) .then((res) => { if (res.ok) cache.put(e.request, res.clone()); return res; }) .catch(() => cached); return cached || network; }) ); return; } // App shell: cache-first, fall back to network, fall back to cached index if (e.request.method === "GET" && url.origin === self.location.origin) { e.respondWith( caches.match(e.request).then( (cached) => cached || fetch(e.request) .then((res) => { if (res.ok) { const clone = res.clone(); caches.open(VERSION).then((c) => c.put(e.request, clone)); } return res; }) .catch(() => caches.match("./index.html")) ) ); } });