style: format static/player/mode.ts
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user