diff --git a/src/screens/PlayerSettingsScreen.tsx b/src/screens/PlayerSettingsScreen.tsx
index 9cb7ba5c..e808efe4 100644
--- a/src/screens/PlayerSettingsScreen.tsx
+++ b/src/screens/PlayerSettingsScreen.tsx
@@ -261,180 +261,7 @@ const PlayerSettingsScreen: React.FC = () => {
},
]}
>
-
-
-
-
-
-
-
- {t('player.autoplay_title')}
-
-
- {t('player.autoplay_desc')}
-
-
- updateSetting('autoplayBestStream', value)}
- trackColor={{ false: '#767577', true: currentTheme.colors.primary }}
- thumbColor={settings.autoplayBestStream ? '#ffffff' : '#f4f3f4'}
- ios_backgroundColor="#3e3e3e"
- />
-
-
-
- {/* Preferred Quality for Autoplay */}
-
-
-
-
-
-
-
- {t('player.preferred_quality_title') || 'Preferred Quality'}
-
-
- {t('player.preferred_quality_desc') || 'Select preferred quality for autoplay'}
-
-
-
-
- {([
- { id: '4K', label: '4K' },
- { id: '1080p', label: '1080p' },
- { id: '720p', label: '720p' },
- { id: '480p', label: '480p' },
- ] as const).map((option) => (
- updateSetting('autoplayPreferredQuality', option.id)}
- style={[
- styles.optionButton,
- settings.autoplayPreferredQuality === option.id && { backgroundColor: currentTheme.colors.primary },
- ]}
- >
-
- {option.label}
-
-
- ))}
-
-
-
- {/* Preferred Language for Autoplay */}
-
-
-
-
-
-
-
- {t('player.preferred_language_title') || 'Preferred Language'}
-
-
- {t('player.preferred_language_desc') || 'Select preferred language for autoplay'}
-
-
-
-
- {([
- { 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) => (
- updateSetting('autoplayPreferredLanguage', option.id)}
- style={[
- styles.optionButton,
- styles.optionButtonLanguage,
- settings.autoplayPreferredLanguage === option.id && { backgroundColor: currentTheme.colors.primary },
- ]}
- >
-
- {option.label}
-
-
- ))}
-
-
-
- {/* Video Player Engine for Android */}
+ {/* Video Player Engine for Android */}
{Platform.OS === 'android' && !settings.useExternalPlayer && (
<>
diff --git a/src/screens/settings/PlaybackSettingsScreen.tsx b/src/screens/settings/PlaybackSettingsScreen.tsx
index c3559e3c..8118cb8f 100644
--- a/src/screens/settings/PlaybackSettingsScreen.tsx
+++ b/src/screens/settings/PlaybackSettingsScreen.tsx
@@ -62,6 +62,19 @@ const SUBTITLE_SOURCE_OPTIONS = [
{ 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
interface PlaybackSettingsContentProps {
isTablet?: boolean;
@@ -151,30 +164,55 @@ export const PlaybackSettingsContent: React.FC = (
const audioLanguageSheetRef = useRef(null);
const subtitleLanguageSheetRef = useRef(null);
const subtitleSourceSheetRef = useRef(null);
+ const autoplayQualitySheetRef = useRef(null);
+ const autoplayLanguageSheetRef = useRef(null);
// Snap points
const languageSnapPoints = useMemo(() => ['70%'], []);
const sourceSnapPoints = useMemo(() => ['45%'], []);
+ const qualitySnapPoints = useMemo(() => ['45%'], []);
// Handlers to present sheets - ensure only one is open at a time
const openAudioLanguageSheet = useCallback(() => {
subtitleLanguageSheetRef.current?.dismiss();
subtitleSourceSheetRef.current?.dismiss();
+ autoplayQualitySheetRef.current?.dismiss();
+ autoplayLanguageSheetRef.current?.dismiss();
setTimeout(() => audioLanguageSheetRef.current?.present(), 100);
}, []);
const openSubtitleLanguageSheet = useCallback(() => {
audioLanguageSheetRef.current?.dismiss();
subtitleSourceSheetRef.current?.dismiss();
+ autoplayQualitySheetRef.current?.dismiss();
+ autoplayLanguageSheetRef.current?.dismiss();
setTimeout(() => subtitleLanguageSheetRef.current?.present(), 100);
}, []);
const openSubtitleSourceSheet = useCallback(() => {
audioLanguageSheetRef.current?.dismiss();
subtitleLanguageSheetRef.current?.dismiss();
+ autoplayQualitySheetRef.current?.dismiss();
+ autoplayLanguageSheetRef.current?.dismiss();
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) => {
if (!config?.items) return true;
const item = config.items[itemId];
@@ -226,6 +264,16 @@ export const PlaybackSettingsContent: React.FC = (
subtitleSourceSheetRef.current?.dismiss();
};
+ const handleSelectAutoplayQuality = (quality: string) => {
+ updateSetting('autoplayPreferredQuality', quality);
+ autoplayQualitySheetRef.current?.dismiss();
+ };
+
+ const handleSelectAutoplayLanguage = (language: string) => {
+ updateSetting('autoplayPreferredLanguage', language);
+ autoplayLanguageSheetRef.current?.dismiss();
+ };
+
return (
<>
{hasVisibleItems(['video_player']) && (
@@ -248,6 +296,38 @@ export const PlaybackSettingsContent: React.FC = (
)}
+ (
+ updateSetting('autoplayBestStream', value)}
+ />
+ )}
+ isTablet={isTablet}
+ />
+ {settings?.autoplayBestStream && (
+ <>
+ }
+ onPress={openAutoplayQualitySheet}
+ isTablet={isTablet}
+ />
+ }
+ onPress={openAutoplayLanguageSheet}
+ isTablet={isTablet}
+ />
+ >
+ )}
= (
})}
+
+ {/* Autoplay Quality Bottom Sheet */}
+
+
+ {t('player.preferred_quality_title')}
+
+
+ {AUTOPLAY_QUALITY_OPTIONS.map((option) => {
+ const isSelected = option.id === (settings?.autoplayPreferredQuality || '1080p');
+ return (
+ handleSelectAutoplayQuality(option.id)}
+ >
+
+ {option.label}
+
+ {isSelected && (
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* Autoplay Language Bottom Sheet */}
+
+
+ {t('player.preferred_language_title')}
+
+
+ {[
+ { 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 (
+ handleSelectAutoplayLanguage(option.id)}
+ >
+
+ {option.label}
+
+ {isSelected && (
+
+ )}
+
+ );
+ })}
+
+
>
);
};
diff --git a/src/screens/streams/useStreamsScreen.ts b/src/screens/streams/useStreamsScreen.ts
index 396228fe..0e88faa0 100644
--- a/src/screens/streams/useStreamsScreen.ts
+++ b/src/screens/streams/useStreamsScreen.ts
@@ -22,6 +22,7 @@ import { TABLET_BREAKPOINT } from './constants';
import {
filterStreamsByQuality,
filterStreamsByLanguage,
+ getLanguageVariations,
getQualityNumeric,
inferVideoTypeFromUrl,
sortStreamsByQuality,
@@ -254,13 +255,20 @@ export const useStreamsScreen = () => {
let languageMatchedStreams = allStreams;
if (preferredLanguage && preferredLanguage !== 'Any') {
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 prefLang = preferredLanguage.toLowerCase();
- // Match by name if lang is not set, or match by lang property
- return streamLang === prefLang ||
- (item.stream.name || '').toLowerCase().includes(prefLang) ||
- (item.stream.title || '').toLowerCase().includes(prefLang) ||
- (item.stream.description || '').toLowerCase().includes(prefLang);
+
+ const variations = getLanguageVariations(preferredLanguage);
+
+ return variations.some(variant => {
+ const variantLower = variant.toLowerCase();
+ return streamLang === variantLower ||
+ streamName.includes(variantLower) ||
+ streamTitle.includes(variantLower) ||
+ streamDesc.includes(variantLower);
+ });
});
}