diff --git a/src/components/player/modals/SubtitleModals.tsx b/src/components/player/modals/SubtitleModals.tsx
index 14e8bad..ff3f0e8 100644
--- a/src/components/player/modals/SubtitleModals.tsx
+++ b/src/components/player/modals/SubtitleModals.tsx
@@ -1,16 +1,16 @@
import React from 'react';
-import { View, Text, TouchableOpacity, ScrollView, ActivityIndicator, Image, Dimensions } from 'react-native';
+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,
+ SlideInRight,
+ SlideOutRight,
useAnimatedStyle,
useSharedValue,
withTiming,
runOnJS,
} from 'react-native-reanimated';
-import { LinearGradient } from 'expo-linear-gradient';
import { styles } from '../utils/playerStyles';
import { WyzieSubtitle, SubtitleCue } from '../utils/playerTypes';
import { getTrackDisplayName, formatLanguage } from '../utils/playerUtils';
@@ -36,51 +36,7 @@ interface SubtitleModalsProps {
}
const { width, height } = Dimensions.get('window');
-
-const MODAL_WIDTH = Math.min(width - 32, 520);
-const MODAL_MAX_HEIGHT = height * 0.85;
-
-const SubtitleBadge = ({
- text,
- color,
- bgColor,
- icon
-}: {
- text: string;
- color: string;
- bgColor: string;
- icon?: string;
-}) => (
-
- {icon && (
-
- )}
-
- {text}
-
-
-);
+const MENU_WIDTH = Math.min(width * 0.85, 400);
export const SubtitleModals: React.FC = ({
showSubtitleModal,
@@ -101,919 +57,414 @@ export const SubtitleModals: React.FC = ({
increaseSubtitleSize,
decreaseSubtitleSize,
}) => {
- const modalOpacity = useSharedValue(0);
- const languageModalOpacity = useSharedValue(0);
-
React.useEffect(() => {
- if (showSubtitleModal) {
- modalOpacity.value = withTiming(1, { duration: 200 });
- } else {
- modalOpacity.value = withTiming(0, { duration: 150 });
- }
-
- return () => {
- modalOpacity.value = 0;
- };
- }, [showSubtitleModal]);
-
- React.useEffect(() => {
- if (showSubtitleLanguageModal) {
- languageModalOpacity.value = withTiming(1, { duration: 200 });
- } else {
- languageModalOpacity.value = withTiming(0, { duration: 150 });
- }
-
- return () => {
- languageModalOpacity.value = 0;
- };
- }, [showSubtitleLanguageModal]);
-
- React.useEffect(() => {
- if (showSubtitleLanguageModal && !isLoadingSubtitleList && availableSubtitles.length === 0) {
+ if (showSubtitleModal && !isLoadingSubtitleList && availableSubtitles.length === 0) {
fetchAvailableSubtitles();
}
- }, [showSubtitleLanguageModal]);
-
- const modalStyle = useAnimatedStyle(() => ({
- opacity: modalOpacity.value,
- }));
-
- const languageModalStyle = useAnimatedStyle(() => ({
- opacity: languageModalOpacity.value,
- }));
+ }, [showSubtitleModal]);
const handleClose = () => {
- modalOpacity.value = withTiming(0, { duration: 150 }, () => {
- runOnJS(setShowSubtitleModal)(false);
- });
+ setShowSubtitleModal(false);
};
const handleLanguageClose = () => {
- languageModalOpacity.value = withTiming(0, { duration: 150 }, () => {
- runOnJS(setShowSubtitleLanguageModal)(false);
- });
+ setShowSubtitleLanguageModal(false);
};
- // Render subtitle settings modal
- const renderSubtitleModal = () => {
+ // Main subtitle menu
+ const renderSubtitleMenu = () => {
if (!showSubtitleModal) return null;
return (
-
-
+ {/* Backdrop */}
+
-
-
-
-
-
-
- Subtitle Settings
-
-
- Customize your subtitle experience
-
-
-
-
-
-
-
-
-
-
-
-
- Size Adjustment
-
-
-
-
-
-
-
-
-
- {subtitleSize}
-
-
- Font Size
-
-
-
-
-
-
-
-
-
-
-
- Subtitle Source
-
-
- fetchAvailableSubtitles()}
- >
-
-
-
- Search Online Subtitles
-
-
-
-
-
-
-
-
-
- setShowSubtitleLanguageModal(true)}
- >
-
-
-
- Change Language
-
-
-
- {selectedTextTrack !== -1 && (
- t.id === selectedTextTrack)?.language?.toUpperCase() || 'UNKNOWN'}
- color="#6B7280"
- bgColor="rgba(107, 114, 128, 0.15)"
- />
- )}
-
-
-
-
-
-
-
-
-
+
-
- );
- };
- // Render subtitle language selection modal
- const renderSubtitleLanguageModal = () => {
- if (!showSubtitleLanguageModal) return null;
-
- return (
-
-
-
-
-
-
+
+ Subtitles
+
+
+
+
+
+
+
+ {/* Font Size Section */}
+
+
+ Font Size
+
+
+
-
+ backgroundColor: 'rgba(255, 255, 255, 0.05)',
+ borderRadius: 12,
+ padding: 16,
+ }}>
+
+
+
+
- Subtitle Language
-
-
- Choose from {vlcTextTracks.length} available tracks
+ {subtitleSize}
+
+
+
+
-
-
-
-
-
+
-
-
- {vlcTextTracks.map((track) => (
-
- {
- selectTextTrack(track.id);
- handleLanguageClose();
- }}
- activeOpacity={0.85}
- >
-
-
-
-
- {getTrackDisplayName(track)}
-
-
- {selectedTextTrack === track.id && (
-
-
-
- ACTIVE
-
-
- )}
-
-
-
-
- {track.language && (
-
- )}
-
-
-
-
-
-
-
-
-
- ))}
-
- {/* Online subtitles section */}
- {isLoadingSubtitleList && (
-
-
-
- )}
-
- {availableSubtitles.length > 0 && (
- <>
-
-
- Online Subtitles
-
-
-
- {availableSubtitles.map((sub) => {
- const isCustomSelected = useCustomSubtitles && customSubtitles.length > 0;
- const isThisSubSelected = isCustomSelected; // Since we only load one custom sub at a time
-
- return (
-
- {
- loadWyzieSubtitle(sub);
- handleLanguageClose();
- }}
- activeOpacity={0.85}
- disabled={isLoadingSubtitles}
- >
-
-
-
-
- {sub.display}
-
-
- {isThisSubSelected && (
-
-
-
- LOADED
-
-
- )}
-
-
-
- {isThisSubSelected && (
-
- )}
-
-
-
-
- {isLoadingSubtitles ? (
-
- ) : (
-
- )}
-
-
-
-
- );
- })}
- >
- )}
-
- {/* No Subtitles Option */}
-
- {
- selectTextTrack(-1);
- handleLanguageClose();
- }}
- activeOpacity={0.85}
- >
-
-
-
+ {/* Built-in Subtitles */}
+ {vlcTextTracks.length > 0 && (
+
+
+ Built-in Subtitles
+
+
+
+ {vlcTextTracks.map((track) => {
+ const isSelected = selectedTextTrack === track.id;
+ return (
+ {
+ selectTextTrack(track.id);
+ }}
+ activeOpacity={0.7}
+ >
+
- No Subtitles
+ {getTrackDisplayName(track)}
-
- {selectedTextTrack === -1 && !useCustomSubtitles && (
-
-
-
- ACTIVE
-
-
+ {isSelected && (
+
)}
-
-
-
-
-
-
-
-
-
-
-
+
+ );
+ })}
-
-
+ )}
+
+ {/* Online Subtitles */}
+
+
+
+ Online Subtitles
+
+ fetchAvailableSubtitles()}
+ disabled={isLoadingSubtitleList}
+ >
+ {isLoadingSubtitleList ? (
+
+ ) : (
+
+ )}
+
+ {isLoadingSubtitleList ? 'Searching' : 'Refresh'}
+
+
+
+
+ {availableSubtitles.length > 0 ? (
+
+ {availableSubtitles.map((sub) => {
+ const isSelected = useCustomSubtitles && customSubtitles.length > 0;
+ return (
+ {
+ loadWyzieSubtitle(sub);
+ }}
+ activeOpacity={0.7}
+ disabled={isLoadingSubtitles}
+ >
+
+
+
+ {sub.display}
+
+
+ {formatLanguage(sub.language)}
+
+
+ {isLoadingSubtitles ? (
+
+ ) : isSelected ? (
+
+ ) : (
+
+ )}
+
+
+ );
+ })}
+
+ ) : !isLoadingSubtitleList ? (
+ fetchAvailableSubtitles()}
+ activeOpacity={0.7}
+ >
+
+
+ Tap to search online
+
+
+ ) : (
+
+
+
+ Searching...
+
+
+ )}
+
+
+ {/* Turn Off Subtitles */}
+
+
+ Options
+
+
+ {
+ selectTextTrack(-1);
+ }}
+ activeOpacity={0.7}
+ >
+
+
+
+
+ Turn Off Subtitles
+
+
+ {selectedTextTrack === -1 && !useCustomSubtitles && (
+
+ )}
+
+
+
+
-
+ >
);
};
return (
<>
- {renderSubtitleModal()}
- {renderSubtitleLanguageModal()}
+ {renderSubtitleMenu()}
>
);
};