/** * PWA Install and Service Worker Helper * Powered by Antigravity AI */ (function () { const BASE_PATH = window.BASE_PATH || ''; // Register Service Worker if ('serviceWorker' in navigator) { window.addEventListener('load', () => { const swUrl = `${BASE_PATH}/sw.js`; navigator.serviceWorker.register(swUrl) .then((registration) => { console.log('[PWA] Service Worker registrato con successo:', registration.scope); }) .catch((error) => { console.error('[PWA] Registrazione Service Worker fallita:', error); }); }); } // Detectors const isStandalone = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); // Se l'app viene aperta in modalità standalone (PWA) su desktop, reindirizza all'interno dell'app if (isStandalone && !isMobile) { const urlParams = new URLSearchParams(window.location.search); if (!urlParams.has('app') || urlParams.get('app') !== 'true') { const currentPath = window.location.pathname; const pathWithoutBase = currentPath.replace(BASE_PATH, '').replace(/^\//, ''); const redirectParam = pathWithoutBase ? '&redirect=' + encodeURIComponent(pathWithoutBase) : ''; window.location.href = BASE_PATH + '/?app=true' + redirectParam; } } // Global variables window.deferredPrompt = null; // Check if banner was dismissed in the last 7 days function isBannerDismissed() { const dismissedTime = localStorage.getItem('pwa-banner-dismissed'); if (!dismissedTime) return false; const sevenDays = 7 * 24 * 60 * 60 * 1000; return (Date.now() - parseInt(dismissedTime, 10)) < sevenDays; } // Dismiss banner function dismissBanner() { localStorage.setItem('pwa-banner-dismissed', Date.now().toString()); const banner = document.getElementById('pwa-install-banner'); if (banner) { banner.classList.remove('show'); setTimeout(() => { banner.style.display = 'none'; }, 400); } } // Initialize UI components and listeners function initPwaUI() { // If already in standalone mode, hide all promotional components if (isStandalone) { console.log('[PWA] Applicazione avviata in modalità Standalone. Nascondo elementi PWA.'); return; } const headerBtn = document.getElementById('pwa-header-install-btn'); const desktopBtn = document.getElementById('desktopPwaInstallBtn'); const banner = document.getElementById('pwa-install-banner'); const bannerInstallBtn = document.getElementById('pwa-banner-install-btn'); const bannerCloseBtn = document.getElementById('pwa-banner-close-btn'); // On iOS, show the installation buttons immediately (as they don't support beforeinstallprompt) if (isIOS) { console.log('[PWA] Rilevato dispositivo iOS'); if (headerBtn) headerBtn.style.display = 'inline-flex'; if (desktopBtn) desktopBtn.style.display = 'inline-flex'; if (banner && !isBannerDismissed()) { banner.style.display = 'flex'; setTimeout(() => banner.classList.add('show'), 100); } } // Attach click listeners to all PWA installation buttons const triggerInstall = (e) => { e.preventDefault(); if (window.deferredPrompt) { // Show native install prompt (Android / Desktop Chrome / Edge) window.deferredPrompt.prompt(); window.deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === 'accepted') { console.log('[PWA] Utente ha installato la PWA'); dismissBanner(); } else { console.log('[PWA] Utente ha annullato l\'installazione'); } window.deferredPrompt = null; }); } else { // Fallback for iOS Safari or other unsupported prompts showInstructionsModal(); } }; if (headerBtn) headerBtn.addEventListener('click', triggerInstall); if (desktopBtn) desktopBtn.addEventListener('click', triggerInstall); if (bannerInstallBtn) bannerInstallBtn.addEventListener('click', triggerInstall); if (bannerCloseBtn) { bannerCloseBtn.addEventListener('click', (e) => { e.preventDefault(); dismissBanner(); }); } // Modal Close logic const modal = document.getElementById('pwa-instructions-modal'); const modalCloseBtnTop = document.getElementById('pwa-modal-close-btn'); const closeModal = () => { if (modal) { modal.classList.remove('show'); setTimeout(() => { modal.style.display = 'none'; }, 300); } }; if (modalCloseBtnTop) modalCloseBtnTop.addEventListener('click', closeModal); if (modal) { modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); }); } } // Listen for beforeinstallprompt (Chrome / Android / Edge) window.addEventListener('beforeinstallprompt', (e) => { // Prevent Chrome 67 and earlier from automatically showing the prompt e.preventDefault(); // Se siamo su desktop, non salviamo il prompt e non mostriamo nessun banner promozionale PWA if (!isMobile) { console.log('[PWA] Installazione via browser intercettata su desktop. Ignorata per requisiti.'); return; } // Stash the event so it can be triggered later. window.deferredPrompt = e; console.log('[PWA] Evento beforeinstallprompt intercettato.'); // Show custom buttons and banner (if not dismissed) const headerBtn = document.getElementById('pwa-header-install-btn'); const desktopBtn = document.getElementById('desktopPwaInstallBtn'); const banner = document.getElementById('pwa-install-banner'); if (headerBtn) headerBtn.style.display = 'inline-flex'; if (desktopBtn) desktopBtn.style.display = 'inline-flex'; if (banner && !isBannerDismissed()) { banner.style.display = 'flex'; setTimeout(() => banner.classList.add('show'), 100); } }); // Track successful installation window.addEventListener('appinstalled', () => { console.log('[PWA] L\'applicazione è stata installata con successo.'); window.deferredPrompt = null; // Hide all promotional components const headerBtn = document.getElementById('pwa-header-install-btn'); const desktopBtn = document.getElementById('desktopPwaInstallBtn'); const banner = document.getElementById('pwa-install-banner'); if (headerBtn) headerBtn.style.display = 'none'; if (desktopBtn) desktopBtn.style.display = 'none'; if (banner) banner.style.display = 'none'; }); // Show instructions modal (iOS / Fallback) function showInstructionsModal() { const modal = document.getElementById('pwa-instructions-modal'); const content = document.getElementById('pwa-instructions-content'); if (!modal || !content) return; if (isIOS) { content.innerHTML = `