const CACHE = 'dashcaddy-shell-v10'; const PRECACHE = [ '/', '/index.html', '/css/themes.css', '/css/dashboard.css', '/css/driver.min.css', '/css/onboarding.css', '/dist/core.js', '/dist/features.js', '/dist/init.js', '/dist/onboarding.js', '/assets/fonts.css', '/assets/site.webmanifest', '/assets/favicon.svg', '/assets/dashcaddy-favicon.ico', '/assets/icon-192.png', '/assets/icon-512.png', '/assets/apple-touch-icon.png', '/assets/dashcaddy-logo-dark.png', '/assets/dashcaddy-logo-light.png', '/assets/sami7777-logo.png', '/assets/fonts/sami-grotesk/SamiGrotesk-Regular.woff2', '/assets/fonts/sami-grotesk/SamiGrotesk-Medium.woff2', '/assets/fonts/sami-grotesk/SamiGrotesk-Bold.woff2', '/assets/fonts/DSEG7Classic-Bold.woff2', '/assets/weather/clear-day.svg', '/assets/weather/clear-night.svg', '/assets/weather/partly-cloudy-day.svg', '/assets/weather/partly-cloudy-night.svg', '/assets/weather/cloudy.svg', '/assets/weather/fog.svg', '/assets/weather/drizzle.svg', '/assets/weather/rain.svg', '/assets/weather/sleet.svg', '/assets/weather/snow.svg', '/assets/weather/thunderstorm.svg', '/assets/weather/wind.svg' ]; function isNavigationRequest(request) { return request.mode === 'navigate'; } function isStaticAsset(pathname) { return pathname.startsWith('/assets/') || pathname.startsWith('/css/') || pathname.startsWith('/dist/'); } async function networkFirst(request, preloadResponsePromise) { const cache = await caches.open(CACHE); try { const preloadResponse = preloadResponsePromise ? await preloadResponsePromise : null; if (preloadResponse) { cache.put(request, preloadResponse.clone()).catch(() => {}); return preloadResponse; } const response = await fetch(request); cache.put(request, response.clone()).catch(() => {}); return response; } catch (_) { return caches.match(request) || caches.match('/index.html'); } } async function staleWhileRevalidate(request) { const cache = await caches.open(CACHE); const cached = await cache.match(request); const networkPromise = fetch(request) .then((response) => { cache.put(request, response.clone()).catch(() => {}); return response; }) .catch(() => null); if (cached) return cached; return networkPromise.then((response) => response || Response.error()); } self.addEventListener('install', (event) => { self.skipWaiting(); event.waitUntil( caches.open(CACHE).then((cache) => cache.addAll(PRECACHE.map((url) => new Request(url, { cache: 'reload' }))) ) ); }); self.addEventListener('activate', (event) => { event.waitUntil((async () => { const keys = await caches.keys(); await Promise.all(keys.filter((key) => key !== CACHE).map((key) => caches.delete(key))); if ('navigationPreload' in self.registration) { await self.registration.navigationPreload.enable(); } await self.clients.claim(); })()); }); self.addEventListener('fetch', (event) => { const { request } = event; if (request.method !== 'GET') return; const url = new URL(request.url); if (url.origin !== self.location.origin) return; if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/probe/')) return; if (isNavigationRequest(request) || url.pathname === '/' || url.pathname.endsWith('/index.html')) { event.respondWith(networkFirst(request, event.preloadResponse)); return; } if (isStaticAsset(url.pathname)) { event.respondWith(staleWhileRevalidate(request)); } });