import React from 'react'; import { BeforeInstallPromptEvent, getStandaloneStatus, isIosDevice, type InstallOutcome, } from '../lib/installPrompt'; type InstallPromptState = { canInstall: boolean; isInstalled: boolean; isStandalone: boolean; isIos: boolean; outcome: InstallOutcome | null; promptInstall: () => Promise; }; export function useInstallPrompt(): InstallPromptState { const [deferredPrompt, setDeferredPrompt] = React.useState(null); const [isInstalled, setIsInstalled] = React.useState(false); const [isStandalone, setIsStandalone] = React.useState(false); const [isIos, setIsIos] = React.useState(false); const [outcome, setOutcome] = React.useState(null); React.useEffect(() => { if (typeof window === 'undefined') { return undefined; } const updateStandalone = () => { const standalone = getStandaloneStatus(); setIsStandalone(standalone); if (standalone) { setIsInstalled(true); } }; setIsIos(isIosDevice(navigator.userAgent ?? '')); updateStandalone(); const handleBeforeInstallPrompt = (event: Event) => { event.preventDefault(); setDeferredPrompt(event as BeforeInstallPromptEvent); }; const handleAppInstalled = () => { setIsInstalled(true); setDeferredPrompt(null); setOutcome('accepted'); }; const mediaQuery = window.matchMedia?.('(display-mode: standalone)'); const handleDisplayModeChange = () => updateStandalone(); window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt); window.addEventListener('appinstalled', handleAppInstalled); mediaQuery?.addEventListener?.('change', handleDisplayModeChange); return () => { window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt); window.removeEventListener('appinstalled', handleAppInstalled); mediaQuery?.removeEventListener?.('change', handleDisplayModeChange); }; }, []); const promptInstall = React.useCallback(async () => { if (!deferredPrompt) { return null; } await deferredPrompt.prompt(); const choice = await deferredPrompt.userChoice; setOutcome(choice.outcome ?? 'unknown'); if (choice.outcome === 'accepted') { setIsInstalled(true); setDeferredPrompt(null); } return choice.outcome ?? 'unknown'; }, [deferredPrompt]); return { canInstall: Boolean(deferredPrompt), isInstalled, isStandalone, isIos, outcome, promptInstall, }; }