diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index 59cba797..df1a045e 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -699,7 +699,7 @@ const HeroSection: React.FC = memo(({ const [trailerLoading, setTrailerLoading] = useState(false); const [trailerError, setTrailerError] = useState(false); const [trailerMuted, setTrailerMuted] = useState(true); - const [trailerPlaying, setTrailerPlaying] = useState(false); + const [isTrailerPlaying, setIsTrailerPlaying] = useState(false); const imageOpacity = useSharedValue(1); const imageLoadOpacity = useSharedValue(0); const shimmerOpacity = useSharedValue(0.3); @@ -961,10 +961,8 @@ const HeroSection: React.FC = memo(({ logger.warn('HeroSection', 'Trailer playback failed, falling back to image'); setTrailerError(true); }} - onProgress={() => { - if (!trailerPlaying) { - setTrailerPlaying(true); - } + onPlaybackStatusUpdate={(status) => { + setIsTrailerPlaying(status.isLoaded && !status.didJustFinish); }} /> ) : shouldLoadSecondaryData && imageSource && !loadingBanner ? ( @@ -977,6 +975,21 @@ const HeroSection: React.FC = memo(({ /> ) : null} + {/* Unmute button for trailer */} + {isTrailerPlaying && trailerUrl && ( + setTrailerMuted(!trailerMuted)} + activeOpacity={0.7} + > + + + )} + = memo(({ style={styles.bottomFadeGradient} pointerEvents="none" /> - + {/* Optimized Title/Logo */} @@ -1103,6 +1118,15 @@ const styles = StyleSheet.create({ textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 3, }, + unmuteButton: { + position: 'absolute', + top: Platform.OS === 'android' ? 40 : 50, + right: width >= 768 ? 32 : 16, + zIndex: 10, + padding: 8, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + borderRadius: 20, + }, heroGradient: { flex: 1, justifyContent: 'flex-end', diff --git a/src/components/video/TrailerPlayer.tsx b/src/components/video/TrailerPlayer.tsx index d3a38bf5..5d84ac0d 100644 --- a/src/components/video/TrailerPlayer.tsx +++ b/src/components/video/TrailerPlayer.tsx @@ -31,6 +31,7 @@ interface TrailerPlayerProps { onLoad?: () => void; onError?: (error: string) => void; onProgress?: (data: OnProgressData) => void; + onPlaybackStatusUpdate?: (status: { isLoaded: boolean; didJustFinish: boolean }) => void; style?: any; } @@ -42,6 +43,7 @@ const TrailerPlayer: React.FC = memo(({ onLoad, onError, onProgress, + onPlaybackStatusUpdate, style, }) => { const { currentTheme } = useTheme(); @@ -143,7 +145,19 @@ const TrailerPlayer: React.FC = memo(({ const handleProgress = useCallback((data: OnProgressData) => { setPosition(data.currentTime * 1000); // Convert to milliseconds onProgress?.(data); - }, [onProgress]); + + if (onPlaybackStatusUpdate) { + onPlaybackStatusUpdate({ + isLoaded: data.currentTime > 0, + didJustFinish: false + }); + } + }, [onProgress, onPlaybackStatusUpdate]); + + // Sync internal muted state with prop + useEffect(() => { + setIsMuted(muted); + }, [muted]); // Cleanup timeout on unmount useEffect(() => { @@ -189,6 +203,9 @@ const TrailerPlayer: React.FC = memo(({ paused={!isPlaying} repeat={true} muted={isMuted} + volume={isMuted ? 0 : 1} + mixWithOthers="duck" + ignoreSilentSwitch="ignore" onLoadStart={handleLoadStart} onLoad={handleLoad} onError={(error: any) => handleError(error?.error?.message || 'Unknown error')}