fix: fixed autoplay stream

This commit is contained in:
tapframe 2026-01-09 16:46:46 +05:30
parent 031c0c8772
commit 01a041aebf
10 changed files with 72 additions and 84 deletions

View file

@ -1604,22 +1604,26 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
});
// Add local scrapers if enabled
localScrapers.filter((scraper: ScraperInfo) => scraper.enabled).forEach((scraper: ScraperInfo) => {
initialStatuses.push({
id: scraper.id,
name: scraper.name,
isLoading: true,
hasCompleted: false,
error: null,
startTime: Date.now(),
endTime: null
const currentSettings = await mmkvStorage.getItem('app_settings');
const enableLocalScrapersNow = currentSettings ? JSON.parse(currentSettings).enableLocalScrapers !== false : true;
if (enableLocalScrapersNow) {
localScrapers.filter((scraper: ScraperInfo) => scraper.enabled).forEach((scraper: ScraperInfo) => {
initialStatuses.push({
id: scraper.id,
name: scraper.name,
isLoading: true,
hasCompleted: false,
error: null,
startTime: Date.now(),
endTime: null
});
initialActiveFetching.push(scraper.name);
});
initialActiveFetching.push(scraper.name);
});
}
setScraperStatuses(initialStatuses);
setActiveFetchingScrapers(initialActiveFetching);
console.log('🔍 [loadStreams] Initialized activeFetchingScrapers:', initialActiveFetching);
// If no scrapers are available, stop loading immediately
if (initialStatuses.length === 0) {
@ -1740,23 +1744,27 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
initialActiveFetching.push(addon.name);
});
// Add local scrapers if enabled
localScrapers.filter((scraper: ScraperInfo) => scraper.enabled).forEach((scraper: ScraperInfo) => {
initialStatuses.push({
id: scraper.id,
name: scraper.name,
isLoading: true,
hasCompleted: false,
error: null,
startTime: Date.now(),
endTime: null
// Add local scrapers if enabled (read from storage to avoid stale closure)
const currentSettings = await mmkvStorage.getItem('app_settings');
const enableLocalScrapersNow = currentSettings ? JSON.parse(currentSettings).enableLocalScrapers !== false : true;
if (enableLocalScrapersNow) {
localScrapers.filter((scraper: ScraperInfo) => scraper.enabled).forEach((scraper: ScraperInfo) => {
initialStatuses.push({
id: scraper.id,
name: scraper.name,
isLoading: true,
hasCompleted: false,
error: null,
startTime: Date.now(),
endTime: null
});
initialActiveFetching.push(scraper.name);
});
initialActiveFetching.push(scraper.name);
});
}
setScraperStatuses(initialStatuses);
setActiveFetchingScrapers(initialActiveFetching);
console.log('🔍 [loadEpisodeStreams] Initialized activeFetchingScrapers:', initialActiveFetching);
// If no scrapers are available, stop loading immediately
if (initialStatuses.length === 0) {

View file

@ -1090,8 +1090,8 @@
"external_title": "مشغل خارجي",
"external_desc": "فتح البثوث في مشغل الفيديو المفضل لديك",
"section_playback": "خيارات التشغيل",
"autoplay_title": "تشغيل أفضل بث تلقائياً",
"autoplay_desc": "بدء أعلى جودة بث متاحة تلقائياً.",
"autoplay_title": "تشغيل أول بث تلقائياً",
"autoplay_desc": "بدء أول بث معروض في القائمة تلقائياً.",
"resume_title": "استكمال دائماً",
"resume_desc": "تخطي مطالبة الاستكمال والمتابعة تلقائياً من حيث توقفت (إذا تمت مشاهدة أقل من 85%).",
"engine_title": "محرك مشغل الفيديو",

View file

@ -1093,8 +1093,8 @@
"external_title": "External Player",
"external_desc": "Open streams in your preferred video player",
"section_playback": "PLAYBACK OPTIONS",
"autoplay_title": "Auto-play Best Stream",
"autoplay_desc": "Automatically start the highest quality stream available.",
"autoplay_title": "Auto-play First Stream",
"autoplay_desc": "Automatically start the first stream shown in the list.",
"resume_title": "Always Resume",
"resume_desc": "Skip the resume prompt and automatically continue where you left off (if less than 85% watched).",
"engine_title": "Video Player Engine",

View file

@ -1090,8 +1090,8 @@
"external_title": "Reproductor externo",
"external_desc": "Abrir fuentes en tu reproductor de video preferido",
"section_playback": "OPCIONES DE REPRODUCCIÓN",
"autoplay_title": "Autorreproducir la mejor fuente",
"autoplay_desc": "Iniciar automáticamente la fuente de mayor calidad disponible.",
"autoplay_title": "Autorreproducir la primera fuente",
"autoplay_desc": "Iniciar automáticamente la primera fuente mostrada en la lista.",
"resume_title": "Reanudar siempre",
"resume_desc": "Saltar el aviso de reanudar y continuar automáticamente donde lo dejaste (si se ha visto menos del 85%).",
"engine_title": "Motor del reproductor",

View file

@ -1090,8 +1090,8 @@
"external_title": "Lecteur externe",
"external_desc": "Ouvrir les flux dans votre lecteur vidéo préféré",
"section_playback": "OPTIONS DE LECTURE",
"autoplay_title": "Lecture automatique du meilleur flux",
"autoplay_desc": "Démarrer automatiquement le flux de la plus haute qualité disponible.",
"autoplay_title": "Lecture automatique du premier flux",
"autoplay_desc": "Démarrer automatiquement le premier flux affiché dans la liste.",
"resume_title": "Toujours reprendre",
"resume_desc": "Passer l'invite de reprise et continuer automatiquement là où vous vous étiez arrêté (si moins de 85% vus).",
"engine_title": "Moteur du lecteur vidéo",

View file

@ -1090,8 +1090,8 @@
"external_title": "Player Esterno",
"external_desc": "Apri gli stream nel tuo video player preferito",
"section_playback": "OPZIONI RIPRODUZIONE",
"autoplay_title": "Auto-play Miglior Stream",
"autoplay_desc": "Avvia automaticamente lo stream alla massima qualità disponibile.",
"autoplay_title": "Auto-play Primo Stream",
"autoplay_desc": "Avvia automaticamente il primo stream mostrato nella lista.",
"resume_title": "Riprendi Sempre",
"resume_desc": "Salta la richiesta di ripresa e continua automaticamente da dove avevi interrotto (se visto meno dell'85%).",
"engine_title": "Motore Video Player",

View file

@ -981,8 +981,8 @@
"external_title": "Player Externo",
"external_desc": "Abrir streams no seu player de vídeo preferido",
"section_playback": "OPÇÕES DE REPRODUÇÃO",
"autoplay_title": "Reprodução Automática (Melhor Stream)",
"autoplay_desc": "Iniciar automaticamente o stream de melhor qualidade disponível.",
"autoplay_title": "Reprodução Automática (Primeiro Stream)",
"autoplay_desc": "Iniciar automaticamente o primeiro stream mostrado na lista.",
"resume_title": "Sempre Retomar",
"resume_desc": "Pular o aviso de retomar e continuar automaticamente de onde parou (se assistido menos de 85%).",
"engine_title": "Motor do Player de Vídeo",

View file

@ -981,8 +981,8 @@
"external_title": "Reprodutor Externo",
"external_desc": "Abrir streams no teu reprodutor de vídeo preferido",
"section_playback": "OPÇÕES DE REPRODUÇÃO",
"autoplay_title": "Reprodução Automática (Melhor Stream)",
"autoplay_desc": "Iniciar automaticamente o stream de melhor qualidade disponível.",
"autoplay_title": "Reprodução Automática (Primeiro Stream)",
"autoplay_desc": "Iniciar automaticamente o primeiro stream mostrado na lista.",
"resume_title": "Sempre Retomar",
"resume_desc": "Saltar o aviso de retomar e continuar automaticamente de onde parou (se assistido menos de 85%).",
"engine_title": "Motor do reprodutor",

View file

@ -294,48 +294,14 @@ const PlayerSettingsScreen: React.FC = () => {
<Switch
value={settings.autoplayBestStream}
onValueChange={(value) => updateSetting('autoplayBestStream', value)}
thumbColor={settings.autoplayBestStream ? currentTheme.colors.primary : undefined}
trackColor={{ false: '#767577', true: currentTheme.colors.primary }}
thumbColor={settings.autoplayBestStream ? '#ffffff' : '#f4f3f4'}
ios_backgroundColor="#3e3e3e"
/>
</View>
</View>
<View style={styles.settingItem}>
<View style={styles.settingContent}>
<View style={[
styles.settingIconContainer,
{ backgroundColor: 'rgba(255,255,255,0.1)' }
]}>
<MaterialIcons
name="restore"
size={20}
color={currentTheme.colors.primary}
/>
</View>
<View style={styles.settingText}>
<Text
style={[
styles.settingTitle,
{ color: currentTheme.colors.text },
]}
>
{t('player.resume_title')}
</Text>
<Text
style={[
styles.settingDescription,
{ color: currentTheme.colors.textMuted },
]}
>
{t('player.resume_desc')}
</Text>
</View>
<Switch
value={settings.alwaysResume}
onValueChange={(value) => updateSetting('alwaysResume', value)}
thumbColor={settings.alwaysResume ? currentTheme.colors.primary : undefined}
/>
</View>
</View>
{/* Video Player Engine for Android */}
{Platform.OS === 'android' && !settings.useExternalPlayer && (

View file

@ -48,7 +48,7 @@ export const useStreamsScreen = () => {
const route = useRoute<RouteProp<RootStackParamList, 'Streams'>>();
const navigation = useNavigation<RootStackNavigationProp>();
const { id, type, episodeId, episodeThumbnail, fromPlayer } = route.params;
const { settings } = useSettings();
const { settings, isLoaded: settingsLoaded } = useSettings();
const { currentTheme } = useTheme();
const { colors } = currentTheme;
const { pauseTrailer, resumeTrailer } = useTrailer();
@ -586,6 +586,16 @@ export const useStreamsScreen = () => {
setAutoplayTriggered(false);
}, [selectedEpisode]);
// Initialize autoplay waiting state when settings are loaded
// This runs after settings are fully loaded to avoid race conditions
useEffect(() => {
if (!settingsLoaded) return; // Wait for settings to load
if (settings.autoplayBestStream && !fromPlayer && !autoplayTriggered) {
setIsAutoplayWaiting(true);
}
}, [settingsLoaded, settings.autoplayBestStream, fromPlayer, autoplayTriggered]);
// Reset provider if no longer available
useEffect(() => {
const isSpecialFilter =
@ -659,11 +669,7 @@ export const useStreamsScreen = () => {
}
setAutoplayTriggered(false);
if (settings.autoplayBestStream && !fromPlayer) {
setIsAutoplayWaiting(true);
} else {
setIsAutoplayWaiting(false);
}
// Note: isAutoplayWaiting is now handled by a separate effect that waits for settings to load
}
} finally {
isLoadingStreamsRef.current = false;
@ -678,6 +684,8 @@ export const useStreamsScreen = () => {
useEffect(() => {
if (settings.autoplayBestStream && !autoplayTriggered && isAutoplayWaiting) {
const streams = selectedEpisode ? episodeStreams : groupedStreams;
const hasLoadingStarted = streamsLoadStart !== null;
const isStillLoading = !hasLoadingStarted || loadingStreams || loadingEpisodeStreams || activeFetchingScrapers.length > 0;
if (Object.keys(streams).length > 0) {
const bestStream = getBestStream(streams);
@ -687,9 +695,11 @@ export const useStreamsScreen = () => {
setAutoplayTriggered(true);
setIsAutoplayWaiting(false);
handleStreamPress(bestStream);
} else {
} else if (!isStillLoading) {
setIsAutoplayWaiting(false);
}
} else if (!isStillLoading) {
setIsAutoplayWaiting(false);
}
}
}, [
@ -703,6 +713,10 @@ export const useStreamsScreen = () => {
handleStreamPress,
metadata,
selectedEpisode,
loadingStreams,
loadingEpisodeStreams,
activeFetchingScrapers.length,
streamsLoadStart,
]);
// Cleanup on unmount