61 lines
2.2 KiB
JavaScript
61 lines
2.2 KiB
JavaScript
// Browser prompt and worker objects stay outside Alpine's reactive state.
|
|
export function setupPWA({installAvailable, updateAvailable, installed, failed}) {
|
|
let prompt;
|
|
let registration;
|
|
const cleanup = [];
|
|
const listen = (target, name, handler) => {
|
|
target.addEventListener(name, handler);
|
|
cleanup.push(() => target.removeEventListener(name, handler));
|
|
};
|
|
const standalone = () => window.matchMedia('(display-mode: standalone)').matches || !!navigator.standalone;
|
|
installed(standalone());
|
|
listen(window, 'beforeinstallprompt', event => {
|
|
event.preventDefault();
|
|
prompt = event;
|
|
installAvailable(true);
|
|
});
|
|
listen(window, 'appinstalled', () => {
|
|
prompt = undefined;
|
|
installAvailable(false);
|
|
installed(true);
|
|
});
|
|
|
|
let destroyed = false;
|
|
if ('serviceWorker' in navigator) {
|
|
let controlled = !!navigator.serviceWorker.controller;
|
|
listen(navigator.serviceWorker, 'controllerchange', () => {
|
|
if (controlled) window.location.reload();
|
|
controlled = true;
|
|
});
|
|
navigator.serviceWorker.register('./sw.js', {scope: './', type: 'module', updateViaCache: 'none'})
|
|
.then(value => {
|
|
if (destroyed) return;
|
|
registration = value;
|
|
const showUpdate = () => updateAvailable(!!registration.waiting);
|
|
showUpdate();
|
|
listen(registration, 'updatefound', () => {
|
|
if (registration.installing) listen(registration.installing, 'statechange', showUpdate);
|
|
});
|
|
}).catch(() => { if (!destroyed) failed(); });
|
|
}
|
|
return {
|
|
async install() {
|
|
if (!prompt) return;
|
|
const pending = prompt;
|
|
prompt = undefined;
|
|
installAvailable(false);
|
|
try {
|
|
await pending.prompt();
|
|
await pending.userChoice;
|
|
} catch { /* Manual installation guidance remains available. */ }
|
|
},
|
|
update() {
|
|
registration?.waiting?.postMessage('ACTIVATE_UPDATE');
|
|
},
|
|
destroy() {
|
|
destroyed = true;
|
|
cleanup.forEach(remove => remove());
|
|
},
|
|
};
|
|
}
|