// Cache the app shell with paths relative to this worker's scope // so a subfolder deploy (Vite base: './') keeps working. const CACHE_NAME = 'matematika-shell-v3' function scopeUrl(path) { return new URL(path, self.registration.scope).href } const ASSETS_TO_CACHE = [ './', './index.html', './manifest.json', './favicon/site.webmanifest', './favicon/web-app-manifest-192x192.png', './favicon/web-app-manifest-512x512.png', './favicon/apple-touch-icon.png', './favicon/favicon-96x96.png' ].map(scopeUrl) self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS_TO_CACHE).catch(err => { console.warn('Precache failed (continuing):', err) }) ) ) 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 => { if (event.request.method !== 'GET') return if (event.request.mode === 'navigate') { event.respondWith( fetch(event.request).then(resp => { if (resp && resp.status === 200) { const respClone = resp.clone() caches.open(CACHE_NAME).then(cache => cache.put(event.request, respClone)) } return resp }).catch(() => caches.match(scopeUrl('./index.html'))) ) return } event.respondWith( caches.match(event.request).then(cached => { const networkFetch = fetch(event.request).then(resp => { if (resp && resp.status === 200) { const respClone = resp.clone() caches.open(CACHE_NAME).then(cache => cache.put(event.request, respClone)) } return resp }).catch(() => null) return cached || networkFetch }) ) }) self.addEventListener('message', event => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting() } })