import { useCallback, useEffect, useState } from "react"; // Detecta si la web se está ejecutando ya como app instalada (modo standalone), // tanto en Chrome/Android (display-mode: standalone) como en Safari/iOS // (navigator.standalone) o dentro de una TWA de Android (referrer android-app://). function calcularSiEsStandalone() { if (typeof window === "undefined") return false; const enModoStandalone = window.matchMedia?.("(display-mode: standalone)")?.matches ?? false; const enIosStandalone = window.navigator?.standalone === true; const enTwaAndroid = document.referrer?.startsWith("android-app://") ?? false; return enModoStandalone || enIosStandalone || enTwaAndroid; } function detectarIos() { if (typeof window === "undefined") return false; return /iphone|ipad|ipod/i.test(window.navigator.userAgent) && !window.MSStream; } /** * Hook que centraliza el estado de instalación de la PWA: * - isInstalled: la app ya se está ejecutando en modo standalone (o el * navegador confirma que está instalada mediante getInstalledRelatedApps). * - canPromptInstall: el navegador ha ofrecido el evento nativo `beforeinstallprompt`, * así que se puede lanzar el diálogo de instalación con promptInstall(). * - isIos: Safari/iOS no soporta beforeinstallprompt, así que ahí solo cabe * mostrar instrucciones manuales ("Compartir → Añadir a pantalla de inicio"). */ export default function usePwaInstall() { const [installPromptEvent, setInstallPromptEvent] = useState(null); const [isInstalled, setIsInstalled] = useState(calcularSiEsStandalone); const [isIos] = useState(detectarIos); useEffect(() => { const alCapturarPrompt = (evento) => { evento.preventDefault(); setInstallPromptEvent(evento); }; const alInstalar = () => { setInstallPromptEvent(null); setIsInstalled(true); }; window.addEventListener("beforeinstallprompt", alCapturarPrompt); window.addEventListener("appinstalled", alInstalar); const consultaDisplayMode = window.matchMedia?.("(display-mode: standalone)"); const alCambiarDisplayMode = () => setIsInstalled(calcularSiEsStandalone()); consultaDisplayMode?.addEventListener?.("change", alCambiarDisplayMode); // Progressive enhancement: en navegadores compatibles (Chrome/Android), // confirma si la PWA ya está instalada aunque se esté viendo en una pestaña normal. navigator.getInstalledRelatedApps?.() .then((apps) => { if (apps.length > 0) setIsInstalled(true); }) .catch(() => {}); return () => { window.removeEventListener("beforeinstallprompt", alCapturarPrompt); window.removeEventListener("appinstalled", alInstalar); consultaDisplayMode?.removeEventListener?.("change", alCambiarDisplayMode); }; }, []); const promptInstall = useCallback(async () => { if (!installPromptEvent) return "unavailable"; installPromptEvent.prompt(); const { outcome } = await installPromptEvent.userChoice; setInstallPromptEvent(null); return outcome; // "accepted" | "dismissed" }, [installPromptEvent]); return { isInstalled, canPromptInstall: Boolean(installPromptEvent), promptInstall, isIos }; }