style: format static/player/mode.ts

This commit is contained in:
2026-06-21 02:04:44 +02:00
committed by Milas Holsting
parent d3e294b7c9
commit d1d6ea9f24

View File

@@ -1,16 +1,21 @@
import type { ModeSource } from "./types"; import type { ModeSource } from "./types";
import { state } from "./state";
import { showControls } from "./controls"; import { showControls } from "./controls";
import { updateSubtitleOptions } from "./subtitles";
import { updateQualityOptions } from "./quality"; import { updateQualityOptions } from "./quality";
import { safeLocalStorage } from "./storage";
import { streamUrlForMode } from "./source"; import { streamUrlForMode } from "./source";
import { loadVideoSource } from "./video"; import { state } from "./state";
import { safeLocalStorage } from "./storage";
import { updateSubtitleOptions } from "./subtitles";
import { isRecord, parseModeSources } from "./validate"; import { isRecord, parseModeSources } from "./validate";
import { loadVideoSource } from "./video";
const alternateModeFor = (mode: string): "sub" | "dub" | null => { const alternateModeFor = (mode: string): "sub" | "dub" | null => {
if (mode === "sub") return "dub"; if (mode === "sub") {
if (mode === "dub") return "sub"; return "dub";
}
if (mode === "dub") {
return "sub";
}
return null; return null;
}; };
@@ -23,10 +28,14 @@ const fetchModeSource = async (
`/api/watch/episode/${state.episode.malID}/${encodeURIComponent(episode)}?mode=${encodeURIComponent(mode)}`, `/api/watch/episode/${state.episode.malID}/${encodeURIComponent(episode)}?mode=${encodeURIComponent(mode)}`,
{ signal }, { signal },
); );
if (!res.ok) throw new Error(`mode source request failed with status ${res.status}`); if (!res.ok) {
throw new Error(`mode source request failed with status ${res.status}`);
}
const data: unknown = await res.json(); const data: unknown = await res.json();
if (!isRecord(data)) return null; if (!isRecord(data)) {
return null;
}
const sources = parseModeSources(data.mode_sources); const sources = parseModeSources(data.mode_sources);
return sources[mode] ?? null; return sources[mode] ?? null;
@@ -35,7 +44,9 @@ const fetchModeSource = async (
export const ensurePreferredModeSource = async (signal?: AbortSignal): Promise<string> => { export const ensurePreferredModeSource = async (signal?: AbortSignal): Promise<string> => {
const storedMode = safeLocalStorage.getItem("player-audio-mode"); const storedMode = safeLocalStorage.getItem("player-audio-mode");
const preferredMode = storedMode === "sub" || storedMode === "dub" ? storedMode : null; const preferredMode = storedMode === "sub" || storedMode === "dub" ? storedMode : null;
if (!preferredMode) return state.playback.currentMode; if (!preferredMode) {
return state.playback.currentMode;
}
if (state.playback.modeSources[preferredMode]?.token) { if (state.playback.modeSources[preferredMode]?.token) {
state.playback.currentMode = preferredMode; state.playback.currentMode = preferredMode;
return preferredMode; return preferredMode;
@@ -43,7 +54,9 @@ export const ensurePreferredModeSource = async (signal?: AbortSignal): Promise<s
try { try {
const preferredSource = await fetchModeSource(state.episode.current, preferredMode, signal); const preferredSource = await fetchModeSource(state.episode.current, preferredMode, signal);
if (!preferredSource?.token) return state.playback.currentMode; if (!preferredSource?.token) {
return state.playback.currentMode;
}
state.playback.modeSources = { state.playback.modeSources = {
...state.playback.modeSources, ...state.playback.modeSources,
@@ -62,12 +75,18 @@ export const ensurePreferredModeSource = async (signal?: AbortSignal): Promise<s
export const hydrateAlternateMode = async (signal?: AbortSignal): Promise<void> => { export const hydrateAlternateMode = async (signal?: AbortSignal): Promise<void> => {
const alternateMode = alternateModeFor(state.playback.currentMode); const alternateMode = alternateModeFor(state.playback.currentMode);
if (!alternateMode) return; if (!alternateMode) {
if (state.playback.modeSources[alternateMode]?.token) return; return;
}
if (state.playback.modeSources[alternateMode]?.token) {
return;
}
try { try {
const alternateSource = await fetchModeSource(state.episode.current, alternateMode, signal); const alternateSource = await fetchModeSource(state.episode.current, alternateMode, signal);
if (!alternateSource?.token) return; if (!alternateSource?.token) {
return;
}
state.playback.modeSources = { state.playback.modeSources = {
...state.playback.modeSources, ...state.playback.modeSources,
@@ -78,17 +97,18 @@ export const hydrateAlternateMode = async (signal?: AbortSignal): Promise<void>
updateQualityOptions(); updateQualityOptions();
updateModeButtons(); updateModeButtons();
} catch (error: unknown) { } catch (error: unknown) {
if (error instanceof DOMException && error.name === "AbortError") return; if (error instanceof DOMException && error.name === "AbortError") {
return;
}
console.error("failed to hydrate alternate mode:", error); console.error("failed to hydrate alternate mode:", error);
} }
}; };
/** /** Switches between sub/dub mode. Saves preference to localStorage, reloads video src. */
* Switches between sub/dub mode.
* Saves preference to localStorage, reloads video src.
*/
const switchMode = (mode: string): void => { const switchMode = (mode: string): void => {
if (!state.playback.availableModes.includes(mode) || mode === state.playback.currentMode) return; if (!state.playback.availableModes.includes(mode) || mode === state.playback.currentMode) {
return;
}
state.playback.currentMode = mode; state.playback.currentMode = mode;
safeLocalStorage.setItem("player-audio-mode", mode); safeLocalStorage.setItem("player-audio-mode", mode);
const qualitySelect = state.elements.container.querySelector( const qualitySelect = state.elements.container.querySelector(
@@ -104,9 +124,13 @@ const switchMode = (mode: string): void => {
const expectedMode = mode; const expectedMode = mode;
const resumeSeconds = state.elements.video.currentTime; const resumeSeconds = state.elements.video.currentTime;
window.setTimeout(() => { window.setTimeout(() => {
if (!expectedToken) return; if (!expectedToken) {
return;
}
const currentSrc = state.elements.video.currentSrc || state.elements.video.src || ""; const currentSrc = state.elements.video.currentSrc || state.elements.video.src || "";
if (currentSrc.includes(`token=${encodeURIComponent(expectedToken)}`)) return; if (currentSrc.includes(`token=${encodeURIComponent(expectedToken)}`)) {
return;
}
try { try {
sessionStorage.setItem("mal:resume-after-mode-switch", String(resumeSeconds)); sessionStorage.setItem("mal:resume-after-mode-switch", String(resumeSeconds));
@@ -123,10 +147,7 @@ const switchMode = (mode: string): void => {
updateModeButtons(); updateModeButtons();
}; };
/** /** Updates dub/sub button styling based on current mode. Disables unavailable modes. */
* Updates dub/sub button styling based on current mode.
* Disables unavailable modes.
*/
export const updateModeButtons = (): void => { export const updateModeButtons = (): void => {
const dub = state.elements.container.querySelector("[data-mode-dub]") as HTMLButtonElement | null; const dub = state.elements.container.querySelector("[data-mode-dub]") as HTMLButtonElement | null;
const sub = state.elements.container.querySelector("[data-mode-sub]") as HTMLButtonElement | null; const sub = state.elements.container.querySelector("[data-mode-sub]") as HTMLButtonElement | null;
@@ -149,9 +170,7 @@ export const updateModeButtons = (): void => {
} }
}; };
/** /** Binds click handlers for mode buttons and autoplay toggle. */
* Binds click handlers for mode buttons and autoplay toggle.
*/
export const setupMode = (): void => { export const setupMode = (): void => {
const dub = state.elements.container.querySelector("[data-mode-dub]") as HTMLButtonElement | null; const dub = state.elements.container.querySelector("[data-mode-dub]") as HTMLButtonElement | null;
const sub = state.elements.container.querySelector("[data-mode-sub]") as HTMLButtonElement | null; const sub = state.elements.container.querySelector("[data-mode-sub]") as HTMLButtonElement | null;