optimzed perf

This commit is contained in:
tapframe 2025-10-17 22:09:42 +05:30
parent bf15c5fb45
commit 3effdee5c0

View file

@ -832,7 +832,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
const titleCardTranslateY = useSharedValue(0); const titleCardTranslateY = useSharedValue(0);
const genreOpacity = useSharedValue(1); const genreOpacity = useSharedValue(1);
// Performance optimization: Cache theme colors // Ultra-optimized theme colors with stable references
const themeColors = useMemo(() => ({ const themeColors = useMemo(() => ({
black: currentTheme.colors.black, black: currentTheme.colors.black,
darkBackground: currentTheme.colors.darkBackground, darkBackground: currentTheme.colors.darkBackground,
@ -840,6 +840,15 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
text: currentTheme.colors.text text: currentTheme.colors.text
}), [currentTheme.colors.black, currentTheme.colors.darkBackground, currentTheme.colors.highEmphasis, currentTheme.colors.text]); }), [currentTheme.colors.black, currentTheme.colors.darkBackground, currentTheme.colors.highEmphasis, currentTheme.colors.text]);
// Pre-calculated style objects for better performance
const staticStyles = useMemo(() => ({
heroWrapper: styles.heroWrapper,
heroSection: styles.heroSection,
absoluteFill: styles.absoluteFill,
thumbnailContainer: styles.thumbnailContainer,
thumbnailImage: styles.thumbnailImage,
}), []);
// Handle trailer preload completion // Handle trailer preload completion
const handleTrailerPreloaded = useCallback(() => { const handleTrailerPreloaded = useCallback(() => {
setTrailerPreloaded(true); setTrailerPreloaded(true);
@ -1153,34 +1162,30 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
opacity: watchProgressOpacity.value, opacity: watchProgressOpacity.value,
}), []); }), []);
// Enhanced backdrop with smooth loading animation and dynamic parallax effect // Ultra-optimized backdrop with cached calculations and minimal worklet overhead
const backdropImageStyle = useAnimatedStyle(() => { const backdropImageStyle = useAnimatedStyle(() => {
'worklet'; 'worklet';
const scrollYValue = scrollY.value; const scrollYValue = scrollY.value;
// Default zoom factor // Pre-calculated constants for better performance
const defaultZoom = 1.1; // 10% zoom by default const DEFAULT_ZOOM = 1.1;
const SCROLL_UP_MULTIPLIER = 0.002;
const SCROLL_DOWN_MULTIPLIER = 0.0001;
const MAX_SCALE = 1.4;
const PARALLAX_FACTOR = 0.3;
// Dynamic scale based on scroll direction and position // Optimized scale calculation with minimal branching
let scale = defaultZoom; const scrollUpScale = DEFAULT_ZOOM + Math.abs(scrollYValue) * SCROLL_UP_MULTIPLIER;
if (scrollYValue < 0) { const scrollDownScale = DEFAULT_ZOOM + scrollYValue * SCROLL_DOWN_MULTIPLIER;
// Scrolling up - zoom in to fill blank area const scale = Math.min(scrollYValue < 0 ? scrollUpScale : scrollDownScale, MAX_SCALE);
scale = defaultZoom + Math.abs(scrollYValue) * 0.002; // More aggressive zoom when scrolling up
} else {
// Scrolling down - subtle scale effect
scale = defaultZoom + scrollYValue * 0.0001;
}
// Cap the scale to prevent excessive zoom // Single parallax calculation
scale = Math.min(scale, 1.4); // Allow up to 40% zoom (including default) const parallaxOffset = scrollYValue * PARALLAX_FACTOR;
// Parallax effect - move image slower than scroll
const parallaxOffset = scrollYValue * 0.3; // 30% of scroll speed
return { return {
opacity: imageOpacity.value * imageLoadOpacity.value, opacity: imageOpacity.value * imageLoadOpacity.value,
transform: [ transform: [
{ scale: scale }, { scale },
{ translateY: parallaxOffset } { translateY: parallaxOffset }
], ],
}; };
@ -1209,29 +1214,29 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
opacity: genreOpacity.value opacity: genreOpacity.value
}), []); }), []);
// Trailer parallax effect - moves slower than scroll for depth with dynamic zoom // Ultra-optimized trailer parallax with cached calculations
const trailerParallaxStyle = useAnimatedStyle(() => { const trailerParallaxStyle = useAnimatedStyle(() => {
'worklet'; 'worklet';
const scrollYValue = scrollY.value; const scrollYValue = scrollY.value;
// Dynamic scale for trailer based on scroll direction // Pre-calculated constants for better performance
let scale = 1; const DEFAULT_ZOOM = 1.0;
if (scrollYValue < 0) { const SCROLL_UP_MULTIPLIER = 0.0015;
// Scrolling up - zoom in to fill blank area const SCROLL_DOWN_MULTIPLIER = 0.0001;
scale = 1 + Math.abs(scrollYValue) * 0.0015; // Slightly less aggressive than background const MAX_SCALE = 1.25;
} else { const PARALLAX_FACTOR = 0.2;
// Scrolling down - subtle scale effect
scale = 1 + scrollYValue * 0.0001;
}
// Cap the scale to prevent excessive zoom // Optimized scale calculation with minimal branching
scale = Math.min(scale, 1.25); // Allow up to 25% zoom for trailer const scrollUpScale = DEFAULT_ZOOM + Math.abs(scrollYValue) * SCROLL_UP_MULTIPLIER;
const scrollDownScale = DEFAULT_ZOOM + scrollYValue * SCROLL_DOWN_MULTIPLIER;
const scale = Math.min(scrollYValue < 0 ? scrollUpScale : scrollDownScale, MAX_SCALE);
const parallaxOffset = scrollYValue * 0.2; // 20% of scroll speed for trailer // Single parallax calculation
const parallaxOffset = scrollYValue * PARALLAX_FACTOR;
return { return {
transform: [ transform: [
{ scale: scale }, { scale },
{ translateY: parallaxOffset } { translateY: parallaxOffset }
], ],
}; };
@ -1384,27 +1389,31 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
} }
}, [isFocused, setTrailerPlaying]); }, [isFocused, setTrailerPlaying]);
// Pause/resume trailer based on scroll with hysteresis and guard // Ultra-optimized scroll-based pause/resume with cached calculations
useDerivedValue(() => { useDerivedValue(() => {
'worklet'; 'worklet';
try { try {
if (!scrollGuardEnabledSV.value || isFocusedSV.value === 0) return; if (!scrollGuardEnabledSV.value || isFocusedSV.value === 0) return;
const pauseThreshold = heroHeight.value * 0.7; // pause when beyond 70%
const resumeThreshold = heroHeight.value * 0.4; // resume when back within 40% // Pre-calculate thresholds for better performance
const pauseThreshold = heroHeight.value * 0.7;
const resumeThreshold = heroHeight.value * 0.4;
const y = scrollY.value; const y = scrollY.value;
const isPlaying = isPlayingSV.value === 1;
const isPausedByScroll = pausedByScrollSV.value === 1;
if (y > pauseThreshold && isPlayingSV.value === 1 && pausedByScrollSV.value === 0) { // Optimized pause/resume logic with minimal branching
if (y > pauseThreshold && isPlaying && !isPausedByScroll) {
pausedByScrollSV.value = 1; pausedByScrollSV.value = 1;
runOnJS(setTrailerPlaying)(false); runOnJS(setTrailerPlaying)(false);
isPlayingSV.value = 0; isPlayingSV.value = 0;
} else if (y < resumeThreshold && pausedByScrollSV.value === 1) { } else if (y < resumeThreshold && isPausedByScroll) {
pausedByScrollSV.value = 0; pausedByScrollSV.value = 0;
runOnJS(setTrailerPlaying)(true); runOnJS(setTrailerPlaying)(true);
isPlayingSV.value = 1; isPlayingSV.value = 1;
} }
} catch (e) { } catch (e) {
// no-op // Silent error handling for performance
} }
}); });
@ -1456,21 +1465,21 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
return ( return (
<View style={styles.heroWrapper}> <View style={staticStyles.heroWrapper}>
<Animated.View style={[styles.heroSection, heroAnimatedStyle]}> <Animated.View style={[staticStyles.heroSection, heroAnimatedStyle]}>
{/* Optimized Background */} {/* Optimized Background */}
<View style={[styles.absoluteFill, { backgroundColor: themeColors.black }]} /> <View style={[staticStyles.absoluteFill, { backgroundColor: themeColors.black }]} />
{/* Shimmer loading effect removed */} {/* Shimmer loading effect removed */}
{/* Background thumbnail image - always rendered when available with parallax */} {/* Background thumbnail image - always rendered when available with parallax */}
{shouldLoadSecondaryData && imageSource && !loadingBanner && ( {shouldLoadSecondaryData && imageSource && !loadingBanner && (
<Animated.View style={[styles.thumbnailContainer, { <Animated.View style={[staticStyles.thumbnailContainer, {
opacity: thumbnailOpacity opacity: thumbnailOpacity
}]}> }]}>
<Animated.Image <Animated.Image
source={{ uri: imageSource }} source={{ uri: imageSource }}
style={[styles.thumbnailImage, backdropImageStyle]} style={[staticStyles.thumbnailImage, backdropImageStyle]}
resizeMode="cover" resizeMode="cover"
onError={handleImageError} onError={handleImageError}
onLoad={handleImageLoad} onLoad={handleImageLoad}
@ -1480,13 +1489,13 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
{/* Hidden preload trailer player - loads in background */} {/* Hidden preload trailer player - loads in background */}
{shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && !trailerPreloaded && ( {shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && !trailerPreloaded && (
<View style={[styles.absoluteFill, { opacity: 0, pointerEvents: 'none' }]}> <View style={[staticStyles.absoluteFill, { opacity: 0, pointerEvents: 'none' }]}>
<TrailerPlayer <TrailerPlayer
key={`preload-${trailerUrl}`} key={`preload-${trailerUrl}`}
trailerUrl={trailerUrl} trailerUrl={trailerUrl}
autoPlay={false} autoPlay={false}
muted={true} muted={true}
style={styles.absoluteFill} style={staticStyles.absoluteFill}
hideLoadingSpinner={true} hideLoadingSpinner={true}
onLoad={handleTrailerPreloaded} onLoad={handleTrailerPreloaded}
onError={handleTrailerError} onError={handleTrailerError}
@ -1496,7 +1505,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
{/* Visible trailer player - rendered on top with fade transition and parallax */} {/* Visible trailer player - rendered on top with fade transition and parallax */}
{shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && trailerPreloaded && ( {shouldLoadSecondaryData && settings?.showTrailers && trailerUrl && !trailerLoading && !trailerError && trailerPreloaded && (
<Animated.View style={[styles.absoluteFill, { <Animated.View style={[staticStyles.absoluteFill, {
opacity: trailerOpacity opacity: trailerOpacity
}, trailerParallaxStyle]}> }, trailerParallaxStyle]}>
<TrailerPlayer <TrailerPlayer
@ -1505,7 +1514,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
trailerUrl={trailerUrl} trailerUrl={trailerUrl}
autoPlay={globalTrailerPlaying} autoPlay={globalTrailerPlaying}
muted={trailerMuted} muted={trailerMuted}
style={styles.absoluteFill} style={staticStyles.absoluteFill}
hideLoadingSpinner={true} hideLoadingSpinner={true}
hideControls={true} hideControls={true}
onFullscreenToggle={handleFullscreenToggle} onFullscreenToggle={handleFullscreenToggle}