diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index 885e7e20..d9204b13 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -8,6 +8,7 @@ import { Platform, InteractionManager, } from 'react-native'; + import { MaterialIcons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { Image } from 'expo-image'; @@ -709,6 +710,7 @@ const HeroSection: React.FC = memo(({ const [isTrailerPlaying, setIsTrailerPlaying] = useState(false); const [trailerReady, setTrailerReady] = useState(false); const [trailerPreloaded, setTrailerPreloaded] = useState(false); + const trailerVideoRef = useRef(null); const imageOpacity = useSharedValue(1); const imageLoadOpacity = useSharedValue(0); const shimmerOpacity = useSharedValue(0.3); @@ -747,6 +749,18 @@ const HeroSection: React.FC = memo(({ trailerOpacity.value = withTiming(1, { duration: 500 }); }, [thumbnailOpacity, trailerOpacity, trailerPreloaded]); + // Handle fullscreen toggle + const handleFullscreenToggle = useCallback(async () => { + try { + if (trailerVideoRef.current) { + // Use the native fullscreen player + await trailerVideoRef.current.presentFullscreenPlayer(); + } + } catch (error) { + logger.error('HeroSection', 'Error toggling fullscreen:', error); + } + }, []); + // Handle trailer error - fade back to thumbnail const handleTrailerError = useCallback(() => { setTrailerError(true); @@ -973,6 +987,8 @@ const HeroSection: React.FC = memo(({ imageLoadOpacity.value = 0; shimmerOpacity.value = 0.3; interactionComplete.current = false; + + // Cleanup on unmount }; }, []); @@ -990,6 +1006,8 @@ const HeroSection: React.FC = memo(({ } }); + + return ( {/* Optimized Background */} @@ -1045,11 +1063,13 @@ const HeroSection: React.FC = memo(({ opacity: trailerOpacity }]}> { @@ -1061,15 +1081,35 @@ const HeroSection: React.FC = memo(({ )} - {/* Unmute button for trailer */} + {/* Trailer control buttons (unmute and fullscreen) */} {settings?.showTrailers && trailerReady && trailerUrl && ( = 768 ? 32 : 16, zIndex: 10, - opacity: trailerOpacity + opacity: trailerOpacity, + flexDirection: 'row', + gap: 8, }}> + {/* Fullscreen button */} + + + + + {/* Unmute button */} { setTrailerMuted(!trailerMuted); @@ -1207,6 +1247,7 @@ const styles = StyleSheet.create({ backgroundColor: '#000', overflow: 'hidden', }, + absoluteFill: { position: 'absolute', top: 0, diff --git a/src/components/metadata/MetadataDetails.tsx b/src/components/metadata/MetadataDetails.tsx index 035baaf8..f87016b9 100644 --- a/src/components/metadata/MetadataDetails.tsx +++ b/src/components/metadata/MetadataDetails.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { View, Text, @@ -12,6 +12,7 @@ import Animated, { FadeIn, } from 'react-native-reanimated'; import { useTheme } from '../../contexts/ThemeContext'; +import { isMDBListEnabled } from '../../screens/MDBListSettingsScreen'; // MetadataSourceSelector removed interface MetadataDetailsProps { @@ -34,6 +35,20 @@ const MetadataDetails: React.FC = ({ }) => { const { currentTheme } = useTheme(); const [isFullDescriptionOpen, setIsFullDescriptionOpen] = useState(false); + const [isMDBEnabled, setIsMDBEnabled] = useState(false); + + useEffect(() => { + const checkMDBListEnabled = async () => { + try { + const enabled = await isMDBListEnabled(); + setIsMDBEnabled(enabled); + } catch (error) { + setIsMDBEnabled(false); // Default to disabled if there's an error + } + }; + + checkMDBListEnabled(); + }, []); return ( <> @@ -60,7 +75,7 @@ const MetadataDetails: React.FC = ({ {metadata.certification && ( {metadata.certification} )} - {metadata.imdbRating && ( + {metadata.imdbRating && !isMDBEnabled && ( void; style?: any; hideLoadingSpinner?: boolean; + onFullscreenToggle?: () => void; } -const TrailerPlayer: React.FC = memo(({ +const TrailerPlayer = React.forwardRef(({ trailerUrl, autoPlay = true, muted = true, @@ -47,7 +48,8 @@ const TrailerPlayer: React.FC = memo(({ onPlaybackStatusUpdate, style, hideLoadingSpinner = false, -}) => { + onFullscreenToggle, +}, ref) => { const { currentTheme } = useTheme(); const videoRef = useRef(null); @@ -171,6 +173,15 @@ const TrailerPlayer: React.FC = memo(({ }; }, []); + // Forward the ref to the video element + React.useImperativeHandle(ref, () => ({ + presentFullscreenPlayer: () => { + if (videoRef.current) { + return videoRef.current.presentFullscreenPlayer(); + } + } + })); + // Animated styles const controlsAnimatedStyle = useAnimatedStyle(() => ({ opacity: controlsOpacity.value, @@ -287,6 +298,16 @@ const TrailerPlayer: React.FC = memo(({ color="white" /> + + {onFullscreenToggle && ( + + + + )} @@ -296,6 +317,8 @@ const TrailerPlayer: React.FC = memo(({ ); }); + + const styles = StyleSheet.create({ container: { flex: 1, diff --git a/src/screens/LibraryScreen.tsx b/src/screens/LibraryScreen.tsx index 5fa42970..6e356baa 100644 --- a/src/screens/LibraryScreen.tsx +++ b/src/screens/LibraryScreen.tsx @@ -735,7 +735,6 @@ const LibraryScreen = () => { numColumns={numColumns} contentContainerStyle={styles.listContainer} showsVerticalScrollIndicator={false} - columnWrapperStyle={styles.columnWrapper} onEndReachedThreshold={0.7} onEndReached={() => {}} /> @@ -776,7 +775,6 @@ const LibraryScreen = () => { renderItem={({ item }) => renderTraktItem({ item })} keyExtractor={(item) => `${item.type}-${item.id}`} numColumns={numColumns} - columnWrapperStyle={styles.row} style={styles.traktContainer} contentContainerStyle={{ paddingBottom: insets.bottom + 80 }} showsVerticalScrollIndicator={false} @@ -874,7 +872,6 @@ const LibraryScreen = () => { numColumns={numColumns} contentContainerStyle={styles.listContainer} showsVerticalScrollIndicator={false} - columnWrapperStyle={styles.columnWrapper} onEndReachedThreshold={0.7} onEndReached={() => {}} />