67 lines
1.5 KiB
JavaScript
67 lines
1.5 KiB
JavaScript
let initialized = false;
|
|
let deferredInstallPrompt = null;
|
|
const listeners = new Set();
|
|
|
|
function notifyAvailability() {
|
|
const canInstall = Boolean(deferredInstallPrompt);
|
|
listeners.forEach((listener) => {
|
|
try {
|
|
listener(canInstall);
|
|
} catch {
|
|
// ignore listener errors
|
|
}
|
|
});
|
|
}
|
|
|
|
export function initPwaInstallPromptHandling() {
|
|
if (initialized) return;
|
|
initialized = true;
|
|
|
|
window.addEventListener('beforeinstallprompt', (event) => {
|
|
event.preventDefault();
|
|
deferredInstallPrompt = event;
|
|
notifyAvailability();
|
|
});
|
|
|
|
window.addEventListener('appinstalled', () => {
|
|
deferredInstallPrompt = null;
|
|
notifyAvailability();
|
|
});
|
|
}
|
|
|
|
export function canInstallPwa() {
|
|
return Boolean(deferredInstallPrompt);
|
|
}
|
|
|
|
export function isStandalonePwaMode() {
|
|
return (
|
|
window.matchMedia?.('(display-mode: standalone)')?.matches ||
|
|
window.navigator?.standalone === true
|
|
);
|
|
}
|
|
|
|
export async function promptPwaInstall() {
|
|
if (!deferredInstallPrompt) {
|
|
return { supported: false, outcome: '' };
|
|
}
|
|
|
|
const promptEvent = deferredInstallPrompt;
|
|
deferredInstallPrompt = null;
|
|
notifyAvailability();
|
|
|
|
await promptEvent.prompt();
|
|
const choice = await promptEvent.userChoice;
|
|
return {
|
|
supported: true,
|
|
outcome: String(choice?.outcome || ''),
|
|
};
|
|
}
|
|
|
|
export function onPwaInstallAvailabilityChange(handler) {
|
|
if (typeof handler !== 'function') return () => {};
|
|
listeners.add(handler);
|
|
return () => {
|
|
listeners.delete(handler);
|
|
};
|
|
}
|