Files
OrionTV/components/SettingsModal.tsx
zimplexing 08e24dd748 Refactor components to use Zustand for state management
- Updated EpisodeSelectionModal to utilize Zustand for episode selection state.
- Refactored PlayerControls to manage playback state and controls using Zustand.
- Simplified SettingsModal to handle settings state with Zustand.
- Introduced homeStore for managing home screen categories and content data.
- Created playerStore for managing video playback and episode details.
- Added settingsStore for managing API settings and modal visibility.
- Updated package.json to include Zustand as a dependency.
- Cleaned up code formatting and improved readability across components.
2025-07-06 20:45:42 +08:00

135 lines
3.9 KiB
TypeScript

import React, { useState, useEffect, useRef } from 'react';
import { Modal, View, Text, TextInput, StyleSheet, Pressable, useColorScheme } from 'react-native';
import { ThemedText } from './ThemedText';
import { ThemedView } from './ThemedView';
import { useSettingsStore } from '@/stores/settingsStore';
export const SettingsModal: React.FC = () => {
const { isModalVisible, hideModal, apiBaseUrl, setApiBaseUrl, saveSettings, loadSettings } = useSettingsStore();
const [isInputFocused, setIsInputFocused] = useState(false);
const colorScheme = useColorScheme();
const inputRef = useRef<TextInput>(null);
useEffect(() => {
if (isModalVisible) {
loadSettings();
const timer = setTimeout(() => {
inputRef.current?.focus();
}, 200);
return () => clearTimeout(timer);
}
}, [isModalVisible, loadSettings]);
const handleSave = () => {
saveSettings();
};
const styles = StyleSheet.create({
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.6)',
},
modalContent: {
width: '80%',
maxWidth: 500,
padding: 24,
borderRadius: 12,
elevation: 10,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
},
input: {
height: 50,
borderWidth: 2,
borderRadius: 8,
paddingHorizontal: 15,
fontSize: 16,
marginBottom: 24,
backgroundColor: colorScheme === 'dark' ? '#3a3a3c' : '#f0f0f0',
color: colorScheme === 'dark' ? 'white' : 'black',
borderColor: 'transparent',
},
inputFocused: {
borderColor: '#007AFF',
shadowColor: '#007AFF',
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.8,
shadowRadius: 10,
elevation: 5,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
},
button: {
flex: 1,
paddingVertical: 12,
borderRadius: 8,
alignItems: 'center',
marginHorizontal: 8,
},
buttonSave: {
backgroundColor: '#007AFF',
},
buttonCancel: {
backgroundColor: colorScheme === 'dark' ? '#444' : '#ccc',
},
buttonText: {
color: 'white',
fontSize: 18,
fontWeight: '500',
},
focusedButton: {
transform: [{ scale: 1.05 }],
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 5,
elevation: 8,
},
});
return (
<Modal animationType="fade" transparent={true} visible={isModalVisible} onRequestClose={hideModal}>
<View style={styles.modalContainer}>
<ThemedView style={styles.modalContent}>
<ThemedText style={styles.title}></ThemedText>
<TextInput
ref={inputRef}
style={[styles.input, isInputFocused && styles.inputFocused]}
value={apiBaseUrl}
onChangeText={setApiBaseUrl}
placeholder="输入 API 地址"
placeholderTextColor={colorScheme === 'dark' ? '#888' : '#555'}
autoCapitalize="none"
autoCorrect={false}
onFocus={() => setIsInputFocused(true)}
onBlur={() => setIsInputFocused(false)}
/>
<View style={styles.buttonContainer}>
<Pressable
style={({ focused }) => [styles.button, styles.buttonCancel, focused && styles.focusedButton]}
onPress={hideModal}
>
<Text style={styles.buttonText}></Text>
</Pressable>
<Pressable
style={({ focused }) => [styles.button, styles.buttonSave, focused && styles.focusedButton]}
onPress={handleSave}
>
<Text style={styles.buttonText}></Text>
</Pressable>
</View>
</ThemedView>
</View>
</Modal>
);
};