From c891382efb1e64dfbe42f173cf7de5ab9949957c Mon Sep 17 00:00:00 2001 From: mkelvers Date: Sun, 14 Jun 2026 21:37:49 +0200 Subject: [PATCH] feat: add type field to ModeSource and pass to loadVideoSource --- static/player/episodes/nav.ts | 6 ++++-- static/player/main.ts | 6 +++++- static/player/mode.ts | 3 ++- static/player/quality.ts | 2 +- static/player/state.ts | 1 + static/player/types.ts | 1 + 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/static/player/episodes/nav.ts b/static/player/episodes/nav.ts index 4165c45..463764b 100644 --- a/static/player/episodes/nav.ts +++ b/static/player/episodes/nav.ts @@ -8,6 +8,7 @@ import { updateOverlay, isAutoplayEnabled, switchEpisodeRange } from "./ui"; import { markEpisodeTransition } from "../progress"; import { safeLocalStorage } from "../storage"; import { completeAnime } from "./complete"; +import { loadVideoSource } from "../video"; /** * Handles video end: either marks complete or loads next episode. @@ -89,8 +90,9 @@ export const goToNextEpisode = async (): Promise => { // load new video (keep preferences) const preferredQuality = safeLocalStorage.getItem("mal:preferred-quality") || "best"; - state.video.src = `${state.streamURL}?mode=${encodeURIComponent(fallback)}&token=${encodeURIComponent(state.modeSources[fallback].token)}${preferredQuality !== "best" ? `&quality=${encodeURIComponent(preferredQuality)}` : ""}`; - state.video.load(); + const source = state.modeSources[fallback]; + const nextSourceURL = `${state.streamURL}?mode=${encodeURIComponent(fallback)}&token=${encodeURIComponent(source.token)}${preferredQuality !== "best" ? `&quality=${encodeURIComponent(preferredQuality)}` : ""}`; + loadVideoSource(nextSourceURL, source.type); if (!state.video.paused) { state.video.play().catch(() => undefined); } diff --git a/static/player/main.ts b/static/player/main.ts index c8b154f..cfc8974 100644 --- a/static/player/main.ts +++ b/static/player/main.ts @@ -13,6 +13,7 @@ import { setupSegmentEditor } from "./skip/editor"; import { setupThumbnails } from "./episodes/thumbnails"; import { markEpisodeTransition, saveEndedProgress, setupProgress } from "./progress"; import { safeLocalStorage } from "./storage"; +import { destroyVideoSource, loadVideoSource } from "./video"; import { absoluteTimeFromDisplay, absoluteTimeFromRatio, @@ -49,6 +50,7 @@ const showPreviewPopover = (): void => { }; const teardownPlayer = (): void => { + destroyVideoSource(); cleanup?.(); cleanup = null; currentContainer = null; @@ -117,7 +119,9 @@ const initPlayer = (): void => { const preferredQuality = safeLocalStorage.getItem("mal:preferred-quality") || "best"; const streamToken = state.modeSources[state.currentMode]?.token; if (streamToken) { - state.video.src = `${state.streamURL}?mode=${encodeURIComponent(state.currentMode)}&token=${encodeURIComponent(streamToken)}${preferredQuality !== "best" ? `&quality=${encodeURIComponent(preferredQuality)}` : ""}`; + const source = state.modeSources[state.currentMode]; + const url = `${state.streamURL}?mode=${encodeURIComponent(state.currentMode)}&token=${encodeURIComponent(streamToken)}${preferredQuality !== "best" ? `&quality=${encodeURIComponent(preferredQuality)}` : ""}`; + loadVideoSource(url, source?.type); } setupProgress(); diff --git a/static/player/mode.ts b/static/player/mode.ts index 0bcaca1..9c14a3c 100644 --- a/static/player/mode.ts +++ b/static/player/mode.ts @@ -33,6 +33,7 @@ const parseModeSources = (v: unknown): Record => { const qualities = value.qualities; out[key] = { token: value.token, + type: typeof value.type === "string" ? value.type : undefined, subtitles, qualities: isStringArray(qualities) ? qualities : undefined, }; @@ -97,7 +98,7 @@ export const switchMode = (mode: string): void => { "[data-quality-select]", ) as HTMLSelectElement | null; const url = streamUrlForMode(mode, qualitySelect?.value); - loadVideoSource(url); + loadVideoSource(url, state.modeSources[mode]?.type); // Fallback: if the media element doesn't actually switch sources (some browsers can get "stuck"), // reload the page with the desired mode and resume time via sessionStorage. diff --git a/static/player/quality.ts b/static/player/quality.ts index 20befdc..bb38650 100644 --- a/static/player/quality.ts +++ b/static/player/quality.ts @@ -11,7 +11,7 @@ export const switchQuality = (quality: string): void => { const url = streamUrlForMode(state.currentMode, quality); if (!url) return; safeLocalStorage.setItem("mal:preferred-quality", quality); - loadVideoSource(url); + loadVideoSource(url, state.modeSources[state.currentMode]?.type); }; /** diff --git a/static/player/state.ts b/static/player/state.ts index a511c45..818919f 100644 --- a/static/player/state.ts +++ b/static/player/state.ts @@ -203,6 +203,7 @@ export const initState = (c: HTMLElement): boolean => { const qualities = value.qualities; out[key] = { token: value.token, + type: typeof value.type === "string" ? value.type : undefined, subtitles, qualities: isStringArray(qualities) ? qualities : undefined, }; diff --git a/static/player/types.ts b/static/player/types.ts index 2baaf92..5b6eabd 100644 --- a/static/player/types.ts +++ b/static/player/types.ts @@ -1,6 +1,7 @@ // stream source for a single mode (sub/dub) export interface ModeSource { token: string; + type?: string; subtitles: SubtitleItem[]; qualities?: string[]; }