Files
PinchChat/public/sw.js
Nicolas Varrot 143e9486c2 feat: PWA install prompt, brand-colored channel icons, image load fix, semantic connection indicator
- Fix image display bug: remove loading='lazy' + use opacity instead of hidden (#66)
- PWA: add id/scope to manifest, fix SW cache name, add install prompt hook + button (#64)
- Colorize channel icons with brand colors (Discord blurple, Telegram blue, etc.) (#68)
- Use semantic green for connection indicator instead of theme accent (#70)
- Replace Sparkles icon with PinchChat logo in sidebar (#65)
- Replace decorative dots in sidebar footer with GitHub link (#71)
2026-02-14 13:58:18 +00:00

63 lines
1.9 KiB
JavaScript

// PinchChat Service Worker — cache static assets for offline/instant load
const CACHE_NAME = 'pinchchat-v1';
// Cache static assets on install
self.addEventListener('install', (event) => {
self.skipWaiting();
});
// Clean old caches on activate
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();
});
// Stale-while-revalidate for static assets, network-first for API/WS
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// Skip non-GET, WebSocket upgrades, and chrome-extension requests
if (event.request.method !== 'GET') return;
if (url.protocol === 'chrome-extension:') return;
// Don't cache API calls or WebSocket-related requests
if (url.pathname.startsWith('/api') || url.pathname.startsWith('/ws')) return;
// For navigation requests (HTML), always go network-first to get latest SPA shell
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.then((response) => {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone));
return response;
})
.catch(() => caches.match(event.request))
);
return;
}
// Static assets (JS, CSS, images, fonts): stale-while-revalidate
if (
url.pathname.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|woff2?|ttf|ico|json)$/) ||
url.pathname.startsWith('/assets/')
) {
event.respondWith(
caches.open(CACHE_NAME).then((cache) =>
cache.match(event.request).then((cached) => {
const fetchPromise = fetch(event.request).then((response) => {
if (response.ok) cache.put(event.request, response.clone());
return response;
});
return cached || fetchPromise;
})
)
);
return;
}
});