docent/web/src/lib/precache.svelte.ts

52 lines
1.3 KiB
TypeScript
Raw Normal View History

2026-05-05 09:33:51 -05:00
import { browser } from '$app/environment';
import { stops } from './stops';
export type PrecacheState = 'idle' | 'running' | 'complete' | 'unsupported';
let state: PrecacheState = $state('idle');
let done = $state(0);
let total = $state(0);
export function precacheState() {
return { state, done, total };
}
export async function precacheAll(): Promise<void> {
if (!browser) return;
if (!('serviceWorker' in navigator)) {
state = 'unsupported';
return;
}
if (state === 'running' || state === 'complete') return;
const reg = await navigator.serviceWorker.ready.catch(() => null);
const target = reg?.active ?? navigator.serviceWorker.controller;
if (!target) {
state = 'unsupported';
return;
}
const urls = stops.flatMap((s) => [s.audio, s.image]);
state = 'running';
done = 0;
total = urls.length;
const onMessage = (event: MessageEvent) => {
const data = event.data;
if (!data || typeof data !== 'object') return;
if (data.type === 'precache-progress') {
done = data.done;
total = data.total;
} else if (data.type === 'precache-done') {
done = data.done;
total = data.total;
state = 'complete';
navigator.serviceWorker.removeEventListener('message', onMessage);
}
};
navigator.serviceWorker.addEventListener('message', onMessage);
target.postMessage({ type: 'precache-stops', urls });
}