Stability improvement on catalogsection

This commit is contained in:
tapframe 2025-09-29 14:55:22 +05:30
parent f86e6256a7
commit ebb7d4cec6
2 changed files with 8 additions and 25 deletions

View file

@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useMemo, useRef } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Platform, Dimensions } from 'react-native';
import { FlashList } from '@shopify/flash-list';
import { NavigationProp, useNavigation } from '@react-navigation/native';
@ -56,32 +56,19 @@ const POSTER_WIDTH = posterLayout.posterWidth;
const CatalogSection = ({ catalog }: CatalogSectionProps) => {
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const { currentTheme } = useTheme();
// Simplified visibility tracking - just load all images immediately for better performance
const [hasLoaded, setHasLoaded] = useState(false);
// Load all images after a short delay to prevent blocking initial render
React.useEffect(() => {
const timer = setTimeout(() => {
setHasLoaded(true);
}, 100);
return () => clearTimeout(timer);
}, []);
const handleContentPress = useCallback((id: string, type: string) => {
navigation.navigate('Metadata', { id, type, addonId: catalog.addon });
}, [navigation, catalog.addon]);
const renderContentItem = useCallback(({ item, index }: { item: StreamingContent, index: number }) => {
// Load images immediately for better scrolling performance
const renderContentItem = useCallback(({ item }: { item: StreamingContent, index: number }) => {
return (
<ContentItem
item={item}
onPress={handleContentPress}
shouldLoadImage={hasLoaded}
deferMs={index * 10} // Small stagger to prevent blocking
/>
);
}, [handleContentPress, hasLoaded]);
}, [handleContentPress]);
// Memoize the ItemSeparatorComponent to prevent re-creation
const ItemSeparator = useCallback(() => <View style={{ width: 8 }} />, []);

View file

@ -152,15 +152,10 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
return item.poster;
}, [item.poster, retryCount, item.id]);
// Smoothly fade in content when settings are ready
// Avoid strong fade animations that can appear as flicker on mount/scroll
useEffect(() => {
if (isLoaded) {
fadeInOpacity.setValue(0);
Animated.timing(fadeInOpacity, {
toValue: 1,
duration: 180,
useNativeDriver: true,
}).start();
fadeInOpacity.setValue(1);
}
}, [isLoaded, fadeInOpacity]);
@ -196,14 +191,14 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
delayLongPress={300}
>
<View ref={itemRef} style={[styles.contentItemContainer, { borderRadius: posterRadius }] }>
{/* Always load image for horizontal scrolling to prevent blank posters */}
{/* Image with lightweight placeholder to reduce flicker */}
{item.poster ? (
<ExpoImage
source={{ uri: optimizedPosterUrl }}
style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, borderRadius: posterRadius }]}
contentFit="cover"
cachePolicy={Platform.OS === 'android' ? 'disk' : 'memory-disk'}
transition={100} // Faster transition for scrolling
transition={0}
allowDownscaling
priority="normal" // Normal priority for horizontal scrolling
onLoad={() => {
@ -222,6 +217,7 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
setImageLoaded(false);
}}
recyclingKey={item.id} // Add recycling key for better performance
placeholder={PLACEHOLDER_BLURHASH}
/>
) : (
// Show placeholder for items without posters