const CACHE_NAME = "wfdash-counter-v1"; const OFFLINE_URL = "/offline"; const PRECACHE_ASSETS = [ "/new-order", "/manifest-counter.json", "/offline", "/android-chrome-192x192.png", "/android-chrome-512x512.png", ]; self.addEventListener("install", (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_ASSETS)) ); self.skipWaiting(); }); self.addEventListener("activate", (event) => { event.waitUntil( caches.keys().then((keys) => Promise.all( keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k)) ) ) ); self.clients.claim(); }); self.addEventListener("fetch", (event) => { const { request } = event; if (request.method !== "GET") return; // Never cache API or admin/upload traffic — every submit must hit // the server live so the order lands on the board immediately. const url = new URL(request.url); if (url.pathname.startsWith("/api/")) return; // Navigation requests: network-first, fall back to cached // /new-order, then /offline. if (request.mode === "navigate") { event.respondWith( fetch(request) .then((response) => { const clone = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); return response; }) .catch(async () => { const cached = await caches.match(request); if (cached) return cached; const newOrder = await caches.match("/new-order"); if (newOrder) return newOrder; return caches.match(OFFLINE_URL); }) ); return; } // Static assets: stale-while-revalidate. event.respondWith( caches.match(request).then((cached) => { const networkFetch = fetch(request) .then((response) => { const clone = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); return response; }) .catch(() => cached); return cached || networkFetch; }) ); });