NuvioStreaming/src/screens/PlayerSettingsScreen.tsx
2025-06-20 14:53:00 +05:30

373 lines
No EOL
9.2 KiB
TypeScript

import React from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
SafeAreaView,
Platform,
TouchableOpacity,
StatusBar,
Switch,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { useSettings, AppSettings } from '../hooks/useSettings';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { useTheme } from '../contexts/ThemeContext';
const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
interface SettingItemProps {
title: string;
description?: string;
icon: string;
isSelected: boolean;
onPress: () => void;
isLast?: boolean;
}
const SettingItem: React.FC<SettingItemProps> = ({
title,
description,
icon,
isSelected,
onPress,
isLast,
}) => {
const { currentTheme } = useTheme();
return (
<TouchableOpacity
onPress={onPress}
activeOpacity={0.7}
style={[
styles.settingItem,
!isLast && styles.settingItemBorder,
{ borderBottomColor: 'rgba(255,255,255,0.08)' },
]}
>
<View style={styles.settingContent}>
<View style={[
styles.settingIconContainer,
{ backgroundColor: 'rgba(255,255,255,0.1)' }
]}>
<MaterialIcons
name={icon}
size={20}
color={currentTheme.colors.primary}
/>
</View>
<View style={styles.settingText}>
<Text
style={[
styles.settingTitle,
{ color: currentTheme.colors.text },
]}
>
{title}
</Text>
{description && (
<Text
style={[
styles.settingDescription,
{ color: currentTheme.colors.textMuted },
]}
>
{description}
</Text>
)}
</View>
{isSelected && (
<MaterialIcons
name="check"
size={24}
color={currentTheme.colors.primary}
style={styles.checkIcon}
/>
)}
</View>
</TouchableOpacity>
);
};
const PlayerSettingsScreen: React.FC = () => {
const { settings, updateSetting } = useSettings();
const { currentTheme } = useTheme();
const navigation = useNavigation();
const playerOptions = [
{
id: 'internal',
title: 'Built-in Player',
description: 'Use the app\'s default video player',
icon: 'play-circle-outline',
},
...(Platform.OS === 'ios' ? [
{
id: 'vlc',
title: 'VLC',
description: 'Open streams in VLC media player',
icon: 'video-library',
},
{
id: 'infuse',
title: 'Infuse',
description: 'Open streams in Infuse player',
icon: 'smart-display',
},
{
id: 'outplayer',
title: 'OutPlayer',
description: 'Open streams in OutPlayer',
icon: 'slideshow',
},
{
id: 'vidhub',
title: 'VidHub',
description: 'Open streams in VidHub player',
icon: 'ondemand-video',
},
] : [
{
id: 'external',
title: 'External Player',
description: 'Open streams in your preferred video player',
icon: 'open-in-new',
},
]),
];
const handleBack = () => {
navigation.goBack();
};
return (
<SafeAreaView
style={[
styles.container,
{ backgroundColor: currentTheme.colors.darkBackground },
]}
>
<StatusBar
translucent
backgroundColor="transparent"
barStyle="light-content"
/>
<View style={styles.header}>
<TouchableOpacity
onPress={handleBack}
style={styles.backButton}
activeOpacity={0.7}
>
<MaterialIcons
name="arrow-back"
size={24}
color={currentTheme.colors.text}
/>
</TouchableOpacity>
<Text
style={[
styles.headerTitle,
{ color: currentTheme.colors.text },
]}
>
Video Player
</Text>
</View>
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.scrollContent}
>
<View style={styles.section}>
<Text
style={[
styles.sectionTitle,
{ color: currentTheme.colors.textMuted },
]}
>
PLAYER SELECTION
</Text>
<View
style={[
styles.card,
{
backgroundColor: currentTheme.colors.elevation2,
},
]}
>
{playerOptions.map((option, index) => (
<SettingItem
key={option.id}
title={option.title}
description={option.description}
icon={option.icon}
isSelected={
Platform.OS === 'ios'
? settings.preferredPlayer === option.id
: settings.useExternalPlayer === (option.id === 'external')
}
onPress={() => {
if (Platform.OS === 'ios') {
updateSetting('preferredPlayer', option.id as AppSettings['preferredPlayer'], false);
} else {
updateSetting('useExternalPlayer', option.id === 'external', false);
}
}}
isLast={index === playerOptions.length - 1}
/>
))}
</View>
</View>
<View style={styles.section}>
<Text
style={[
styles.sectionTitle,
{ color: currentTheme.colors.textMuted },
]}
>
PLAYBACK OPTIONS
</Text>
<View
style={[
styles.card,
{
backgroundColor: currentTheme.colors.elevation2,
},
]}
>
<View style={styles.settingItem}>
<View style={styles.settingContent}>
<View style={[
styles.settingIconContainer,
{ backgroundColor: 'rgba(255,255,255,0.1)' }
]}>
<MaterialIcons
name="play-arrow"
size={20}
color={currentTheme.colors.primary}
/>
</View>
<View style={styles.settingText}>
<Text
style={[
styles.settingTitle,
{ color: currentTheme.colors.text },
]}
>
Auto-play Best Stream
</Text>
<Text
style={[
styles.settingDescription,
{ color: currentTheme.colors.textMuted },
]}
>
Automatically play the highest quality stream when available
</Text>
</View>
<Switch
value={settings.autoplayBestStream}
onValueChange={(value) => updateSetting('autoplayBestStream', value)}
trackColor={{
false: 'rgba(255,255,255,0.2)',
true: currentTheme.colors.primary + '40'
}}
thumbColor={settings.autoplayBestStream ? currentTheme.colors.primary : 'rgba(255,255,255,0.8)'}
ios_backgroundColor="rgba(255,255,255,0.2)"
/>
</View>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 16 : 16,
paddingBottom: 8,
},
backButton: {
padding: 8,
marginRight: 16,
borderRadius: 20,
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
},
scrollView: {
flex: 1,
},
scrollContent: {
paddingBottom: 24,
},
section: {
paddingHorizontal: 16,
paddingTop: 24,
},
sectionTitle: {
fontSize: 13,
fontWeight: '600',
marginBottom: 8,
paddingHorizontal: 4,
letterSpacing: 0.5,
},
card: {
borderRadius: 12,
overflow: 'hidden',
marginBottom: 24,
shadowColor: 'rgba(0,0,0,0.1)',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.5,
shadowRadius: 4,
elevation: 3,
},
settingItem: {
paddingVertical: 16,
paddingHorizontal: 16,
},
settingItemBorder: {
borderBottomWidth: 1,
},
settingContent: {
flexDirection: 'row',
alignItems: 'center',
},
settingIconContainer: {
width: 36,
height: 36,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center',
marginRight: 16,
},
settingText: {
flex: 1,
},
settingTitle: {
fontSize: 16,
fontWeight: '500',
marginBottom: 2,
},
settingDescription: {
fontSize: 14,
marginTop: 2,
},
checkIcon: {
marginLeft: 16,
},
});
export default PlayerSettingsScreen;