mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +00:00
slide parallax fix appletv hero
This commit is contained in:
parent
b3765f13da
commit
674dbcf818
2 changed files with 31 additions and 43 deletions
|
|
@ -224,7 +224,8 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
const thumbnailOpacity = useSharedValue(1);
|
const thumbnailOpacity = useSharedValue(1);
|
||||||
const trailerOpacity = useSharedValue(0);
|
const trailerOpacity = useSharedValue(0);
|
||||||
const trailerMuted = settings?.trailerMuted ?? true;
|
const trailerMuted = settings?.trailerMuted ?? true;
|
||||||
const heroOpacity = useSharedValue(0); // Start hidden for smooth fade-in
|
// Initialize to 0 for smooth fade-in
|
||||||
|
const heroOpacity = useSharedValue(0);
|
||||||
|
|
||||||
// Handler for trailer end
|
// Handler for trailer end
|
||||||
const handleTrailerEnd = useCallback(() => {
|
const handleTrailerEnd = useCallback(() => {
|
||||||
|
|
@ -270,15 +271,8 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
'worklet';
|
'worklet';
|
||||||
const scrollYValue = scrollY.value;
|
const scrollYValue = scrollY.value;
|
||||||
|
|
||||||
// Disable parallax during drag to avoid transform conflicts
|
// Keep parallax active during drag to prevent jumps
|
||||||
if (isDragging.value > 0) {
|
// if (isDragging.value > 0) { ... }
|
||||||
return {
|
|
||||||
transform: [
|
|
||||||
{ scale: 1.0 },
|
|
||||||
{ translateY: 0 }
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-calculated constants - start at 1.0 for normal size
|
// Pre-calculated constants - start at 1.0 for normal size
|
||||||
const DEFAULT_ZOOM = 1.0;
|
const DEFAULT_ZOOM = 1.0;
|
||||||
|
|
@ -308,15 +302,8 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
'worklet';
|
'worklet';
|
||||||
const scrollYValue = scrollY.value;
|
const scrollYValue = scrollY.value;
|
||||||
|
|
||||||
// Disable parallax during drag to avoid transform conflicts
|
// Keep parallax active during drag to prevent jumps
|
||||||
if (isDragging.value > 0) {
|
// if (isDragging.value > 0) { ... }
|
||||||
return {
|
|
||||||
transform: [
|
|
||||||
{ scale: 1.0 },
|
|
||||||
{ translateY: 0 }
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-calculated constants - start at 1.0 for normal size
|
// Pre-calculated constants - start at 1.0 for normal size
|
||||||
const DEFAULT_ZOOM = 1.0;
|
const DEFAULT_ZOOM = 1.0;
|
||||||
|
|
@ -360,13 +347,10 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
// Smooth fade-in when content loads
|
// Smooth fade-in when content loads
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentItem && !loading) {
|
if (currentItem && !loading) {
|
||||||
heroOpacity.value = withDelay(
|
heroOpacity.value = withTiming(1, {
|
||||||
100,
|
duration: 800,
|
||||||
withTiming(1, {
|
easing: Easing.out(Easing.cubic),
|
||||||
duration: 500,
|
});
|
||||||
easing: Easing.out(Easing.cubic),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, [currentItem, loading, heroOpacity]);
|
}, [currentItem, loading, heroOpacity]);
|
||||||
|
|
||||||
|
|
@ -970,7 +954,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
setCurrentIndex(index);
|
setCurrentIndex(index);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
if (loading && !currentItem) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { height: HERO_HEIGHT, marginTop: -insets.top }]}>
|
<View style={[styles.container, { height: HERO_HEIGHT, marginTop: -insets.top }]}>
|
||||||
<View style={styles.skeletonContainer}>
|
<View style={styles.skeletonContainer}>
|
||||||
|
|
@ -1008,8 +992,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
return (
|
return (
|
||||||
<GestureDetector gesture={panGesture}>
|
<GestureDetector gesture={panGesture}>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
entering={initialLoadComplete ? undefined : FadeIn.duration(600).delay(150)}
|
style={[styles.container, heroContainerStyle, { height: HERO_HEIGHT, marginTop: -insets.top, backgroundColor: currentTheme.colors.darkBackground }]}
|
||||||
style={[styles.container, heroContainerStyle, { height: HERO_HEIGHT, marginTop: -insets.top }]}
|
|
||||||
>
|
>
|
||||||
{/* Background Images with Crossfade */}
|
{/* Background Images with Crossfade */}
|
||||||
<View style={styles.backgroundContainer}>
|
<View style={styles.backgroundContainer}>
|
||||||
|
|
@ -1029,17 +1012,19 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
|
||||||
|
|
||||||
{/* Next/Preview Image - Animated overlay during drag */}
|
{/* Next/Preview Image - Animated overlay during drag */}
|
||||||
{nextIndex !== currentIndex && (
|
{nextIndex !== currentIndex && (
|
||||||
<Animated.View style={[styles.imageWrapperAbsolute, nextImageStyle, backgroundParallaxStyle]}>
|
<Animated.View style={[styles.imageWrapperAbsolute, backgroundParallaxStyle]}>
|
||||||
<FastImage
|
<Animated.View style={[StyleSheet.absoluteFill, nextImageStyle]}>
|
||||||
source={{
|
<FastImage
|
||||||
uri: nextBannerUrl,
|
source={{
|
||||||
priority: FastImage.priority.high,
|
uri: nextBannerUrl,
|
||||||
cache: FastImage.cacheControl.immutable,
|
priority: FastImage.priority.high,
|
||||||
}}
|
cache: FastImage.cacheControl.immutable,
|
||||||
style={styles.backgroundImage}
|
}}
|
||||||
resizeMode={FastImage.resizeMode.cover}
|
style={styles.backgroundImage}
|
||||||
onLoad={() => setBannerLoaded((prev) => ({ ...prev, [nextIndex]: true }))}
|
resizeMode={FastImage.resizeMode.cover}
|
||||||
/>
|
onLoad={() => setBannerLoaded((prev) => ({ ...prev, [nextIndex]: true }))}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,10 @@ export function useFeaturedContent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
// Only show loading if we don't have any content
|
||||||
|
if (!featuredContent && !persistentStore.featuredContent) {
|
||||||
|
setLoading(true);
|
||||||
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
abortControllerRef.current = new AbortController();
|
abortControllerRef.current = new AbortController();
|
||||||
const signal = abortControllerRef.current.signal;
|
const signal = abortControllerRef.current.signal;
|
||||||
|
|
@ -116,8 +119,8 @@ export function useFeaturedContent() {
|
||||||
try {
|
try {
|
||||||
if (base.logo && !isTmdbUrl(base.logo)) {
|
if (base.logo && !isTmdbUrl(base.logo)) {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.enrichMetadataWithTMDB) {
|
if (!settings.enrichMetadataWithTMDB) {
|
||||||
return { ...base, logo: base.logo || undefined };
|
return { ...base, logo: base.logo || undefined };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue