// Service Worker pour Portail RH Inter Santé const CACHE_NAME = 'inter-sante-portal-v1.0'; const OFFLINE_URL = '/offline.html'; // Ressources à mettre en cache immédiatement const PRECACHE_URLS = [ '/', '/style_office.css', '/ux_enhancements.css', '/ux-manager.js', '/manifest.json', '/icons/icon-192x192.png', '/icons/icon-512x512.png' ]; // Installation - Pré-cache des ressources essentielles self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => { console.log('[Service Worker] Pré-cache des ressources'); return cache.addAll(PRECACHE_URLS); }) .then(() => { console.log('[Service Worker] Installation terminée'); return self.skipWaiting(); }) ); }); // Activation - Nettoyage des anciens caches self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { if (cacheName !== CACHE_NAME) { console.log('[Service Worker] Suppression ancien cache:', cacheName); return caches.delete(cacheName); } }) ); }).then(() => { console.log('[Service Worker] Activation terminée'); return self.clients.claim(); }) ); }); // Stratégie de cache: Network First, fallback Cache self.addEventListener('fetch', event => { // Ignorer les requêtes non-GET et les requêtes cross-origin if (event.request.method !== 'GET' || !event.request.url.startsWith(self.location.origin)) { return; } // Pour les pages HTML: Network First if (event.request.headers.get('accept').includes('text/html')) { event.respondWith( fetch(event.request) .then(response => { // Mettre à jour le cache avec la nouvelle version const responseClone = response.clone(); caches.open(CACHE_NAME) .then(cache => cache.put(event.request, responseClone)); return response; }) .catch(() => { // Fallback au cache ou page offline return caches.match(event.request) .then(cachedResponse => { return cachedResponse || caches.match(OFFLINE_URL); }); }) ); return; } // Pour les autres ressources: Cache First event.respondWith( caches.match(event.request) .then(cachedResponse => { if (cachedResponse) { return cachedResponse; } return fetch(event.request) .then(response => { // Ne pas mettre en cache les erreurs if (!response || response.status !== 200 || response.type !== 'basic') { return response; } // Mettre en cache pour la prochaine fois const responseToCache = response.clone(); caches.open(CACHE_NAME) .then(cache => cache.put(event.request, responseToCache)); return response; }) .catch(() => { // Pour les CSS/JS, on peut retourner une réponse vide if (event.request.url.includes('.css')) { return new Response('/* Ressource non disponible hors ligne */', { headers: { 'Content-Type': 'text/css' } }); } if (event.request.url.includes('.js')) { return new Response('// Ressource non disponible hors ligne', { headers: { 'Content-Type': 'application/javascript' } }); } }); }) ); }); // Gestion des messages self.addEventListener('message', event => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting(); } });