48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
|
|
export interface BeforeInstallPromptEvent extends Event {
|
|
prompt(): Promise<void>;
|
|
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
|
|
}
|
|
|
|
const DISMISSED_KEY = 'pwa-dismissed';
|
|
|
|
export function usePwaInstall() {
|
|
const [promptEvent, setPromptEvent] = useState<BeforeInstallPromptEvent | null>(null);
|
|
const [isInstalled, setIsInstalled] = useState(false);
|
|
const [isDismissed, setIsDismissed] = useState(() => !!localStorage.getItem(DISMISSED_KEY));
|
|
|
|
useEffect(() => {
|
|
if (window.matchMedia('(display-mode: standalone)').matches) {
|
|
setIsInstalled(true);
|
|
return;
|
|
}
|
|
|
|
const handler = (e: Event) => {
|
|
e.preventDefault();
|
|
setPromptEvent(e as BeforeInstallPromptEvent);
|
|
};
|
|
|
|
window.addEventListener('beforeinstallprompt', handler);
|
|
return () => window.removeEventListener('beforeinstallprompt', handler);
|
|
}, []);
|
|
|
|
const install = async (): Promise<boolean> => {
|
|
if (!promptEvent) return false;
|
|
await promptEvent.prompt();
|
|
const { outcome } = await promptEvent.userChoice;
|
|
if (outcome === 'accepted') {
|
|
setPromptEvent(null);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
const dismiss = () => {
|
|
localStorage.setItem(DISMISSED_KEY, '1');
|
|
setIsDismissed(true);
|
|
};
|
|
|
|
return { promptEvent, isInstalled, isDismissed, install, dismiss };
|
|
}
|