refactor: migrate app to Alpine.js
This commit is contained in:
1 parent
766212f119
commit
bc236db952
9 files changed
+269
-216
No files matched your search
@@ -1,51 +1,60 @@
|
||||
export function setupPWA({failed}) {
|
||||
const install = document.getElementById('install');
|
||||
const guide = document.getElementById('install-guide');
|
||||
const update = document.getElementById('update');
|
||||
const standalone = () => window.matchMedia('(display-mode: standalone)').matches || navigator.standalone;
|
||||
// Browser prompt and worker objects stay outside Alpine's reactive state.
|
||||
export function setupPWA({installAvailable, updateAvailable, installed, failed}) {
|
||||
let prompt;
|
||||
guide.hidden = !!standalone();
|
||||
window.addEventListener('beforeinstallprompt', event => {
|
||||
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;
|
||||
install.hidden = false;
|
||||
guide.hidden = true;
|
||||
installAvailable(true);
|
||||
});
|
||||
install.addEventListener('click', async () => {
|
||||
if (!prompt) return;
|
||||
const pending = prompt;
|
||||
listen(window, 'appinstalled', () => {
|
||||
prompt = undefined;
|
||||
install.hidden = true;
|
||||
try {
|
||||
await pending.prompt();
|
||||
await pending.userChoice;
|
||||
} catch {
|
||||
// Keep manual installation guidance available if the prompt fails.
|
||||
} finally {
|
||||
guide.hidden = !!standalone();
|
||||
}
|
||||
installAvailable(false);
|
||||
installed(true);
|
||||
});
|
||||
window.addEventListener('appinstalled', () => {
|
||||
prompt = undefined;
|
||||
install.hidden = true;
|
||||
guide.hidden = true;
|
||||
});
|
||||
if (!('serviceWorker' in navigator)) return;
|
||||
let controlled = !!navigator.serviceWorker.controller;
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||
if (controlled) window.location.reload();
|
||||
controlled = true;
|
||||
});
|
||||
navigator.serviceWorker.register('./sw.js', {scope: './', type: 'module', updateViaCache: 'none'})
|
||||
.then(registration => {
|
||||
const showUpdate = () => { update.hidden = !registration.waiting; };
|
||||
showUpdate();
|
||||
registration.addEventListener('updatefound', () => {
|
||||
const worker = registration.installing;
|
||||
if (worker) worker.addEventListener('statechange', showUpdate);
|
||||
});
|
||||
update.addEventListener('click', () => {
|
||||
if (registration.waiting) registration.waiting.postMessage('ACTIVATE_UPDATE');
|
||||
});
|
||||
}).catch(failed);
|
||||
|
||||
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());
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user