/* Konoha Fighting service worker (based on AETHER CLASH by Bang Tutorial). preload.js fills the 'aether-assets' cache (with content hashes) on each visit, so this worker only has to answer from it: - pictures and fonts: cache first (instant screens, works offline); - pages, CSS and JS: network first, so a new deploy shows up at once; the cache is the offline fallback; - audio/video and range requests: left to the network and HTTP cache (Safari needs real 206 range answers); - a page that can be loaded from neither the network nor the cache gets offline.html (PWA, RENCANA 4.7). It lives in its own small cache because preload.js drops every 'aether-assets' entry that is not listed in precache.js. */ const CACHE = 'aether-assets'; const SHELL = 'konoha-offline-v1'; const OFFLINE = 'offline.html'; self.addEventListener('install', event => event.waitUntil(caches.open(SHELL).then(cache => cache.add(new Request(OFFLINE, { cache: 'reload' }))).catch(() => {}).then(() => self.skipWaiting()))); self.addEventListener('activate', event => event.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(key => key.startsWith('konoha-offline-') && key !== SHELL).map(key => caches.delete(key)))).catch(() => {}).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 !== location.origin || req.headers.has('range') || /\.(mp3|mp4)$/i.test(url.pathname)) return; const fromCache = () => caches.open(CACHE).then(cache => cache.match(url.href, { ignoreSearch: true }) .then(hit => hit || (url.pathname.endsWith('/') ? cache.match(new URL('index.html', url).href) : undefined))); const offlinePage = () => caches.match(new URL(OFFLINE, self.registration.scope).href).then(hit => hit || Response.error()); if (/\.(webp|png|svg|ttf|woff2)$/i.test(url.pathname)) { event.respondWith(fromCache().then(hit => hit || fetch(req))); return; } event.respondWith(fetch(req).catch(() => fromCache().then(hit => hit || (req.mode === 'navigate' ? offlinePage() : Response.error())))); });