52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
|
|
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 });
|
||
|
|
}
|