import React, { useState, useEffect, useRef } from "react"; import { View, StyleSheet, FlatList, Alert, KeyboardAvoidingView, Platform } from "react-native"; import { useTVEventHandler } from "react-native"; import { ThemedText } from "@/components/ThemedText"; import { ThemedView } from "@/components/ThemedView"; import { StyledButton } from "@/components/StyledButton"; import { useThemeColor } from "@/hooks/useThemeColor"; import { useSettingsStore } from "@/stores/settingsStore"; import useAuthStore from "@/stores/authStore"; import { useRemoteControlStore } from "@/stores/remoteControlStore"; import { APIConfigSection } from "@/components/settings/APIConfigSection"; import { LiveStreamSection } from "@/components/settings/LiveStreamSection"; import { RemoteInputSection } from "@/components/settings/RemoteInputSection"; import { VideoSourceSection } from "@/components/settings/VideoSourceSection"; import Toast from "react-native-toast-message"; export default function SettingsScreen() { const { loadSettings, saveSettings, setApiBaseUrl, setM3uUrl } = useSettingsStore(); const { lastMessage } = useRemoteControlStore(); const { isLoggedIn, logout } = useAuthStore(); const backgroundColor = useThemeColor({}, "background"); const [hasChanges, setHasChanges] = useState(false); const [isLoading, setIsLoading] = useState(false); const [currentFocusIndex, setCurrentFocusIndex] = useState(0); const [currentSection, setCurrentSection] = useState(null); const saveButtonRef = useRef(null); const apiSectionRef = useRef(null); const liveStreamSectionRef = useRef(null); useEffect(() => { loadSettings(); }, [loadSettings]); useEffect(() => { if (lastMessage) { const realMessage = lastMessage.split("_")[0]; handleRemoteInput(realMessage); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [lastMessage]); const handleRemoteInput = (message: string) => { // Handle remote input based on currently focused section if (currentSection === "api" && apiSectionRef.current) { // API Config Section setApiBaseUrl(message); } else if (currentSection === "livestream" && liveStreamSectionRef.current) { // Live Stream Section setM3uUrl(message); } }; const handleSave = async () => { setIsLoading(true); try { await saveSettings(); setHasChanges(false); Toast.show({ type: "success", text1: "保存成功", }); } catch { Alert.alert("错误", "保存设置失败"); } finally { setIsLoading(false); } }; const markAsChanged = () => { setHasChanges(true); }; const sections = [ { component: ( { setCurrentFocusIndex(0); setCurrentSection("remote"); }} /> ), key: "remote", }, { component: ( { setCurrentFocusIndex(1); setCurrentSection("api"); }} /> ), key: "api", }, { component: ( { setCurrentFocusIndex(2); setCurrentSection("livestream"); }} /> ), key: "livestream", }, { component: ( { setCurrentFocusIndex(3); setCurrentSection("videoSource"); }} /> ), key: "videoSource", }, ]; // TV遥控器事件处理 const handleTVEvent = React.useCallback( (event: any) => { if (event.eventType === "down") { const nextIndex = Math.min(currentFocusIndex + 1, sections.length); setCurrentFocusIndex(nextIndex); if (nextIndex === sections.length) { saveButtonRef.current?.focus(); } } else if (event.eventType === "up") { const prevIndex = Math.max(currentFocusIndex - 1, 0); setCurrentFocusIndex(prevIndex); } }, [currentFocusIndex, sections.length] ); useTVEventHandler(handleTVEvent); return ( 设置 item.component} keyExtractor={(item) => item.key} showsVerticalScrollIndicator={false} /> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 12, }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 10, }, title: { fontSize: 32, fontWeight: "bold", paddingTop: 24, }, backButton: { minWidth: 100, }, scrollView: { flex: 1, }, footer: { paddingTop: 12, alignItems: "flex-end", }, saveButton: { minHeight: 50, width: 120, }, disabledButton: { opacity: 0.5, }, });