feat: wire episode navigation into player init

This commit is contained in:
2026-07-04 05:03:59 +02:00
parent 2952bd0e89
commit 8ababab46b

View File

@@ -2,7 +2,7 @@ import { onHtmxLoad, onReady } from "../utils";
import { setupControls, showControls } from "./controls"; import { setupControls, showControls } from "./controls";
import { formatTime } from "./controls"; import { formatTime } from "./controls";
import { setupEpisodeMetadata } from "./episodes/metadata"; import { setupEpisodeMetadata } from "./episodes/metadata";
import { goToNextEpisode } from "./episodes/nav"; import { goToNextEpisode, setupEpisodeNavigation } from "./episodes/nav";
import { setupAutoplayButton, updateEpisodeHighlight, switchEpisodeRange } from "./episodes/ui"; import { setupAutoplayButton, updateEpisodeHighlight, switchEpisodeRange } from "./episodes/ui";
import { setupKeyboard } from "./keyboard"; import { setupKeyboard } from "./keyboard";
import { import {
@@ -11,7 +11,7 @@ import {
setupMode, setupMode,
updateModeButtons, updateModeButtons,
} from "./mode"; } from "./mode";
import { markEpisodeTransition, saveEndedProgress, setupProgress } from "./progress"; import { saveEndedProgress, setupProgress } from "./progress";
import { setupQuality, updateQualityOptions } from "./quality"; import { setupQuality, updateQualityOptions } from "./quality";
import { setupSkip, updateSkipButton, updateAutoSkipButton } from "./skip"; import { setupSkip, updateSkipButton, updateAutoSkipButton } from "./skip";
import { setupSegmentEditor } from "./skip/editor"; import { setupSegmentEditor } from "./skip/editor";
@@ -147,6 +147,7 @@ const initPlayer = async (): Promise<void> => {
setupSubtitles(); setupSubtitles();
setupQuality(); setupQuality();
setupMode(); setupMode();
setupEpisodeNavigation(signal);
updateSubtitleOptions(); updateSubtitleOptions();
updateQualityOptions(); updateQualityOptions();
@@ -285,7 +286,7 @@ const initPlayer = async (): Promise<void> => {
state.elements.video.addEventListener( state.elements.video.addEventListener(
"error", "error",
() => { () => {
if (sourceRefreshInFlight) { if (sourceRefreshInFlight || state.episode.transitionEpisode !== null) {
return; return;
} }
sourceRefreshInFlight = true; sourceRefreshInFlight = true;
@@ -391,38 +392,6 @@ const initPlayer = async (): Promise<void> => {
{ signal }, { signal },
); );
// track next-episode links outside the player so they start fresh after finishing an episode
document.addEventListener(
"click",
(e) => {
const { target } = e;
if (!(target instanceof Element)) {
return;
}
const anchor = target.closest("a[href]");
if (!(anchor instanceof HTMLAnchorElement)) {
return;
}
const url = new URL(anchor.href, location.origin);
if (url.origin !== location.origin) {
return;
}
const parts = url.pathname.split("/").filter(Boolean);
if (parts[0] !== "anime" || parts[2] !== "watch") {
return;
}
if (Number.parseInt(parts[1], 10) !== state.episode.malID) {
return;
}
const nextEpisode = Number.parseInt(url.searchParams.get("ep") ?? "1", 10);
const currentEpisode = Number.parseInt(state.episode.current, 10);
if (nextEpisode === currentEpisode + 1) {
markEpisodeTransition(nextEpisode);
}
},
{ signal },
);
state.elements.video.addEventListener("click", showControls, { signal }); state.elements.video.addEventListener("click", showControls, { signal });
const searchInput = document.querySelector("[data-episode-search]") as HTMLInputElement | null; const searchInput = document.querySelector("[data-episode-search]") as HTMLInputElement | null;