Diff -- /var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/sw.js
Diff

/var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/sw.js

added on local at 2026-07-01 13:47:45

Added
+83
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 707e59c0a618
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1// AffSoft service worker -- minimal network-first with offline fallback.
2// Keeps the mobile dashboard usable while the device is briefly offline
3// (commute, elevator, etc.) without staling out fresh stats when online.
4const CACHE = 'affsoft-v1';
5const STATIC_ASSETS = [
6 '/manifest.webmanifest',
7 '/assets/css/site.css',
8];
9
10self.addEventListener('install', e => {
11 e.waitUntil(caches.open(CACHE).then(c => c.addAll(STATIC_ASSETS)).then(() => self.skipWaiting()));
12});
13
14self.addEventListener('activate', e => {
15 e.waitUntil(
16 caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k))))
17 .then(() => self.clients.claim())
18 );
19});
20
21// Web Push: show notification when AffSoft pings us with new earnings.
22self.addEventListener('push', e => {
23 let data = { title: 'AffSoft', body: 'You have new activity.' };
24 try { data = e.data.json(); } catch(_) { try { data.body = e.data.text(); } catch(_){} }
25 const title = data.title || 'AffSoft';
26 const body = data.body || '';
27 const url = data.url || '/m.cgi';
28 e.waitUntil(self.registration.showNotification(title, {
29 body,
30 icon: '/assets/icon-192.png',
31 badge: '/assets/icon-192.png',
32 data: { url },
33 vibrate: [120, 60, 120],
34 tag: data.tag || 'affsoft-notify',
35 }));
36});
37
38self.addEventListener('notificationclick', e => {
39 e.notification.close();
40 const url = (e.notification.data && e.notification.data.url) || '/m.cgi';
41 e.waitUntil(clients.matchAll({type:'window'}).then(list => {
42 for (const c of list) {
43 if (c.url.includes(url.split('?')[0]) && 'focus' in c) return c.focus();
44 }
45 return clients.openWindow(url);
46 }));
47});
48
49self.addEventListener('fetch', e => {
50 const req = e.request;
51 if (req.method !== 'GET') return;
52 const url = new URL(req.url);
53 if (url.origin !== self.location.origin) return;
54
55 // Network-first for CGI; falls back to cache only if offline.
56 // Static assets: cache-first, populate from network.
57 if (url.pathname.endsWith('.cgi') || url.pathname === '/m.cgi' || url.pathname === '/') {
58 e.respondWith(
59 fetch(req).then(res => {
60 if (res && res.ok) {
61 const clone = res.clone();
62 caches.open(CACHE).then(c => c.put(req, clone)).catch(()=>{});
63 }
64 return res;
65 }).catch(() => caches.match(req).then(c => c || new Response(
66 '<h1>Offline</h1><p>Reconnect to refresh your stats.</p>',
67 { headers: { 'Content-Type': 'text/html' } }
68 )))
69 );
70 return;
71 }
72
73 // Static: cache-first
74 e.respondWith(
75 caches.match(req).then(cached => cached || fetch(req).then(res => {
76 if (res && res.ok) {
77 const clone = res.clone();
78 caches.open(CACHE).then(c => c.put(req, clone)).catch(()=>{});
79 }
80 return res;
81 }))
82 );
83});
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help