UNPKG

use-pwa

Version:

React hook for PWA installation detection and handling

80 lines (79 loc) 2.1 kB
// src/hooks/use-pwa.ts import { useCallback, useEffect, useRef, useState } from "react"; var capturedEvent = null; if (typeof window !== "undefined") { window.addEventListener("beforeinstallprompt", (event) => { event.preventDefault(); capturedEvent = event; }); } function usePwa() { const promptEvent = useRef(capturedEvent); const [canInstall, setCanInstall] = useState(false); const [isInstalled, setIsInstalled] = useState(false); const [isSupported, setIsSupported] = useState(false); const install = useCallback(async () => { if (!promptEvent.current) { return void 0; } await promptEvent.current.prompt(); const choice = await promptEvent.current.userChoice; if (choice.outcome === "accepted") { setCanInstall(false); promptEvent.current = null; capturedEvent = null; } return choice; }, []); useEffect(() => { if (capturedEvent) { promptEvent.current = capturedEvent; setCanInstall(true); } const handleBeforeInstallPrompt = (event) => { event.preventDefault(); promptEvent.current = event; capturedEvent = event; setCanInstall(true); }; window.addEventListener("beforeinstallprompt", handleBeforeInstallPrompt); return () => { window.removeEventListener( "beforeinstallprompt", handleBeforeInstallPrompt ); }; }, []); useEffect(() => { if (document.referrer.includes("android-app://")) { setIsInstalled(true); return; } const displayModes = ["fullscreen", "standalone", "minimal-ui"]; const isDisplayModePwa = displayModes.some( (mode) => window.matchMedia(`(display-mode: ${mode})`).matches ); if (isDisplayModePwa) { setIsInstalled(true); return; } if (navigator.standalone) { setIsInstalled(true); } }, []); useEffect(() => { if ("BeforeInstallPromptEvent" in window) { setIsSupported(true); } }, []); return { canInstall, install, isInstalled, isSupported }; } export { usePwa as default, usePwa };