use-pwa
Version:
React hook for PWA installation detection and handling
80 lines (79 loc) • 2.1 kB
JavaScript
// 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
};