fix: Autoplay now resets time to zero and ignores trigger if episode already started (#3)
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 3m48s
Traceability Validation / Check Requirement Traces (push) Successful in 22s
Build & Release / Run Tests (push) Successful in 3m27s
🏗️ Build and Test JellyTau / Build Android APK (push) Successful in 18m31s
Build & Release / Build Linux (push) Successful in 15m52s
Build & Release / Build Android (push) Successful in 18m43s
Build & Release / Create Release (push) Successful in 12s
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 3m48s
Traceability Validation / Check Requirement Traces (push) Successful in 22s
Build & Release / Run Tests (push) Successful in 3m27s
🏗️ Build and Test JellyTau / Build Android APK (push) Successful in 18m31s
Build & Release / Build Linux (push) Successful in 15m52s
Build & Release / Build Android (push) Successful in 18m43s
Build & Release / Create Release (push) Successful in 12s
Reviewed-on: #3 Co-authored-by: Duncan Tourolle <duncan@tourolle.paris> Co-committed-by: Duncan Tourolle <duncan@tourolle.paris>
This commit was merged in pull request #3.
This commit is contained in:
@@ -25,6 +25,9 @@
|
||||
const itemId = $derived($page.params.id);
|
||||
const queueParam = $derived($page.url.searchParams.get("queue"));
|
||||
const shuffleParam = $derived($page.url.searchParams.get("shuffle") === "true");
|
||||
// When advancing to a next episode we always start from the beginning,
|
||||
// even if the episode was previously started or watched.
|
||||
const restartParam = $derived($page.url.searchParams.get("restart") === "true");
|
||||
|
||||
// Derive playback context from URL query params
|
||||
const playbackContext = $derived.by(() => {
|
||||
@@ -80,9 +83,12 @@
|
||||
// Load when itemId changes (handles both initial load and navigation)
|
||||
$effect(() => {
|
||||
const id = itemId;
|
||||
const restart = restartParam;
|
||||
if (id && id !== loadedItemId) {
|
||||
console.log("[AutoPlay] $effect triggered: loading new item", id, "(was:", loadedItemId, ")");
|
||||
loadAndPlay(id);
|
||||
console.log("[AutoPlay] $effect triggered: loading new item", id, "(was:", loadedItemId, ") restart:", restart);
|
||||
// restart=true (advancing to next episode) forces start-from-beginning,
|
||||
// bypassing the resume-progress check.
|
||||
loadAndPlay(id, restart ? 0 : undefined, restart);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -96,7 +102,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
async function loadAndPlay(id: string, startPosition?: number) {
|
||||
async function loadAndPlay(id: string, startPosition?: number, forceRestart = false) {
|
||||
loading = true;
|
||||
error = null;
|
||||
loadedItemId = id;
|
||||
@@ -118,9 +124,11 @@
|
||||
}
|
||||
|
||||
// If this track is already playing in the backend, just show the UI
|
||||
// without restarting playback (e.g., when expanding from MiniPlayer)
|
||||
// without restarting playback (e.g., when expanding from MiniPlayer).
|
||||
// forceRestart bypasses this so advancing to the next episode always
|
||||
// restarts from the beginning even if it were already loaded.
|
||||
const alreadyPlayingMedia = get(storeCurrentMedia);
|
||||
if (alreadyPlayingMedia?.id === id && !startPosition) {
|
||||
if (alreadyPlayingMedia?.id === id && !startPosition && !forceRestart) {
|
||||
console.log("loadAndPlay: Track already playing, showing UI without restarting");
|
||||
isVideo = item.type === "Movie" || item.type === "Episode";
|
||||
isPlaying = true;
|
||||
@@ -155,11 +163,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Check for saved progress if no start position specified
|
||||
// Check for saved progress if no start position specified.
|
||||
// When forceRestart is set (advancing to a next episode) we always start
|
||||
// from the beginning, skipping the resume check and resume dialog.
|
||||
const userId = auth.getUserId();
|
||||
console.log("Resume check - userId:", userId, "itemId:", id, "startPosition:", startPosition);
|
||||
console.log("Resume check - userId:", userId, "itemId:", id, "startPosition:", startPosition, "forceRestart:", forceRestart);
|
||||
|
||||
if (!startPosition && userId) {
|
||||
if (!startPosition && !forceRestart && userId) {
|
||||
try {
|
||||
const progress = await commands.storageGetPlaybackProgress(userId, id);
|
||||
console.log("Resume check - retrieved progress:", progress);
|
||||
@@ -471,23 +481,30 @@
|
||||
}
|
||||
|
||||
// Playback reporting callbacks
|
||||
function handleReportStart(positionSeconds: number) {
|
||||
const id = itemId;
|
||||
//
|
||||
// These receive the reporting item id from the VideoPlayer (its own media.id),
|
||||
// NOT the live URL param (itemId). During autoplay the URL flips to the next
|
||||
// episode before the outgoing VideoPlayer's onDestroy fires its final
|
||||
// reportStop. Keying off itemId would stamp the old episode's near-end
|
||||
// position onto the new episode, making it resume at ~99% (or pop the resume
|
||||
// dialog). The VideoPlayer always knows which media it actually played.
|
||||
function handleReportStart(positionSeconds: number, reportId?: string) {
|
||||
const id = reportId ?? itemId;
|
||||
const context = playbackContext; // playbackContext is a derived value, not a function
|
||||
if (id) {
|
||||
reportPlaybackStart(id, positionSeconds, context.type, context.id);
|
||||
}
|
||||
}
|
||||
|
||||
function handleReportProgress(positionSeconds: number, isPaused: boolean) {
|
||||
const id = itemId;
|
||||
function handleReportProgress(positionSeconds: number, isPaused: boolean, reportId?: string) {
|
||||
const id = reportId ?? itemId;
|
||||
if (id) {
|
||||
reportPlaybackProgress(id, positionSeconds, isPaused);
|
||||
}
|
||||
}
|
||||
|
||||
function handleReportStop(positionSeconds: number) {
|
||||
const id = itemId;
|
||||
function handleReportStop(positionSeconds: number, reportId?: string) {
|
||||
const id = reportId ?? itemId;
|
||||
if (id) {
|
||||
reportPlaybackStopped(id, positionSeconds);
|
||||
}
|
||||
@@ -538,8 +555,10 @@
|
||||
|
||||
function handleSkipToNextEpisode() {
|
||||
if (nextEpisode) {
|
||||
// Use replaceState so "close/back" returns to the library, not the previous episode
|
||||
goto(`/player/${nextEpisode.id}`, { replaceState: true });
|
||||
// Use replaceState so "close/back" returns to the library, not the previous episode.
|
||||
// restart=true so advancing to the next episode always starts from the beginning,
|
||||
// even if it was previously started or watched.
|
||||
goto(`/player/${nextEpisode.id}?restart=true`, { replaceState: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user