From 7f55bba2aa55a3f3bccab04cb64b24994550567c Mon Sep 17 00:00:00 2001 From: Nayif Noushad Date: Tue, 15 Apr 2025 14:48:03 +0530 Subject: [PATCH] some animations and fixes --- src/components/NuvioHeader.tsx | 29 ++++-- src/screens/HomeScreen.tsx | 61 +++++++----- src/screens/MetadataScreen.tsx | 169 +++++++++++++++------------------ 3 files changed, 136 insertions(+), 123 deletions(-) diff --git a/src/components/NuvioHeader.tsx b/src/components/NuvioHeader.tsx index ce983e1..ba05222 100644 --- a/src/components/NuvioHeader.tsx +++ b/src/components/NuvioHeader.tsx @@ -7,27 +7,35 @@ import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import type { RootStackParamList } from '../navigation/AppNavigator'; import { BlurView as ExpoBlurView } from 'expo-blur'; import { BlurView as CommunityBlurView } from '@react-native-community/blur'; +import Constants, { ExecutionEnvironment } from 'expo-constants'; type NavigationProp = NativeStackNavigationProp; export const NuvioHeader = () => { const navigation = useNavigation(); + // Determine if running in Expo Go + const isExpoGo = Constants.executionEnvironment === ExecutionEnvironment.StoreClient; + return ( {Platform.OS === 'ios' ? ( ) : ( - - - + isExpoGo ? ( + + ) : ( + + + + ) )} @@ -83,6 +91,9 @@ const styles = StyleSheet.create({ flex: 1, backgroundColor: 'transparent', }, + androidFallbackBlur: { + backgroundColor: 'rgba(0,0,0,0.6)', + }, contentContainer: { flexDirection: 'row', alignItems: 'center', diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index c1cea6c..039fa41 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -654,50 +654,46 @@ const HomeScreen = () => { }, [featuredContent, navigation]); const renderFeaturedContent = () => { - if (!featuredContent) return null; + if (!featuredContent) { + return ; + } return ( - + - - + {featuredContent.logo ? ( - ) : ( - {featuredContent.name} + {featuredContent.name} )} - - {featuredContent.genres?.slice(0, 3).map((genre, index, array) => ( - - {genre} - {index < array.length - 1 && ( - - )} - + {featuredContent.genres?.slice(0, 3).map((genre, index) => ( + {genre} ))} - { Info - + - + ); }; @@ -1253,6 +1249,25 @@ const styles = StyleSheet.create({ alignItems: 'center', borderRadius: 12, }, + featuredImage: { + width: '100%', + height: '100%', + }, + featuredContentContainer: { + flex: 1, + justifyContent: 'flex-end', + }, + featuredTitleText: { + color: colors.highEmphasis, + fontSize: 28, + fontWeight: '900', + marginBottom: 8, + textShadowColor: 'rgba(0,0,0,0.6)', + textShadowOffset: { width: 0, height: 2 }, + textShadowRadius: 4, + textAlign: 'center', + paddingHorizontal: 16, + }, }); export default HomeScreen; \ No newline at end of file diff --git a/src/screens/MetadataScreen.tsx b/src/screens/MetadataScreen.tsx index 0b147cf..bf2f2ec 100644 --- a/src/screens/MetadataScreen.tsx +++ b/src/screens/MetadataScreen.tsx @@ -52,7 +52,7 @@ const { width, height } = Dimensions.get('window'); // Animation configs const springConfig = { - damping: 15, + damping: 20, mass: 1, stiffness: 100 }; @@ -87,7 +87,6 @@ const MetadataScreen = () => { const contentRef = useRef(null); const [lastScrollTop, setLastScrollTop] = useState(0); const [isFullDescriptionOpen, setIsFullDescriptionOpen] = useState(false); - const fullDescriptionAnimation = useSharedValue(0); // Animation values const screenScale = useSharedValue(0.8); @@ -103,12 +102,15 @@ const MetadataScreen = () => { episodeId?: string; } | null>(null); - // Add new animated value for creator height - const creatorHeight = useSharedValue(0); - // Add new animated value for watch progress - const watchProgressHeight = useSharedValue(0); const watchProgressOpacity = useSharedValue(0); + const watchProgressScaleY = useSharedValue(0); + + // Add new animated value for logo scale + const logoScale = useSharedValue(0); + + // Add new animated value for creator fade-in + const creatorOpacity = useSharedValue(0); // Debug log for route params // logger.log('[MetadataScreen] Component mounted with route params:', { id, type, episodeId }); @@ -304,64 +306,85 @@ const MetadataScreen = () => { // Add effect to animate watch progress when it changes useEffect(() => { if (watchProgress && watchProgress.duration > 0) { - watchProgressHeight.value = withSpring(48, { - mass: 0.3, - stiffness: 120, - damping: 15, - velocity: 0.5 - }); watchProgressOpacity.value = withSpring(1, { mass: 0.2, stiffness: 100, - damping: 12 + damping: 14 }); - } else { - watchProgressHeight.value = withSpring(0, { + watchProgressScaleY.value = withSpring(1, { mass: 0.3, stiffness: 120, - damping: 15 + damping: 18 }); + } else { watchProgressOpacity.value = withSpring(0, { mass: 0.2, stiffness: 100, - damping: 12 + damping: 14 + }); + watchProgressScaleY.value = withSpring(0, { + mass: 0.3, + stiffness: 120, + damping: 18 }); } }, [watchProgress]); // Add animated style for watch progress const watchProgressAnimatedStyle = useAnimatedStyle(() => { - const progress = interpolate( - watchProgressHeight.value, - [0, 48], + const translateY = interpolate( + watchProgressScaleY.value, [0, 1], + [-8, 0], Extrapolate.CLAMP ); return { - height: watchProgressHeight.value, opacity: watchProgressOpacity.value, transform: [ - { - translateY: interpolate( - progress, - [0, 1], - [-8, 0], - Extrapolate.CLAMP - ) - }, - { - scale: interpolate( - progress, - [0, 1], - [0.95, 1], - Extrapolate.CLAMP - ) - } + { translateY: translateY }, + { scaleY: watchProgressScaleY.value } ] }; }); + // Add animated style for logo + const logoAnimatedStyle = useAnimatedStyle(() => { + return { + transform: [{ scale: logoScale.value }], + }; + }); + + // Effect to animate logo scale when logo URI is available + useEffect(() => { + if (metadata?.logo) { + logoScale.value = withSpring(1, { + damping: 18, + stiffness: 120, + mass: 0.5 + }); + } else { + // Optional: Reset scale if logo disappears? + // logoScale.value = withTiming(0, { duration: 100 }); + } + }, [metadata?.logo]); + + // Add animated style for creator fade-in + const creatorFadeInStyle = useAnimatedStyle(() => { + return { + opacity: creatorOpacity.value, + }; + }); + + // Effect to fade in creator section when data is available + useEffect(() => { + const hasCreators = metadata?.directors?.length || metadata?.creators?.length; + creatorOpacity.value = withTiming(hasCreators ? 1 : 0, { + duration: 300, // Adjust duration as needed + easing: Easing.out(Easing.quad), // Use an easing function + }); + }, [metadata?.directors, metadata?.creators]); + // Update the watch progress render function const renderWatchProgress = () => { if (!watchProgress || watchProgress.duration === 0) { @@ -513,46 +536,6 @@ const MetadataScreen = () => { ) })); - // Add animated style for creator container - const creatorAnimatedStyle = useAnimatedStyle(() => ({ - maxHeight: creatorHeight.value, - opacity: interpolate( - creatorHeight.value, - [0, 24], - [0, 1], - Extrapolate.CLAMP - ), - transform: [ - { - translateY: interpolate( - creatorHeight.value, - [0, 24], - [-8, 0], - Extrapolate.CLAMP - ) - } - ] - })); - - // Add effect to animate height when metadata changes - useEffect(() => { - if (metadata?.directors?.length || metadata?.creators?.length) { - creatorHeight.value = withSpring(24, { - mass: 0.5, - stiffness: 100, - damping: 12, - velocity: 0.4 - }); - } else { - creatorHeight.value = withSpring(0, { - mass: 0.5, - stiffness: 100, - damping: 12, - velocity: 0.4 - }); - } - }, [metadata?.directors, metadata?.creators]); - // Debug logs for director/creator data React.useEffect(() => { if (metadata && metadata.id) { @@ -615,8 +598,11 @@ const MetadataScreen = () => { React.useEffect(() => { screenScale.value = withSpring(1, springConfig); screenOpacity.value = withSpring(1, springConfig); - heroHeight.value = withSpring(height * 0.5, springConfig); - contentTranslateY.value = withSpring(0, springConfig); + contentTranslateY.value = withSpring(0, { + damping: 25, + mass: 1, + stiffness: 100 + }); }, []); const handleBack = useCallback(() => { @@ -716,7 +702,7 @@ const MetadataScreen = () => { style={styles.scrollView} showsVerticalScrollIndicator={false} onScroll={(e) => { - setLastScrollTop(e.nativeEvent.contentOffset.y); + // setLastScrollTop(e.nativeEvent.contentOffset.y); // Remove unused onScroll handler logic }} scrollEventThrottle={16} > @@ -740,14 +726,16 @@ const MetadataScreen = () => { locations={[0, 0.4, 0.65, 0.8, 0.9, 1]} style={styles.heroGradient} > - + {/* Title */} {metadata.logo ? ( - + + + ) : ( {metadata.name} )} @@ -802,11 +790,10 @@ const MetadataScreen = () => { {/* Creator/Director Info */} - {metadata.directors && metadata.directors.length > 0 && ( @@ -1131,7 +1118,6 @@ const styles = StyleSheet.create({ creatorContainer: { marginBottom: 2, paddingHorizontal: 16, - overflow: 'hidden' }, creatorSection: { flexDirection: 'row', @@ -1157,7 +1143,8 @@ const styles = StyleSheet.create({ marginBottom: 8, width: '100%', alignItems: 'center', - overflow: 'hidden' + overflow: 'hidden', + height: 48, }, watchProgressBar: { width: '75%',