From 7057e876e66cd1b1daed4560ac557a6ae1e30de6 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Tue, 24 Mar 2026 00:30:54 -0400 Subject: [PATCH] feat: Add service worker for offline capability (Fixes #212) --- index.html | 13 +++++++++ sw.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 sw.js diff --git a/index.html b/index.html index 795f24e..c4b449c 100644 --- a/index.html +++ b/index.html @@ -49,6 +49,19 @@
⚡ SOVEREIGNTY ⚡
+
diff --git a/sw.js b/sw.js new file mode 100644 index 0000000..64fd994 --- /dev/null +++ b/sw.js @@ -0,0 +1,77 @@ +const CACHE_NAME = 'nexus-cache-v1'; +const ASSETS = [ + '/', + '/index.html', + '/app.js', + '/style.css', + '/manifest.json', + 'https://unpkg.com/three@0.183.0/build/three.module.js', + 'https://unpkg.com/three@0.183.0/examples/jsm/' // This might need to be more specific, or handled differently +]; + +self.addEventListener('install', (event) => { + event.waitUntil( + caches.open(CACHE_NAME) + .then((cache) => { + console.log('Opened cache'); + return cache.addAll(ASSETS); + }) + ); +}); + +self.addEventListener('fetch', (event) => { + const requestUrl = new URL(event.request.url); + + // Cache-first for assets + const isAsset = ASSETS.some(asset => event.request.url.includes(asset)); + + if (isAsset || requestUrl.origin === location.origin) { + event.respondWith( + caches.match(event.request) + .then((response) => { + if (response) { + return response; + } + return fetch(event.request) + .then((networkResponse) => { + // Only cache successful responses + if (networkResponse.ok) { + return caches.open(CACHE_NAME).then((cache) => { + cache.put(event.request, networkResponse.clone()); + return networkResponse; + }); + } + return networkResponse; + }); + }) + .catch(() => { + // Fallback for offline if no cache and no network + // This could be a more robust offline page if needed + return new Response('You are offline.'); + }) + ); + } else { + // Network-first for other requests (e.g., API calls) + event.respondWith( + fetch(event.request) + .catch(() => { + return caches.match(event.request); + }) + ); + } +}); + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheName !== CACHE_NAME) { + console.log('Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + ); +}); -- 2.43.0