From b5b61d05f8eca4eda4e44baa0d96fa8471a866eb Mon Sep 17 00:00:00 2001 From: tapframe Date: Wed, 8 Oct 2025 16:53:56 +0530 Subject: [PATCH] ui changes --- src/screens/SearchScreen.tsx | 306 +++++++++++++++++++---------------- 1 file changed, 164 insertions(+), 142 deletions(-) diff --git a/src/screens/SearchScreen.tsx b/src/screens/SearchScreen.tsx index fc116c5a..13b623af 100644 --- a/src/screens/SearchScreen.tsx +++ b/src/screens/SearchScreen.tsx @@ -381,27 +381,41 @@ const SearchScreen = () => { } catch {} const handle = catalogService.startLiveSearch(searchQuery, async (section: AddonSearchResults) => { - // Append/update this addon section immediately + // Append/update this addon section immediately with minimal changes setResults(prev => { - const existingIndex = prev.byAddon.findIndex(s => s.addonId === section.addonId); - let nextByAddon: AddonSearchResults[]; - if (existingIndex >= 0) { - nextByAddon = prev.byAddon.slice(); - nextByAddon[existingIndex] = section; - } else { - nextByAddon = [...prev.byAddon, section]; - } - // Sort by installation order const rank = addonOrderRankRef.current; - nextByAddon = nextByAddon.slice().sort((a, b) => { - const ra = rank[a.addonId] ?? Number.MAX_SAFE_INTEGER; - const rb = rank[b.addonId] ?? Number.MAX_SAFE_INTEGER; - return ra - rb; - }); + const getRank = (id: string) => rank[id] ?? Number.MAX_SAFE_INTEGER; + + const existingIndex = prev.byAddon.findIndex(s => s.addonId === section.addonId); + + if (existingIndex >= 0) { + // Update existing section in-place (preserve order and other sections) + const copy = prev.byAddon.slice(); + copy[existingIndex] = section; + return { byAddon: copy, allResults: prev.allResults }; + } + + // Insert new section at correct position based on rank + const insertRank = getRank(section.addonId); + let insertAt = prev.byAddon.length; + for (let i = 0; i < prev.byAddon.length; i++) { + if (getRank(prev.byAddon[i].addonId) > insertRank) { + insertAt = i; + break; + } + } + + const nextByAddon = [ + ...prev.byAddon.slice(0, insertAt), + section, + ...prev.byAddon.slice(insertAt) + ]; + // Hide loading overlay once first section arrives - if (nextByAddon.length === 1) { + if (prev.byAddon.length === 0) { setSearching(false); } + return { byAddon: nextByAddon, allResults: prev.allResults }; }); @@ -601,6 +615,131 @@ const SearchScreen = () => { return results.byAddon.length > 0; }, [results]); + // Memoized addon section to prevent re-rendering unchanged sections + const AddonSection = React.memo(({ + addonGroup, + addonIndex + }: { + addonGroup: AddonSearchResults; + addonIndex: number; + }) => { + const movieResults = useMemo(() => + addonGroup.results.filter(item => item.type === 'movie'), + [addonGroup.results] + ); + const seriesResults = useMemo(() => + addonGroup.results.filter(item => item.type === 'series'), + [addonGroup.results] + ); + const otherResults = useMemo(() => + addonGroup.results.filter(item => item.type !== 'movie' && item.type !== 'series'), + [addonGroup.results] + ); + + return ( + + {/* Addon Header */} + + + {addonGroup.addonName} + + + + {addonGroup.results.length} + + + + + {/* Movies */} + {movieResults.length > 0 && ( + + + Movies ({movieResults.length}) + + ( + + )} + keyExtractor={item => `${addonGroup.addonId}-movie-${item.id}`} + horizontal + showsHorizontalScrollIndicator={false} + contentContainerStyle={styles.horizontalListContent} + extraData={refreshFlag} + /> + + )} + + {/* TV Shows */} + {seriesResults.length > 0 && ( + + + TV Shows ({seriesResults.length}) + + ( + + )} + keyExtractor={item => `${addonGroup.addonId}-series-${item.id}`} + horizontal + showsHorizontalScrollIndicator={false} + contentContainerStyle={styles.horizontalListContent} + extraData={refreshFlag} + /> + + )} + + {/* Other types */} + {otherResults.length > 0 && ( + + + {otherResults[0].type.charAt(0).toUpperCase() + otherResults[0].type.slice(1)} ({otherResults.length}) + + ( + + )} + keyExtractor={item => `${addonGroup.addonId}-${item.type}-${item.id}`} + horizontal + showsHorizontalScrollIndicator={false} + contentContainerStyle={styles.horizontalListContent} + extraData={refreshFlag} + /> + + )} + + ); + }, (prev, next) => { + // Only re-render if this section's reference changed + return prev.addonGroup === next.addonGroup && prev.addonIndex === next.addonIndex; + }); + const headerBaseHeight = Platform.OS === 'android' ? 80 : 60; const topSpacing = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top; const headerHeight = headerBaseHeight + topSpacing + 60; @@ -741,131 +880,14 @@ const SearchScreen = () => { showsVerticalScrollIndicator={false} > {!query.trim() && renderRecentSearches()} - {/* Render results grouped by addon */} - {results.byAddon.map((addonGroup, addonIndex) => { - // Group by type within each addon - const movieResults = addonGroup.results.filter(item => item.type === 'movie'); - const seriesResults = addonGroup.results.filter(item => item.type === 'series'); - const otherResults = addonGroup.results.filter(item => item.type !== 'movie' && item.type !== 'series'); - - return ( - - {/* Addon Header */} - - - - {addonGroup.addonName} - - - - {addonGroup.results.length} - - - - - {/* Movies from this addon */} - {movieResults.length > 0 && ( - - - Movies ({movieResults.length}) - - ( - - )} - keyExtractor={item => `${addonGroup.addonId}-movie-${item.id}`} - horizontal - showsHorizontalScrollIndicator={false} - contentContainerStyle={styles.horizontalListContent} - extraData={refreshFlag} - /> - - )} - - {/* TV Shows from this addon */} - {seriesResults.length > 0 && ( - - - TV Shows ({seriesResults.length}) - - ( - - )} - keyExtractor={item => `${addonGroup.addonId}-series-${item.id}`} - horizontal - showsHorizontalScrollIndicator={false} - contentContainerStyle={styles.horizontalListContent} - extraData={refreshFlag} - /> - - )} - - {/* Other content types (anime, etc.) */} - {otherResults.length > 0 && ( - - - {otherResults[0].type.charAt(0).toUpperCase() + otherResults[0].type.slice(1)} ({otherResults.length}) - - ( - - )} - keyExtractor={item => `${addonGroup.addonId}-${item.type}-${item.id}`} - horizontal - showsHorizontalScrollIndicator={false} - contentContainerStyle={styles.horizontalListContent} - extraData={refreshFlag} - /> - - )} - - ); - })} + {/* Render results grouped by addon using memoized component */} + {results.byAddon.map((addonGroup, addonIndex) => ( + + ))} )} @@ -1015,7 +1037,7 @@ const styles = StyleSheet.create({ borderBottomColor: 'rgba(255,255,255,0.1)', }, addonHeaderIcon: { - marginRight: 8, + // removed icon }, addonHeaderText: { fontSize: isTablet ? 18 : 16,