fix(audio): replace autoStartPending bool with autoStartChapter number

The boolean flag was set by onended before goto() resolved, causing the
still-mounted outgoing chapter's AudioPlayer $effect to fire and call
startPlayback() for the wrong (old) chapter — restarting it from scratch.

Replace with autoStartChapter (number | null): the AudioPlayer only acts
when its own chapter prop === autoStartChapter, so the outgoing component
never matches and the incoming one fires exactly once on mount.
This commit is contained in:
Admin
2026-03-04 18:08:12 +05:00
parent 80da1bb3e2
commit 0eee2eedf3
3 changed files with 17 additions and 8 deletions

View File

@@ -85,11 +85,16 @@ class AudioStore {
nextChapter = $state<number | null>(null); nextChapter = $state<number | null>(null);
/** /**
* Set to true by the layout's onended handler (when autoNext fires a * Set to the chapter number that should auto-start by the layout's onended
* navigation). The AudioPlayer on the new page checks this on mount * handler (when autoNext fires a navigation). The AudioPlayer on the new
* and, if true, immediately starts the play flow then clears the flag. * page checks this on mount: if it matches the component's own chapter prop
* it starts playback and clears the value.
*
* Using the target chapter number (instead of a plain boolean) prevents the
* still-mounted outgoing AudioPlayer from reacting to the flag before the
* navigation completes — it only matches the incoming chapter's component.
*/ */
autoStartPending = $state(false); autoStartChapter = $state<number | null>(null);
// ── Next-chapter pre-fetch state ───────────────────────────────────────── // ── Next-chapter pre-fetch state ─────────────────────────────────────────
/** /**

View File

@@ -70,9 +70,11 @@
}); });
// Auto-start: if the layout navigated here via auto-next, kick off playback. // Auto-start: if the layout navigated here via auto-next, kick off playback.
// We match against the chapter prop so the outgoing chapter's AudioPlayer
// (still mounted during the brief navigation window) never reacts to this.
$effect(() => { $effect(() => {
if (audioStore.autoStartPending) { if (audioStore.autoStartChapter === chapter) {
audioStore.autoStartPending = false; audioStore.autoStartChapter = null;
startPlayback(); startPlayback();
} }
}); });

View File

@@ -184,9 +184,11 @@
// we need. // we need.
const targetSlug = audioStore.slug; const targetSlug = audioStore.slug;
const targetChapter = audioStore.nextChapter; const targetChapter = audioStore.nextChapter;
audioStore.autoStartPending = true; // Store the target chapter number so only the newly-mounted AudioPlayer
// for that chapter reacts — not the outgoing chapter's component.
audioStore.autoStartChapter = targetChapter;
goto(`/books/${targetSlug}/chapters/${targetChapter}`).catch(() => { goto(`/books/${targetSlug}/chapters/${targetChapter}`).catch(() => {
audioStore.autoStartPending = false; audioStore.autoStartChapter = null;
}); });
} }
}} }}