homescreen optomziation

This commit is contained in:
tapframe 2025-09-10 15:16:05 +05:30
parent ccde944bfa
commit 097073fcd3
3 changed files with 32 additions and 18 deletions

View file

@ -61,11 +61,15 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
navigation.navigate('Metadata', { id, type, addonId: catalog.addon });
}, [navigation, catalog.addon]);
const renderContentItem = useCallback(({ item }: { item: StreamingContent, index: number }) => {
const renderContentItem = useCallback(({ item, index }: { item: StreamingContent, index: number }) => {
// Only load images for the first few items eagerly; others defer based on viewability
const eager = index < 6;
return (
<ContentItem
item={item}
onPress={handleContentPress}
shouldLoadImage={eager}
deferMs={eager ? 0 : Math.min(400 + index * 15, 1500)}
/>
);
}, [handleContentPress]);
@ -108,8 +112,7 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
ItemSeparatorComponent={ItemSeparator}
onEndReachedThreshold={0.7}
onEndReached={() => {}}
scrollEventThrottle={16}
estimatedItemSize={POSTER_WIDTH + 8}
scrollEventThrottle={32}
/>
</Animated.View>
);

View file

@ -10,6 +10,8 @@ import { DropUpMenu } from './DropUpMenu';
interface ContentItemProps {
item: StreamingContent;
onPress: (id: string, type: string) => void;
shouldLoadImage?: boolean;
deferMs?: number;
}
const { width } = Dimensions.get('window');
@ -56,12 +58,12 @@ const POSTER_WIDTH = posterLayout.posterWidth;
const PLACEHOLDER_BLURHASH = 'LEHV6nWB2yk8pyo0adR*.7kCMdnj';
const ContentItem = ({ item, onPress }: ContentItemProps) => {
const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, deferMs = 0 }: ContentItemProps) => {
const [menuVisible, setMenuVisible] = useState(false);
const [isWatched, setIsWatched] = useState(false);
const [imageLoaded, setImageLoaded] = useState(false);
const [imageError, setImageError] = useState(false);
const [shouldLoadImage, setShouldLoadImage] = useState(false);
const [shouldLoadImageState, setShouldLoadImageState] = useState(false);
const [retryCount, setRetryCount] = useState(0);
const { currentTheme } = useTheme();
const { settings } = useSettings();
@ -111,14 +113,22 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
setMenuVisible(false);
}, []);
// Lazy load images - only load when likely to be visible
// Lazy load images - only load when asked by parent (viewability) or after small defer
useEffect(() => {
if (shouldLoadImageProp !== undefined) {
if (shouldLoadImageProp) {
const t = setTimeout(() => setShouldLoadImageState(true), deferMs);
return () => clearTimeout(t);
} else {
setShouldLoadImageState(false);
}
return;
}
const timer = setTimeout(() => {
setShouldLoadImage(true);
}, 50); // Reduced delay for faster loading
setShouldLoadImageState(true);
}, 80);
return () => clearTimeout(timer);
}, []);
}, [shouldLoadImageProp, deferMs]);
// Get optimized poster URL for smaller tiles
const getOptimizedPosterUrl = useCallback((originalUrl: string) => {
@ -158,12 +168,12 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
>
<View ref={itemRef} style={[styles.contentItemContainer, { borderRadius: posterRadius }] }>
{/* Only load image when shouldLoadImage is true (lazy loading) */}
{shouldLoadImage && item.poster ? (
{(shouldLoadImageProp ?? shouldLoadImageState) && item.poster ? (
<ExpoImage
source={{ uri: getOptimizedPosterUrl(item.poster) }}
style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, borderRadius: posterRadius }]}
contentFit="cover"
cachePolicy="memory-disk" // Use both memory and disk cache
cachePolicy={Platform.OS === 'android' ? 'disk' : 'memory-disk'}
transition={0} // Disable transition to reduce GPU work
placeholder={{ blurhash: PLACEHOLDER_BLURHASH } as any}
placeholderContentFit="cover"

View file

@ -158,7 +158,7 @@ const HomeScreen = () => {
let catalogIndex = 0;
// Limit concurrent catalog loading to prevent overwhelming the system
const MAX_CONCURRENT_CATALOGS = 1; // Single catalog at a time to minimize heating
const MAX_CONCURRENT_CATALOGS = 1; // Single catalog at a time to minimize heating/memory
let activeCatalogLoads = 0;
const catalogQueue: (() => Promise<void>)[] = [];
@ -196,8 +196,9 @@ const HomeScreen = () => {
const metas = await stremioService.getCatalog(manifest, catalog.type, catalog.id, 1);
if (metas && metas.length > 0) {
// Limit items per catalog to reduce memory usage
const limitedMetas = metas.slice(0, 30);
// Aggressively limit items per catalog on Android to reduce memory usage
const limit = Platform.OS === 'android' ? 18 : 30;
const limitedMetas = metas.slice(0, limit);
const items = limitedMetas.map((meta: any) => ({
id: meta.id,
@ -217,7 +218,7 @@ const HomeScreen = () => {
certification: meta.certification
}));
// Skip prefetching to reduce memory pressure
// Skip prefetching to reduce memory pressure (keep disabled)
// Resolve custom display name; if custom exists, use as-is
const originalName = catalog.name || catalog.id;
let displayName = await getCatalogDisplayName(addon.id, catalog.type, catalog.id, originalName);
@ -282,7 +283,7 @@ const HomeScreen = () => {
// Initialize catalogs array with proper length
setCatalogs(new Array(catalogIndex).fill(null));
// Start processing the catalog queue (parallel fetching continues in background)
// Start processing the catalog queue
processCatalogQueue();
} catch (error) {
if (__DEV__) console.error('[HomeScreen] Error in progressive catalog loading:', error);
@ -650,7 +651,7 @@ const HomeScreen = () => {
const renderListItem = useCallback(({ item, index }: { item: HomeScreenListItem, index: number }) => {
const wrapper = (child: React.ReactNode) => (
<Animated.View entering={FadeIn.duration(350).delay(Math.min(index * 70, 700))}>
<Animated.View>
{child}
</Animated.View>
);