diff --git a/static/icons/apple-touch-icon.png b/static/icons/apple-touch-icon.png new file mode 100644 index 0000000..de01f1f Binary files /dev/null and b/static/icons/apple-touch-icon.png differ diff --git a/static/icons/favicon-32.png b/static/icons/favicon-32.png new file mode 100644 index 0000000..97da705 Binary files /dev/null and b/static/icons/favicon-32.png differ diff --git a/static/icons/icon-192.png b/static/icons/icon-192.png new file mode 100644 index 0000000..bff2b20 Binary files /dev/null and b/static/icons/icon-192.png differ diff --git a/static/icons/icon-512.png b/static/icons/icon-512.png new file mode 100644 index 0000000..0cdc634 Binary files /dev/null and b/static/icons/icon-512.png differ diff --git a/static/manifest.json b/static/manifest.json index 4a2eb81..aefdafa 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -3,10 +3,21 @@ "short_name": "INTERCEPT", "description": "Unified SIGINT platform for software-defined radio analysis", "start_url": "/", + "scope": "/", "display": "standalone", "background_color": "#0b1118", "theme_color": "#0b1118", "icons": [ + { + "src": "/static/icons/icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/static/icons/icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, { "src": "/static/icons/icon.svg", "sizes": "any", diff --git a/static/sw.js b/static/sw.js index af523e5..b270128 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,22 +1,22 @@ -/* INTERCEPT Service Worker — cache-first static, network-only for API/SSE/WS */ -const CACHE_NAME = 'intercept-v2'; - -const NETWORK_ONLY_PREFIXES = [ - '/stream', '/ws/', '/api/', '/gps/', '/wifi/', '/bluetooth/', - '/adsb/', '/ais/', '/acars/', '/aprs/', '/tscm/', '/satellite/', - '/meshtastic/', '/bt_locate/', '/receiver/', '/sensor/', '/pager/', - '/sstv/', '/weather-sat/', '/subghz/', '/rtlamr/', '/dsc/', '/vdl2/', +/* INTERCEPT Service Worker — cache-first static, network-only for API/SSE/WS */ +const CACHE_NAME = 'intercept-v3'; + +const NETWORK_ONLY_PREFIXES = [ + '/stream', '/ws/', '/api/', '/gps/', '/wifi/', '/bluetooth/', + '/adsb/', '/ais/', '/acars/', '/aprs/', '/tscm/', '/satellite/', + '/meshtastic/', '/bt_locate/', '/receiver/', '/sensor/', '/pager/', + '/sstv/', '/weather-sat/', '/subghz/', '/rtlamr/', '/dsc/', '/vdl2/', '/spy/', '/space-weather/', '/websdr/', '/analytics/', '/correlation/', '/recordings/', '/controller/', '/ops/', ]; - -const STATIC_PREFIXES = [ - '/static/css/', - '/static/js/', - '/static/icons/', - '/static/fonts/', -]; - + +const STATIC_PREFIXES = [ + '/static/css/', + '/static/js/', + '/static/icons/', + '/static/fonts/', +]; + const CACHE_EXACT = ['/manifest.json']; function isHttpRequest(req) { @@ -29,9 +29,9 @@ function isNetworkOnly(req) { const accept = req.headers.get('Accept') || ''; if (accept.includes('text/event-stream')) return true; const url = new URL(req.url); - return NETWORK_ONLY_PREFIXES.some(p => url.pathname.startsWith(p)); -} - + return NETWORK_ONLY_PREFIXES.some(p => url.pathname.startsWith(p)); +} + function isStaticAsset(req) { const url = new URL(req.url); if (CACHE_EXACT.includes(url.pathname)) return true; @@ -62,19 +62,19 @@ function fallbackResponse(req, status = 503) { headers: { 'Content-Type': 'text/plain; charset=utf-8' }, }); } - -self.addEventListener('install', (e) => { - self.skipWaiting(); -}); - -self.addEventListener('activate', (e) => { - e.waitUntil( - caches.keys().then(keys => - Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k))) - ).then(() => self.clients.claim()) - ); -}); - + +self.addEventListener('install', (e) => { + self.skipWaiting(); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then(keys => + Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k))) + ).then(() => self.clients.claim()) + ); +}); + self.addEventListener('fetch', (e) => { const req = e.request; @@ -90,18 +90,18 @@ self.addEventListener('fetch', (e) => { ); return; } - - // Cache-first for static assets - if (isStaticAsset(req)) { - e.respondWith( - caches.open(CACHE_NAME).then(cache => - cache.match(req).then(cached => { - if (cached) { - // Revalidate in background - fetch(req).then(res => { - if (res && res.status === 200) cache.put(req, res.clone()); - }).catch(() => {}); - return cached; + + // Cache-first for static assets + if (isStaticAsset(req)) { + e.respondWith( + caches.open(CACHE_NAME).then(cache => + cache.match(req).then(cached => { + if (cached) { + // Revalidate in background + fetch(req).then(res => { + if (res && res.status === 200) cache.put(req, res.clone()); + }).catch(() => {}); + return cached; } return fetch(req).then(res => { if (res && res.status === 200) cache.put(req, res.clone()); @@ -111,12 +111,12 @@ self.addEventListener('fetch', (e) => { ) ); return; - } - - // Network-first for HTML pages - e.respondWith( - fetch(req).catch(() => - caches.match(req).then(cached => cached || new Response('Offline', { status: 503 })) - ) - ); -}); + } + + // Network-first for HTML pages + e.respondWith( + fetch(req).catch(() => + caches.match(req).then(cached => cached || new Response('Offline', { status: 503 })) + ) + ); +}); diff --git a/templates/index.html b/templates/index.html index f3415b4..0ca2dfc 100644 --- a/templates/index.html +++ b/templates/index.html @@ -10,7 +10,7 @@ - +