/* Cyrene v2 PWA service worker — core-resource caching + offline shell. */ const CACHE = "cyrene-web-v1"; const PRECACHE = ["/", "/index.html", "/manifest.json", "/images/Cyrene_Avatar/3rd_Form/Cyrene-3F-Q-Happy-1.png"]; self.addEventListener("install", (event) => { event.waitUntil( caches .open(CACHE) .then((cache) => cache.addAll(PRECACHE)) .then(() => self.skipWaiting()) ); }); self.addEventListener("activate", (event) => { event.waitUntil( caches .keys() .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))) ) .then(() => self.clients.claim()) ); }); self.addEventListener("fetch", (event) => { const req = event.request; if (req.method !== "GET") return; const url = new URL(req.url); if (url.origin !== self.location.origin) return; // let API/WS pass through // Network-first for document navigations so the shell stays fresh, falling // back to cached index.html when offline. if (req.mode === "navigate") { event.respondWith( fetch(req) .then((res) => { const copy = res.clone(); caches.open(CACHE).then((cache) => cache.put("/index.html", copy)); return res; }) .catch(() => caches.match("/index.html")) ); return; } // Cache-first for static assets (hashed by Vite) with background refresh. event.respondWith( caches.match(req).then((cached) => { const fetched = fetch(req) .then((res) => { if (res && res.status === 200) { const copy = res.clone(); caches.open(CACHE).then((cache) => cache.put(req, copy)); } return res; }) .catch(() => cached); return cached || fetched; }) ); });