feat: Add service worker for offline capability (Fixes #212)
Some checks failed
CI / validate (pull_request) Failing after 18s
CI / auto-merge (pull_request) Has been skipped

This commit is contained in:
Alexander Whitestone
2026-03-24 00:30:54 -04:00
parent b61f651226
commit 7057e876e6
2 changed files with 90 additions and 0 deletions

View File

@@ -49,6 +49,19 @@
<div id="sovereignty-msg">⚡ SOVEREIGNTY ⚡</div>
<script type="module" src="app.js"></script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered: ', registration);
})
.catch(error => {
console.log('Service Worker registration failed: ', error);
});
});
}
</script>
<div id="loading" style="position: fixed; top: 0; left: 0; right: 0; height: 4px; background: #222; z-index: 1000;">
<div id="loading-bar" style="height: 100%; background: var(--color-accent); width: 0;"></div>
</div>

77
sw.js Normal file
View File

@@ -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);
}
})
);
})
);
});