// gandora's service worker: the shell is cached so the app opens and the library plays with no signal. // Tracks live in IndexedDB already; the DJ and new renders need the network and the page says so. // REV is stamped by the shots workflow on every push, so an installed app sees each update as a new worker. const REV = "split-62f6f39"; const SHELL = "gandora-shell-" + REV; const FILES = ["/", "/index.html", "/app.js", "/core.js", "/covers.js", "/dj.js", "/mashup.js", "/player.js", "/render.js", "/store.js", "/ui/library.js", "/ui/player.js", "/ui/sheet.js", "/ui/taste.js", "/stats.html", "/favicon.svg", "/manifest.json", "/icons/icon.svg"]; self.addEventListener("install", (e) => { e.waitUntil(caches.open(SHELL).then((c) => c.addAll(FILES)).then(() => self.skipWaiting())); }); self.addEventListener("activate", (e) => { e.waitUntil(caches.keys().then((ks) => Promise.all(ks.filter((k) => k !== SHELL).map((k) => caches.delete(k)))).then(() => self.clients.claim())); }); // same-origin GETs: network first (so a deploy shows up on the next open), cache as the fallback; everything else untouched self.addEventListener("fetch", (e) => { const u = new URL(e.request.url); if (e.request.method !== "GET" || u.origin !== location.origin) return; e.respondWith(fetch(e.request).then((r) => { if (r.ok) caches.open(SHELL).then((c) => c.put(e.request, r.clone())); return r; }) .catch(() => caches.match(e.request, { ignoreSearch: true }).then((r) => r || caches.match("/")))); });