import { useEffect, useState } from "react"; import { Platform, TouchableOpacity, View, type ViewProps } from "react-native"; const _DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null; import { Ionicons } from "@expo/vector-icons"; import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client"; import { useTranslation } from "react-i18next"; import { Switch } from "react-native-gesture-handler"; import Dropdown from "@/components/common/Dropdown"; import { Stepper } from "@/components/inputs/Stepper"; import { useSettings } from "@/utils/atoms/settings"; import { storage } from "@/utils/mmkv"; import { Text } from "../common/Text"; import { ListGroup } from "../list/ListGroup"; import { ListItem } from "../list/ListItem"; import { useMedia } from "./MediaContext"; interface Props extends ViewProps {} const VLC_COLORS = { Black: 0, Gray: 8421504, Silver: 12632256, White: 16777215, Maroon: 8388608, Red: 16711680, Fuchsia: 16711935, Yellow: 16776960, Olive: 8421376, Green: 32768, Teal: 32896, Lime: 65280, Purple: 8388736, Navy: 128, Blue: 255, Aqua: 65535, }; const OUTLINE_THICKNESS = { None: 0, Thin: 2, Normal: 4, Thick: 6, }; export const SubtitleToggles: React.FC = ({ ...props }) => { const isTv = Platform.isTV; const media = useMedia(); const { pluginSettings } = useSettings(); const { settings, updateSettings } = media; const cultures = media.cultures; const { t } = useTranslation(); // VLC subtitle styling states const [textColor, setTextColor] = useState( storage.getString("vlc.textColor") || "White", ); const [backgroundColor, setBackgroundColor] = useState( storage.getString("vlc.backgroundColor") || "Black", ); const [outlineColor, setOutlineColor] = useState( storage.getString("vlc.outlineColor") || "Black", ); const [outlineThickness, setOutlineThickness] = useState( storage.getString("vlc.outlineThickness") || "Normal", ); const [backgroundOpacity, setBackgroundOpacity] = useState( storage.getNumber("vlc.backgroundOpacity") || 128, ); const [outlineOpacity, setOutlineOpacity] = useState( storage.getNumber("vlc.outlineOpacity") || 255, ); const [isBold, setIsBold] = useState( storage.getBoolean("vlc.isBold") || false, ); // VLC settings effects useEffect(() => { storage.set("vlc.textColor", textColor); }, [textColor]); useEffect(() => { storage.set("vlc.backgroundColor", backgroundColor); }, [backgroundColor]); useEffect(() => { storage.set("vlc.outlineColor", outlineColor); }, [outlineColor]); useEffect(() => { storage.set("vlc.outlineThickness", outlineThickness); }, [outlineThickness]); useEffect(() => { storage.set("vlc.backgroundOpacity", backgroundOpacity); }, [backgroundOpacity]); useEffect(() => { storage.set("vlc.outlineOpacity", outlineOpacity); }, [outlineOpacity]); useEffect(() => { storage.set("vlc.isBold", isBold); }, [isBold]); if (isTv) return null; if (!settings) return null; const subtitleModes = [ SubtitlePlaybackMode.Default, SubtitlePlaybackMode.Smart, SubtitlePlaybackMode.OnlyForced, SubtitlePlaybackMode.Always, SubtitlePlaybackMode.None, ]; const subtitleModeKeys = { [SubtitlePlaybackMode.Default]: "home.settings.subtitles.modes.Default", [SubtitlePlaybackMode.Smart]: "home.settings.subtitles.modes.Smart", [SubtitlePlaybackMode.OnlyForced]: "home.settings.subtitles.modes.OnlyForced", [SubtitlePlaybackMode.Always]: "home.settings.subtitles.modes.Always", [SubtitlePlaybackMode.None]: "home.settings.subtitles.modes.None", }; return ( {t("home.settings.subtitles.subtitle_hint")} } > item?.ThreeLetterISOLanguageName ?? "unknown" } titleExtractor={(item) => item?.DisplayName} title={ {settings?.defaultSubtitleLanguage?.DisplayName || t("home.settings.subtitles.none")} } label={t("home.settings.subtitles.language")} onSelected={(defaultSubtitleLanguage) => updateSettings({ defaultSubtitleLanguage: defaultSubtitleLanguage.DisplayName === t("home.settings.subtitles.none") ? null : defaultSubtitleLanguage, }) } /> t(subtitleModeKeys[item]) || String(item)} title={ {t(subtitleModeKeys[settings?.subtitleMode]) || t("home.settings.subtitles.loading")} } label={t("home.settings.subtitles.subtitle_mode")} onSelected={(subtitleMode) => updateSettings({ subtitleMode })} /> updateSettings({ rememberSubtitleSelections: value }) } /> updateSettings({ subtitleSize })} /> item} titleExtractor={(item) => t(`home.settings.subtitles.colors.${item}`) } title={ {t(`home.settings.subtitles.colors.${textColor}`)} } label={t("home.settings.subtitles.text_color")} onSelected={setTextColor} /> item} titleExtractor={(item) => t(`home.settings.subtitles.colors.${item}`) } title={ {t(`home.settings.subtitles.colors.${backgroundColor}`)} } label={t("home.settings.subtitles.background_color")} onSelected={setBackgroundColor} /> item} titleExtractor={(item) => t(`home.settings.subtitles.colors.${item}`) } title={ {t(`home.settings.subtitles.colors.${outlineColor}`)} } label={t("home.settings.subtitles.outline_color")} onSelected={setOutlineColor} /> item} titleExtractor={(item) => t(`home.settings.subtitles.thickness.${item}`) } title={ {t(`home.settings.subtitles.thickness.${outlineThickness}`)} } label={t("home.settings.subtitles.outline_thickness")} onSelected={setOutlineThickness} /> `${Math.round((item / 255) * 100)}%`} title={ {`${Math.round((backgroundOpacity / 255) * 100)}%`} } label={t("home.settings.subtitles.background_opacity")} onSelected={setBackgroundOpacity} /> `${Math.round((item / 255) * 100)}%`} title={ {`${Math.round((outlineOpacity / 255) * 100)}%`} } label={t("home.settings.subtitles.outline_opacity")} onSelected={setOutlineOpacity} /> ); };