// public/sw.js const APP_VERSION = '__APP_VERSION__'; const CACHE_NAME = `timepulse-${APP_VERSION}`; const filesToCache = [ '/', '/index.html', '/style/style.css', '/js/main.js', '/js/ui.js', '/js/api.js', '/js/utils.js', '/manifest.json', '/icons/icon-192x192.webp', '/icons/icon-512x512.webp' ]; // --- Install Event --- self.addEventListener('install', event => { event.waitUntil(caches.open(CACHE_NAME).then(cache => cache.addAll(filesToCache))); self.skipWaiting(); }); // --- Activate Event --- self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all( keys.map(key => { if (key !== CACHE_NAME) { return caches.delete(key); } }) )) ); self.clients.claim(); }); // --- Fetch Event --- self.addEventListener('fetch', event => { if (event.request.method !== 'GET' || event.request.url.includes('/api/')) { return; } const url = new URL(event.request.url); if (event.request.mode === 'navigate' || url.pathname === '/' || url.pathname.endsWith('/index.html')) { event.respondWith( fetch(event.request) .then(response => { const responseClone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseClone)); return response; }) .catch(() => caches.match(event.request)) ); return; } event.respondWith( caches.match(event.request).then(cached => { const fetchPromise = fetch(event.request).then(response => { if (response && response.ok) { const responseClone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseClone)); } return response; }); return cached || fetchPromise; }) ); }); // --- Push Event (The missing part!) --- self.addEventListener('push', e => { try { const data = e.data.json(); self.registration.showNotification(data.title, { body: data.body, icon: '/icons/icon-192x192.webp' }); } catch (error) { console.error('Error in push event:', error); self.registration.showNotification('New Notification', { body: 'You have a new update.' }); } });