const CACHE_NAME = 'teknav-v5'; const ASSETS_TO_CACHE = [ '/', '/index.html', '/manifest.json', '/favicon.png' ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME) .then((cache) => cache.addAll(ASSETS_TO_CACHE)) .then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys() .then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)))) .then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (event) => { const { request } = event; if (request.method !== 'GET') return; const url = new URL(request.url); if (url.origin === location.origin && (url.pathname.startsWith('/article/') || url.pathname === '/' || url.pathname === '/articles')) { event.respondWith( fetch(request) .then((response) => { const copy = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, copy)); return response; }) .catch(() => caches.match(request).then((cached) => cached || caches.match('/index.html'))) ); return; } if (url.origin === location.origin && url.pathname.startsWith('/api/articles')) { event.respondWith(fetch(request)); return; } if (request.headers.get('Accept')?.includes('text/html')) { event.respondWith( fetch(request) .then((response) => { const copy = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, copy)); return response; }) .catch(() => caches.match(request).then((cached) => cached || caches.match('/index.html'))) ); return; } event.respondWith(caches.match(request).then((response) => response || fetch(request))); }); self.addEventListener('push', (event) => { const data = event.data ? event.data.json() : { title: 'تکناو', body: '', url: '/', icon: '/icons/icon-192x192.png' }; event.waitUntil( self.registration.showNotification(data.title, { body: data.body, icon: data.icon || '/icons/icon-192x192.png', badge: '/icons/badge-72x72.png', dir: 'rtl', lang: 'fa', data: { url: data.url || '/' }, }) ); }); self.addEventListener('notificationclick', (event) => { event.notification.close(); const targetUrl = (event.notification.data && event.notification.data.url) || '/'; event.waitUntil( clients.matchAll({ type: 'window', includeUncontrolled: true }).then((list) => { for (const client of list) { if ('focus' in client) { client.navigate(targetUrl); return client.focus(); } } return clients.openWindow(targetUrl); }) ); });