mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
Refactor ContentItem and MetadataScreen for improved loading handling and UI consistency
This update removes unnecessary state management for image loading in the ContentItem component, streamlining the image display logic. In the MetadataScreen, loading states are now handled more effectively, ensuring a loading screen is shown when metadata is not ready. The overall structure has been simplified for better readability and maintainability.
This commit is contained in:
parent
8cbda5c902
commit
0e9426b6c6
2 changed files with 23 additions and 71 deletions
|
|
@ -53,8 +53,6 @@ const POSTER_WIDTH = posterLayout.posterWidth;
|
|||
const ContentItem = React.memo(({ item, onPress }: ContentItemProps) => {
|
||||
const [menuVisible, setMenuVisible] = useState(false);
|
||||
const [isWatched, setIsWatched] = useState(false);
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const [imageError, setImageError] = useState(false);
|
||||
const { currentTheme } = useTheme();
|
||||
|
||||
const handleLongPress = useCallback(() => {
|
||||
|
|
@ -108,25 +106,7 @@ const ContentItem = React.memo(({ item, onPress }: ContentItemProps) => {
|
|||
placeholder={{ uri: 'https://via.placeholder.com/300x450' }}
|
||||
placeholderContentFit="cover"
|
||||
recyclingKey={item.id}
|
||||
onLoadStart={() => {
|
||||
setImageLoaded(false);
|
||||
setImageError(false);
|
||||
}}
|
||||
onLoadEnd={() => setImageLoaded(true)}
|
||||
onError={() => {
|
||||
setImageError(true);
|
||||
setImageLoaded(true);
|
||||
}}
|
||||
/>
|
||||
{(!imageLoaded || imageError) && (
|
||||
<View style={[styles.loadingOverlay, { backgroundColor: currentTheme.colors.elevation2 }]}>
|
||||
{!imageError ? (
|
||||
<ActivityIndicator color={currentTheme.colors.primary} size="small" />
|
||||
) : (
|
||||
<MaterialIcons name="broken-image" size={24} color={currentTheme.colors.lightGray} />
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
{isWatched && (
|
||||
<View style={styles.watchedIndicator}>
|
||||
<MaterialIcons name="check-circle" size={22} color={currentTheme.colors.success} />
|
||||
|
|
|
|||
|
|
@ -281,6 +281,11 @@ const MetadataScreen: React.FC = () => {
|
|||
return ErrorComponent;
|
||||
}
|
||||
|
||||
// Show loading screen if metadata is not yet available
|
||||
if (loading || !isContentReady) {
|
||||
return <MetadataLoadingScreen type={type as 'movie' | 'series'} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={[containerStyle, styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}
|
||||
|
|
@ -352,64 +357,31 @@ const MetadataScreen: React.FC = () => {
|
|||
/>
|
||||
|
||||
{/* Cast Section with skeleton when loading */}
|
||||
{loadingCast ? (
|
||||
<View style={styles.skeletonSection}>
|
||||
<View style={[styles.skeletonTitle, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
<View style={styles.skeletonCastRow}>
|
||||
{[...Array(4)].map((_, index) => (
|
||||
<View key={index} style={[styles.skeletonCastItem, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<CastSection
|
||||
cast={cast}
|
||||
loadingCast={loadingCast}
|
||||
onSelectCastMember={handleSelectCastMember}
|
||||
/>
|
||||
)}
|
||||
<CastSection
|
||||
cast={cast}
|
||||
loadingCast={loadingCast}
|
||||
onSelectCastMember={handleSelectCastMember}
|
||||
/>
|
||||
|
||||
{/* Recommendations Section with skeleton when loading */}
|
||||
{type === 'movie' && (
|
||||
loadingRecommendations ? (
|
||||
<View style={styles.skeletonSection}>
|
||||
<View style={[styles.skeletonTitle, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
<View style={styles.skeletonRecommendationsRow}>
|
||||
{[...Array(3)].map((_, index) => (
|
||||
<View key={index} style={[styles.skeletonRecommendationItem, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<MoreLikeThisSection
|
||||
recommendations={recommendations}
|
||||
loadingRecommendations={loadingRecommendations}
|
||||
/>
|
||||
)
|
||||
<MoreLikeThisSection
|
||||
recommendations={recommendations}
|
||||
loadingRecommendations={loadingRecommendations}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Series/Movie Content with episode skeleton when loading */}
|
||||
{type === 'series' ? (
|
||||
(loadingSeasons || Object.keys(groupedEpisodes).length === 0) ? (
|
||||
<View style={styles.skeletonSection}>
|
||||
<View style={[styles.skeletonTitle, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
<View style={styles.skeletonEpisodesContainer}>
|
||||
{[...Array(6)].map((_, index) => (
|
||||
<View key={index} style={[styles.skeletonEpisodeItem, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<SeriesContent
|
||||
episodes={Object.values(groupedEpisodes).flat()}
|
||||
selectedSeason={selectedSeason}
|
||||
loadingSeasons={loadingSeasons}
|
||||
onSeasonChange={handleSeasonChangeWithHaptics}
|
||||
onSelectEpisode={handleEpisodeSelect}
|
||||
groupedEpisodes={groupedEpisodes}
|
||||
metadata={metadata || undefined}
|
||||
/>
|
||||
)
|
||||
<SeriesContent
|
||||
episodes={Object.values(groupedEpisodes).flat()}
|
||||
selectedSeason={selectedSeason}
|
||||
loadingSeasons={loadingSeasons}
|
||||
onSeasonChange={handleSeasonChangeWithHaptics}
|
||||
onSelectEpisode={handleEpisodeSelect}
|
||||
groupedEpisodes={groupedEpisodes}
|
||||
metadata={metadata || undefined}
|
||||
/>
|
||||
) : (
|
||||
metadata && <MovieContent metadata={metadata} />
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue