diff --git a/index.html b/index.html index dd4d42d..a3eee3c 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,8 @@ The Nexus — Timmy's Sovereign Home + + @@ -172,6 +174,12 @@ + +
{ + event.waitUntil( + caches.open(ASSET_CACHE).then((cache) => cache.addAll(CORE_ASSETS)) + .then(() => self.skipWaiting()) + ); +}); + +// Activate: clean up old caches +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((keys) => + Promise.all( + keys + .filter((key) => key !== CACHE_NAME && key !== ASSET_CACHE) + .map((key) => caches.delete(key)) + ) + ).then(() => self.clients.claim()) + ); +}); + +self.addEventListener('fetch', (event) => { + const { request } = event; + const url = new URL(request.url); + + // Network-first for API calls (Gitea / WebSocket upgrades / portals.json live data) + if ( + url.pathname.startsWith('/api/') || + url.hostname.includes('143.198.27.163') || + request.headers.get('Upgrade') === 'websocket' + ) { + event.respondWith(networkFirst(request)); + return; + } + + // Cache-first for everything else (local assets + CDN) + event.respondWith(cacheFirst(request)); +}); + +async function cacheFirst(request) { + const cached = await caches.match(request); + if (cached) return cached; + + try { + const response = await fetch(request); + if (response.ok) { + const cache = await caches.open(ASSET_CACHE); + cache.put(request, response.clone()); + } + return response; + } catch { + // Offline and not cached — return a minimal fallback for navigation + if (request.mode === 'navigate') { + const fallback = await caches.match('/index.html'); + if (fallback) return fallback; + } + return new Response('Offline', { status: 503, statusText: 'Service Unavailable' }); + } +} + +async function networkFirst(request) { + try { + const response = await fetch(request); + if (response.ok) { + const cache = await caches.open(CACHE_NAME); + cache.put(request, response.clone()); + } + return response; + } catch { + const cached = await caches.match(request); + return cached || new Response('Offline', { status: 503, statusText: 'Service Unavailable' }); + } +}