From 0edb4ece08c486b04dba689890d620f5c5aad697 Mon Sep 17 00:00:00 2001
From: Pas <74743263+Pasithea0@users.noreply.github.com>
Date: Mon, 7 Jul 2025 22:44:18 -0600
Subject: [PATCH] make native subtitles a proper setting
---
src/backend/accounts/settings.ts | 2 +
.../atoms/settings/CaptionSettingsView.tsx | 27 +-
src/hooks/auth/useAuthData.ts | 8 +
src/pages/parts/auth/VerifyPassphrasePart.tsx | 2 +
src/pages/parts/settings/CaptionsPart.tsx | 402 ++++++++++--------
src/stores/preferences/index.tsx | 8 +
6 files changed, 260 insertions(+), 189 deletions(-)
diff --git a/src/backend/accounts/settings.ts b/src/backend/accounts/settings.ts
index 86f6af2a..4c39e21e 100644
--- a/src/backend/accounts/settings.ts
+++ b/src/backend/accounts/settings.ts
@@ -23,6 +23,7 @@ export interface SettingsInput {
enableSourceOrder?: boolean;
proxyTmdb?: boolean;
enableLowPerformanceMode?: boolean;
+ enableNativeSubtitles?: boolean;
}
export interface SettingsResponse {
@@ -44,6 +45,7 @@ export interface SettingsResponse {
enableSourceOrder?: boolean;
proxyTmdb?: boolean;
enableLowPerformanceMode?: boolean;
+ enableNativeSubtitles?: boolean;
}
export function updateSettings(
diff --git a/src/components/player/atoms/settings/CaptionSettingsView.tsx b/src/components/player/atoms/settings/CaptionSettingsView.tsx
index 4b091485..b56584e6 100644
--- a/src/components/player/atoms/settings/CaptionSettingsView.tsx
+++ b/src/components/player/atoms/settings/CaptionSettingsView.tsx
@@ -10,6 +10,7 @@ import { Menu } from "@/components/player/internals/ContextMenu";
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
import { useProgressBar } from "@/hooks/useProgressBar";
import { usePlayerStore } from "@/stores/player/store";
+import { usePreferencesStore } from "@/stores/preferences";
import { SubtitleStyling, useSubtitleStore } from "@/stores/subtitles";
export function ColorOption(props: {
@@ -229,6 +230,7 @@ export function CaptionSettingsView({
const { t } = useTranslation();
const router = useOverlayRouter(id);
const subtitleStore = useSubtitleStore();
+ const preferencesStore = usePreferencesStore();
const styling = subtitleStore.styling;
const overrideCasing = subtitleStore.overrideCasing;
const delay = subtitleStore.delay;
@@ -236,12 +238,17 @@ export function CaptionSettingsView({
const setDelay = subtitleStore.setDelay;
const updateStyling = subtitleStore.updateStyling;
const setCaptionAsTrack = usePlayerStore((s) => s.setCaptionAsTrack);
- const captionAsTrack = usePlayerStore((s) => s.caption.asTrack);
+ const enableNativeSubtitles = preferencesStore.enableNativeSubtitles;
useEffect(() => {
subtitleStore.updateStyling(styling);
}, [styling, subtitleStore]);
+ // Sync preferences with player store
+ useEffect(() => {
+ setCaptionAsTrack(enableNativeSubtitles);
+ }, [enableNativeSubtitles, setCaptionAsTrack]);
+
const handleStylingChange = (newStyling: SubtitleStyling) => {
updateStyling(newStyling);
};
@@ -267,7 +274,7 @@ export function CaptionSettingsView({
{t("player.menus.subtitles.settings.backlink")}
- {!captionAsTrack ? (
+ {!enableNativeSubtitles ? (
<>
@@ -275,8 +282,12 @@ export function CaptionSettingsView({
setCaptionAsTrack(!captionAsTrack)}
+ enabled={enableNativeSubtitles}
+ onClick={() =>
+ preferencesStore.setEnableNativeSubtitles(
+ !enableNativeSubtitles,
+ )
+ }
/>
@@ -478,8 +489,12 @@ export function CaptionSettingsView({
setCaptionAsTrack(!captionAsTrack)}
+ enabled={enableNativeSubtitles}
+ onClick={() =>
+ preferencesStore.setEnableNativeSubtitles(
+ !enableNativeSubtitles,
+ )
+ }
/>
diff --git a/src/hooks/auth/useAuthData.ts b/src/hooks/auth/useAuthData.ts
index 5247f0c5..b1278168 100644
--- a/src/hooks/auth/useAuthData.ts
+++ b/src/hooks/auth/useAuthData.ts
@@ -57,6 +57,9 @@ export function useAuthData() {
const setEnableLowPerformanceMode = usePreferencesStore(
(s) => s.setEnableLowPerformanceMode,
);
+ const setEnableNativeSubtitles = usePreferencesStore(
+ (s) => s.setEnableNativeSubtitles,
+ );
const login = useCallback(
async (
@@ -164,6 +167,10 @@ export function useAuthData() {
if (settings.enableLowPerformanceMode !== undefined) {
setEnableLowPerformanceMode(settings.enableLowPerformanceMode);
}
+
+ if (settings.enableNativeSubtitles !== undefined) {
+ setEnableNativeSubtitles(settings.enableNativeSubtitles);
+ }
},
[
replaceBookmarks,
@@ -185,6 +192,7 @@ export function useAuthData() {
setProxyTmdb,
setFebboxKey,
setEnableLowPerformanceMode,
+ setEnableNativeSubtitles,
],
);
diff --git a/src/pages/parts/auth/VerifyPassphrasePart.tsx b/src/pages/parts/auth/VerifyPassphrasePart.tsx
index 32ed628f..d3f9b77d 100644
--- a/src/pages/parts/auth/VerifyPassphrasePart.tsx
+++ b/src/pages/parts/auth/VerifyPassphrasePart.tsx
@@ -54,6 +54,8 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
enableSourceOrder: store.enableSourceOrder,
proxyTmdb: store.proxyTmdb,
febboxKey: store.febboxKey,
+ enableLowPerformanceMode: store.enableLowPerformanceMode,
+ enableNativeSubtitles: store.enableNativeSubtitles,
}));
const backendUrl = useBackendUrl();
diff --git a/src/pages/parts/settings/CaptionsPart.tsx b/src/pages/parts/settings/CaptionsPart.tsx
index 2e5c281e..d0b01f8e 100644
--- a/src/pages/parts/settings/CaptionsPart.tsx
+++ b/src/pages/parts/settings/CaptionsPart.tsx
@@ -16,6 +16,8 @@ import { Menu } from "@/components/player/internals/ContextMenu";
import { CaptionCue } from "@/components/player/Player";
import { Heading1 } from "@/components/utils/Text";
import { Transition } from "@/components/utils/Transition";
+import { usePlayerStore } from "@/stores/player/store";
+import { usePreferencesStore } from "@/stores/preferences";
import { SubtitleStyling, useSubtitleStore } from "@/stores/subtitles";
export function CaptionPreview(props: {
@@ -86,11 +88,19 @@ export function CaptionsPart(props: {
const [fullscreenPreview, setFullscreenPreview] = useState(false);
const subtitleStore = useSubtitleStore();
+ const preferencesStore = usePreferencesStore();
+ const setCaptionAsTrack = usePlayerStore((s) => s.setCaptionAsTrack);
+ const enableNativeSubtitles = preferencesStore.enableNativeSubtitles;
useEffect(() => {
subtitleStore.updateStyling(props.styling);
}, [props.styling, subtitleStore, subtitleStore.updateStyling]);
+ // Sync preferences with player store
+ useEffect(() => {
+ setCaptionAsTrack(enableNativeSubtitles);
+ }, [enableNativeSubtitles, setCaptionAsTrack]);
+
const handleStylingChange = (newStyling: SubtitleStyling) => {
props.setStyling(newStyling);
subtitleStore.updateStyling(newStyling);
@@ -114,203 +124,229 @@ export function CaptionsPart(props: {
{t("settings.subtitles.title")}
-
- handleStylingChange({
- ...props.styling,
- backgroundOpacity: v / 100,
- })
- }
- value={props.styling.backgroundOpacity * 100}
- textTransformer={(s) => `${s}%`}
- />
-
- handleStylingChange({
- ...props.styling,
- backgroundBlur: v / 100,
- })
- }
- value={props.styling.backgroundBlur * 100}
- textTransformer={(s) => `${s}%`}
- />
- `${s}%`}
- onChange={(v) =>
- handleStylingChange({
- ...props.styling,
- size: v / 100,
- })
- }
- value={props.styling.size * 100}
- />
- {t("settings.subtitles.textStyle.title")}
-
-
-
- handleStylingChange({
- ...props.styling,
- fontStyle: item.id,
- })
- }
- />
-
-
-
-
- {t("settings.subtitles.textBoldLabel")}
+ {t("player.menus.subtitles.useNativeSubtitles")}
- handleStylingChange({
- ...props.styling,
- bold: !props.styling.bold,
- })
+ preferencesStore.setEnableNativeSubtitles(
+ !enableNativeSubtitles,
+ )
}
/>
-
-
- {t("settings.subtitles.colorLabel")}
-
-
- {colors.map((v) => (
-
- handleStylingChange({
- ...props.styling,
- color: v,
- })
- }
- color={v}
- active={props.styling.color === v}
- key={v}
- />
- ))}
-
-
{
- const color = e.target.value;
- handleStylingChange({ ...props.styling, color });
- subtitleStore.updateStyling({
- ...props.styling,
- color,
- });
- }}
- className="absolute opacity-0 cursor-pointer w-8 h-8"
- />
-
-
+
+ {t("player.menus.subtitles.useNativeSubtitlesDescription")}
+
+ {!enableNativeSubtitles && (
+ <>
+
+ handleStylingChange({
+ ...props.styling,
+ backgroundOpacity: v / 100,
+ })
+ }
+ value={props.styling.backgroundOpacity * 100}
+ textTransformer={(s) => `${s}%`}
+ />
+
+ handleStylingChange({
+ ...props.styling,
+ backgroundBlur: v / 100,
+ })
+ }
+ value={props.styling.backgroundBlur * 100}
+ textTransformer={(s) => `${s}%`}
+ />
+ `${s}%`}
+ onChange={(v) =>
+ handleStylingChange({
+ ...props.styling,
+ size: v / 100,
+ })
+ }
+ value={props.styling.size * 100}
+ />
+
+
+ {t("settings.subtitles.textStyle.title")}
+
+
+
+ handleStylingChange({
+ ...props.styling,
+ fontStyle: item.id,
+ })
+ }
+ />
-
-
-
-
- {t("settings.subtitles.verticalPositionLabel")}
-
-
-
-
+ {t("settings.reset")}
+
+ >
+ )}
-
setFullscreenPreview((s) => !s)}
- />
- setFullscreenPreview((s) => !s)}
- />
-
- {t("settings.reset")}
-
+ {!enableNativeSubtitles && (
+ <>
+ setFullscreenPreview((s) => !s)}
+ />
+ setFullscreenPreview((s) => !s)}
+ />
+ >
+ )}
);
diff --git a/src/stores/preferences/index.tsx b/src/stores/preferences/index.tsx
index 60387c15..211739be 100644
--- a/src/stores/preferences/index.tsx
+++ b/src/stores/preferences/index.tsx
@@ -18,6 +18,7 @@ export interface PreferencesStore {
febboxKey: string | null;
realDebridKey: string | null;
enableLowPerformanceMode: boolean;
+ enableNativeSubtitles: boolean;
setEnableThumbnails(v: boolean): void;
setEnableAutoplay(v: boolean): void;
@@ -34,6 +35,7 @@ export interface PreferencesStore {
setFebboxKey(v: string | null): void;
setRealDebridKey(v: string | null): void;
setEnableLowPerformanceMode(v: boolean): void;
+ setEnableNativeSubtitles(v: boolean): void;
}
export const usePreferencesStore = create(
@@ -54,6 +56,7 @@ export const usePreferencesStore = create(
febboxKey: null,
realDebridKey: null,
enableLowPerformanceMode: false,
+ enableNativeSubtitles: false,
setEnableThumbnails(v) {
set((s) => {
s.enableThumbnails = v;
@@ -129,6 +132,11 @@ export const usePreferencesStore = create(
s.enableLowPerformanceMode = v;
});
},
+ setEnableNativeSubtitles(v) {
+ set((s) => {
+ s.enableNativeSubtitles = v;
+ });
+ },
})),
{
name: "__MW::preferences",