import { useEffect, useState } from "react"; export interface BeforeInstallPromptEvent extends Event { prompt(): Promise; userChoice: Promise<{ outcome: "accepted" | "dismissed" }>; } const DISMISSED_KEY = "pwa-dismissed"; export function usePwaInstall() { const [promptEvent, setPromptEvent] = useState(null); const [isInstalled, setIsInstalled] = useState(false); const [isDismissed, setIsDismissed] = useState( () => !!localStorage.getItem(DISMISSED_KEY), ); useEffect(() => { if (window.matchMedia("(display-mode: standalone)").matches) { setIsInstalled(true); return; } const handleBeforeInstallPrompt = (e: Event) => { e.preventDefault(); setPromptEvent(e as BeforeInstallPromptEvent); }; const handleAppInstalled = () => { setIsInstalled(true); setPromptEvent(null); }; window.addEventListener( "beforeinstallprompt", handleBeforeInstallPrompt, ); window.addEventListener("appinstalled", handleAppInstalled); return () => { window.removeEventListener( "beforeinstallprompt", handleBeforeInstallPrompt, ); window.removeEventListener("appinstalled", handleAppInstalled); }; }, []); const install = async (): Promise => { if (!promptEvent) return false; try { await promptEvent.prompt(); const { outcome } = await promptEvent.userChoice; return outcome === "accepted"; } finally { setPromptEvent(null); } }; const dismiss = () => { localStorage.setItem(DISMISSED_KEY, "1"); setIsDismissed(true); }; return { promptEvent, isInstalled, isDismissed, install, dismiss }; }