Fix playback regression
Some checks failed
🏗️ Build and Test JellyTau / Run Tests (push) Has been cancelled
🏗️ Build and Test JellyTau / Build Android APK (push) Has been cancelled
Traceability Validation / Check Requirement Traces (push) Has been cancelled

This commit is contained in:
Duncan Tourolle 2026-06-28 21:07:00 +02:00
parent 0eae81ec59
commit 78f5cd9db9

View File

@ -203,6 +203,7 @@
seekOffset = 0;
isMediaReady = false; // Reset to loading state when stream URL changes
hasPerformedInitialSeek = false; // Reset so new video can seek to initial position
lastAppliedInitialPosition = undefined; // New stream - forget the previously-applied resume point
endedFired = false; // New stream loaded - allow onEnded to fire again
}
});
@ -373,19 +374,37 @@
}
});
// Handle initial position changes (for resuming same video from different position)
// Handle initial position changes (for resuming the *same* loaded video from a
// different position, e.g. the resume point is re-chosen without a reload).
//
// This must only react to a genuine change of the `initialPosition` prop to a
// value we haven't already applied. The previous version re-fired on the very
// first seek (it also depended on, and wrote, `hasPerformedInitialSeek`), and
// since seeking a transcoded/HLS stream re-buffers and fires `canplay` again,
// the two seek paths ping-ponged forever — the player appeared to pause/resume
// in a loop. We now snapshot the last-applied position and only seek when the
// prop actually moves to a new value, untracking the writes so this effect
// can't re-trigger itself.
let lastAppliedInitialPosition = $state<number | undefined>(undefined);
$effect(() => {
// Track initialPosition changes - if it changes and video is ready, seek to new position
const pos = initialPosition;
if (pos && pos > 0 && isMediaReady && videoElement && hasPerformedInitialSeek) {
// Position changed after initial seek was done - seek to new position
if (!pos || pos <= 0 || !isMediaReady) return;
// Only act on a real change to a not-yet-applied position.
if (pos === untrack(() => lastAppliedInitialPosition)) return;
// Skip the very first application; handleCanPlay owns the initial seek.
if (!untrack(() => hasPerformedInitialSeek)) {
lastAppliedInitialPosition = pos;
return;
}
untrack(() => {
console.log("[VideoPlayer] Initial position changed, seeking to:", pos);
hasPerformedInitialSeek = false; // Reset flag to allow handleCanPlay to seek
// Trigger seek directly since canplay won't fire for same video
lastAppliedInitialPosition = pos;
if (videoElement) {
videoElement.currentTime = pos;
currentTime = pos;
}
});
});
// Set up progress reporting interval
onMount(async () => {
@ -645,6 +664,7 @@
if (initialPosition && initialPosition > 0 && !hasPerformedInitialSeek && videoElement) {
console.log("[VideoPlayer] Seeking to initial position:", initialPosition);
hasPerformedInitialSeek = true;
lastAppliedInitialPosition = initialPosition; // mark this value as applied so the change-effect ignores it
// Pause video to prevent autoplay from starting at position 0
const wasPlaying = !videoElement.paused;