cleaned VLC

This commit is contained in:
tapframe 2025-09-18 02:09:34 +05:30
parent 18815b8233
commit 688ea2b9d3
6 changed files with 65 additions and 172 deletions

105
package-lock.json generated
View file

@ -72,7 +72,6 @@
"react-native-svg": "15.8.0", "react-native-svg": "15.8.0",
"react-native-url-polyfill": "^2.0.0", "react-native-url-polyfill": "^2.0.0",
"react-native-video": "^6.12.0", "react-native-video": "^6.12.0",
"react-native-vlc-media-player": "^1.0.87",
"react-native-web": "~0.19.13", "react-native-web": "~0.19.13",
"react-native-wheel-color-picker": "^1.3.1" "react-native-wheel-color-picker": "^1.3.1"
}, },
@ -12738,15 +12737,6 @@
"react-native": "*" "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": { "node_modules/react-native-svg": {
"version": "15.8.0", "version": "15.8.0",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz",
@ -12898,91 +12888,6 @@
"react-native": "*" "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": { "node_modules/react-native-video": {
"version": "6.16.1", "version": "6.16.1",
"resolved": "https://registry.npmjs.org/react-native-video/-/react-native-video-6.16.1.tgz", "resolved": "https://registry.npmjs.org/react-native-video/-/react-native-video-6.16.1.tgz",
@ -12993,16 +12898,6 @@
"react-native": "*" "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": { "node_modules/react-native-web": {
"version": "0.19.13", "version": "0.19.13",
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz",

View file

@ -72,7 +72,6 @@
"react-native-svg": "15.8.0", "react-native-svg": "15.8.0",
"react-native-url-polyfill": "^2.0.0", "react-native-url-polyfill": "^2.0.0",
"react-native-video": "^6.12.0", "react-native-video": "^6.12.0",
"react-native-vlc-media-player": "^1.0.87",
"react-native-web": "~0.19.13", "react-native-web": "~0.19.13",
"react-native-wheel-color-picker": "^1.3.1" "react-native-wheel-color-picker": "^1.3.1"
}, },

View file

@ -46,7 +46,7 @@ import * as Brightness from 'expo-brightness';
const VideoPlayer: React.FC = () => { const VideoPlayer: React.FC = () => {
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const route = useRoute<RouteProp<RootStackParamList, 'Player'>>(); const route = useRoute<RouteProp<RootStackParamList, 'Player'>>();
const { uri, headers, forceVlc, streamProvider } = route.params as any; const { uri, headers, streamProvider } = route.params as any;
// Detect if stream is MKV format // Detect if stream is MKV format
const isMkvFile = isMkvStream(uri, headers); const isMkvFile = isMkvStream(uri, headers);
@ -150,8 +150,8 @@ const VideoPlayer: React.FC = () => {
const [isBackdropLoaded, setIsBackdropLoaded] = useState(false); const [isBackdropLoaded, setIsBackdropLoaded] = useState(false);
const backdropImageOpacityAnim = useRef(new Animated.Value(0)).current; const backdropImageOpacityAnim = useRef(new Animated.Value(0)).current;
const [isBuffering, setIsBuffering] = useState(false); const [isBuffering, setIsBuffering] = useState(false);
const [vlcAudioTracks, setVlcAudioTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]); const [ksAudioTracks, setKsAudioTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]);
const [vlcTextTracks, setVlcTextTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]); const [ksTextTracks, setKsTextTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]);
const [isPlayerReady, setIsPlayerReady] = useState(false); const [isPlayerReady, setIsPlayerReady] = useState(false);
// Removed progressAnim and progressBarRef - no longer needed with React Native Community Slider // Removed progressAnim and progressBarRef - no longer needed with React Native Community Slider
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
@ -193,10 +193,10 @@ const VideoPlayer: React.FC = () => {
const [isLoadingSubtitleList, setIsLoadingSubtitleList] = useState<boolean>(false); const [isLoadingSubtitleList, setIsLoadingSubtitleList] = useState<boolean>(false);
const [showSourcesModal, setShowSourcesModal] = useState<boolean>(false); const [showSourcesModal, setShowSourcesModal] = useState<boolean>(false);
const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {}); const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {});
// Decode URLs for VLC compatibility - VLC has issues with encoded URLs // Decode URLs for KSPlayer compatibility - KSPlayer handles encoded URLs better
const decodeUrlForVlc = (url: string): string => { const decodeUrlForKsPlayer = (url: string): string => {
try { 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); const decoded = decodeURIComponent(url);
return decoded; return decoded;
} catch (e) { } catch (e) {
@ -205,7 +205,7 @@ const VideoPlayer: React.FC = () => {
} }
}; };
const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(decodeUrlForVlc(uri)); const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(decodeUrlForKsPlayer(uri));
const [isChangingSource, setIsChangingSource] = useState<boolean>(false); const [isChangingSource, setIsChangingSource] = useState<boolean>(false);
const [showErrorModal, setShowErrorModal] = useState(false); const [showErrorModal, setShowErrorModal] = useState(false);
const [errorDetails, setErrorDetails] = useState<string>(''); const [errorDetails, setErrorDetails] = useState<string>('');
@ -244,20 +244,20 @@ const VideoPlayer: React.FC = () => {
const castDetailsScale = useRef(new Animated.Value(0.95)).current; const castDetailsScale = useRef(new Animated.Value(0.95)).current;
// Volume and brightness controls // 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 [brightness, setBrightness] = useState(1.0);
const [showVolumeOverlay, setShowVolumeOverlay] = useState(false); const [showVolumeOverlay, setShowVolumeOverlay] = useState(false);
const [showBrightnessOverlay, setShowBrightnessOverlay] = useState(false); const [showBrightnessOverlay, setShowBrightnessOverlay] = useState(false);
const [showVlcVolumeWarning, setShowVlcVolumeWarning] = useState(false); const [showKsVolumeWarning, setShowKsVolumeWarning] = useState(false);
const [hasShownVlcWarning, setHasShownVlcWarning] = useState(false); const [hasShownKsWarning, setHasShownKsWarning] = useState(false);
// Load VLC warning state from storage // Load KSPlayer warning state from storage
useEffect(() => { useEffect(() => {
const loadWarningState = async () => { const loadWarningState = async () => {
try { try {
const warningShown = await AsyncStorage.getItem('vlc_volume_warning_shown'); const warningShown = await AsyncStorage.getItem('ks_volume_warning_shown');
if (warningShown === 'true') { if (warningShown === 'true') {
setHasShownVlcWarning(true); setHasShownKsWarning(true);
} }
} catch (error) { } catch (error) {
// Ignore storage errors // Ignore storage errors
@ -428,17 +428,17 @@ const VideoPlayer: React.FC = () => {
const { translationY, state } = event.nativeEvent; const { translationY, state } = event.nativeEvent;
if (state === State.ACTIVE) { if (state === State.ACTIVE) {
// Show VLC volume warning only once per session // Show KSPlayer volume warning only once per session
if (!showVlcVolumeWarning && !hasShownVlcWarning) { if (!showKsVolumeWarning && !hasShownKsWarning) {
setShowVlcVolumeWarning(true); setShowKsVolumeWarning(true);
setHasShownVlcWarning(true); setHasShownKsWarning(true);
// Save to storage that warning has been shown // 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 // Hide warning after 4 seconds
setTimeout(() => { setTimeout(() => {
setShowVlcVolumeWarning(false); setShowKsVolumeWarning(false);
}, 4000); }, 4000);
} }
} }
@ -552,10 +552,10 @@ const VideoPlayer: React.FC = () => {
startOpeningAnimation(); startOpeningAnimation();
// Initialize current volume and brightness levels // Initialize current volume and brightness levels
// Volume starts at 100 (full volume) for VLC // Volume starts at 100 (full volume) for KSPlayer
setVolume(100); setVolume(100);
if (DEBUG_MODE) { if (DEBUG_MODE) {
logger.log(`[VideoPlayer] Initial volume: 100 (VLC native)`); logger.log(`[VideoPlayer] Initial volume: 100 (KSPlayer native)`);
} }
try { try {
@ -901,11 +901,11 @@ const VideoPlayer: React.FC = () => {
setLastAudioTrackCheck(now); setLastAudioTrackCheck(now);
// Check if audio track is disabled (-1) and we have available tracks // 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'); logger.warn('[VideoPlayer] Detected disabled audio track, attempting fallback');
// Find a fallback audio track (prefer stereo/standard formats) // 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 trackName = (track.name || '').toLowerCase();
const trackLang = (track.language || '').toLowerCase(); const trackLang = (track.language || '').toLowerCase();
// Prefer stereo, AAC, or standard audio formats, avoid heavy codecs // Prefer stereo, AAC, or standard audio formats, avoid heavy codecs
@ -919,7 +919,7 @@ const VideoPlayer: React.FC = () => {
}); });
if (fallbackTrack) { 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})`); logger.warn(`[VideoPlayer] Switching to fallback audio track: ${fallbackTrack.name || 'Unknown'} (index: ${fallbackIndex})`);
// Increment fallback attempts counter // Increment fallback attempts counter
@ -1073,7 +1073,7 @@ const VideoPlayer: React.FC = () => {
language: trackLanguage, language: trackLanguage,
}; };
}); });
setVlcAudioTracks(formattedAudioTracks); setKsAudioTracks(formattedAudioTracks);
// Auto-select English audio track if available, otherwise first track // Auto-select English audio track if available, otherwise first track
if (selectedAudioTrack === null && formattedAudioTracks.length > 0) { if (selectedAudioTrack === null && formattedAudioTracks.length > 0) {
@ -1110,7 +1110,7 @@ const VideoPlayer: React.FC = () => {
isImageSubtitle: track.isImageSubtitle || false isImageSubtitle: track.isImageSubtitle || false
})); }));
setVlcTextTracks(formattedTextTracks); setKsTextTracks(formattedTextTracks);
// Auto-select English subtitle track if available // Auto-select English subtitle track if available
if (selectedTextTrack === -1 && !useCustomSubtitles && formattedTextTracks.length > 0) { if (selectedTextTrack === -1 && !useCustomSubtitles && formattedTextTracks.length > 0) {
@ -1351,11 +1351,11 @@ const VideoPlayer: React.FC = () => {
(error?.title && /codec not supported/i.test(error.title)); (error?.title && /codec not supported/i.test(error.title));
// Handle audio codec errors with automatic fallback // 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'); logger.warn('[VideoPlayer] Audio codec error detected, attempting audio track fallback');
// Find a fallback audio track (prefer stereo/standard formats) // 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 trackName = (track.name || '').toLowerCase();
const trackLang = (track.language || '').toLowerCase(); const trackLang = (track.language || '').toLowerCase();
// Prefer stereo, AAC, or standard audio formats, avoid heavy codecs // Prefer stereo, AAC, or standard audio formats, avoid heavy codecs
@ -1369,7 +1369,7 @@ const VideoPlayer: React.FC = () => {
}); });
if (fallbackTrack) { 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})`); logger.warn(`[VideoPlayer] Switching to fallback audio track: ${fallbackTrack.name || 'Unknown'} (index: ${fallbackIndex})`);
// Clear any existing error state // Clear any existing error state
@ -1478,18 +1478,18 @@ const VideoPlayer: React.FC = () => {
const selectAudioTrack = (trackId: number) => { const selectAudioTrack = (trackId: number) => {
if (DEBUG_MODE) { if (DEBUG_MODE) {
logger.log(`[VideoPlayer] Selecting audio track: ${trackId}`); logger.log(`[VideoPlayer] Selecting audio track: ${trackId}`);
logger.log(`[VideoPlayer] Available tracks:`, vlcAudioTracks); logger.log(`[VideoPlayer] Available tracks:`, ksAudioTracks);
} }
// Validate that the track exists // Validate that the track exists
const trackExists = vlcAudioTracks.some(track => track.id === trackId); const trackExists = ksAudioTracks.some(track => track.id === trackId);
if (!trackExists) { if (!trackExists) {
logger.error(`[VideoPlayer] Audio track ${trackId} not found in available tracks`); logger.error(`[VideoPlayer] Audio track ${trackId} not found in available tracks`);
return; return;
} }
// Get the selected track info for logging // 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) { if (selectedTrack && DEBUG_MODE) {
logger.log(`[VideoPlayer] Switching to track: ${selectedTrack.name} (${selectedTrack.language})`); 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. // and re-applied when switching back to built-in tracks. This prevents double-rendering.
useEffect(() => { useEffect(() => {
try { try {
if (useCustomSubtitles) { if (useCustomSubtitles) {
// -1 disables native subtitle rendering in VLC // -1 disables native subtitle rendering in KSPlayer
setSelectedTextTrack(-1); setSelectedTextTrack(-1);
} else if (typeof selectedTextTrack === 'number' && selectedTextTrack >= 0) { } else if (typeof selectedTextTrack === 'number' && selectedTextTrack >= 0) {
// KSPlayer picks it up via prop // KSPlayer picks it up via prop
@ -1692,7 +1692,7 @@ const VideoPlayer: React.FC = () => {
const parsedCues = parseSRT(srtContent); const parsedCues = parseSRT(srtContent);
logger.log(`[VideoPlayer] Parsed cues count=${parsedCues.length}`); 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); setIsLoadingSubtitles(false);
logger.log('[VideoPlayer] isLoadingSubtitles -> false (early)'); logger.log('[VideoPlayer] isLoadingSubtitles -> false (early)');
@ -1825,7 +1825,6 @@ const VideoPlayer: React.FC = () => {
streamProvider: addonName, streamProvider: addonName,
streamName: bestStream.name || bestStream.title, streamName: bestStream.name || bestStream.title,
headers: bestStream.headers || undefined, headers: bestStream.headers || undefined,
forceVlc: false,
id, id,
type: 'series', type: 'series',
episodeId: nextEpisodeId, episodeId: nextEpisodeId,
@ -2121,8 +2120,8 @@ const VideoPlayer: React.FC = () => {
// Handle audio track changes with proper logging // Handle audio track changes with proper logging
useEffect(() => { useEffect(() => {
if (selectedAudioTrack !== null && vlcAudioTracks.length > 0) { if (selectedAudioTrack !== null && ksAudioTracks.length > 0) {
const selectedTrack = vlcAudioTracks.find(track => track.id === selectedAudioTrack); const selectedTrack = ksAudioTracks.find(track => track.id === selectedAudioTrack);
if (selectedTrack) { if (selectedTrack) {
if (DEBUG_MODE) { if (DEBUG_MODE) {
logger.log(`[VideoPlayer] Audio track selected: ${selectedTrack.name} (${selectedTrack.language}) - ID: ${selectedAudioTrack}`); 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`); logger.warn(`[VideoPlayer] Selected audio track ${selectedAudioTrack} not found in available tracks`);
} }
} }
}, [selectedAudioTrack, vlcAudioTracks]); }, [selectedAudioTrack, ksAudioTracks]);
const increaseSubtitleSize = () => { const increaseSubtitleSize = () => {
const newSize = Math.min(subtitleSize + 2, 32); const newSize = Math.min(subtitleSize + 2, 32);
@ -2231,8 +2230,8 @@ const VideoPlayer: React.FC = () => {
// Set pending seek state // Set pending seek state
setPendingSeek({ position: savedPosition, shouldPlay: wasPlaying }); setPendingSeek({ position: savedPosition, shouldPlay: wasPlaying });
// Update the stream URL and details immediately (decode URL for VLC) // Update the stream URL and details immediately (decode URL for KSPlayer)
setCurrentStreamUrl(decodeUrlForVlc(newStream.url)); setCurrentStreamUrl(decodeUrlForKsPlayer(newStream.url));
setCurrentQuality(newQuality); setCurrentQuality(newQuality);
setCurrentStreamProvider(newProvider); setCurrentStreamProvider(newProvider);
setCurrentStreamName(newStreamName); setCurrentStreamName(newStreamName);
@ -2559,7 +2558,7 @@ const VideoPlayer: React.FC = () => {
currentTime={currentTime} currentTime={currentTime}
duration={duration} duration={duration}
zoomScale={zoomScale} zoomScale={zoomScale}
vlcAudioTracks={vlcAudioTracks} ksAudioTracks={ksAudioTracks}
selectedAudioTrack={selectedAudioTrack} selectedAudioTrack={selectedAudioTrack}
availableStreams={availableStreams} availableStreams={availableStreams}
togglePlayback={togglePlayback} togglePlayback={togglePlayback}
@ -3148,8 +3147,8 @@ const VideoPlayer: React.FC = () => {
</Animated.View> </Animated.View>
)} )}
{/* VLC Volume Warning Overlay */} {/* KSPlayer Volume Warning Overlay */}
{showVlcVolumeWarning && ( {showKsVolumeWarning && (
<View <View
style={{ style={{
position: 'absolute', position: 'absolute',
@ -3201,7 +3200,7 @@ const VideoPlayer: React.FC = () => {
lineHeight: 18, lineHeight: 18,
marginBottom: 12, 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.
</Text> </Text>
<Text style={{ <Text style={{
@ -3223,7 +3222,7 @@ const VideoPlayer: React.FC = () => {
<AudioTrackModal <AudioTrackModal
showAudioModal={showAudioModal} showAudioModal={showAudioModal}
setShowAudioModal={setShowAudioModal} setShowAudioModal={setShowAudioModal}
vlcAudioTracks={vlcAudioTracks} ksAudioTracks={ksAudioTracks}
selectedAudioTrack={selectedAudioTrack} selectedAudioTrack={selectedAudioTrack}
selectAudioTrack={selectAudioTrack} selectAudioTrack={selectAudioTrack}
/> />
@ -3236,7 +3235,7 @@ const VideoPlayer: React.FC = () => {
isLoadingSubtitles={isLoadingSubtitles} isLoadingSubtitles={isLoadingSubtitles}
customSubtitles={customSubtitles} customSubtitles={customSubtitles}
availableSubtitles={availableSubtitles} availableSubtitles={availableSubtitles}
vlcTextTracks={vlcTextTracks} ksTextTracks={ksTextTracks}
selectedTextTrack={selectedTextTrack} selectedTextTrack={selectedTextTrack}
useCustomSubtitles={useCustomSubtitles} useCustomSubtitles={useCustomSubtitles}
subtitleSize={subtitleSize} subtitleSize={subtitleSize}

View file

@ -23,7 +23,7 @@ interface PlayerControlsProps {
duration: number; duration: number;
zoomScale: number; zoomScale: number;
currentResizeMode?: string; currentResizeMode?: string;
vlcAudioTracks: Array<{id: number, name: string, language?: string}>; ksAudioTracks: Array<{id: number, name: string, language?: string}>;
selectedAudioTrack: number | null; selectedAudioTrack: number | null;
availableStreams?: { [providerId: string]: { streams: any[]; addonName: string } }; availableStreams?: { [providerId: string]: { streams: any[]; addonName: string } };
togglePlayback: () => void; togglePlayback: () => void;
@ -58,7 +58,7 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
duration, duration,
zoomScale, zoomScale,
currentResizeMode, currentResizeMode,
vlcAudioTracks, ksAudioTracks,
selectedAudioTrack, selectedAudioTrack,
availableStreams, availableStreams,
togglePlayback, togglePlayback,
@ -170,17 +170,17 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
{/* Audio Button - Updated to use vlcAudioTracks */} {/* Audio Button - Updated to use ksAudioTracks */}
<TouchableOpacity <TouchableOpacity
style={styles.bottomButton} style={styles.bottomButton}
onPress={() => setShowAudioModal(true)} onPress={() => setShowAudioModal(true)}
disabled={vlcAudioTracks.length <= 1} disabled={ksAudioTracks.length <= 1}
> >
<Ionicons name="volume-high" size={20} color={vlcAudioTracks.length <= 1 ? 'grey' : 'white'} /> <Ionicons name="volume-high" size={20} color={ksAudioTracks.length <= 1 ? 'grey' : 'white'} />
<Text style={[styles.bottomButtonText, vlcAudioTracks.length <= 1 && {color: 'grey'}]} numberOfLines={1}> <Text style={[styles.bottomButtonText, ksAudioTracks.length <= 1 && {color: 'grey'}]} numberOfLines={1}>
{(() => { {(() => {
const trackName = getTrackDisplayName( 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 // Truncate long audio track names to prevent UI cramping
const maxLength = 12; // Limit to 12 characters const maxLength = 12; // Limit to 12 characters

View file

@ -13,7 +13,7 @@ import { logger } from '../../../utils/logger';
interface AudioTrackModalProps { interface AudioTrackModalProps {
showAudioModal: boolean; showAudioModal: boolean;
setShowAudioModal: (show: boolean) => void; setShowAudioModal: (show: boolean) => void;
vlcAudioTracks: Array<{id: number, name: string, language?: string}>; ksAudioTracks: Array<{id: number, name: string, language?: string}>;
selectedAudioTrack: number | null; selectedAudioTrack: number | null;
selectAudioTrack: (trackId: number) => void; selectAudioTrack: (trackId: number) => void;
} }
@ -24,7 +24,7 @@ const MENU_WIDTH = Math.min(width * 0.85, 400);
export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({ export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({
showAudioModal, showAudioModal,
setShowAudioModal, setShowAudioModal,
vlcAudioTracks, ksAudioTracks,
selectedAudioTrack, selectedAudioTrack,
selectAudioTrack, selectAudioTrack,
}) => { }) => {
@ -36,9 +36,9 @@ export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({
React.useEffect(() => { React.useEffect(() => {
if (showAudioModal && DEBUG_MODE) { if (showAudioModal && DEBUG_MODE) {
logger.log(`[AudioTrackModal] Modal opened with selectedAudioTrack:`, selectedAudioTrack); logger.log(`[AudioTrackModal] Modal opened with selectedAudioTrack:`, selectedAudioTrack);
logger.log(`[AudioTrackModal] Available tracks:`, vlcAudioTracks); logger.log(`[AudioTrackModal] Available tracks:`, ksAudioTracks);
if (typeof selectedAudioTrack === 'number') { if (typeof selectedAudioTrack === 'number') {
const selectedTrack = vlcAudioTracks.find(track => track.id === selectedAudioTrack); const selectedTrack = ksAudioTracks.find(track => track.id === selectedAudioTrack);
if (selectedTrack) { if (selectedTrack) {
logger.log(`[AudioTrackModal] Selected track found: ${selectedTrack.name} (${selectedTrack.language})`); logger.log(`[AudioTrackModal] Selected track found: ${selectedTrack.name} (${selectedTrack.language})`);
} else { } else {
@ -46,7 +46,7 @@ export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({
} }
} }
} }
}, [showAudioModal, selectedAudioTrack, vlcAudioTracks]); }, [showAudioModal, selectedAudioTrack, ksAudioTracks]);
if (!showAudioModal) return null; if (!showAudioModal) return null;
@ -143,11 +143,11 @@ export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({
textTransform: 'uppercase', textTransform: 'uppercase',
letterSpacing: 0.5, letterSpacing: 0.5,
}}> }}>
Available Tracks ({vlcAudioTracks.length}) Available Tracks ({ksAudioTracks.length})
</Text> </Text>
<View style={{ gap: 8 }}> <View style={{ gap: 8 }}>
{vlcAudioTracks.map((track) => { {ksAudioTracks.map((track) => {
// Determine if track is selected // Determine if track is selected
const isSelected = selectedAudioTrack === track.id; const isSelected = selectedAudioTrack === track.id;
@ -203,7 +203,7 @@ export const AudioTrackModal: React.FC<AudioTrackModalProps> = ({
})} })}
</View> </View>
{vlcAudioTracks.length === 0 && ( {ksAudioTracks.length === 0 && (
<View style={{ <View style={{
backgroundColor: 'rgba(255, 255, 255, 0.05)', backgroundColor: 'rgba(255, 255, 255, 0.05)',
borderRadius: 16, borderRadius: 16,

View file

@ -21,7 +21,7 @@ interface SubtitleModalsProps {
isLoadingSubtitles: boolean; isLoadingSubtitles: boolean;
customSubtitles: SubtitleCue[]; customSubtitles: SubtitleCue[];
availableSubtitles: WyzieSubtitle[]; availableSubtitles: WyzieSubtitle[];
vlcTextTracks: Array<{id: number, name: string, language?: string}>; ksTextTracks: Array<{id: number, name: string, language?: string}>;
selectedTextTrack: number; selectedTextTrack: number;
useCustomSubtitles: boolean; useCustomSubtitles: boolean;
subtitleSize: number; subtitleSize: number;
@ -68,7 +68,7 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
isLoadingSubtitles, isLoadingSubtitles,
customSubtitles, customSubtitles,
availableSubtitles, availableSubtitles,
vlcTextTracks, ksTextTracks,
selectedTextTrack, selectedTextTrack,
useCustomSubtitles, useCustomSubtitles,
subtitleSize, subtitleSize,
@ -286,10 +286,10 @@ export const SubtitleModals: React.FC<SubtitleModalsProps> = ({
</Text> </Text>
<View style={{ gap: 8 }}> <View style={{ gap: 8 }}>
{vlcTextTracks.map((track) => { {ksTextTracks.map((track) => {
const isSelected = selectedTextTrack === track.id && !useCustomSubtitles; const isSelected = selectedTextTrack === track.id && !useCustomSubtitles;
// Debug logging for subtitle selection // 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); console.log('[SubtitleModals] Track:', track.id, track.name, 'Selected:', selectedTextTrack, 'isSelected:', isSelected, 'useCustom:', useCustomSubtitles);
} }
return ( return (