diff --git a/src/components/home/CatalogSection.tsx b/src/components/home/CatalogSection.tsx index 70606c51..6bd96683 100644 --- a/src/components/home/CatalogSection.tsx +++ b/src/components/home/CatalogSection.tsx @@ -7,6 +7,7 @@ import { LinearGradient } from 'expo-linear-gradient'; import { CatalogContent, StreamingContent } from '../../services/catalogService'; import { useTheme } from '../../contexts/ThemeContext'; import ContentItem from './ContentItem'; +import Animated, { FadeIn } from 'react-native-reanimated'; import { RootStackParamList } from '../../navigation/AppNavigator'; interface CatalogSectionProps { @@ -76,7 +77,7 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => { const keyExtractor = useCallback((item: StreamingContent) => `${item.id}-${item.type}`, []); return ( - + {catalog.name} @@ -109,7 +110,7 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => { onEndReached={() => {}} scrollEventThrottle={16} /> - + ); }; diff --git a/src/components/home/ContinueWatchingSection.tsx b/src/components/home/ContinueWatchingSection.tsx index 76433535..a4092161 100644 --- a/src/components/home/ContinueWatchingSection.tsx +++ b/src/components/home/ContinueWatchingSection.tsx @@ -11,7 +11,7 @@ import { ActivityIndicator } from 'react-native'; import { FlashList } from '@shopify/flash-list'; -import Animated from 'react-native-reanimated'; +import Animated, { FadeIn } from 'react-native-reanimated'; import { useNavigation } from '@react-navigation/native'; import { NavigationProp } from '@react-navigation/native'; import { RootStackParamList } from '../../navigation/AppNavigator'; @@ -509,7 +509,7 @@ const ContinueWatchingSection = React.forwardRef((props, re } return ( - + Continue Watching @@ -632,7 +632,7 @@ const ContinueWatchingSection = React.forwardRef((props, re onEndReachedThreshold={0.7} onEndReached={() => {}} /> - + ); }); diff --git a/src/components/home/ThisWeekSection.tsx b/src/components/home/ThisWeekSection.tsx index d5b62415..2f7f619a 100644 --- a/src/components/home/ThisWeekSection.tsx +++ b/src/components/home/ThisWeekSection.tsx @@ -20,7 +20,7 @@ import { tmdbService } from '../../services/tmdbService'; import { useLibrary } from '../../hooks/useLibrary'; import { RootStackParamList } from '../../navigation/AppNavigator'; import { parseISO, isThisWeek, format, isAfter, isBefore } from 'date-fns'; -import Animated from 'react-native-reanimated'; +import Animated, { FadeIn } from 'react-native-reanimated'; import { useCalendarData } from '../../hooks/useCalendarData'; const { width } = Dimensions.get('window'); @@ -179,7 +179,7 @@ export const ThisWeekSection = React.memo(() => { }; return ( - + This Week @@ -203,7 +203,7 @@ export const ThisWeekSection = React.memo(() => { snapToAlignment="start" ItemSeparatorComponent={() => } /> - + ); }); diff --git a/src/components/metadata/SeriesContent.tsx b/src/components/metadata/SeriesContent.tsx index 6d0137b0..0858441e 100644 --- a/src/components/metadata/SeriesContent.tsx +++ b/src/components/metadata/SeriesContent.tsx @@ -654,7 +654,6 @@ export const SeriesContent: React.FC = ({ data={currentSeasonEpisodes} renderItem={({ item: episode, index }) => ( = ({ horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={isTablet ? styles.episodeListContentHorizontalTablet : styles.episodeListContentHorizontal} + estimatedItemSize={(isTablet ? width * 0.4 : width * 0.75) + (isTablet ? 20 : 16)} + overrideItemLayout={(layout, _item, _index) => { + const cardWidth = isTablet ? width * 0.4 : width * 0.75; + const margin = isTablet ? 20 : 16; + layout.size = cardWidth + margin; + layout.span = 1; + }} + removeClippedSubviews /> ) : ( // Vertical Layout (Traditional) @@ -676,7 +683,6 @@ export const SeriesContent: React.FC = ({ data={currentSeasonEpisodes} renderItem={({ item: episode, index }) => ( {renderVerticalEpisodeCard(episode)} @@ -684,6 +690,14 @@ export const SeriesContent: React.FC = ({ )} keyExtractor={episode => episode.id.toString()} contentContainerStyle={isTablet ? styles.episodeListContentVerticalTablet : styles.episodeListContentVertical} + estimatedItemSize={isTablet ? 160 + 16 : 120 + 16} + overrideItemLayout={(layout, _item, _index) => { + // height along main axis for vertical list + const itemHeight = (isTablet ? 160 : 120) + 16; // card height + marginBottom + layout.size = itemHeight; + layout.span = 1; + }} + removeClippedSubviews /> ) )} diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 9861a4b3..81c9736a 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -621,19 +621,22 @@ const HomeScreen = () => { const memoizedThisWeekSection = useMemo(() => , []); const memoizedContinueWatchingSection = useMemo(() => , []); - const renderListItem = useCallback(({ item }: { item: HomeScreenListItem }) => { + const renderListItem = useCallback(({ item, index }: { item: HomeScreenListItem, index: number }) => { + const wrapper = (child: React.ReactNode) => ( + + {child} + + ); switch (item.type) { // featured is rendered via ListHeaderComponent to avoid remounts case 'thisWeek': - return memoizedThisWeekSection; + return wrapper(memoizedThisWeekSection); case 'continueWatching': - return memoizedContinueWatchingSection; + return wrapper(memoizedContinueWatchingSection); case 'catalog': - return ( - - ); + return wrapper(); case 'placeholder': - return ( + return wrapper( @@ -669,7 +672,7 @@ const HomeScreen = () => { ); case 'welcome': - return ; + return wrapper(); default: return null; }