diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index a2c925a..68fd412 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -29,12 +29,12 @@ import { } from './utils/playerTypes'; import { safeDebugLog, parseSRT, DEBUG_MODE, formatTime } from './utils/playerUtils'; import { styles } from './utils/playerStyles'; -import SubtitleModals from './modals/SubtitleModals'; -import AudioTrackModal from './modals/AudioTrackModal'; +import { SubtitleModals } from './modals/SubtitleModals'; +import { AudioTrackModal } from './modals/AudioTrackModal'; import ResumeOverlay from './modals/ResumeOverlay'; import PlayerControls from './controls/PlayerControls'; import CustomSubtitles from './subtitles/CustomSubtitles'; -import SourcesModal from './modals/SourcesModal'; +import { SourcesModal } from './modals/SourcesModal'; // Map VLC resize modes to react-native-video resize modes const getVideoResizeMode = (resizeMode: ResizeModeType) => { diff --git a/src/components/player/modals/AudioTrackModal.tsx b/src/components/player/modals/AudioTrackModal.tsx index 77e3bbb..cfc50d6 100644 --- a/src/components/player/modals/AudioTrackModal.tsx +++ b/src/components/player/modals/AudioTrackModal.tsx @@ -1,16 +1,12 @@ import React from 'react'; import { View, Text, TouchableOpacity, ScrollView, Dimensions } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; -import { BlurView } from 'expo-blur'; import Animated, { FadeIn, FadeOut, - useAnimatedStyle, - useSharedValue, - withTiming, + SlideInRight, + SlideOutRight, } from 'react-native-reanimated'; -import { LinearGradient } from 'expo-linear-gradient'; -import { styles } from '../utils/playerStyles'; import { getTrackDisplayName } from '../utils/playerUtils'; interface AudioTrackModalProps { @@ -21,52 +17,8 @@ interface AudioTrackModalProps { selectAudioTrack: (trackId: number) => void; } -const { width, height } = Dimensions.get('window'); - -const MODAL_WIDTH = Math.min(width - 32, 520); -const MODAL_MAX_HEIGHT = height * 0.85; - -const AudioBadge = ({ - text, - color, - bgColor, - icon -}: { - text: string; - color: string; - bgColor: string; - icon?: string; -}) => ( - - {icon && ( - - )} - - {text} - - -); +const { width } = Dimensions.get('window'); +const MENU_WIDTH = Math.min(width * 0.85, 400); export const AudioTrackModal: React.FC = ({ showAudioModal, @@ -75,325 +27,173 @@ export const AudioTrackModal: React.FC = ({ selectedAudioTrack, selectAudioTrack, }) => { - const modalOpacity = useSharedValue(0); - - React.useEffect(() => { - if (showAudioModal) { - modalOpacity.value = withTiming(1, { duration: 200 }); - } - }, [showAudioModal]); - - const modalStyle = useAnimatedStyle(() => ({ - opacity: modalOpacity.value, - })); - const handleClose = () => { - modalOpacity.value = withTiming(0, { duration: 150 }); - setTimeout(() => setShowAudioModal(false), 150); + setShowAudioModal(false); }; if (!showAudioModal) return null; return ( - - + {/* Backdrop */} + - - - - - - - Audio Tracks - - - Choose from {vlcAudioTracks.length} available track{vlcAudioTracks.length !== 1 ? 's' : ''} - - - - - - - + + - + {/* Header */} + + + Audio Tracks + + - - {vlcAudioTracks.length > 0 ? vlcAudioTracks.map((track) => ( - + + + + + + {/* Audio Tracks */} + + + Available Tracks ({vlcAudioTracks.length}) + + + + {vlcAudioTracks.map((track) => { + const isSelected = selectedAudioTrack === track.id; + return ( { selectAudioTrack(track.id); - handleClose(); }} - activeOpacity={0.85} + activeOpacity={0.7} > - - - + + + {getTrackDisplayName(track)} + + {track.language && ( - {getTrackDisplayName(track)} + {track.language.toUpperCase()} - - {selectedAudioTrack === track.id && ( - - - - ACTIVE - - - )} - - - - - {track.language && ( - - )} - - - - - + )} + {isSelected && ( + + )} - - )) : ( - - - - No audio tracks found - - - No audio tracks are available for this content.{'\n'}Try a different source or check your connection. - - - )} + ); + })} - - - - - ); -}; -export default AudioTrackModal; \ No newline at end of file + {vlcAudioTracks.length === 0 && ( + + + + No audio tracks available + + + )} + + + + + ); +}; \ No newline at end of file diff --git a/src/components/player/modals/SourcesModal.tsx b/src/components/player/modals/SourcesModal.tsx index 9533f6f..f8aa33a 100644 --- a/src/components/player/modals/SourcesModal.tsx +++ b/src/components/player/modals/SourcesModal.tsx @@ -1,19 +1,13 @@ import React from 'react'; import { View, Text, TouchableOpacity, ScrollView, ActivityIndicator, Dimensions } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; -import { BlurView } from 'expo-blur'; import Animated, { FadeIn, FadeOut, - useAnimatedStyle, - useSharedValue, - withTiming, - runOnJS, + SlideInRight, + SlideOutRight, } from 'react-native-reanimated'; -import { LinearGradient } from 'expo-linear-gradient'; -import { styles } from '../utils/playerStyles'; import { Stream } from '../../../types/streams'; -import QualityBadge from '../../metadata/QualityBadge'; interface SourcesModalProps { showSourcesModal: boolean; @@ -24,12 +18,10 @@ interface SourcesModalProps { isChangingSource: boolean; } -const { width, height } = Dimensions.get('window'); +const { width } = Dimensions.get('window'); +const MENU_WIDTH = Math.min(width * 0.85, 400); -const MODAL_WIDTH = Math.min(width - 32, 520); -const MODAL_MAX_HEIGHT = height * 0.85; - -const QualityIndicator = ({ quality }: { quality: string | null }) => { +const QualityBadge = ({ quality }: { quality: string | null }) => { if (!quality) return null; const qualityNum = parseInt(quality); @@ -54,22 +46,15 @@ const QualityIndicator = ({ quality }: { quality: string | null }) => { borderColor: `${color}60`, borderWidth: 1, paddingHorizontal: 8, - paddingVertical: 3, + paddingVertical: 4, borderRadius: 8, flexDirection: 'row', alignItems: 'center', }} > - @@ -79,49 +64,7 @@ const QualityIndicator = ({ quality }: { quality: string | null }) => { ); }; -const StreamMetaBadge = ({ - text, - color, - bgColor, - icon -}: { - text: string; - color: string; - bgColor: string; - icon?: string; -}) => ( - - {icon && ( - - )} - - {text} - - -); - -const SourcesModal: React.FC = ({ +export const SourcesModal: React.FC = ({ showSourcesModal, setShowSourcesModal, availableStreams, @@ -129,28 +72,8 @@ const SourcesModal: React.FC = ({ onSelectStream, isChangingSource, }) => { - const modalOpacity = useSharedValue(0); - - React.useEffect(() => { - if (showSourcesModal) { - modalOpacity.value = withTiming(1, { duration: 200 }); - } else { - modalOpacity.value = withTiming(0, { duration: 150 }); - } - - return () => { - modalOpacity.value = 0; - }; - }, [showSourcesModal]); - - const modalStyle = useAnimatedStyle(() => ({ - opacity: modalOpacity.value, - })); - const handleClose = () => { - modalOpacity.value = withTiming(0, { duration: 150 }, () => { - runOnJS(setShowSourcesModal)(false); - }); + setShowSourcesModal(false); }; if (!showSourcesModal) return null; @@ -174,305 +97,237 @@ const SourcesModal: React.FC = ({ }; return ( - - + {/* Backdrop */} + - - - - + + + {/* Side Menu */} + + {/* Header */} + + + Change Source + + + + + + + + {isChangingSource && ( + - + }}> + - Video Sources - - - Choose from {Object.values(availableStreams).reduce((acc, curr) => acc + curr.streams.length, 0)} available sources + Switching source... - - - - - + )} - - {sortedProviders.map(([providerId, { streams, addonName }]) => ( - - 0 ? ( + sortedProviders.map(([providerId, providerData]) => ( + + - - {addonName} - - - - {streams.length} - - - - - {streams.map((stream, index) => { - const isSelected = isStreamSelected(stream); - const quality = getQualityFromTitle(stream.title); - - return ( - + {providerData.addonName} ({providerData.streams.length}) + + + + {providerData.streams.map((stream, index) => { + const isSelected = isStreamSelected(stream); + const quality = getQualityFromTitle(stream.title) || stream.quality; + + return ( handleStreamSelect(stream)} - activeOpacity={0.85} + activeOpacity={0.7} disabled={isChangingSource} > - - + + - {stream.title || 'Untitled Stream'} + {stream.title || stream.name || `Stream ${index + 1}`} - - {isSelected && ( - - - - PLAYING - - - )} + {quality && } - - {quality && } - - + {(stream.size || stream.lang) && ( + + {stream.size && ( + + + + {(stream.size / (1024 * 1024 * 1024)).toFixed(1)} GB + + + )} + {stream.lang && ( + + + + {stream.lang.toUpperCase()} + + + )} + + )} - {isChangingSource ? ( - + {isSelected ? ( + ) : ( - + )} - - ); - })} + ); + })} + - ))} - - + )) + ) : ( + + + + No sources available + + + Try searching for different content + + + )} + - + ); -}; - -export default SourcesModal; \ No newline at end of file +}; \ No newline at end of file