From 098ab73ba1b282f86f5f4678c4098acff0ca039d Mon Sep 17 00:00:00 2001 From: tapframe Date: Thu, 23 Oct 2025 13:26:43 +0530 Subject: [PATCH] anim changes ios ksplayer --- .../player/KSPlayerWithTransition.tsx | 110 ++++++++++++++++++ src/navigation/AppNavigator.tsx | 9 +- src/screens/StreamsScreen.tsx | 3 - 3 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 src/components/player/KSPlayerWithTransition.tsx diff --git a/src/components/player/KSPlayerWithTransition.tsx b/src/components/player/KSPlayerWithTransition.tsx new file mode 100644 index 000000000..d568b0e7b --- /dev/null +++ b/src/components/player/KSPlayerWithTransition.tsx @@ -0,0 +1,110 @@ +import React, { useEffect, useRef } from 'react'; +import { Animated, Easing, BackHandler } from 'react-native'; +import { useNavigation } from '@react-navigation/native'; +import KSPlayerCore from './KSPlayerCore'; + +const KSPlayerWithTransition: React.FC = () => { + const fadeAnim = useRef(new Animated.Value(0)).current; + const scaleAnim = useRef(new Animated.Value(1.15)).current; + const translateYAnim = useRef(new Animated.Value(0)).current; + const blurRadiusAnim = useRef(new Animated.Value(20)).current; + const rotateAnim = useRef(new Animated.Value(0.5)).current; + const isExiting = useRef(false); + const navigation = useNavigation(); + + useEffect(() => { + // Cinematic entrance animation with multiple stages + // Stage 1: Quick fade in and scale down (zoom out effect) + Animated.sequence([ + Animated.parallel([ + // Ultra-fast initial fade + Animated.timing(fadeAnim, { + toValue: 1, + duration: 200, + easing: Easing.out(Easing.quad), + useNativeDriver: true, + }), + // Zoom out from 1.15x to create depth + Animated.timing(scaleAnim, { + toValue: 1, + duration: 800, + easing: Easing.bezier(0.25, 0.1, 0.25, 1), // Custom bezier for smooth deceleration + useNativeDriver: true, + }), + // Subtle rotation for dynamic feel + Animated.timing(rotateAnim, { + toValue: 0, + duration: 800, + easing: Easing.out(Easing.cubic), + useNativeDriver: true, + }), + ]), + ]).start(); + + // Handle back button press with exit animation + const backHandler = BackHandler.addEventListener('hardwareBackPress', () => { + if (!isExiting.current) { + isExiting.current = true; + + // Start exit animation + Animated.parallel([ + // Fade out + Animated.timing(fadeAnim, { + toValue: 0, + duration: 300, + easing: Easing.in(Easing.cubic), + useNativeDriver: true, + }), + // Scale down slightly + Animated.timing(scaleAnim, { + toValue: 0.95, + duration: 300, + easing: Easing.in(Easing.cubic), + useNativeDriver: true, + }), + // Slide down slightly + Animated.timing(translateYAnim, { + toValue: 15, + duration: 300, + easing: Easing.in(Easing.cubic), + useNativeDriver: true, + }), + ]).start(() => { + // Navigate back after animation completes + navigation.goBack(); + }); + + return true; // Prevent default back behavior + } + return false; + }); + + return () => { + backHandler.remove(); + }; + }, [navigation]); + + // Interpolate rotation (0.5 deg to 0 deg for subtle dynamic effect) + const rotation = rotateAnim.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '0.5deg'], + }); + + return ( + + + + ); +}; + +export default KSPlayerWithTransition; diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx index 365504a0e..ffe0c7215 100644 --- a/src/navigation/AppNavigator.tsx +++ b/src/navigation/AppNavigator.tsx @@ -39,6 +39,7 @@ import SettingsScreen from '../screens/SettingsScreen'; import DownloadsScreen from '../screens/DownloadsScreen'; import MetadataScreen from '../screens/MetadataScreen'; import KSPlayerCore from '../components/player/KSPlayerCore'; +import KSPlayerWithTransition from '../components/player/KSPlayerWithTransition'; import AndroidVideoPlayer from '../components/player/AndroidVideoPlayer'; import CatalogScreen from '../screens/CatalogScreen'; import AddonsScreen from '../screens/AddonsScreen'; @@ -1188,10 +1189,10 @@ const InnerNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootSta /> { }, [type, id, currentEpisode?.season_number, currentEpisode?.episode_number]); const navigateToPlayer = useCallback(async (stream: Stream, options?: { forceVlc?: boolean; headers?: Record }) => { - // Add 50ms delay before navigating to player - await new Promise(resolve => setTimeout(resolve, 50)); - // Prepare available streams for the change source feature const streamsToPass = (type === 'series' || (type === 'other' && selectedEpisode)) ? episodeStreams : groupedStreams;