"use client"; import { useCallback, useEffect, useState } from "react"; type BeforeInstallPromptEvent = Event & { prompt: () => Promise; userChoice: Promise<{ outcome: "accepted" | "dismissed" }>; }; export const PWAInstallPrompt = (): JSX.Element | null => { const [deferred, setDeferred] = useState( null ); const [isInstalled, setIsInstalled] = useState(false); useEffect(() => { if (typeof window === "undefined") return; const onBeforeInstallPrompt = (e: Event) => { setDeferred(e as BeforeInstallPromptEvent); }; const onAppInstalled = () => { setDeferred(null); setIsInstalled(true); }; window.addEventListener("beforeinstallprompt", onBeforeInstallPrompt); window.addEventListener("appinstalled", onAppInstalled); if (window.matchMedia("(display-mode: standalone)").matches) { setIsInstalled(true); } return () => { window.removeEventListener("beforeinstallprompt", onBeforeInstallPrompt); window.removeEventListener("appinstalled", onAppInstalled); }; }, []); const onInstall = useCallback(async () => { if (!deferred) return; try { await deferred.prompt(); const choice = await deferred.userChoice; if (choice.outcome === "accepted") { setDeferred(null); } } catch (_err) { } }, [deferred]); if (isInstalled || !deferred) return null; return ( ); };