// sw-register.js - Version 2.0 // Enregistrement et gestion du Service Worker (function() { 'use strict'; // ============================================ // 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...'); 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 newWorker = registration.installing; log('Nouvelle version du Service Worker trouvée:', newWorker.state); 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(); } }); }); // É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 => { log('Pas de mise à jour disponible:', err.message); }); }, CHECK_INTERVAL); // 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(); }); 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'); } } // ============================================ // 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(); } } } function showOnlineNotification() { const isAnglophone = window.appConfig?.isAnglophone || false; showToast( isAnglophone ? 'Online' : 'En ligne', isAnglophone ? 'Connection restored. Data will be synchronized.' : 'Connexion rétablie. Les données seront synchronisées.', 'success', 3000 ); // Notifier le Service Worker if (navigator.serviceWorker.controller) { navigator.serviceWorker.controller.postMessage({ type: 'NETWORK_RESTORED', timestamp: Date.now() }); } } function showOfflineNotification() { const isAnglophone = window.appConfig?.isAnglophone || false; showToast( isAnglophone ? 'Offline' : 'Hors ligne', isAnglophone ? 'No internet connection. Working in offline mode.' : 'Pas de connexion Internet. Mode hors ligne actif.', 'warning', 5000 ); } function showToast(title, message, type, duration) { const toast = document.createElement('div'); toast.className = `sw-toast sw-toast-${type}`; toast.style.cssText = ` position: fixed; top: 20px; right: 20px; background: ${type === 'success' ? '#27ae60' : '#e74c3c'}; color: white; padding: 15px 20px; border-radius: 8px; z-index: 9999; box-shadow: 0 4px 12px rgba(0,0,0,0.15); max-width: 300px; animation: slideIn 0.3s ease; `; toast.innerHTML = `