mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-20 11:13:43 +08:00
87 lines
2.7 KiB
TypeScript
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,
|
|
};
|
|
}
|