mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-09 19:40:44 +00:00
perfomance optimziations
This commit is contained in:
parent
27b52a5a45
commit
a562e45ffd
1 changed files with 68 additions and 34 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
import { View, Text, StyleSheet, Dimensions, TouchableOpacity, ViewStyle, TextStyle, ImageStyle, FlatList, StyleProp } from 'react-native';
|
import { View, Text, StyleSheet, Dimensions, TouchableOpacity, ViewStyle, TextStyle, ImageStyle, FlatList, StyleProp } from 'react-native';
|
||||||
import Animated, { FadeIn, FadeOut, Easing } from 'react-native-reanimated';
|
import Animated, { FadeIn, FadeOut, Easing, useSharedValue, withTiming, useAnimatedStyle } from 'react-native-reanimated';
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
import { Image as ExpoImage } from 'expo-image';
|
import { Image as ExpoImage } from 'expo-image';
|
||||||
import { MaterialIcons } from '@expo/vector-icons';
|
import { MaterialIcons } from '@expo/vector-icons';
|
||||||
|
|
@ -77,7 +77,12 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
const interval = CARD_WIDTH + 16;
|
const interval = CARD_WIDTH + 16;
|
||||||
const idx = Math.round(offsetX / interval);
|
const idx = Math.round(offsetX / interval);
|
||||||
const clamped = Math.max(0, Math.min(idx, data.length - 1));
|
const clamped = Math.max(0, Math.min(idx, data.length - 1));
|
||||||
if (clamped !== activeIndex) setActiveIndex(clamped);
|
if (clamped !== activeIndex) {
|
||||||
|
// Small delay to ensure smooth transition
|
||||||
|
setTimeout(() => {
|
||||||
|
setActiveIndex(clamped);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleScroll = (event: any) => {
|
const handleScroll = (event: any) => {
|
||||||
|
|
@ -85,9 +90,62 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
const interval = CARD_WIDTH + 16;
|
const interval = CARD_WIDTH + 16;
|
||||||
const idx = Math.round(offsetX / interval);
|
const idx = Math.round(offsetX / interval);
|
||||||
const clamped = Math.max(0, Math.min(idx, data.length - 1));
|
const clamped = Math.max(0, Math.min(idx, data.length - 1));
|
||||||
if (clamped !== activeIndex) setActiveIndex(clamped);
|
if (clamped !== activeIndex) {
|
||||||
|
setActiveIndex(clamped);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Memoized background component with improved timing
|
||||||
|
const BackgroundImage = React.memo(({
|
||||||
|
item,
|
||||||
|
insets
|
||||||
|
}: {
|
||||||
|
item: StreamingContent;
|
||||||
|
insets: any;
|
||||||
|
}) => {
|
||||||
|
const animatedOpacity = useSharedValue(1);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Start with opacity 0 and animate to 1
|
||||||
|
animatedOpacity.value = 0;
|
||||||
|
animatedOpacity.value = withTiming(1, { duration: 400 });
|
||||||
|
}, [item.id]);
|
||||||
|
|
||||||
|
const animatedStyle = useAnimatedStyle(() => ({
|
||||||
|
opacity: animatedOpacity.value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.backgroundContainer,
|
||||||
|
{ top: -insets.top },
|
||||||
|
] as StyleProp<ViewStyle>}
|
||||||
|
pointerEvents="none"
|
||||||
|
>
|
||||||
|
<Animated.View
|
||||||
|
key={item.id}
|
||||||
|
style={[animatedStyle, { flex: 1 }] as any}
|
||||||
|
>
|
||||||
|
<ExpoImage
|
||||||
|
source={{ uri: item.banner || item.poster }}
|
||||||
|
style={styles.backgroundImage as ImageStyle}
|
||||||
|
contentFit="cover"
|
||||||
|
blurRadius={24}
|
||||||
|
cachePolicy="memory-disk"
|
||||||
|
transition={300}
|
||||||
|
priority="high"
|
||||||
|
/>
|
||||||
|
<LinearGradient
|
||||||
|
colors={["rgba(0,0,0,0.45)", "rgba(0,0,0,0.75)"]}
|
||||||
|
locations={[0.4, 1]}
|
||||||
|
style={styles.backgroundOverlay as ViewStyle}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View entering={FadeIn.duration(350).easing(Easing.out(Easing.cubic))}>
|
<Animated.View entering={FadeIn.duration(350).easing(Easing.out(Easing.cubic))}>
|
||||||
<View style={styles.container as ViewStyle}>
|
<View style={styles.container as ViewStyle}>
|
||||||
|
|
@ -113,36 +171,12 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{data[activeIndex] && (
|
{data[activeIndex] && (
|
||||||
<View
|
<BackgroundImage
|
||||||
style={[
|
item={data[activeIndex]}
|
||||||
styles.backgroundContainer,
|
insets={insets}
|
||||||
{ top: -insets.top },
|
/>
|
||||||
] as StyleProp<ViewStyle>}
|
)}
|
||||||
pointerEvents="none"
|
|
||||||
>
|
|
||||||
<Animated.View
|
|
||||||
key={data[activeIndex].id}
|
|
||||||
entering={FadeIn.duration(300).easing(Easing.out(Easing.cubic))}
|
|
||||||
exiting={FadeOut.duration(300).easing(Easing.in(Easing.cubic))}
|
|
||||||
style={{ flex: 1 } as ViewStyle}
|
|
||||||
>
|
|
||||||
<ExpoImage
|
|
||||||
source={{ uri: data[activeIndex].banner || data[activeIndex].poster }}
|
|
||||||
style={styles.backgroundImage as ImageStyle}
|
|
||||||
contentFit="cover"
|
|
||||||
blurRadius={36}
|
|
||||||
cachePolicy="memory-disk"
|
|
||||||
transition={220}
|
|
||||||
/>
|
|
||||||
<LinearGradient
|
|
||||||
colors={["rgba(0,0,0,0.45)", "rgba(0,0,0,0.75)"]}
|
|
||||||
locations={[0.4, 1]}
|
|
||||||
style={styles.backgroundOverlay as ViewStyle}
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
{/* Bottom blend to HomeScreen background (not the card) */}
|
{/* Bottom blend to HomeScreen background (not the card) */}
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={["transparent", currentTheme.colors.darkBackground]}
|
colors={["transparent", currentTheme.colors.darkBackground]}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue