Starts at same time as stopped

This commit is contained in:
2026-10-10 13:10:31 +02:00
parent 295defa954
commit bb916ee043
+15 -5
View File
@@ -188,7 +188,7 @@
const S = { const S = {
user: null, q: "", mode: "sub", entry: null, episodes: [], ep: null, user: null, q: "", mode: "sub", entry: null, episodes: [], ep: null,
last: null, playToken: 0, hls: null, prefetch: null, lastSave: 0, ended: false, last: null, playToken: 0, hls: null, prefetch: null, lastSave: 0, ended: false,
resumeAt: 0, retried: false, resumeAt: 0, retried: false, canSave: false,
}; };
const video = $("video"); const video = $("video");
@@ -388,6 +388,7 @@
S.resumeAt = opts.resume !== undefined ? opts.resume : S.resumeAt = opts.resume !== undefined ? opts.resume :
(S.last && S.last.episode === ep && S.last.duration > 0 && S.last.position > 10 && (S.last && S.last.episode === ep && S.last.duration > 0 && S.last.position > 10 &&
S.last.position < S.last.duration - 30 ? S.last.position : 0); S.last.position < S.last.duration - 30 ? S.last.position : 0);
S.canSave = false; // don't overwrite the saved time with 0:00 while the stream is still loading
renderEpisodes(); renderEpisodes();
$("wSub").textContent = `Episode ${ep} of ${S.episodes.length} · ${S.mode}`; $("wSub").textContent = `Episode ${ep} of ${S.episodes.length} · ${S.mode}`;
if (S.hls) { S.hls.destroy(); S.hls = null; } if (S.hls) { S.hls.destroy(); S.hls = null; }
@@ -415,15 +416,23 @@
if (info.subtitle) { if (info.subtitle) {
video.append(el("track", { kind: "subtitles", label: "Subtitles", srclang: "en", src: info.subtitle, default: true })); video.append(el("track", { kind: "subtitles", label: "Subtitles", srclang: "en", src: info.subtitle, default: true }));
} }
const target = S.resumeAt > 1 ? S.resumeAt : 0;
S.resumeAt = 0;
const settle = () => { // called once playback really runs at the resumed position
if (token !== S.playToken || S.canSave) return;
if (target && video.currentTime < target - 5) { try { video.currentTime = target; } catch {} }
S.canSave = true;
};
if (target) video.addEventListener("playing", settle, { once: true });
const onReady = () => { const onReady = () => {
if (token !== S.playToken) return; if (token !== S.playToken) return;
hideOverlay(); hideOverlay();
if (S.resumeAt > 0) { try { video.currentTime = S.resumeAt; } catch {} S.resumeAt = 0; } if (target && !(S.hls)) { try { video.currentTime = target; } catch {} } // MP4 / native HLS
video.play().catch(() => showOverlay("Press play to start.", false, null)); video.play().catch(() => showOverlay("Press play to start.", false, null));
saveProgress(true); if (!target) { S.canSave = true; saveProgress(true); } // new episode: record it as the last watched
}; };
if (info.kind === "hls" && window.Hls && Hls.isSupported()) { if (info.kind === "hls" && window.Hls && Hls.isSupported()) {
const hls = new Hls({ maxBufferLength: 40 }); const hls = new Hls({ maxBufferLength: 40, startPosition: target || -1 });
S.hls = hls; S.hls = hls;
hls.loadSource(info.src); hls.loadSource(info.src);
hls.attachMedia(video); hls.attachMedia(video);
@@ -489,8 +498,9 @@
video.addEventListener("pause", () => { if (!video.ended) saveProgress(true); }); video.addEventListener("pause", () => { if (!video.ended) saveProgress(true); });
function saveProgress(force, keepalive) { function saveProgress(force, keepalive) {
if (!S.user || !S.entry || !S.ep) return; if (!S.user || !S.entry || !S.ep || !S.canSave) return;
const pos = video.currentTime || 0, dur = video.duration || 0; const pos = video.currentTime || 0, dur = video.duration || 0;
S.last = { episode: S.ep, position: Number.isFinite(pos) ? pos : 0, duration: Number.isFinite(dur) ? dur : 0 };
// while a new episode is still loading there's no position to report; record the start of it // while a new episode is still loading there's no position to report; record the start of it
S.lastSave = Date.now(); S.lastSave = Date.now();
api("/api/progress", { method: "POST", keepalive: !!keepalive, body: { api("/api/progress", { method: "POST", keepalive: !!keepalive, body: {