47 lines
2 KiB
JavaScript
47 lines
2 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Service Worker
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
if ('serviceWorker' in navigator) {
|
||
|
|
window.addEventListener('load', () => {
|
||
|
|
// Registered from '/sw.js' (root), not '/static/js/sw.js': a service
|
||
|
|
// worker's default scope is its own script's directory, so registering
|
||
|
|
// it from under /static/js/ would only ever let it control requests
|
||
|
|
// under that path — page navigations to '/', '/books/' etc. would never
|
||
|
|
// be intercepted, breaking offline entirely.
|
||
|
|
navigator.serviceWorker.register('/sw.js', {scope: '/'}).catch(err => {
|
||
|
|
console.warn('Service worker registration failed:', err);
|
||
|
|
});
|
||
|
|
// Drop any leftover registration from the old, wrongly-scoped '/static/js/sw.js'
|
||
|
|
// path so it doesn't keep running or fight the new root-scoped worker.
|
||
|
|
navigator.serviceWorker.getRegistrations().then(regs => {
|
||
|
|
regs.forEach(r => { if (r.scope.endsWith('/static/js/')) r.unregister(); });
|
||
|
|
});
|
||
|
|
});
|
||
|
|
// When a new SW activates it sends SW_ACTIVATED — reload to get fresh assets,
|
||
|
|
// but never in the middle of something: not while a book is open, radio or a
|
||
|
|
// podcast plays, or a text field has the focus — then as soon as that's over.
|
||
|
|
let reloadPending = false;
|
||
|
|
const busy = () => {
|
||
|
|
if (currentBookId || isPlaying) return true;
|
||
|
|
const host = window.DioraPodcastHost;
|
||
|
|
if (host && host.playerState) {
|
||
|
|
try { if (JSON.parse(host.playerState()).playing) return true; } catch (_) {}
|
||
|
|
}
|
||
|
|
const el = document.activeElement;
|
||
|
|
return !!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));
|
||
|
|
};
|
||
|
|
const reloadWhenIdle = () => {
|
||
|
|
if (busy()) setTimeout(reloadWhenIdle, 5000);
|
||
|
|
else window.location.reload();
|
||
|
|
};
|
||
|
|
navigator.serviceWorker.addEventListener('message', e => {
|
||
|
|
if (e.data?.type === 'SW_ACTIVATED' && !reloadPending) {
|
||
|
|
reloadPending = true;
|
||
|
|
reloadWhenIdle();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|