mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
fix(web): tick player time every frame and keep lyrics in sync (#107)
`store.elapsed` is a Pinia getter (a cached Vue computed) that interpolates with `Date.now()`. Because `Date.now()` is not a reactive dependency, the computed only re-ran on WebSocket pushes / the 3s server poll, so the bottom progress bar jumped ~3s at a time and lyric highlighting lagged ~half a line — even though the consumers read it from a 60fps requestAnimationFrame loop. Add a pure `interpolateElapsed()` helper and a non-cached `liveElapsed()` store action. The per-frame consumers now call `liveElapsed()` so the value advances every frame instead of returning a frozen cache: - web/src/components/Player.vue (desktop progress bar, rAF) - web/src/App.vue (mobile progress bar, rAF) - web/src/views/Lyrics.vue (lyric highlight, 500ms interval) pause() now freezes at the live value rather than a possibly-stale cached one. The `elapsed` getter is refactored onto the same helper (behaviour unchanged). Adds web/src/stores/elapsed.test.ts covering the time-advancing interpolation, paused freeze, no-anchor, and duration-clamp cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ea6820204d
commit
45f5d236c1
5 files changed
+107
-11
No files matched your search
+3
-1
@@ -118,8 +118,10 @@ let mobileRaf: number | null = null;
|
||||
|
||||
function updateMobileProgress() {
|
||||
const duration = currentSong.value?.duration ?? 0;
|
||||
// liveElapsed() recomputes each frame; the cached `elapsed` getter would
|
||||
// leave the mobile bar frozen between server pushes (#107).
|
||||
mobileProgressPct.value = duration > 0
|
||||
? Math.min((playerStore.elapsed / duration) * 100, 100)
|
||||
? Math.min((playerStore.liveElapsed() / duration) * 100, 100)
|
||||
: 0;
|
||||
mobileRaf = requestAnimationFrame(updateMobileProgress);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user