Files
rhinelab-ui/public/update.js
T

46 lines
2.0 KiB
JavaScript

// Network-only recovery entry: older workers do not intercept this page.
const button = document.querySelector('#update');
const status = document.querySelector('#status');
function waitForState(worker, states) {
return new Promise((resolve, reject) => {
const finish = error => {
clearTimeout(timer);
worker.removeEventListener('statechange', check);
error ? reject(error) : resolve();
};
const check = () => {
if (states.includes(worker.state)) finish();
else if (worker.state === 'redundant') finish(new Error('download'));
};
const timer = setTimeout(() => finish(new Error('timeout')), 120000);
worker.addEventListener('statechange', check);
check();
});
}
button.addEventListener('click', async () => {
button.disabled = true;
status.textContent = '正在检查并下载完整资源,请保持联网…';
try {
if (!window.isSecureContext || !('serviceWorker' in navigator)) throw new Error('unsupported');
const base = new URL('./', location.href);
const registration = await navigator.serviceWorker.register(new URL('sw.js', base), {scope: base.href, updateViaCache: 'none'});
// Await the network check even if a previous waiting version already exists.
await registration.update();
const installing = registration.installing;
if (installing) await waitForState(installing, ['installed', 'activating', 'activated']);
const worker = registration.waiting || registration.active;
if (!worker) throw new Error('download');
if (registration.waiting) {
status.textContent = '资源已就绪,正在应用更新…';
worker.postMessage({type: 'RHINE_APPLY_UPDATE'});
}
await waitForState(worker, ['activated']);
// Claiming clients is part of the worker's activation; navigate afterwards.
location.replace(base.href);
} catch {
status.textContent = '更新未完成,已保留原有数据。请确认网络可用后重试。';
button.textContent = '重试更新 ↻';
button.disabled = false;
}
});