Files
KVideo/lib/hooks/usePWAInstall.ts
T

87 lines
2.7 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
interface BeforeInstallPromptEvent extends Event {
readonly platforms: string[];
readonly userChoice: Promise<{
outcome: 'accepted' | 'dismissed';
platform: string;
}>;
prompt(): Promise<void>;
}
export function usePWAInstall() {
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null);
const [isInstallable, setIsInstallable] = useState(false);
const [isInstalled, setIsInstalled] = useState(false);
const [isIOS, setIsIOS] = useState(false);
const [isStandalone, setIsStandalone] = useState(false);
useEffect(() => {
// Check if app is already installed/standalone
const checkStandalone = () => {
const isStandaloneMode = window.matchMedia('(display-mode: standalone)').matches
|| (window.navigator as any).standalone
|| document.referrer.includes('android-app://');
setIsStandalone(isStandaloneMode);
setIsInstalled(isStandaloneMode);
};
checkStandalone();
// Check if iOS
const checkIOS = () => {
const ua = window.navigator.userAgent.toLowerCase();
const isIOSDevice = /iphone|ipad|ipod/.test(ua);
setIsIOS(isIOSDevice);
};
checkIOS();
const handleBeforeInstallPrompt = (e: Event) => {
// Prevent the mini-infobar from appearing on mobile
e.preventDefault();
// Stash the event so it can be triggered later.
setDeferredPrompt(e as BeforeInstallPromptEvent);
setIsInstallable(true);
};
const handleAppInstalled = () => {
setIsInstalled(true);
setIsInstallable(false);
setDeferredPrompt(null);
};
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
window.addEventListener('appinstalled', handleAppInstalled);
return () => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
window.removeEventListener('appinstalled', handleAppInstalled);
};
}, []);
const handleInstallClick = async () => {
if (!deferredPrompt) return;
// Show the install prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
setIsInstallable(false);
setDeferredPrompt(null);
}
};
return {
isInstallable: isInstallable && !isInstalled,
isIOS: isIOS && !isStandalone,
isInstalled,
handleInstallClick,
};
}