import { useCallback, useEffect, useRef, useState } from "react"; const DISMISSED_KEY = "pwa-install-dismissed"; interface BeforeInstallPromptEvent extends Event { prompt(): Promise<{ outcome: "accepted" | "dismissed" }>; } export function useInstallPrompt() { const deferredPrompt = useRef(null); const [canInstall, setCanInstall] = useState(false); const [isDismissed, setIsDismissed] = useState( () => localStorage.getItem(DISMISSED_KEY) === "true" ); const isStandalone = typeof window !== "undefined" && typeof window.matchMedia === "function" && (window.matchMedia("(display-mode: standalone)")?.matches ?? false); const isIOS = typeof navigator !== "undefined" && /iPad|iPhone|iPod/.test(navigator.userAgent); useEffect(() => { const handler = (e: Event) => { e.preventDefault(); deferredPrompt.current = e as BeforeInstallPromptEvent; setCanInstall(true); }; window.addEventListener("beforeinstallprompt", handler); return () => window.removeEventListener("beforeinstallprompt", handler); }, []); const promptInstall = useCallback(async () => { if (!deferredPrompt.current) return; const result = await deferredPrompt.current.prompt(); if (result.outcome === "accepted") { deferredPrompt.current = null; setCanInstall(false); } }, []); const dismiss = useCallback(() => { setIsDismissed(true); localStorage.setItem(DISMISSED_KEY, "true"); }, []); return { canInstall, isStandalone, isIOS, isDismissed, promptInstall, dismiss }; }