feat(audio-player): apply the resume-rewind setting on open and unpause
The chapters payload now carries resume_rewind_seconds (server-side per-user setting); the player applies it at two events, each rewinding once from where playback currently sits — never stacked: - open-resume: restorePosition starts the rewind early from the saved spot (percentage and chapter+offset branches, clamped at the book start). Deep links (?loc=) stay exempt — an explicit jump is not a resume. - unpause: a genuine pause→play steps back again (the re-orientation gap). Programmatic plays — post-restore autoplay and track-switch autoplays — set a suppress flag: their play event is the session start the open-rewind already positioned, not an unpause. Math lives in audio-rewind.ts (pure, unit-tested) after the audio-scrubber pattern; payload values gate through the 0/5/10 allow-list so stale or foreign servers degrade to exact resume.
This commit is contained in:
1 parent
9cf9e1d305
commit
7b7ce39826
3 files changed
+95
-3
No files matched your search
@@ -0,0 +1,21 @@
|
||||
// Resume rewind (per-user server setting): how many seconds before the
|
||||
// saved position the audiobook/podcast player starts. Applied on
|
||||
// open-resume AND again on every genuine unpause — each event rewinds
|
||||
// once from where playback currently sits, never stacked. Pure math;
|
||||
// the Alpine component owns when to call it (the play-event suppress
|
||||
// flag keeps restore-autoplay and track switches from double-firing).
|
||||
|
||||
// applyResumeRewind maps a position back by the rewind amount, clamped
|
||||
// to the start of the book.
|
||||
export function applyResumeRewind(positionSeconds: number, rewindSeconds: number): number {
|
||||
if (!Number.isFinite(positionSeconds)) return 0;
|
||||
if (!Number.isFinite(rewindSeconds) || rewindSeconds <= 0) return Math.max(0, positionSeconds);
|
||||
return Math.max(0, positionSeconds - rewindSeconds);
|
||||
}
|
||||
|
||||
// normalizeResumeRewind gates the server payload value to the setting's
|
||||
// allow-list (0/5/10) — anything else means off.
|
||||
export function normalizeResumeRewind(value: unknown): number {
|
||||
const n = Number(value);
|
||||
return n === 5 || n === 10 ? n : 0;
|
||||
}
|
||||
Reference in new issue
Block a user