diff --git a/package-lock.json b/package-lock.json index 1c929c7..0e57348 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,6 @@ "react-native-svg": "15.8.0", "react-native-url-polyfill": "^2.0.0", "react-native-video": "^6.12.0", - "react-native-vlc-media-player": "^1.0.87", "react-native-web": "~0.19.13", "react-native-wheel-color-picker": "^1.3.1" }, @@ -12738,15 +12737,6 @@ "react-native": "*" } }, - "node_modules/react-native-slider": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/react-native-slider/-/react-native-slider-0.11.0.tgz", - "integrity": "sha512-jV9K87eu9uWr0uJIyrSpBLnCKvVlOySC2wynq9TFCdV9oGgjt7Niq8Q1A8R8v+5GHsuBw/s8vEj1AAkkUi+u+w==", - "license": "MIT", - "dependencies": { - "prop-types": "^15.5.6" - } - }, "node_modules/react-native-svg": { "version": "15.8.0", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz", @@ -12898,91 +12888,6 @@ "react-native": "*" } }, - "node_modules/react-native-vector-icons": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz", - "integrity": "sha512-wKYLaFuQST/chH3AJRjmOLoLy3JEs1JR6zMNgTaemFpNoXs0ztRnTxcxFD9xhX7cJe1/zoN5BpQYe7kL0m5yyA==", - "deprecated": "react-native-vector-icons package has moved to a new model of per-icon-family packages. See the https://github.com/oblador/react-native-vector-icons/blob/master/MIGRATION.md on how to migrate", - "license": "MIT", - "dependencies": { - "prop-types": "^15.7.2", - "yargs": "^16.1.1" - }, - "bin": { - "fa5-upgrade": "bin/fa5-upgrade.sh", - "generate-icon": "bin/generate-icon.js" - } - }, - "node_modules/react-native-vector-icons/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/react-native-vector-icons/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/react-native-vector-icons/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-vector-icons/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-vector-icons/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-vector-icons/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/react-native-video": { "version": "6.16.1", "resolved": "https://registry.npmjs.org/react-native-video/-/react-native-video-6.16.1.tgz", @@ -12993,16 +12898,6 @@ "react-native": "*" } }, - "node_modules/react-native-vlc-media-player": { - "version": "1.0.94", - "resolved": "https://registry.npmjs.org/react-native-vlc-media-player/-/react-native-vlc-media-player-1.0.94.tgz", - "integrity": "sha512-6Ee09NY3ir4UN7mSFv8N+4GBiUQzAyVWU54ilwBAOZO8ICU2aJJmOq9ptYxvswIiRcbSz8Z+aB7LnjIlMR6WoQ==", - "license": "MIT", - "dependencies": { - "react-native-slider": "^0.11.0", - "react-native-vector-icons": "^9.2.0" - } - }, "node_modules/react-native-web": { "version": "0.19.13", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", diff --git a/package.json b/package.json index b0c2782..e188db6 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "react-native-svg": "15.8.0", "react-native-url-polyfill": "^2.0.0", "react-native-video": "^6.12.0", - "react-native-vlc-media-player": "^1.0.87", "react-native-web": "~0.19.13", "react-native-wheel-color-picker": "^1.3.1" }, diff --git a/src/components/player/VideoPlayer.tsx b/src/components/player/VideoPlayer.tsx index 3e5e367..3e4322b 100644 --- a/src/components/player/VideoPlayer.tsx +++ b/src/components/player/VideoPlayer.tsx @@ -46,7 +46,7 @@ import * as Brightness from 'expo-brightness'; const VideoPlayer: React.FC = () => { const insets = useSafeAreaInsets(); const route = useRoute>(); - const { uri, headers, forceVlc, streamProvider } = route.params as any; + const { uri, headers, streamProvider } = route.params as any; // Detect if stream is MKV format const isMkvFile = isMkvStream(uri, headers); @@ -150,8 +150,8 @@ const VideoPlayer: React.FC = () => { const [isBackdropLoaded, setIsBackdropLoaded] = useState(false); const backdropImageOpacityAnim = useRef(new Animated.Value(0)).current; const [isBuffering, setIsBuffering] = useState(false); - const [vlcAudioTracks, setVlcAudioTracks] = useState>([]); - const [vlcTextTracks, setVlcTextTracks] = useState>([]); + const [ksAudioTracks, setKsAudioTracks] = useState>([]); + const [ksTextTracks, setKsTextTracks] = useState>([]); const [isPlayerReady, setIsPlayerReady] = useState(false); // Removed progressAnim and progressBarRef - no longer needed with React Native Community Slider const [isDragging, setIsDragging] = useState(false); @@ -193,10 +193,10 @@ const VideoPlayer: React.FC = () => { const [isLoadingSubtitleList, setIsLoadingSubtitleList] = useState(false); const [showSourcesModal, setShowSourcesModal] = useState(false); const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {}); - // Decode URLs for VLC compatibility - VLC has issues with encoded URLs - const decodeUrlForVlc = (url: string): string => { + // Decode URLs for KSPlayer compatibility - KSPlayer handles encoded URLs better + const decodeUrlForKsPlayer = (url: string): string => { try { - // Always decode URLs for VLC as it has trouble with encoded characters + // KSPlayer handles encoded URLs well, but decode for consistency const decoded = decodeURIComponent(url); return decoded; } catch (e) { @@ -205,7 +205,7 @@ const VideoPlayer: React.FC = () => { } }; - const [currentStreamUrl, setCurrentStreamUrl] = useState(decodeUrlForVlc(uri)); + const [currentStreamUrl, setCurrentStreamUrl] = useState(decodeUrlForKsPlayer(uri)); const [isChangingSource, setIsChangingSource] = useState(false); const [showErrorModal, setShowErrorModal] = useState(false); const [errorDetails, setErrorDetails] = useState(''); @@ -244,20 +244,20 @@ const VideoPlayer: React.FC = () => { const castDetailsScale = useRef(new Animated.Value(0.95)).current; // Volume and brightness controls - const [volume, setVolume] = useState(100); // VLC uses 0-100 range + const [volume, setVolume] = useState(100); // KSPlayer uses 0-100 range const [brightness, setBrightness] = useState(1.0); const [showVolumeOverlay, setShowVolumeOverlay] = useState(false); const [showBrightnessOverlay, setShowBrightnessOverlay] = useState(false); - const [showVlcVolumeWarning, setShowVlcVolumeWarning] = useState(false); - const [hasShownVlcWarning, setHasShownVlcWarning] = useState(false); + const [showKsVolumeWarning, setShowKsVolumeWarning] = useState(false); + const [hasShownKsWarning, setHasShownKsWarning] = useState(false); - // Load VLC warning state from storage + // Load KSPlayer warning state from storage useEffect(() => { const loadWarningState = async () => { try { - const warningShown = await AsyncStorage.getItem('vlc_volume_warning_shown'); + const warningShown = await AsyncStorage.getItem('ks_volume_warning_shown'); if (warningShown === 'true') { - setHasShownVlcWarning(true); + setHasShownKsWarning(true); } } catch (error) { // Ignore storage errors @@ -428,17 +428,17 @@ const VideoPlayer: React.FC = () => { const { translationY, state } = event.nativeEvent; if (state === State.ACTIVE) { - // Show VLC volume warning only once per session - if (!showVlcVolumeWarning && !hasShownVlcWarning) { - setShowVlcVolumeWarning(true); - setHasShownVlcWarning(true); + // Show KSPlayer volume warning only once per session + if (!showKsVolumeWarning && !hasShownKsWarning) { + setShowKsVolumeWarning(true); + setHasShownKsWarning(true); // Save to storage that warning has been shown - AsyncStorage.setItem('vlc_volume_warning_shown', 'true').catch(() => {}); + AsyncStorage.setItem('ks_volume_warning_shown', 'true').catch(() => {}); // Hide warning after 4 seconds setTimeout(() => { - setShowVlcVolumeWarning(false); + setShowKsVolumeWarning(false); }, 4000); } } @@ -552,10 +552,10 @@ const VideoPlayer: React.FC = () => { startOpeningAnimation(); // Initialize current volume and brightness levels - // Volume starts at 100 (full volume) for VLC + // Volume starts at 100 (full volume) for KSPlayer setVolume(100); if (DEBUG_MODE) { - logger.log(`[VideoPlayer] Initial volume: 100 (VLC native)`); + logger.log(`[VideoPlayer] Initial volume: 100 (KSPlayer native)`); } try { @@ -901,11 +901,11 @@ const VideoPlayer: React.FC = () => { setLastAudioTrackCheck(now); // Check if audio track is disabled (-1) and we have available tracks - if (selectedAudioTrack === -1 && vlcAudioTracks.length > 1) { + if (selectedAudioTrack === -1 && ksAudioTracks.length > 1) { logger.warn('[VideoPlayer] Detected disabled audio track, attempting fallback'); // Find a fallback audio track (prefer stereo/standard formats) - const fallbackTrack = vlcAudioTracks.find((track, index) => { + const fallbackTrack = ksAudioTracks.find((track, index) => { const trackName = (track.name || '').toLowerCase(); const trackLang = (track.language || '').toLowerCase(); // Prefer stereo, AAC, or standard audio formats, avoid heavy codecs @@ -919,7 +919,7 @@ const VideoPlayer: React.FC = () => { }); if (fallbackTrack) { - const fallbackIndex = vlcAudioTracks.indexOf(fallbackTrack); + const fallbackIndex = ksAudioTracks.indexOf(fallbackTrack); logger.warn(`[VideoPlayer] Switching to fallback audio track: ${fallbackTrack.name || 'Unknown'} (index: ${fallbackIndex})`); // Increment fallback attempts counter @@ -1073,7 +1073,7 @@ const VideoPlayer: React.FC = () => { language: trackLanguage, }; }); - setVlcAudioTracks(formattedAudioTracks); + setKsAudioTracks(formattedAudioTracks); // Auto-select English audio track if available, otherwise first track if (selectedAudioTrack === null && formattedAudioTracks.length > 0) { @@ -1110,7 +1110,7 @@ const VideoPlayer: React.FC = () => { isImageSubtitle: track.isImageSubtitle || false })); - setVlcTextTracks(formattedTextTracks); + setKsTextTracks(formattedTextTracks); // Auto-select English subtitle track if available if (selectedTextTrack === -1 && !useCustomSubtitles && formattedTextTracks.length > 0) { @@ -1351,11 +1351,11 @@ const VideoPlayer: React.FC = () => { (error?.title && /codec not supported/i.test(error.title)); // Handle audio codec errors with automatic fallback - if (isAudioCodecError && vlcAudioTracks.length > 1) { + if (isAudioCodecError && ksAudioTracks.length > 1) { logger.warn('[VideoPlayer] Audio codec error detected, attempting audio track fallback'); // Find a fallback audio track (prefer stereo/standard formats) - const fallbackTrack = vlcAudioTracks.find((track, index) => { + const fallbackTrack = ksAudioTracks.find((track, index) => { const trackName = (track.name || '').toLowerCase(); const trackLang = (track.language || '').toLowerCase(); // Prefer stereo, AAC, or standard audio formats, avoid heavy codecs @@ -1369,7 +1369,7 @@ const VideoPlayer: React.FC = () => { }); if (fallbackTrack) { - const fallbackIndex = vlcAudioTracks.indexOf(fallbackTrack); + const fallbackIndex = ksAudioTracks.indexOf(fallbackTrack); logger.warn(`[VideoPlayer] Switching to fallback audio track: ${fallbackTrack.name || 'Unknown'} (index: ${fallbackIndex})`); // Clear any existing error state @@ -1478,18 +1478,18 @@ const VideoPlayer: React.FC = () => { const selectAudioTrack = (trackId: number) => { if (DEBUG_MODE) { logger.log(`[VideoPlayer] Selecting audio track: ${trackId}`); - logger.log(`[VideoPlayer] Available tracks:`, vlcAudioTracks); + logger.log(`[VideoPlayer] Available tracks:`, ksAudioTracks); } // Validate that the track exists - const trackExists = vlcAudioTracks.some(track => track.id === trackId); + const trackExists = ksAudioTracks.some(track => track.id === trackId); if (!trackExists) { logger.error(`[VideoPlayer] Audio track ${trackId} not found in available tracks`); return; } // Get the selected track info for logging - const selectedTrack = vlcAudioTracks.find(track => track.id === trackId); + const selectedTrack = ksAudioTracks.find(track => track.id === trackId); if (selectedTrack && DEBUG_MODE) { logger.log(`[VideoPlayer] Switching to track: ${selectedTrack.name} (${selectedTrack.language})`); @@ -1541,12 +1541,12 @@ const VideoPlayer: React.FC = () => { } }; - // Ensure native VLC text tracks are disabled when using custom (addon) subtitles + // Ensure native KSPlayer text tracks are disabled when using custom (addon) subtitles // and re-applied when switching back to built-in tracks. This prevents double-rendering. useEffect(() => { try { if (useCustomSubtitles) { - // -1 disables native subtitle rendering in VLC + // -1 disables native subtitle rendering in KSPlayer setSelectedTextTrack(-1); } else if (typeof selectedTextTrack === 'number' && selectedTextTrack >= 0) { // KSPlayer picks it up via prop @@ -1692,7 +1692,7 @@ const VideoPlayer: React.FC = () => { const parsedCues = parseSRT(srtContent); logger.log(`[VideoPlayer] Parsed cues count=${parsedCues.length}`); - // For VLC on iOS: stop spinner early, then clear-apply and micro-seek nudge + // For KSPlayer on iOS: stop spinner early, then clear-apply and micro-seek nudge setIsLoadingSubtitles(false); logger.log('[VideoPlayer] isLoadingSubtitles -> false (early)'); @@ -1825,7 +1825,6 @@ const VideoPlayer: React.FC = () => { streamProvider: addonName, streamName: bestStream.name || bestStream.title, headers: bestStream.headers || undefined, - forceVlc: false, id, type: 'series', episodeId: nextEpisodeId, @@ -2121,8 +2120,8 @@ const VideoPlayer: React.FC = () => { // Handle audio track changes with proper logging useEffect(() => { - if (selectedAudioTrack !== null && vlcAudioTracks.length > 0) { - const selectedTrack = vlcAudioTracks.find(track => track.id === selectedAudioTrack); + if (selectedAudioTrack !== null && ksAudioTracks.length > 0) { + const selectedTrack = ksAudioTracks.find(track => track.id === selectedAudioTrack); if (selectedTrack) { if (DEBUG_MODE) { logger.log(`[VideoPlayer] Audio track selected: ${selectedTrack.name} (${selectedTrack.language}) - ID: ${selectedAudioTrack}`); @@ -2131,7 +2130,7 @@ const VideoPlayer: React.FC = () => { logger.warn(`[VideoPlayer] Selected audio track ${selectedAudioTrack} not found in available tracks`); } } - }, [selectedAudioTrack, vlcAudioTracks]); + }, [selectedAudioTrack, ksAudioTracks]); const increaseSubtitleSize = () => { const newSize = Math.min(subtitleSize + 2, 32); @@ -2231,8 +2230,8 @@ const VideoPlayer: React.FC = () => { // Set pending seek state setPendingSeek({ position: savedPosition, shouldPlay: wasPlaying }); - // Update the stream URL and details immediately (decode URL for VLC) - setCurrentStreamUrl(decodeUrlForVlc(newStream.url)); + // Update the stream URL and details immediately (decode URL for KSPlayer) + setCurrentStreamUrl(decodeUrlForKsPlayer(newStream.url)); setCurrentQuality(newQuality); setCurrentStreamProvider(newProvider); setCurrentStreamName(newStreamName); @@ -2559,7 +2558,7 @@ const VideoPlayer: React.FC = () => { currentTime={currentTime} duration={duration} zoomScale={zoomScale} - vlcAudioTracks={vlcAudioTracks} + ksAudioTracks={ksAudioTracks} selectedAudioTrack={selectedAudioTrack} availableStreams={availableStreams} togglePlayback={togglePlayback} @@ -3148,8 +3147,8 @@ const VideoPlayer: React.FC = () => { )} - {/* VLC Volume Warning Overlay */} - {showVlcVolumeWarning && ( + {/* KSPlayer Volume Warning Overlay */} + {showKsVolumeWarning && ( { lineHeight: 18, marginBottom: 12, }}> - VLC player doesn't support volume gestures.{'\n'}Use your device volume buttons instead. + KSPlayer doesn't support volume gestures.{'\n'}Use your device volume buttons instead. { @@ -3236,7 +3235,7 @@ const VideoPlayer: React.FC = () => { isLoadingSubtitles={isLoadingSubtitles} customSubtitles={customSubtitles} availableSubtitles={availableSubtitles} - vlcTextTracks={vlcTextTracks} + ksTextTracks={ksTextTracks} selectedTextTrack={selectedTextTrack} useCustomSubtitles={useCustomSubtitles} subtitleSize={subtitleSize} diff --git a/src/components/player/controls/PlayerControls.tsx b/src/components/player/controls/PlayerControls.tsx index 7b3f2e7..16d6d43 100644 --- a/src/components/player/controls/PlayerControls.tsx +++ b/src/components/player/controls/PlayerControls.tsx @@ -23,7 +23,7 @@ interface PlayerControlsProps { duration: number; zoomScale: number; currentResizeMode?: string; - vlcAudioTracks: Array<{id: number, name: string, language?: string}>; + ksAudioTracks: Array<{id: number, name: string, language?: string}>; selectedAudioTrack: number | null; availableStreams?: { [providerId: string]: { streams: any[]; addonName: string } }; togglePlayback: () => void; @@ -58,7 +58,7 @@ export const PlayerControls: React.FC = ({ duration, zoomScale, currentResizeMode, - vlcAudioTracks, + ksAudioTracks, selectedAudioTrack, availableStreams, togglePlayback, @@ -170,17 +170,17 @@ export const PlayerControls: React.FC = ({ - {/* Audio Button - Updated to use vlcAudioTracks */} + {/* Audio Button - Updated to use ksAudioTracks */} setShowAudioModal(true)} - disabled={vlcAudioTracks.length <= 1} + disabled={ksAudioTracks.length <= 1} > - - + + {(() => { const trackName = getTrackDisplayName( - vlcAudioTracks.find(t => t.id === selectedAudioTrack) || { id: -1, name: 'Default' } + ksAudioTracks.find(t => t.id === selectedAudioTrack) || { id: -1, name: 'Default' } ); // Truncate long audio track names to prevent UI cramping const maxLength = 12; // Limit to 12 characters diff --git a/src/components/player/modals/AudioTrackModal.tsx b/src/components/player/modals/AudioTrackModal.tsx index 58fade0..a0a2304 100644 --- a/src/components/player/modals/AudioTrackModal.tsx +++ b/src/components/player/modals/AudioTrackModal.tsx @@ -13,7 +13,7 @@ import { logger } from '../../../utils/logger'; interface AudioTrackModalProps { showAudioModal: boolean; setShowAudioModal: (show: boolean) => void; - vlcAudioTracks: Array<{id: number, name: string, language?: string}>; + ksAudioTracks: Array<{id: number, name: string, language?: string}>; selectedAudioTrack: number | null; selectAudioTrack: (trackId: number) => void; } @@ -24,7 +24,7 @@ const MENU_WIDTH = Math.min(width * 0.85, 400); export const AudioTrackModal: React.FC = ({ showAudioModal, setShowAudioModal, - vlcAudioTracks, + ksAudioTracks, selectedAudioTrack, selectAudioTrack, }) => { @@ -36,9 +36,9 @@ export const AudioTrackModal: React.FC = ({ React.useEffect(() => { if (showAudioModal && DEBUG_MODE) { logger.log(`[AudioTrackModal] Modal opened with selectedAudioTrack:`, selectedAudioTrack); - logger.log(`[AudioTrackModal] Available tracks:`, vlcAudioTracks); + logger.log(`[AudioTrackModal] Available tracks:`, ksAudioTracks); if (typeof selectedAudioTrack === 'number') { - const selectedTrack = vlcAudioTracks.find(track => track.id === selectedAudioTrack); + const selectedTrack = ksAudioTracks.find(track => track.id === selectedAudioTrack); if (selectedTrack) { logger.log(`[AudioTrackModal] Selected track found: ${selectedTrack.name} (${selectedTrack.language})`); } else { @@ -46,7 +46,7 @@ export const AudioTrackModal: React.FC = ({ } } } - }, [showAudioModal, selectedAudioTrack, vlcAudioTracks]); + }, [showAudioModal, selectedAudioTrack, ksAudioTracks]); if (!showAudioModal) return null; @@ -143,11 +143,11 @@ export const AudioTrackModal: React.FC = ({ textTransform: 'uppercase', letterSpacing: 0.5, }}> - Available Tracks ({vlcAudioTracks.length}) + Available Tracks ({ksAudioTracks.length}) - {vlcAudioTracks.map((track) => { + {ksAudioTracks.map((track) => { // Determine if track is selected const isSelected = selectedAudioTrack === track.id; @@ -203,7 +203,7 @@ export const AudioTrackModal: React.FC = ({ })} - {vlcAudioTracks.length === 0 && ( + {ksAudioTracks.length === 0 && ( ; + ksTextTracks: Array<{id: number, name: string, language?: string}>; selectedTextTrack: number; useCustomSubtitles: boolean; subtitleSize: number; @@ -68,7 +68,7 @@ export const SubtitleModals: React.FC = ({ isLoadingSubtitles, customSubtitles, availableSubtitles, - vlcTextTracks, + ksTextTracks, selectedTextTrack, useCustomSubtitles, subtitleSize, @@ -286,10 +286,10 @@ export const SubtitleModals: React.FC = ({ - {vlcTextTracks.map((track) => { + {ksTextTracks.map((track) => { const isSelected = selectedTextTrack === track.id && !useCustomSubtitles; // Debug logging for subtitle selection - if (__DEV__ && vlcTextTracks.length > 0) { + if (__DEV__ && ksTextTracks.length > 0) { console.log('[SubtitleModals] Track:', track.id, track.name, 'Selected:', selectedTextTrack, 'isSelected:', isSelected, 'useCustom:', useCustomSubtitles); } return (