mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
homescreen entrance animation improvement
This commit is contained in:
parent
ebf9a71430
commit
71a9042dc4
5 changed files with 36 additions and 18 deletions
|
|
@ -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 (
|
||||
<View style={styles.catalogContainer}>
|
||||
<Animated.View style={styles.catalogContainer} entering={FadeIn.duration(350)}>
|
||||
<View style={styles.catalogHeader}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={[styles.catalogTitle, { color: currentTheme.colors.text }]} numberOfLines={1}>{catalog.name}</Text>
|
||||
|
|
@ -109,7 +110,7 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
|
|||
onEndReached={() => {}}
|
||||
scrollEventThrottle={16}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ContinueWatchingRef>((props, re
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Animated.View style={styles.container} entering={FadeIn.duration(350)}>
|
||||
<View style={styles.header}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={[styles.title, { color: currentTheme.colors.text }]}>Continue Watching</Text>
|
||||
|
|
@ -632,7 +632,7 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
|
|||
onEndReachedThreshold={0.7}
|
||||
onEndReached={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<View style={styles.container}>
|
||||
<Animated.View style={styles.container} entering={FadeIn.duration(350)}>
|
||||
<View style={styles.header}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={[styles.title, { color: currentTheme.colors.text }]}>This Week</Text>
|
||||
|
|
@ -203,7 +203,7 @@ export const ThisWeekSection = React.memo(() => {
|
|||
snapToAlignment="start"
|
||||
ItemSeparatorComponent={() => <View style={{ width: 16 }} />}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -654,7 +654,6 @@ export const SeriesContent: React.FC<SeriesContentProps> = ({
|
|||
data={currentSeasonEpisodes}
|
||||
renderItem={({ item: episode, index }) => (
|
||||
<Animated.View
|
||||
key={episode.id}
|
||||
entering={FadeIn.duration(300).delay(100 + index * 30)}
|
||||
style={[
|
||||
styles.episodeCardWrapperHorizontal,
|
||||
|
|
@ -668,6 +667,14 @@ export const SeriesContent: React.FC<SeriesContentProps> = ({
|
|||
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<SeriesContentProps> = ({
|
|||
data={currentSeasonEpisodes}
|
||||
renderItem={({ item: episode, index }) => (
|
||||
<Animated.View
|
||||
key={episode.id}
|
||||
entering={FadeIn.duration(300).delay(100 + index * 30)}
|
||||
>
|
||||
{renderVerticalEpisodeCard(episode)}
|
||||
|
|
@ -684,6 +690,14 @@ export const SeriesContent: React.FC<SeriesContentProps> = ({
|
|||
)}
|
||||
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
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -621,19 +621,22 @@ const HomeScreen = () => {
|
|||
const memoizedThisWeekSection = useMemo(() => <ThisWeekSection />, []);
|
||||
const memoizedContinueWatchingSection = useMemo(() => <ContinueWatchingSection ref={continueWatchingRef} />, []);
|
||||
|
||||
const renderListItem = useCallback(({ item }: { item: HomeScreenListItem }) => {
|
||||
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))}>
|
||||
{child}
|
||||
</Animated.View>
|
||||
);
|
||||
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 (
|
||||
<CatalogSection catalog={item.catalog} />
|
||||
);
|
||||
return wrapper(<CatalogSection catalog={item.catalog} />);
|
||||
case 'placeholder':
|
||||
return (
|
||||
return wrapper(
|
||||
<View style={styles.catalogPlaceholder}>
|
||||
<View style={styles.placeholderHeader}>
|
||||
<View style={[styles.placeholderTitle, { backgroundColor: currentTheme.colors.elevation1 }]} />
|
||||
|
|
@ -669,7 +672,7 @@ const HomeScreen = () => {
|
|||
</Animated.View>
|
||||
);
|
||||
case 'welcome':
|
||||
return <FirstTimeWelcome />;
|
||||
return wrapper(<FirstTimeWelcome />);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue