anim changes ios ksplayer
This commit is contained in:
parent
060b0b927b
commit
098ab73ba1
3 changed files with 115 additions and 7 deletions
110
src/components/player/KSPlayerWithTransition.tsx
Normal file
110
src/components/player/KSPlayerWithTransition.tsx
Normal file
|
|
@ -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 (
|
||||
<Animated.View
|
||||
style={{
|
||||
flex: 1,
|
||||
opacity: fadeAnim,
|
||||
transform: [
|
||||
{ scale: scaleAnim },
|
||||
{ translateY: translateYAnim },
|
||||
{ rotateZ: rotation },
|
||||
],
|
||||
}}
|
||||
>
|
||||
<KSPlayerCore />
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
export default KSPlayerWithTransition;
|
||||
|
|
@ -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
|
|||
/>
|
||||
<Stack.Screen
|
||||
name="PlayerIOS"
|
||||
component={KSPlayerCore as any}
|
||||
component={KSPlayerWithTransition as any}
|
||||
options={{
|
||||
animation: 'default',
|
||||
animationDuration: 0,
|
||||
animation: 'fade',
|
||||
animationDuration: 300,
|
||||
// Force fullscreen presentation on iPad
|
||||
presentation: 'fullScreenModal',
|
||||
// Disable gestures during video playback
|
||||
|
|
@ -1203,7 +1204,7 @@ const InnerNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootSta
|
|||
},
|
||||
// iPad-specific fullscreen options
|
||||
statusBarHidden: true,
|
||||
statusBarAnimation: 'none',
|
||||
statusBarAnimation: 'fade',
|
||||
// Freeze when blurred to release resources safely
|
||||
freezeOnBlur: true,
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -755,9 +755,6 @@ export const StreamsScreen = () => {
|
|||
}, [type, id, currentEpisode?.season_number, currentEpisode?.episode_number]);
|
||||
|
||||
const navigateToPlayer = useCallback(async (stream: Stream, options?: { forceVlc?: boolean; headers?: Record<string, string> }) => {
|
||||
// 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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue