60 lines
1.9 KiB
JavaScript
60 lines
1.9 KiB
JavaScript
(function (A) {
|
|
let deferredPrompt = null;
|
|
let swRegistration = null;
|
|
|
|
A.pwa = {
|
|
isFileProtocol() {
|
|
return location.protocol === 'file:';
|
|
},
|
|
isSupported() {
|
|
return 'serviceWorker' in navigator && !A.pwa.isFileProtocol();
|
|
},
|
|
isStandalone() {
|
|
return window.matchMedia('(display-mode: standalone)').matches
|
|
|| window.navigator.standalone === true;
|
|
},
|
|
getPlatform() {
|
|
const ua = navigator.userAgent;
|
|
const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
|
|
const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
|
|
if (isIOS || isIPadOS) return 'ios';
|
|
if (/Android/.test(ua)) return 'android';
|
|
if (/Chrome|Chromium|Edg/.test(ua)) return 'desktop-chromium';
|
|
if (/Firefox/.test(ua)) return 'firefox';
|
|
if (/Safari/.test(ua)) return 'desktop-safari';
|
|
return 'other';
|
|
},
|
|
canPromptInstall() {
|
|
return deferredPrompt !== null;
|
|
},
|
|
async promptInstall() {
|
|
if (!deferredPrompt) return { outcome: 'unavailable' };
|
|
deferredPrompt.prompt();
|
|
const choice = await deferredPrompt.userChoice;
|
|
deferredPrompt = null;
|
|
return choice;
|
|
},
|
|
async register() {
|
|
if (!A.pwa.isSupported()) return null;
|
|
try {
|
|
swRegistration = await navigator.serviceWorker.register('./sw.js', { scope: './' });
|
|
return swRegistration;
|
|
} catch (err) {
|
|
console.warn('Service worker registration failed:', err);
|
|
return null;
|
|
}
|
|
}
|
|
};
|
|
|
|
window.addEventListener('beforeinstallprompt', (e) => {
|
|
e.preventDefault();
|
|
deferredPrompt = e;
|
|
document.dispatchEvent(new CustomEvent('pwa:install-available'));
|
|
});
|
|
|
|
window.addEventListener('appinstalled', () => {
|
|
deferredPrompt = null;
|
|
document.dispatchEvent(new CustomEvent('pwa:installed'));
|
|
});
|
|
})(window.App.Application);
|