diff --git a/app/(auth)/(tabs)/(home)/settings.tv.tsx b/app/(auth)/(tabs)/(home)/settings.tv.tsx index a4bc7774..1734ee40 100644 --- a/app/(auth)/(tabs)/(home)/settings.tv.tsx +++ b/app/(auth)/(tabs)/(home)/settings.tv.tsx @@ -7,7 +7,8 @@ import { Animated, Pressable, ScrollView, TextInput, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { Text } from "@/components/common/Text"; import type { TVOptionItem } from "@/components/tv"; -import { TVOptionSelector, useTVFocusAnimation } from "@/components/tv"; +import { useTVFocusAnimation } from "@/components/tv"; +import { useTVOptionModal } from "@/hooks/useTVOptionModal"; import { apiAtom, useJellyfin, userAtom } from "@/providers/JellyfinProvider"; import { AudioTranscodeMode, useSettings } from "@/utils/atoms/settings"; @@ -112,7 +113,7 @@ const TVSettingsToggle: React.FC<{ width: 56, height: 32, borderRadius: 16, - backgroundColor: value ? "#7c3aed" : "#4B5563", + backgroundColor: value ? "#34C759" : "#4B5563", justifyContent: "center", paddingHorizontal: 2, }} @@ -195,16 +196,20 @@ const TVSettingsStepper: React.FC<{ style={[ minusAnim.animatedStyle, { - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: minusAnim.focused ? "#7c3aed" : "#4B5563", + width: 48, + height: 36, + borderRadius: 18, + backgroundColor: minusAnim.focused ? "#FFFFFF" : "#4B5563", justifyContent: "center", alignItems: "center", }, ]} > - + - + @@ -371,7 +380,7 @@ const TVSettingsTextInput: React.FC<{ paddingVertical: 12, paddingHorizontal: 16, borderWidth: focused ? 2 : 1, - borderColor: focused ? "#7c3aed" : "#4B5563", + borderColor: focused ? "#FFFFFF" : "#4B5563", }} /> @@ -450,14 +459,6 @@ const TVLogoutButton: React.FC<{ onPress: () => void; disabled?: boolean }> = ({ ); }; -// Modal type for tracking open bottom sheets -type SettingsModalType = - | "audioTranscode" - | "subtitleMode" - | "alignX" - | "alignY" - | null; - export default function SettingsTV() { const { t } = useTranslation(); const insets = useSafeAreaInsets(); @@ -465,9 +466,7 @@ export default function SettingsTV() { const { logout } = useJellyfin(); const [user] = useAtom(userAtom); const [api] = useAtom(apiAtom); - - // Modal state for option selectors - const [openModal, setOpenModal] = useState(null); + const { showOptions } = useTVOptionModal(); // Local state for OpenSubtitles API key (only commit on blur) const [openSubtitlesApiKey, setOpenSubtitlesApiKey] = useState( @@ -592,18 +591,9 @@ export default function SettingsTV() { return option?.label || "Bottom"; }, [alignYOptions]); - const isModalOpen = openModal !== null; - return ( - + setOpenModal("audioTranscode")} + onPress={() => + showOptions({ + title: t("home.settings.audio.transcode_mode.title"), + options: audioTranscodeModeOptions, + onSelect: (value) => + updateSettings({ audioTranscodeMode: value }), + }) + } isFirst - disabled={isModalOpen} /> {/* Subtitles Section */} @@ -640,8 +636,13 @@ export default function SettingsTV() { setOpenModal("subtitleMode")} - disabled={isModalOpen} + onPress={() => + showOptions({ + title: t("home.settings.subtitles.subtitle_mode"), + options: subtitleModeOptions, + onSelect: (value) => updateSettings({ subtitleMode: value }), + }) + } /> updateSettings({ rememberSubtitleSelections: value }) } - disabled={isModalOpen} /> `${v.toFixed(1)}x`} - disabled={isModalOpen} /> {/* MPV Subtitles Section */} @@ -690,7 +689,6 @@ export default function SettingsTV() { }); }} formatValue={(v) => `${v.toFixed(1)}x`} - disabled={isModalOpen} /> setOpenModal("alignX")} - disabled={isModalOpen} + onPress={() => + showOptions({ + title: "Horizontal Alignment", + options: alignXOptions, + onSelect: (value) => + updateSettings({ + mpvSubtitleAlignX: value as "left" | "center" | "right", + }), + }) + } /> setOpenModal("alignY")} - disabled={isModalOpen} + onPress={() => + showOptions({ + title: "Vertical Alignment", + options: alignYOptions, + onSelect: (value) => + updateSettings({ + mpvSubtitleAlignY: value as "top" | "center" | "bottom", + }), + }) + } /> {/* OpenSubtitles Section */} @@ -754,7 +767,6 @@ export default function SettingsTV() { onChangeText={setOpenSubtitlesApiKey} onBlur={() => updateSettings({ openSubtitlesApiKey })} secureTextEntry - disabled={isModalOpen} /> updateSettings({ mergeNextUpAndContinueWatching: value }) } - disabled={isModalOpen} /> updateSettings({ showHomeBackdrop: value })} - disabled={isModalOpen} /> {/* User Section */} @@ -793,62 +803,19 @@ export default function SettingsTV() { label={t("home.settings.user_info.user")} value={user?.Name || "-"} showChevron={false} - disabled={isModalOpen} /> {/* Logout Button */} - + - - {/* Bottom sheet modals using shared TVOptionSelector */} - updateSettings({ audioTranscodeMode: value })} - onClose={() => setOpenModal(null)} - /> - - updateSettings({ subtitleMode: value })} - onClose={() => setOpenModal(null)} - /> - - - updateSettings({ - mpvSubtitleAlignX: value as "left" | "center" | "right", - }) - } - onClose={() => setOpenModal(null)} - /> - - - updateSettings({ - mpvSubtitleAlignY: value as "top" | "center" | "bottom", - }) - } - onClose={() => setOpenModal(null)} - /> ); }