feat: Enhance settings screen with section tracking and success notifications; update remote control UI to support localization

This commit is contained in:
zimplexing
2025-07-11 19:11:25 +08:00
parent 7947a532ec
commit 6df4f256e9
4 changed files with 47 additions and 29 deletions

View File

@@ -11,6 +11,7 @@ import { APIConfigSection } from "@/components/settings/APIConfigSection";
import { LiveStreamSection } from "@/components/settings/LiveStreamSection"; import { LiveStreamSection } from "@/components/settings/LiveStreamSection";
import { RemoteInputSection } from "@/components/settings/RemoteInputSection"; import { RemoteInputSection } from "@/components/settings/RemoteInputSection";
import { VideoSourceSection } from "@/components/settings/VideoSourceSection"; import { VideoSourceSection } from "@/components/settings/VideoSourceSection";
import Toast from "react-native-toast-message";
export default function SettingsScreen() { export default function SettingsScreen() {
const { loadSettings, saveSettings, setApiBaseUrl, setM3uUrl } = useSettingsStore(); const { loadSettings, saveSettings, setApiBaseUrl, setM3uUrl } = useSettingsStore();
@@ -20,6 +21,7 @@ export default function SettingsScreen() {
const [hasChanges, setHasChanges] = useState(false); const [hasChanges, setHasChanges] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [currentFocusIndex, setCurrentFocusIndex] = useState(0); const [currentFocusIndex, setCurrentFocusIndex] = useState(0);
const [currentSection, setCurrentSection] = useState<string | null>(null);
const saveButtonRef = useRef<any>(null); const saveButtonRef = useRef<any>(null);
const apiSectionRef = useRef<any>(null); const apiSectionRef = useRef<any>(null);
@@ -39,10 +41,10 @@ export default function SettingsScreen() {
const handleRemoteInput = (message: string) => { const handleRemoteInput = (message: string) => {
// Handle remote input based on currently focused section // Handle remote input based on currently focused section
if (currentFocusIndex === 1 && apiSectionRef.current) { if (currentSection === "api" && apiSectionRef.current) {
// API Config Section // API Config Section
setApiBaseUrl(message); setApiBaseUrl(message);
} else if (currentFocusIndex === 2 && liveStreamSectionRef.current) { } else if (currentSection === "livestream" && liveStreamSectionRef.current) {
// Live Stream Section // Live Stream Section
setM3uUrl(message); setM3uUrl(message);
} }
@@ -53,6 +55,10 @@ export default function SettingsScreen() {
try { try {
await saveSettings(); await saveSettings();
setHasChanges(false); setHasChanges(false);
Toast.show({
type: "success",
text1: "保存成功",
});
} catch { } catch {
Alert.alert("错误", "保存设置失败"); Alert.alert("错误", "保存设置失败");
} finally { } finally {
@@ -66,12 +72,27 @@ export default function SettingsScreen() {
const sections = [ const sections = [
{ {
component: <RemoteInputSection onChanged={markAsChanged} onFocus={() => setCurrentFocusIndex(0)} />, component: (
<RemoteInputSection
onChanged={markAsChanged}
onFocus={() => {
setCurrentFocusIndex(0);
setCurrentSection("remote");
}}
/>
),
key: "remote", key: "remote",
}, },
{ {
component: ( component: (
<APIConfigSection ref={apiSectionRef} onChanged={markAsChanged} onFocus={() => setCurrentFocusIndex(1)} /> <APIConfigSection
ref={apiSectionRef}
onChanged={markAsChanged}
onFocus={() => {
setCurrentFocusIndex(1);
setCurrentSection("api");
}}
/>
), ),
key: "api", key: "api",
}, },
@@ -80,14 +101,25 @@ export default function SettingsScreen() {
<LiveStreamSection <LiveStreamSection
ref={liveStreamSectionRef} ref={liveStreamSectionRef}
onChanged={markAsChanged} onChanged={markAsChanged}
onFocus={() => setCurrentFocusIndex(2)} onFocus={() => {
setCurrentFocusIndex(2);
setCurrentSection("livestream");
}}
/> />
), ),
key: "livestream", key: "livestream",
}, },
{ {
component: <VideoSourceSection onChanged={markAsChanged} onFocus={() => setCurrentFocusIndex(3)} />, component: (
key: "playback", <VideoSourceSection
onChanged={markAsChanged}
onFocus={() => {
setCurrentFocusIndex(3);
setCurrentSection("videoSource");
}}
/>
),
key: "videoSource",
}, },
]; ];

View File

@@ -1,18 +1,6 @@
import React, { useCallback, useState } from "react"; import React from "react";
import { View, Text, StyleSheet, TouchableOpacity, Pressable } from "react-native"; import { View, Text, StyleSheet, Pressable } from "react-native";
import { useRouter } from "expo-router"; import { Pause, Play, SkipForward, List, Tv, ArrowDownToDot, ArrowUpFromDot } from "lucide-react-native";
import { AVPlaybackStatus } from "expo-av";
import {
Pause,
Play,
SkipForward,
List,
ChevronsRight,
ChevronsLeft,
Tv,
ArrowDownToDot,
ArrowUpFromDot,
} from "lucide-react-native";
import { ThemedText } from "@/components/ThemedText"; import { ThemedText } from "@/components/ThemedText";
import { MediaButton } from "@/components/MediaButton"; import { MediaButton } from "@/components/MediaButton";
@@ -24,7 +12,6 @@ interface PlayerControlsProps {
} }
export const PlayerControls: React.FC<PlayerControlsProps> = ({ showControls, setShowControls }) => { export const PlayerControls: React.FC<PlayerControlsProps> = ({ showControls, setShowControls }) => {
const router = useRouter();
const { const {
detail, detail,
currentEpisodeIndex, currentEpisodeIndex,
@@ -33,7 +20,6 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({ showControls, se
isSeeking, isSeeking,
seekPosition, seekPosition,
progressPosition, progressPosition,
seek,
togglePlayPause, togglePlayPause,
playEpisode, playEpisode,
setShowEpisodeModal, setShowEpisodeModal,

View File

@@ -18,9 +18,9 @@ const getRemotePageHTML = () => {
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<h3>Send a message to TV</h3> <h3>向电视发送文本</h3>
<input id="text" placeholder="Type here..." /> <input id="text" placeholder="请输入..." />
<button onclick="send()">Send</button> <button onclick="send()">发送</button>
</div> </div>
<script> <script>
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {

View File

@@ -183,13 +183,13 @@ export class SearchHistoryManager {
export class SettingsManager { export class SettingsManager {
static async get(): Promise<AppSettings> { static async get(): Promise<AppSettings> {
const defaultSettings: AppSettings = { const defaultSettings: AppSettings = {
apiBaseUrl: "https://orion-tv.edu.deal", apiBaseUrl: "",
remoteInputEnabled: true, remoteInputEnabled: true,
videoSource: { videoSource: {
enabledAll: true, enabledAll: true,
sources: {}, sources: {},
}, },
m3uUrl: "https://raw.githubusercontent.com/sjnhnp/adblock/refs/heads/main/filtered_http_only_valid.m3u", m3uUrl: "https://ghfast.top/https://raw.githubusercontent.com/sjnhnp/adblock/refs/heads/main/filtered_http_only_valid.m3u",
}; };
try { try {
const data = await AsyncStorage.getItem(STORAGE_KEYS.SETTINGS); const data = await AsyncStorage.getItem(STORAGE_KEYS.SETTINGS);