// NexoUnite — makes the app installable: registers the service worker (public/sw.js) and keeps the browser's // "install" offer for a button (Settings → Install the app). Nothing here runs on a page served over plain http, // except on this computer (localhost), where browsers allow it for testing. let offer = null; const listeners = new Set(); const tell = () => listeners.forEach((fn) => { try { fn(); } catch { /* a closed view */ } }); const secure = typeof location !== 'undefined' && (location.protocol === 'https:' || ['localhost', '127.0.0.1'].includes(location.hostname)); if (secure && typeof navigator !== 'undefined' && 'serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js').catch(() => { /* not installable here: the site works the same */ }); }); } if (typeof window !== 'undefined') { // Chrome and Edge (computer and Android) offer the installation through this event; Safari does not have it. window.addEventListener('beforeinstallprompt', (e) => { e.preventDefault(); offer = e; tell(); }); window.addEventListener('appinstalled', () => { offer = null; tell(); }); } /** Is the page already running as the installed app? */ export const installed = () => typeof window !== 'undefined' && (window.matchMedia?.('(display-mode: standalone)').matches || navigator.standalone === true); /** Can this browser show its install window now (Chrome, Edge)? */ export const canInstall = () => Boolean(offer); /** Shows the browser's install window. Resolves with true when the person installed the app. */ export async function install() { if (!offer) return false; const e = offer; offer = null; e.prompt(); const choice = await e.userChoice.catch(() => null); tell(); return choice?.outcome === 'accepted'; } export const onInstallChange = (fn) => { listeners.add(fn); return () => listeners.delete(fn); };