diff --git a/Js/sw-register.js b/Js/sw-register.js index a90b3b7..687b1d2 100644 --- a/Js/sw-register.js +++ b/Js/sw-register.js @@ -1,245 +1,452 @@ -// Enregistrement du Service Worker amélioré +// sw-register.js - Version 2.0 +// Enregistrement et gestion du Service Worker + (function() { - // Vérifier si le Service Worker est supporté - if (!('serviceWorker' in navigator)) { - console.warn('[App] Service Worker non supporté'); - return; - } - - // Vérifier si nous sommes en HTTPS ou localhost - if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') { - console.warn('[App] Service Worker nécessite HTTPS en production'); - return; - } - - // Fonction principale d'enregistrement - function registerServiceWorker() { - const swUrl = '/service-worker.js?v=1.1'; + 'use strict'; - navigator.serviceWorker.register(swUrl) - .then(function(registration) { - console.log('[Service Worker] Enregistré avec succès:', registration.scope); + // ============================================ + // CONFIGURATION + // ============================================ + + const SW_URL = '/service-worker.js?v=2.1'; + const CHECK_INTERVAL = 60 * 60 * 1000; // 1 heure + const DEBUG = true; + + // ============================================ + // VÉRIFICATIONS PRÉALABLES + // ============================================ + + // 1. Vérifier si le Service Worker est supporté + if (!('serviceWorker' in navigator)) { + log('Service Worker non supporté par ce navigateur'); + return; + } + + // 2. Vérifier si on est en HTTPS ou localhost + if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') { + log('Service Worker nécessite HTTPS en production'); + return; + } + + // ============================================ + // FONCTION PRINCIPALE D'ENREGISTREMENT + // ============================================ + + function registerServiceWorker() { + log('Tentative d\'enregistrement du Service Worker...'); - // Vérifier si une mise à jour est disponible + navigator.serviceWorker.register(SW_URL) + .then(handleRegistrationSuccess) + .catch(handleRegistrationError); + } + + // ============================================ + // GESTION DE LA RÉUSSITE + // ============================================ + + function handleRegistrationSuccess(registration) { + log('Service Worker enregistré avec succès:', registration.scope); + + // Configurer les écouteurs d'événements + setupEventListeners(registration); + + // Configurer la vérification périodique des mises à jour + setupUpdateChecking(registration); + + // Initialiser la gestion hors ligne + setupOfflineManagement(); + + // Exposer l'API publique + exposePublicAPI(registration); + } + + // ============================================ + // GESTION DES ERREURS + // ============================================ + + function handleRegistrationError(error) { + console.error('Erreur d\'enregistrement du Service Worker:', error); + + // Suggestions de dépannage basées sur l'erreur + if (error.name === 'SecurityError') { + console.warn('⚠️ Vérifiez que vous êtes en HTTPS'); + } else if (error.name === 'TypeError') { + console.warn('⚠️ Vérifiez le chemin du Service Worker'); + } else if (error.message.includes('MIME type')) { + console.warn('⚠️ Vérifiez l\'en-tête Content-Type du Service Worker'); + } + } + + // ============================================ + // CONFIGURATION DES ÉCOUTEURS + // ============================================ + + function setupEventListeners(registration) { + // Écouter les mises à jour du Service Worker registration.addEventListener('updatefound', function() { - const installingWorker = registration.installing; - console.log('[Service Worker] Mise à jour trouvée:', installingWorker.state); - - installingWorker.addEventListener('statechange', function() { - console.log('[Service Worker] Nouvel état:', this.state); + const newWorker = registration.installing; + log('Nouvelle version du Service Worker trouvée:', newWorker.state); - if (this.state === 'installed' && navigator.serviceWorker.controller) { - // Nouvelle version disponible - showUpdateNotification(); - } - - if (this.state === 'activated') { - console.log('[Service Worker] Nouveau Service Worker activé'); - // Notifier tous les clients - sendMessageToSW({ type: 'NEW_VERSION_ACTIVATED' }); - } - }); + newWorker.addEventListener('statechange', function() { + log('État du nouveau Service Worker:', this.state); + + if (this.state === 'installed' && navigator.serviceWorker.controller) { + showUpdateNotification(); + } + + if (this.state === 'activated') { + log('Nouveau Service Worker activé'); + notifyClientsOfUpdate(); + } + }); }); - // Vérifier l'état du Service Worker périodiquement + // Écouter les messages du Service Worker + navigator.serviceWorker.addEventListener('message', handleServiceWorkerMessage); + } + + // ============================================ + // GESTION DES MESSAGES DU SERVICE WORKER + // ============================================ + + function handleServiceWorkerMessage(event) { + log('Message reçu du Service Worker:', event.data); + + switch (event.data.type) { + case 'SW_ACTIVATED': + log('Service Worker activé, version:', event.data.version); + break; + + case 'CACHE_UPDATED': + log('Cache mis à jour:', event.data.resources); + break; + + case 'OFFLINE_MODE': + showOfflineNotification(); + break; + } + } + + // ============================================ + // VÉRIFICATION PÉRIODIQUE DES MISES À JOUR + // ============================================ + + function setupUpdateChecking(registration) { + // Vérifier les mises à jour toutes les heures setInterval(() => { - registration.update().catch(err => { - console.debug('[SW] Pas de mise à jour disponible:', err); - }); - }, 60 * 60 * 1000); // Toutes les heures + registration.update().catch(err => { + log('Pas de mise à jour disponible:', err.message); + }); + }, CHECK_INTERVAL); - return registration; - }) - .catch(function(error) { - console.error('[Service Worker] Erreur d\'enregistrement:', error); + // Vérifier aussi quand la page redevient visible + document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + registration.update().catch(() => {}); + } + }); + } + + // ============================================ + // GESTION HORS LIGNE + // ============================================ + + function setupOfflineManagement() { + window.addEventListener('online', function() { + log('Connexion rétablie'); + document.documentElement.classList.remove('offline'); + showOnlineNotification(); + syncData(); + }); - // Tentative de récupération - if (error.name === 'SecurityError') { - console.warn('[SW] Erreur de sécurité - Vérifiez HTTPS'); - } else if (error.name === 'TypeError') { - console.warn('[SW] Erreur de type - Vérifiez le chemin du SW'); + window.addEventListener('offline', function() { + log('Mode hors ligne'); + document.documentElement.classList.add('offline'); + showOfflineNotification(); + }); + + // Vérifier l'état initial + if (!navigator.onLine) { + document.documentElement.classList.add('offline'); } - }); - } - - // Gestion de l'état de connexion - function setupConnectionHandlers() { - window.addEventListener('online', function() { - console.log('[App] Connexion rétablie'); - document.documentElement.classList.remove('offline'); - showOnlineNotification(); - - // Synchroniser les données - if (navigator.serviceWorker.controller) { - sendMessageToSW({ type: 'SYNC_DATA' }); - } - }); - - window.addEventListener('offline', function() { - console.log('[App] Mode hors ligne'); - document.documentElement.classList.add('offline'); - showOfflineNotification(); - }); - - // Vérifier l'état initial - if (!navigator.onLine) { - document.documentElement.classList.add('offline'); } - } - - // Notification de mise à jour - function showUpdateNotification() { - const isAnglophone = window.appConfig?.isAnglophone || false; - // Utiliser SweetAlert2 si disponible - if (typeof Swal !== 'undefined') { - Swal.fire({ - title: isAnglophone ? 'Update Available' : 'Mise à jour disponible', - text: isAnglophone - ? 'A new version is available. Reload to update?' - : 'Une nouvelle version est disponible. Recharger pour mettre à jour ?', - icon: 'info', - showCancelButton: true, - confirmButtonText: isAnglophone ? 'Reload' : 'Recharger', - cancelButtonText: isAnglophone ? 'Later' : 'Plus tard', - allowOutsideClick: false - }).then((result) => { - if (result.isConfirmed) { - window.location.reload(); + // ============================================ + // NOTIFICATIONS + // ============================================ + + function showUpdateNotification() { + const isAnglophone = window.appConfig?.isAnglophone || false; + const message = isAnglophone + ? 'A new version is available. Reload to update?' + : 'Une nouvelle version est disponible. Recharger pour mettre à jour ?'; + + // Utiliser SweetAlert2 si disponible + if (typeof Swal !== 'undefined') { + Swal.fire({ + title: isAnglophone ? 'Update Available' : 'Mise à jour disponible', + text: message, + icon: 'info', + showCancelButton: true, + confirmButtonText: isAnglophone ? 'Reload' : 'Recharger', + cancelButtonText: isAnglophone ? 'Later' : 'Plus tard', + allowOutsideClick: false + }).then((result) => { + if (result.isConfirmed) { + window.location.reload(); + } + }); + } else { + // Fallback simple + if (confirm(message)) { + window.location.reload(); + } } - }); - } else { - // Fallback simple - if (confirm(isAnglophone - ? 'New version available. Reload?' - : 'Nouvelle version disponible. Recharger ?')) { - window.location.reload(); - } } - } - - // Notification en ligne - function showOnlineNotification() { - // Créer un toast temporaire - const toast = document.createElement('div'); - toast.className = 'position-fixed top-0 end-0 p-3'; - toast.style.zIndex = '9999'; - const isAnglophone = window.appConfig?.isAnglophone || false; - - toast.innerHTML = ` -