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:
@@ -1,6 +1,6 @@
|
||||
<!-- TRACES: UR-003, UR-005, UR-020, UR-021, UR-026 | DR-010, DR-023, DR-024 -->
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import { onMount, onDestroy, untrack } from "svelte";
|
||||
import { commands } from "$lib/api/bindings";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import Hls from "hls.js";
|
||||
@@ -20,9 +20,13 @@
|
||||
needsTranscoding?: boolean; // Whether content needs transcoding (HEVC/10-bit) - affects seeking behavior
|
||||
onClose: () => void;
|
||||
onSeek?: (positionSeconds: number, audioStreamIndex?: number) => Promise<string>; // Returns new stream URL for transcoded seeking
|
||||
onReportProgress?: (positionSeconds: number, isPaused: boolean) => void;
|
||||
onReportStart?: (positionSeconds: number) => void;
|
||||
onReportStop?: (positionSeconds: number) => void;
|
||||
// Reporting callbacks pass the played media's id explicitly so a late
|
||||
// reportStop (fired from onDestroy during autoplay navigation) is attributed
|
||||
// to the episode this player actually played, not the next episode whose URL
|
||||
// is already active on the page.
|
||||
onReportProgress?: (positionSeconds: number, isPaused: boolean, reportId?: string) => void;
|
||||
onReportStart?: (positionSeconds: number, reportId?: string) => void;
|
||||
onReportStop?: (positionSeconds: number, reportId?: string) => void;
|
||||
onEnded?: () => void; // Called when video playback ends naturally
|
||||
onNext?: () => void; // Called when user clicks next episode button
|
||||
hasNext?: boolean; // Whether there is a next episode available
|
||||
@@ -30,6 +34,12 @@
|
||||
|
||||
let { media, streamUrl, mediaSourceId, initialPosition, needsTranscoding = false, onClose, onSeek, onReportProgress, onReportStart, onReportStop, onEnded, onNext, hasNext = false }: Props = $props();
|
||||
|
||||
// The id this player instance reports progress against. Snapshotted from the
|
||||
// media prop so a late reportStop (e.g. from onDestroy during autoplay
|
||||
// navigation) is always attributed to the episode this player played.
|
||||
// untrack() makes the intent explicit: capture the initial value only.
|
||||
const reportMediaId = untrack(() => media?.id);
|
||||
|
||||
let videoElement: HTMLVideoElement | null = $state(null);
|
||||
let isPlaying = $state(false);
|
||||
let currentTime = $state(0);
|
||||
@@ -470,7 +480,7 @@
|
||||
// Report progress every 10 seconds while playing
|
||||
progressInterval = setInterval(() => {
|
||||
if (isPlaying && !isSeeking && onReportProgress) {
|
||||
onReportProgress(currentTime, false);
|
||||
onReportProgress(currentTime, false, reportMediaId);
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
@@ -536,7 +546,7 @@
|
||||
|
||||
// Report stop when component is destroyed
|
||||
if (onReportStop && currentTime > 0) {
|
||||
onReportStop(currentTime);
|
||||
onReportStop(currentTime, reportMediaId);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -730,7 +740,7 @@
|
||||
startTimeUpdates(); // Start RAF loop for smooth time updates
|
||||
// Report playback start on first play
|
||||
if (!hasReportedStart && onReportStart) {
|
||||
onReportStart(currentTime);
|
||||
onReportStart(currentTime, reportMediaId);
|
||||
hasReportedStart = true;
|
||||
}
|
||||
}
|
||||
@@ -740,7 +750,7 @@
|
||||
stopTimeUpdates(); // Stop RAF loop when paused
|
||||
// Report progress when paused
|
||||
if (onReportProgress) {
|
||||
onReportProgress(currentTime, true);
|
||||
onReportProgress(currentTime, true, reportMediaId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +759,7 @@
|
||||
stopTimeUpdates(); // Stop RAF loop when ended
|
||||
// Report stop when video ends
|
||||
if (onReportStop) {
|
||||
onReportStop(currentTime);
|
||||
onReportStop(currentTime, reportMediaId);
|
||||
}
|
||||
// Notify parent that video has ended (for next episode popup)
|
||||
if (onEnded) {
|
||||
|
||||
Reference in New Issue
Block a user