import { useEffect, useMemo, useState } from 'react' function isStandaloneDisplay() { if (typeof window === 'undefined') return false return ( window.matchMedia?.('(display-mode: standalone)').matches || window.navigator.standalone === true ) } function detectPlatform() { if (typeof navigator === 'undefined') return 'desktop' const userAgent = navigator.userAgent || '' const isIOS = /iPad|iPhone|iPod/.test(userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) if (isIOS) return 'ios' if (/Android/i.test(userAgent)) return 'android' return 'desktop' } function getManualInstallInstructions(platform) { if (platform === 'ios') { return 'Open this app in Safari, tap Share, then choose Add to Home Screen.' } if (platform === 'android') { return 'Open the browser menu and choose Install app or Add to Home screen.' } return 'Open the browser menu and choose Install OwnGPT, Install app, or Create shortcut.' } export function useInstallPrompt() { const [deferredPrompt, setDeferredPrompt] = useState(null) const [isInstalled, setIsInstalled] = useState(() => isStandaloneDisplay()) const [platform, setPlatform] = useState(() => detectPlatform()) useEffect(() => { if (typeof window === 'undefined') return undefined const handleBeforeInstallPrompt = (event) => { event.preventDefault() setDeferredPrompt(event) } const handleInstalled = () => { setDeferredPrompt(null) setIsInstalled(true) } const handleModeChange = () => { setIsInstalled(isStandaloneDisplay()) } const mediaQuery = window.matchMedia?.('(display-mode: standalone)') window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.addEventListener('appinstalled', handleInstalled) mediaQuery?.addEventListener?.('change', handleModeChange) setPlatform(detectPlatform()) setIsInstalled(isStandaloneDisplay()) return () => { window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.removeEventListener('appinstalled', handleInstalled) mediaQuery?.removeEventListener?.('change', handleModeChange) } }, []) const manualInstructions = useMemo(() => getManualInstallInstructions(platform), [platform]) const installState = isInstalled ? 'installed' : deferredPrompt ? 'ready' : 'manual' const install = async () => { if (isInstalled) { return { status: 'installed', platform, instructions: manualInstructions } } if (!deferredPrompt) { return { status: 'manual', platform, instructions: manualInstructions } } deferredPrompt.prompt() const choice = await deferredPrompt.userChoice.catch(() => null) setDeferredPrompt(null) return { status: choice?.outcome === 'accepted' ? 'accepted' : 'dismissed', platform, instructions: manualInstructions, } } return { install, installState, canPromptInstall: Boolean(deferredPrompt), isInstalled, platform, manualInstructions, } }