web-player: split player, navigation and accent state into focused modules

This commit is contained in:
2026-09-24 05:25:35 +02:00
parent e89463fb83
commit 5cda7cb4c1
47 changed files with 520 additions and 457 deletions
@@ -0,0 +1,36 @@
const MAX_INTERPOLATION_SECONDS = 0.25;
export class ProgressClock {
#rafId: number | null = null;
#time = 0;
#stamp = 0;
constructor(
private getAudio: () => HTMLAudioElement | null,
private onProgress: (seconds: number) => void
) {}
#tick = (now: number) => {
const audio = this.getAudio();
if (!audio) return;
if (audio.currentTime !== this.#time) {
this.#time = audio.currentTime;
this.#stamp = now;
}
const elapsed = Math.min(MAX_INTERPOLATION_SECONDS, (now - this.#stamp) / 1000);
const smooth = this.#time + (audio.paused ? 0 : elapsed * audio.playbackRate);
this.onProgress(Math.min(smooth, Number.isFinite(audio.duration) ? audio.duration : smooth));
this.#rafId = requestAnimationFrame(this.#tick);
};
start() {
if (this.#rafId !== null) return;
this.#rafId = requestAnimationFrame(this.#tick);
}
stop() {
if (this.#rafId === null) return;
cancelAnimationFrame(this.#rafId);
this.#rafId = null;
}
}