mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
fix(player): prevent streaming seek UI freezes and progress snapbacks (#236)
* fix(player): prevent streaming seek UI freezes and progress snapbacks Move blocking seek work off the command path with a bounded timeout, switch fullscreen/mobile seek bars to commit-on-release, and stabilize fallback progress state so rapid early seeks on streamed tracks do not freeze the UI or jump progress to zero. * fix(player): avoid second-seek lockups and progress flicker Add a short lock timeout for audio seek state access to prevent UI stalls when rapid seeks overlap, and keep waveform progress stable right after seek commit to eliminate brief visual snapbacks. * fix(player): harden seek recovery and reduce stream log noise Keep seek fallback stable during delayed backend responses to prevent occasional resets to track start, and remove per-read stream blocking logs so normal playback diagnostics stay readable. --------- Co-authored-by: Maxim Isaev <im@friclub.ru>
This commit is contained in:
committed by
GitHub
parent
c61bcacd0d
commit
fa21379dbb
@@ -801,6 +801,9 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function WaveformSeek({ trackId }: Props) {
|
||||
const SEEK_COMMIT_GUARD_MS = 900;
|
||||
const SEEK_COMMIT_MIN_HOLD_MS = 320;
|
||||
const SEEK_COMMIT_PROGRESS_EPS = 0.02;
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const heightsRef = useRef<Float32Array | null>(null);
|
||||
const progressRef = useRef(usePlayerStore.getState().progress);
|
||||
@@ -835,6 +838,15 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
// While user drags, keep the local preview stable. External progress ticks
|
||||
// during streaming/recovery would otherwise fight the cursor and flicker.
|
||||
if (isDragging.current) return;
|
||||
const pendingCommit = pendingCommittedSeekRef.current;
|
||||
if (pendingCommit) {
|
||||
const ageMs = Date.now() - pendingCommit.setAtMs;
|
||||
if (ageMs < SEEK_COMMIT_MIN_HOLD_MS) return;
|
||||
const matched = Math.abs(state.progress - pendingCommit.fraction) <= SEEK_COMMIT_PROGRESS_EPS;
|
||||
const expired = ageMs > SEEK_COMMIT_GUARD_MS;
|
||||
if (!matched && !expired) return;
|
||||
pendingCommittedSeekRef.current = null;
|
||||
}
|
||||
progressRef.current = state.progress;
|
||||
bufferedRef.current = state.buffered;
|
||||
if (!ANIMATED_STYLES.has(styleRef.current)) {
|
||||
@@ -894,6 +906,7 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
const seekRef = useRef(seek);
|
||||
seekRef.current = seek;
|
||||
const pendingSeekRef = useRef<number | null>(null);
|
||||
const pendingCommittedSeekRef = useRef<{ fraction: number; setAtMs: number } | null>(null);
|
||||
|
||||
// Preview a 0–1 fraction while dragging: draw immediately for 1:1
|
||||
// responsiveness; the actual seek is committed on mouseup.
|
||||
@@ -910,6 +923,7 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
const fraction = pendingSeekRef.current;
|
||||
if (fraction === null) return;
|
||||
pendingSeekRef.current = null;
|
||||
pendingCommittedSeekRef.current = { fraction, setAtMs: Date.now() };
|
||||
seekRef.current(fraction);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user