Enhance StreamsScreen loading state management and provider status updates

This update improves the loading state management in the StreamsScreen component by refining how loading cycles are tracked and provider statuses are updated. It introduces a more dynamic approach to handling expected providers, ensuring accurate loading indicators and success/error messages based on the availability of streams. Additionally, a helper function for sorting stream quality has been added, enhancing the user experience when selecting streams. Overall, these changes contribute to a more robust and user-friendly streaming experience.
This commit is contained in:
tapframe 2025-05-27 21:21:48 +05:30
parent 5751d755db
commit a4b09e6afe

View file

@ -267,41 +267,108 @@ export const StreamsScreen = () => {
}
}>({});
// Monitor streams loading start
// Monitor streams loading start and completion
useEffect(() => {
const now = Date.now();
// Define all providers you expect to load. This could be dynamic.
const expectedProviders = ['stremio', 'hdrezka'];
if (loadingStreams || loadingEpisodeStreams) {
logger.log("⏱️ Stream loading started");
const now = Date.now();
setLoadStartTime(now);
setProviderLoadTimes({});
// --- Stream Loading has STARTED or is IN PROGRESS ---
logger.log("⏱️ Stream loading started or in progress...");
// Reset provider status - include HDRezka
setProviderStatus({
'stremio': {
loading: true,
success: false,
error: false,
message: 'Loading...',
timeStarted: now,
timeCompleted: 0
},
'hdrezka': {
loading: true,
success: false,
error: false,
message: 'Loading...',
timeStarted: now,
timeCompleted: 0
}
});
// Set load start time only if this is the beginning of a new loading cycle
if (loadStartTime === 0) {
setLoadStartTime(now);
}
// Also update the simpler loading state - include HDRezka
setLoadingProviders({
'stremio': true,
'hdrezka': true
setProviderLoadTimes({}); // Reset individual provider load times tracker
// Update provider status to loading for all expected providers
setProviderStatus(prevStatus => {
const newStatus = { ...prevStatus };
expectedProviders.forEach(providerId => {
// If not already marked as loading, or if it's a fresh cycle, set to loading
if (!newStatus[providerId] || !newStatus[providerId].loading || loadStartTime === 0) {
newStatus[providerId] = {
loading: true,
success: false,
error: false,
message: 'Loading...',
timeStarted: (newStatus[providerId]?.loading && newStatus[providerId]?.timeStarted) ? newStatus[providerId].timeStarted : now,
timeCompleted: 0,
};
}
});
return newStatus;
});
// Update simple loading flag for all expected providers
setLoadingProviders(prevLoading => {
const newLoading = { ...prevLoading };
expectedProviders.forEach(providerId => {
newLoading[providerId] = true;
});
return newLoading;
});
} else if (loadStartTime > 0) {
// --- Stream Loading has FINISHED ---
// (loadStartTime > 0 implies a loading cycle was active and has now completed)
logger.log("🏁 Stream loading finished. Processing results.");
const currentStreamsData = type === 'series' ? episodeStreams : groupedStreams;
// Update simple loading flag: all expected providers are no longer loading
setLoadingProviders(prevLoading => {
const newLoading = { ...prevLoading };
expectedProviders.forEach(providerId => {
newLoading[providerId] = false;
});
return newLoading;
});
// Update detailed provider status based on results
setProviderStatus(prevStatus => {
const newStatus = { ...prevStatus };
expectedProviders.forEach(providerId => {
if (newStatus[providerId]) { // Ensure the provider entry exists
const providerHasStreams = currentStreamsData[providerId] &&
currentStreamsData[providerId].streams &&
currentStreamsData[providerId].streams.length > 0;
newStatus[providerId] = {
...newStatus[providerId], // Preserve timeStarted
loading: false,
success: providerHasStreams,
// Mark error if it was loading and now no streams, and wasn't already successful
error: !providerHasStreams && newStatus[providerId].loading && !newStatus[providerId].success,
message: providerHasStreams ? 'Loaded successfully' : (newStatus[providerId].error ? 'Error or no streams' : 'No streams found'),
timeCompleted: now,
};
} else {
// Fallback if somehow not initialized (should be caught by loading phase)
newStatus[providerId] = {
loading: false,
success: false,
error: true,
message: 'Provider status error (not initialized)',
timeStarted: 0,
timeCompleted: now,
};
}
});
return newStatus;
});
// Update the set of available providers based on what actually loaded streams
const providersWithStreams = new Set(Object.keys(currentStreamsData));
setAvailableProviders(providersWithStreams);
// Reset loadStartTime to signify the end of this loading cycle
setLoadStartTime(0);
}
}, [loadingStreams, loadingEpisodeStreams]);
}, [loadingStreams, loadingEpisodeStreams, groupedStreams, episodeStreams, type /* loadStartTime is intentionally omitted from deps here */]);
React.useEffect(() => {
if (type === 'series' && episodeId) {
@ -314,20 +381,14 @@ export const StreamsScreen = () => {
loadEpisodeStreams(episodeId);
} else if (type === 'movie') {
logger.log(`🎬 Loading movie streams for: ${id}`);
setLoadingProviders({
'stremio': true,
'hdrezka': true
});
// setLoadingProviders({ // This is now handled by the main effect
// 'stremio': true,
// 'hdrezka': true
// });
loadStreams();
}
}, [type, episodeId]);
React.useEffect(() => {
const streams = type === 'series' ? episodeStreams : groupedStreams;
const providers = new Set(Object.keys(streams));
setAvailableProviders(providers);
}, [type, groupedStreams, episodeStreams]);
React.useEffect(() => {
// Trigger entrance animations
headerOpacity.value = withTiming(1, { duration: 400 });
@ -609,6 +670,13 @@ export const StreamsScreen = () => {
const streams = type === 'series' ? episodeStreams : groupedStreams;
const installedAddons = stremioService.getInstalledAddons();
// Helper function to extract quality as a number for sorting
const getQualityNumeric = (title: string | undefined): number => {
if (!title) return 0;
const match = title.match(/(\d+)p/);
return match ? parseInt(match[1], 10) : 0;
};
// Filter streams by selected provider - only if not "all"
const filteredEntries = Object.entries(streams)
.filter(([addonId]) => {
@ -633,11 +701,21 @@ export const StreamsScreen = () => {
if (indexB !== -1) return 1;
return 0;
})
.map(([addonId, { addonName, streams }]) => ({
title: addonName,
addonId,
data: streams
}));
.map(([addonId, { addonName, streams: providerStreams }]) => {
let sortedProviderStreams = providerStreams;
if (addonId === 'hdrezka') {
sortedProviderStreams = [...providerStreams].sort((a, b) => {
const qualityA = getQualityNumeric(a.title);
const qualityB = getQualityNumeric(b.title);
return qualityB - qualityA; // Sort descending (e.g., 1080p before 720p)
});
}
return {
title: addonName,
addonId,
data: sortedProviderStreams
};
});
return filteredEntries;
}, [selectedProvider, type, episodeStreams, groupedStreams]);