const CACHE_NAME = 'gridtv-v2'; // Ressources statiques à mettre en cache immédiatement const STATIC_ASSETS = [ '/', '/index.php', '/manifest.json', '/assets/fonts/fonts.css', '/assets/icon-192.png', '/assets/icon-512.png', '/assets/vendor/hls.min.js' ]; // Install : mise en cache des assets statiques self.addEventListener('install', e => { e.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(STATIC_ASSETS)) .then(() => self.skipWaiting()) ); }); // Activate : purger les anciens caches 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()) ); }); // Fetch : stratégie selon le type de ressource self.addEventListener('fetch', e => { const url = new URL(e.request.url); // Flux EPG/M3U et API GitHub : network only (pas de cache) if ( url.pathname.includes('xmltv') || url.pathname.includes('.m3u') || url.hostname === 'api.github.com' || url.pathname.includes('proxy.php') ) { return; } // Assets statiques : cache first if ( e.request.destination === 'style' || e.request.destination === 'script' || e.request.destination === 'font' || e.request.destination === 'image' || url.pathname.endsWith('.json') || url.pathname.endsWith('.css') || url.pathname.endsWith('.js') ) { e.respondWith( caches.match(e.request).then(cached => cached || fetch(e.request).then(res => { const clone = res.clone(); caches.open(CACHE_NAME).then(cache => cache.put(e.request, clone)); return res; })) ); return; } // Pages PHP (index.php) : network first, fallback cache e.respondWith( fetch(e.request) .then(res => { const clone = res.clone(); caches.open(CACHE_NAME).then(cache => cache.put(e.request, clone)); return res; }) .catch(() => caches.match(e.request)) ); });