import { useEffect, useRef, useState } from "react"; import { devolverEvento, eventoDisponible, marcarInstalado, suscribir, tomarEvento, yaInstalado, } from "./installPrompt"; export type InstallPromptState = "unsupported" | "available" | "ios-instructions" | "installed"; const DISMISSED_STORAGE_KEY = "agendamax-install-dismissed"; function hasDismissedPrompt() { try { return window.sessionStorage.getItem(DISMISSED_STORAGE_KEY) === "1"; } catch { return false; } } function clearDismissedPrompt() { try { window.sessionStorage.removeItem(DISMISSED_STORAGE_KEY); } catch { // Storage can be unavailable in privacy-restricted browsers. } } function persistDismissedPrompt() { try { window.sessionStorage.setItem(DISMISSED_STORAGE_KEY, "1"); } catch { // Storage can be unavailable in privacy-restricted browsers. } } function isStandalone() { return window.matchMedia("(display-mode: standalone)").matches || ("standalone" in navigator && Boolean((navigator as Navigator & { standalone?: boolean }).standalone)); } function isIOSSafari() { const ua = navigator.userAgent; const ios = /iPad|iPhone|iPod/.test(ua) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1); return ios && /Safari/i.test(ua) && !/CriOS|FxiOS|EdgiOS|OPiOS/i.test(ua); } /** * El estado inicial ya consulta el almacén de `installPrompt`: cuando este hook corre, el * evento puede haberse disparado hace rato. No se registra un listener propio aquí a * propósito — ver el comentario de `src/lib/installPrompt.ts`. */ export function useInstallPrompt() { const [state, setState] = useState(() => { if (typeof window === "undefined") return "unsupported"; if (isStandalone() || yaInstalado()) return "installed"; if (eventoDisponible()) return hasDismissedPrompt() ? "unsupported" : "available"; return isIOSSafari() ? "ios-instructions" : "unsupported"; }); const [dismissed, setDismissed] = useState(() => typeof window !== "undefined" && hasDismissedPrompt()); const installInFlight = useRef(false); useEffect(() => { if (isStandalone()) { setState("installed"); return; } const sincronizar = () => { if (yaInstalado()) { // Instalar borra el descarte: el aviso ya cumplió su función. clearDismissedPrompt(); setDismissed(false); setState("installed"); return; } if (eventoDisponible()) { if (!hasDismissedPrompt()) setState("available"); return; } // Sin evento pendiente: se cae al comportamiento de iOS, que nunca lo dispara. setState(isIOSSafari() ? "ios-instructions" : "unsupported"); }; sincronizar(); return suscribir(sincronizar); }, []); const install = async () => { if (installInFlight.current) return; const event = tomarEvento(); if (!event) return; installInFlight.current = true; try { await event.prompt(); const choice = await event.userChoice; if (choice.outcome === "accepted") { marcarInstalado(); setState("installed"); } else { persistDismissedPrompt(); setDismissed(true); } } catch { // Devolver el evento al almacén: es la única oportunidad de instalar de esta carga. devolverEvento(event); setState("available"); } finally { installInFlight.current = false; } }; return { state: dismissed ? "unsupported" : state, install, dismiss: () => setDismissed(true) }; }