mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-19 16:31:44 +00:00
added prefered quality and language autoplaing
This commit is contained in:
parent
dee6bd3f52
commit
622315f944
3 changed files with 184 additions and 180 deletions
|
|
@ -261,180 +261,7 @@ const PlayerSettingsScreen: React.FC = () => {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={styles.settingItem}>
|
{/* Video Player Engine for Android */}
|
||||||
<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 },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.autoplay_title')}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.settingDescription,
|
|
||||||
{ color: currentTheme.colors.textMuted },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.autoplay_desc')}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<Switch
|
|
||||||
value={settings.autoplayBestStream}
|
|
||||||
onValueChange={(value) => updateSetting('autoplayBestStream', value)}
|
|
||||||
trackColor={{ false: '#767577', true: currentTheme.colors.primary }}
|
|
||||||
thumbColor={settings.autoplayBestStream ? '#ffffff' : '#f4f3f4'}
|
|
||||||
ios_backgroundColor="#3e3e3e"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Preferred Quality for Autoplay */}
|
|
||||||
<View style={[styles.settingItem, styles.settingItemBorder, { borderTopColor: 'rgba(255,255,255,0.08)', borderTopWidth: 1 }]}>
|
|
||||||
<View style={styles.settingContent}>
|
|
||||||
<View style={[
|
|
||||||
styles.settingIconContainer,
|
|
||||||
{ backgroundColor: 'rgba(255,255,255,0.1)' }
|
|
||||||
]}>
|
|
||||||
<MaterialIcons
|
|
||||||
name="high-quality"
|
|
||||||
size={20}
|
|
||||||
color={currentTheme.colors.primary}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={styles.settingText}>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.settingTitle,
|
|
||||||
{ color: currentTheme.colors.text },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.preferred_quality_title') || 'Preferred Quality'}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.settingDescription,
|
|
||||||
{ color: currentTheme.colors.textMuted },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.preferred_quality_desc') || 'Select preferred quality for autoplay'}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View style={styles.optionButtonsRow}>
|
|
||||||
{([
|
|
||||||
{ id: '4K', label: '4K' },
|
|
||||||
{ id: '1080p', label: '1080p' },
|
|
||||||
{ id: '720p', label: '720p' },
|
|
||||||
{ id: '480p', label: '480p' },
|
|
||||||
] as const).map((option) => (
|
|
||||||
<TouchableOpacity
|
|
||||||
key={option.id}
|
|
||||||
onPress={() => updateSetting('autoplayPreferredQuality', option.id)}
|
|
||||||
style={[
|
|
||||||
styles.optionButton,
|
|
||||||
settings.autoplayPreferredQuality === option.id && { backgroundColor: currentTheme.colors.primary },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.optionButtonText,
|
|
||||||
{ color: settings.autoplayPreferredQuality === option.id ? '#fff' : currentTheme.colors.text },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{option.label}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Preferred Language for Autoplay */}
|
|
||||||
<View style={[styles.settingItem, styles.settingItemBorder, { borderTopColor: 'rgba(255,255,255,0.08)', borderTopWidth: 1 }]}>
|
|
||||||
<View style={styles.settingContent}>
|
|
||||||
<View style={[
|
|
||||||
styles.settingIconContainer,
|
|
||||||
{ backgroundColor: 'rgba(255,255,255,0.1)' }
|
|
||||||
]}>
|
|
||||||
<MaterialIcons
|
|
||||||
name="language"
|
|
||||||
size={20}
|
|
||||||
color={currentTheme.colors.primary}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={styles.settingText}>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.settingTitle,
|
|
||||||
{ color: currentTheme.colors.text },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.preferred_language_title') || 'Preferred Language'}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.settingDescription,
|
|
||||||
{ color: currentTheme.colors.textMuted },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('player.preferred_language_desc') || 'Select preferred language for autoplay'}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<ScrollView
|
|
||||||
horizontal
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
contentContainerStyle={styles.optionButtonsRowScroll}
|
|
||||||
>
|
|
||||||
{([
|
|
||||||
{ id: 'Any', label: t('common.any') || 'Any' },
|
|
||||||
{ id: 'English', label: t('settings.english') || 'English' },
|
|
||||||
{ id: 'Spanish', label: t('settings.spanish') || 'Spanish' },
|
|
||||||
{ id: 'French', label: t('settings.french') || 'French' },
|
|
||||||
{ id: 'German', label: t('settings.german') || 'German' },
|
|
||||||
{ id: 'Italian', label: t('settings.italian') || 'Italian' },
|
|
||||||
{ id: 'Portuguese', label: t('settings.portuguese') || 'Portuguese' },
|
|
||||||
{ id: 'Russian', label: t('settings.russian') || 'Russian' },
|
|
||||||
{ id: 'Hindi', label: t('settings.hindi') || 'Hindi' },
|
|
||||||
{ id: 'Chinese', label: t('settings.chinese') || 'Chinese' },
|
|
||||||
{ id: 'Japanese', label: t('settings.japanese') || 'Japanese' },
|
|
||||||
{ id: 'Korean', label: t('settings.korean') || 'Korean' },
|
|
||||||
] as const).map((option) => (
|
|
||||||
<TouchableOpacity
|
|
||||||
key={option.id}
|
|
||||||
onPress={() => updateSetting('autoplayPreferredLanguage', option.id)}
|
|
||||||
style={[
|
|
||||||
styles.optionButton,
|
|
||||||
styles.optionButtonLanguage,
|
|
||||||
settings.autoplayPreferredLanguage === option.id && { backgroundColor: currentTheme.colors.primary },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.optionButtonText,
|
|
||||||
{ color: settings.autoplayPreferredLanguage === option.id ? '#fff' : currentTheme.colors.text },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{option.label}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
))}
|
|
||||||
</ScrollView>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Video Player Engine for Android */}
|
|
||||||
{Platform.OS === 'android' && !settings.useExternalPlayer && (
|
{Platform.OS === 'android' && !settings.useExternalPlayer && (
|
||||||
<>
|
<>
|
||||||
<View style={[styles.settingItem, styles.settingItemBorder, { borderTopColor: 'rgba(255,255,255,0.08)', borderTopWidth: 1 }]}>
|
<View style={[styles.settingItem, styles.settingItemBorder, { borderTopColor: 'rgba(255,255,255,0.08)', borderTopWidth: 1 }]}>
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,19 @@ const SUBTITLE_SOURCE_OPTIONS = [
|
||||||
{ value: 'any', label: 'Any Available', description: 'Use first available subtitle track' },
|
{ value: 'any', label: 'Any Available', description: 'Use first available subtitle track' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const AUTOPLAY_QUALITY_OPTIONS = [
|
||||||
|
{ id: '4320p', label: '8K' },
|
||||||
|
{ id: '4K', label: '4K' },
|
||||||
|
{ id: '3660p', label: '3660p' },
|
||||||
|
{ id: '1440p', label: '1440p' },
|
||||||
|
{ id: '1080p', label: '1080p' },
|
||||||
|
{ id: '720p', label: '720p' },
|
||||||
|
{ id: '480p', label: '480p' },
|
||||||
|
{ id: '360p', label: '360p' },
|
||||||
|
{ id: '240p', label: '240p' },
|
||||||
|
{ id: '140p', label: '140p' },
|
||||||
|
];
|
||||||
|
|
||||||
// Props for the reusable content component
|
// Props for the reusable content component
|
||||||
interface PlaybackSettingsContentProps {
|
interface PlaybackSettingsContentProps {
|
||||||
isTablet?: boolean;
|
isTablet?: boolean;
|
||||||
|
|
@ -151,30 +164,55 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
||||||
const audioLanguageSheetRef = useRef<BottomSheetModal>(null);
|
const audioLanguageSheetRef = useRef<BottomSheetModal>(null);
|
||||||
const subtitleLanguageSheetRef = useRef<BottomSheetModal>(null);
|
const subtitleLanguageSheetRef = useRef<BottomSheetModal>(null);
|
||||||
const subtitleSourceSheetRef = useRef<BottomSheetModal>(null);
|
const subtitleSourceSheetRef = useRef<BottomSheetModal>(null);
|
||||||
|
const autoplayQualitySheetRef = useRef<BottomSheetModal>(null);
|
||||||
|
const autoplayLanguageSheetRef = useRef<BottomSheetModal>(null);
|
||||||
|
|
||||||
// Snap points
|
// Snap points
|
||||||
const languageSnapPoints = useMemo(() => ['70%'], []);
|
const languageSnapPoints = useMemo(() => ['70%'], []);
|
||||||
const sourceSnapPoints = useMemo(() => ['45%'], []);
|
const sourceSnapPoints = useMemo(() => ['45%'], []);
|
||||||
|
const qualitySnapPoints = useMemo(() => ['45%'], []);
|
||||||
|
|
||||||
// Handlers to present sheets - ensure only one is open at a time
|
// Handlers to present sheets - ensure only one is open at a time
|
||||||
const openAudioLanguageSheet = useCallback(() => {
|
const openAudioLanguageSheet = useCallback(() => {
|
||||||
subtitleLanguageSheetRef.current?.dismiss();
|
subtitleLanguageSheetRef.current?.dismiss();
|
||||||
subtitleSourceSheetRef.current?.dismiss();
|
subtitleSourceSheetRef.current?.dismiss();
|
||||||
|
autoplayQualitySheetRef.current?.dismiss();
|
||||||
|
autoplayLanguageSheetRef.current?.dismiss();
|
||||||
setTimeout(() => audioLanguageSheetRef.current?.present(), 100);
|
setTimeout(() => audioLanguageSheetRef.current?.present(), 100);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const openSubtitleLanguageSheet = useCallback(() => {
|
const openSubtitleLanguageSheet = useCallback(() => {
|
||||||
audioLanguageSheetRef.current?.dismiss();
|
audioLanguageSheetRef.current?.dismiss();
|
||||||
subtitleSourceSheetRef.current?.dismiss();
|
subtitleSourceSheetRef.current?.dismiss();
|
||||||
|
autoplayQualitySheetRef.current?.dismiss();
|
||||||
|
autoplayLanguageSheetRef.current?.dismiss();
|
||||||
setTimeout(() => subtitleLanguageSheetRef.current?.present(), 100);
|
setTimeout(() => subtitleLanguageSheetRef.current?.present(), 100);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const openSubtitleSourceSheet = useCallback(() => {
|
const openSubtitleSourceSheet = useCallback(() => {
|
||||||
audioLanguageSheetRef.current?.dismiss();
|
audioLanguageSheetRef.current?.dismiss();
|
||||||
subtitleLanguageSheetRef.current?.dismiss();
|
subtitleLanguageSheetRef.current?.dismiss();
|
||||||
|
autoplayQualitySheetRef.current?.dismiss();
|
||||||
|
autoplayLanguageSheetRef.current?.dismiss();
|
||||||
setTimeout(() => subtitleSourceSheetRef.current?.present(), 100);
|
setTimeout(() => subtitleSourceSheetRef.current?.present(), 100);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const openAutoplayQualitySheet = useCallback(() => {
|
||||||
|
audioLanguageSheetRef.current?.dismiss();
|
||||||
|
subtitleLanguageSheetRef.current?.dismiss();
|
||||||
|
subtitleSourceSheetRef.current?.dismiss();
|
||||||
|
autoplayLanguageSheetRef.current?.dismiss();
|
||||||
|
setTimeout(() => autoplayQualitySheetRef.current?.present(), 100);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const openAutoplayLanguageSheet = useCallback(() => {
|
||||||
|
audioLanguageSheetRef.current?.dismiss();
|
||||||
|
subtitleLanguageSheetRef.current?.dismiss();
|
||||||
|
subtitleSourceSheetRef.current?.dismiss();
|
||||||
|
autoplayQualitySheetRef.current?.dismiss();
|
||||||
|
setTimeout(() => autoplayLanguageSheetRef.current?.present(), 100);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const isItemVisible = (itemId: string) => {
|
const isItemVisible = (itemId: string) => {
|
||||||
if (!config?.items) return true;
|
if (!config?.items) return true;
|
||||||
const item = config.items[itemId];
|
const item = config.items[itemId];
|
||||||
|
|
@ -226,6 +264,16 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
||||||
subtitleSourceSheetRef.current?.dismiss();
|
subtitleSourceSheetRef.current?.dismiss();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectAutoplayQuality = (quality: string) => {
|
||||||
|
updateSetting('autoplayPreferredQuality', quality);
|
||||||
|
autoplayQualitySheetRef.current?.dismiss();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectAutoplayLanguage = (language: string) => {
|
||||||
|
updateSetting('autoplayPreferredLanguage', language);
|
||||||
|
autoplayLanguageSheetRef.current?.dismiss();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hasVisibleItems(['video_player']) && (
|
{hasVisibleItems(['video_player']) && (
|
||||||
|
|
@ -248,6 +296,38 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SettingsCard title={t('player.section_playback', { defaultValue: 'Playback' })} isTablet={isTablet}>
|
<SettingsCard title={t('player.section_playback', { defaultValue: 'Playback' })} isTablet={isTablet}>
|
||||||
|
<SettingItem
|
||||||
|
title={t('player.autoplay_title', { defaultValue: 'Auto-play First Stream' })}
|
||||||
|
description={t('player.autoplay_desc', { defaultValue: 'Automatically start the first stream shown in the list.' })}
|
||||||
|
icon="play-arrow"
|
||||||
|
renderControl={() => (
|
||||||
|
<CustomSwitch
|
||||||
|
value={settings?.autoplayBestStream ?? false}
|
||||||
|
onValueChange={(value) => updateSetting('autoplayBestStream', value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
isTablet={isTablet}
|
||||||
|
/>
|
||||||
|
{settings?.autoplayBestStream && (
|
||||||
|
<>
|
||||||
|
<SettingItem
|
||||||
|
title={t('player.preferred_quality_title', { defaultValue: 'Preferred Quality' })}
|
||||||
|
description={settings?.autoplayPreferredQuality || '1080p'}
|
||||||
|
icon="high-quality"
|
||||||
|
renderControl={() => <ChevronRight />}
|
||||||
|
onPress={openAutoplayQualitySheet}
|
||||||
|
isTablet={isTablet}
|
||||||
|
/>
|
||||||
|
<SettingItem
|
||||||
|
title={t('player.preferred_language_title', { defaultValue: 'Preferred Language' })}
|
||||||
|
description={settings?.autoplayPreferredLanguage === 'Any' ? t('common.any') : settings?.autoplayPreferredLanguage || t('common.any')}
|
||||||
|
icon="language"
|
||||||
|
renderControl={() => <ChevronRight />}
|
||||||
|
onPress={openAutoplayLanguageSheet}
|
||||||
|
isTablet={isTablet}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<SettingItem
|
<SettingItem
|
||||||
title={t('player.skip_intro_settings_title', { defaultValue: 'Skip Intro' })}
|
title={t('player.skip_intro_settings_title', { defaultValue: 'Skip Intro' })}
|
||||||
description={t('player.powered_by_introdb', { defaultValue: 'Powered by IntroDB' })}
|
description={t('player.powered_by_introdb', { defaultValue: 'Powered by IntroDB' })}
|
||||||
|
|
@ -528,6 +608,95 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
||||||
})}
|
})}
|
||||||
</BottomSheetScrollView>
|
</BottomSheetScrollView>
|
||||||
</BottomSheetModal>
|
</BottomSheetModal>
|
||||||
|
|
||||||
|
{/* Autoplay Quality Bottom Sheet */}
|
||||||
|
<BottomSheetModal
|
||||||
|
ref={autoplayQualitySheetRef}
|
||||||
|
index={0}
|
||||||
|
snapPoints={qualitySnapPoints}
|
||||||
|
enableDynamicSizing={false}
|
||||||
|
enablePanDownToClose={true}
|
||||||
|
backdropComponent={renderBackdrop}
|
||||||
|
backgroundStyle={{ backgroundColor: '#1a1a1a' }}
|
||||||
|
handleIndicatorStyle={{ backgroundColor: 'rgba(255,255,255,0.3)' }}
|
||||||
|
>
|
||||||
|
<View style={styles.sheetHeader}>
|
||||||
|
<Text style={styles.sheetTitle}>{t('player.preferred_quality_title')}</Text>
|
||||||
|
</View>
|
||||||
|
<BottomSheetScrollView contentContainerStyle={styles.sheetContent}>
|
||||||
|
{AUTOPLAY_QUALITY_OPTIONS.map((option) => {
|
||||||
|
const isSelected = option.id === (settings?.autoplayPreferredQuality || '1080p');
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={option.id}
|
||||||
|
style={[
|
||||||
|
styles.languageItem,
|
||||||
|
isSelected && { backgroundColor: currentTheme.colors.primary + '20' }
|
||||||
|
]}
|
||||||
|
onPress={() => handleSelectAutoplayQuality(option.id)}
|
||||||
|
>
|
||||||
|
<Text style={[styles.languageName, { color: isSelected ? currentTheme.colors.primary : '#fff' }]}>
|
||||||
|
{option.label}
|
||||||
|
</Text>
|
||||||
|
{isSelected && (
|
||||||
|
<MaterialIcons name="check" size={20} color={currentTheme.colors.primary} />
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</BottomSheetScrollView>
|
||||||
|
</BottomSheetModal>
|
||||||
|
|
||||||
|
{/* Autoplay Language Bottom Sheet */}
|
||||||
|
<BottomSheetModal
|
||||||
|
ref={autoplayLanguageSheetRef}
|
||||||
|
index={0}
|
||||||
|
snapPoints={languageSnapPoints}
|
||||||
|
enableDynamicSizing={false}
|
||||||
|
enablePanDownToClose={true}
|
||||||
|
backdropComponent={renderBackdrop}
|
||||||
|
backgroundStyle={{ backgroundColor: '#1a1a1a' }}
|
||||||
|
handleIndicatorStyle={{ backgroundColor: 'rgba(255,255,255,0.3)' }}
|
||||||
|
>
|
||||||
|
<View style={styles.sheetHeader}>
|
||||||
|
<Text style={styles.sheetTitle}>{t('player.preferred_language_title')}</Text>
|
||||||
|
</View>
|
||||||
|
<BottomSheetScrollView contentContainerStyle={styles.sheetContent}>
|
||||||
|
{[
|
||||||
|
{ id: 'Any', label: t('common.any') || 'Any' },
|
||||||
|
{ id: 'English', label: t('settings.english') || 'English' },
|
||||||
|
{ id: 'Spanish', label: t('settings.spanish') || 'Spanish' },
|
||||||
|
{ id: 'French', label: t('settings.french') || 'French' },
|
||||||
|
{ id: 'German', label: t('settings.german') || 'German' },
|
||||||
|
{ id: 'Italian', label: t('settings.italian') || 'Italian' },
|
||||||
|
{ id: 'Portuguese', label: t('settings.portuguese') || 'Portuguese' },
|
||||||
|
{ id: 'Russian', label: t('settings.russian') || 'Russian' },
|
||||||
|
{ id: 'Hindi', label: t('settings.hindi') || 'Hindi' },
|
||||||
|
{ id: 'Chinese', label: t('settings.chinese') || 'Chinese' },
|
||||||
|
{ id: 'Japanese', label: t('settings.japanese') || 'Japanese' },
|
||||||
|
{ id: 'Korean', label: t('settings.korean') || 'Korean' },
|
||||||
|
].map((option) => {
|
||||||
|
const isSelected = option.id === (settings?.autoplayPreferredLanguage || 'Any');
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={option.id}
|
||||||
|
style={[
|
||||||
|
styles.languageItem,
|
||||||
|
isSelected && { backgroundColor: currentTheme.colors.primary + '20' }
|
||||||
|
]}
|
||||||
|
onPress={() => handleSelectAutoplayLanguage(option.id)}
|
||||||
|
>
|
||||||
|
<Text style={[styles.languageName, { color: isSelected ? currentTheme.colors.primary : '#fff' }]}>
|
||||||
|
{option.label}
|
||||||
|
</Text>
|
||||||
|
{isSelected && (
|
||||||
|
<MaterialIcons name="check" size={20} color={currentTheme.colors.primary} />
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</BottomSheetScrollView>
|
||||||
|
</BottomSheetModal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import { TABLET_BREAKPOINT } from './constants';
|
||||||
import {
|
import {
|
||||||
filterStreamsByQuality,
|
filterStreamsByQuality,
|
||||||
filterStreamsByLanguage,
|
filterStreamsByLanguage,
|
||||||
|
getLanguageVariations,
|
||||||
getQualityNumeric,
|
getQualityNumeric,
|
||||||
inferVideoTypeFromUrl,
|
inferVideoTypeFromUrl,
|
||||||
sortStreamsByQuality,
|
sortStreamsByQuality,
|
||||||
|
|
@ -254,13 +255,20 @@ export const useStreamsScreen = () => {
|
||||||
let languageMatchedStreams = allStreams;
|
let languageMatchedStreams = allStreams;
|
||||||
if (preferredLanguage && preferredLanguage !== 'Any') {
|
if (preferredLanguage && preferredLanguage !== 'Any') {
|
||||||
languageMatchedStreams = allStreams.filter(item => {
|
languageMatchedStreams = allStreams.filter(item => {
|
||||||
|
const streamName = (item.stream.name || '').toLowerCase();
|
||||||
|
const streamTitle = (item.stream.title || '').toLowerCase();
|
||||||
|
const streamDesc = (item.stream.description || '').toLowerCase();
|
||||||
const streamLang = (item.stream.lang || '').toLowerCase();
|
const streamLang = (item.stream.lang || '').toLowerCase();
|
||||||
const prefLang = preferredLanguage.toLowerCase();
|
|
||||||
// Match by name if lang is not set, or match by lang property
|
const variations = getLanguageVariations(preferredLanguage);
|
||||||
return streamLang === prefLang ||
|
|
||||||
(item.stream.name || '').toLowerCase().includes(prefLang) ||
|
return variations.some(variant => {
|
||||||
(item.stream.title || '').toLowerCase().includes(prefLang) ||
|
const variantLower = variant.toLowerCase();
|
||||||
(item.stream.description || '').toLowerCase().includes(prefLang);
|
return streamLang === variantLower ||
|
||||||
|
streamName.includes(variantLower) ||
|
||||||
|
streamTitle.includes(variantLower) ||
|
||||||
|
streamDesc.includes(variantLower);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue