Files
HRM-System/resources/js/hooks/usePWAInstall.ts
2026-04-13 08:16:56 +08:00

60 lines
1.7 KiB
TypeScript
Executable File

import { useState, useEffect } from 'react';
interface BeforeInstallPromptEvent extends Event {
prompt(): Promise<void>;
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
}
export function usePWAInstall() {
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null);
const [isInstallable, setIsInstallable] = useState(false);
const [isInstalled, setIsInstalled] = useState(false);
useEffect(() => {
// Check if app is already installed
if (window.matchMedia('(display-mode: standalone)').matches) {
setIsInstalled(true);
}
const handleBeforeInstallPrompt = (e: BeforeInstallPromptEvent) => {
e.preventDefault();
setDeferredPrompt(e);
setIsInstallable(true);
};
const handleAppInstalled = () => {
setIsInstalled(true);
setIsInstallable(false);
setDeferredPrompt(null);
};
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt as EventListener);
window.addEventListener('appinstalled', handleAppInstalled);
return () => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt as EventListener);
window.removeEventListener('appinstalled', handleAppInstalled);
};
}, []);
const install = async (): Promise<'accepted' | 'dismissed' | 'unavailable'> => {
if (!deferredPrompt) {
return 'unavailable';
}
await deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
setDeferredPrompt(null);
setIsInstallable(false);
return outcome;
};
return {
isInstallable,
isInstalled,
install,
canInstall: isInstallable && !isInstalled
};
}