Enhance AndroidVideoPlayer component with dynamic resize mode support

This update introduces a new optional prop for resize mode in the AndroidVideoPlayer component, allowing users to specify how the video should be displayed. The default resize mode is set to 'contain', and the component now supports cycling through various resize modes. Additionally, the PlayerControls component has been updated to reflect the current resize mode, improving user interaction and experience.
This commit is contained in:
tapframe 2025-06-21 15:49:43 +05:30
parent 0ab9ce19c0
commit 1605d5251e
6 changed files with 40 additions and 30 deletions

View file

@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { Platform } from 'react-native';
import Video, { VideoRef, SelectedTrack, BufferingStrategyType } from 'react-native-video';
import Video, { VideoRef, SelectedTrack, BufferingStrategyType, ResizeMode } from 'react-native-video';
interface VideoPlayerProps {
src: string;
@ -9,6 +9,7 @@ interface VideoPlayerProps {
currentTime: number;
selectedAudioTrack?: SelectedTrack;
selectedTextTrack?: SelectedTrack;
resizeMode?: ResizeMode;
onProgress?: (data: { currentTime: number; playableDuration: number }) => void;
onLoad?: (data: { duration: number }) => void;
onError?: (error: any) => void;
@ -24,6 +25,7 @@ export const AndroidVideoPlayer: React.FC<VideoPlayerProps> = ({
currentTime,
selectedAudioTrack,
selectedTextTrack,
resizeMode = 'contain' as ResizeMode,
onProgress,
onLoad,
onError,
@ -93,7 +95,7 @@ export const AndroidVideoPlayer: React.FC<VideoPlayerProps> = ({
onBuffer={handleBuffer}
onError={handleError}
onEnd={handleEnd}
resizeMode="contain"
resizeMode={resizeMode}
controls={false}
playInBackground={false}
playWhenInactive={false}

View file

@ -95,7 +95,7 @@ const AndroidVideoPlayer: React.FC = () => {
const [selectedAudioTrack, setSelectedAudioTrack] = useState<number | null>(null);
const [textTracks, setTextTracks] = useState<TextTrack[]>([]);
const [selectedTextTrack, setSelectedTextTrack] = useState<number>(-1);
const [resizeMode, setResizeMode] = useState<ResizeModeType>('stretch');
const [resizeMode, setResizeMode] = useState<ResizeModeType>('contain');
const [buffered, setBuffered] = useState(0);
const [seekTime, setSeekTime] = useState<number | null>(null);
const videoRef = useRef<VideoRef>(null);
@ -526,13 +526,14 @@ const AndroidVideoPlayer: React.FC = () => {
};
const cycleAspectRatio = () => {
const newZoom = zoomScale === 1.1 ? 1 : 1.1;
setZoomScale(newZoom);
setZoomTranslateX(0);
setZoomTranslateY(0);
setLastZoomScale(newZoom);
setLastTranslateX(0);
setLastTranslateY(0);
// Android: cycle through native resize modes
const resizeModes: ResizeModeType[] = ['contain', 'cover', 'stretch', 'none'];
const currentIndex = resizeModes.indexOf(resizeMode);
const nextIndex = (currentIndex + 1) % resizeModes.length;
setResizeMode(resizeModes[nextIndex]);
if (DEBUG_MODE) {
logger.log(`[AndroidVideoPlayer] Resize mode changed to: ${resizeModes[nextIndex]}`);
}
};
const enableImmersiveMode = () => {
@ -1081,6 +1082,7 @@ const AndroidVideoPlayer: React.FC = () => {
currentTime={currentTime}
duration={duration}
zoomScale={zoomScale}
currentResizeMode={resizeMode}
vlcAudioTracks={rnVideoAudioTracks}
selectedAudioTrack={selectedAudioTrack}
availableStreams={availableStreams}

View file

@ -388,7 +388,7 @@ const VideoPlayer: React.FC = () => {
isSeeking.current = false;
if (DEBUG_MODE) {
logger.log(`[VideoPlayer] Android seek completed to ${timeInSeconds.toFixed(2)}s`);
}
}
}
}, 500);
} else {
@ -659,11 +659,11 @@ const VideoPlayer: React.FC = () => {
// If video is already loaded and ready, seek immediately
if (isPlayerReady && duration > 0 && vlcRef.current) {
seekToTime(resumePosition);
seekToTime(resumePosition);
} else {
// Otherwise, set initial position for when video loads
setInitialPosition(resumePosition);
}
}
}
};

View file

@ -20,6 +20,7 @@ interface PlayerControlsProps {
currentTime: number;
duration: number;
zoomScale: number;
currentResizeMode?: string;
vlcAudioTracks: Array<{id: number, name: string, language?: string}>;
selectedAudioTrack: number | null;
availableStreams?: { [providerId: string]: { streams: any[]; addonName: string } };
@ -55,6 +56,7 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
currentTime,
duration,
zoomScale,
currentResizeMode,
vlcAudioTracks,
selectedAudioTrack,
availableStreams,
@ -178,7 +180,11 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
<TouchableOpacity style={styles.bottomButton} onPress={cycleAspectRatio}>
<Ionicons name="resize" size={20} color="white" />
<Text style={[styles.bottomButtonText, { fontSize: 14, textAlign: 'center' }]}>
{zoomScale === 1.1 ? 'Fill' : 'Cover'}
{currentResizeMode ?
(currentResizeMode === 'none' ? 'Original' :
currentResizeMode.charAt(0).toUpperCase() + currentResizeMode.slice(1)) :
(zoomScale === 1.1 ? 'Fill' : 'Cover')
}
</Text>
</TouchableOpacity>

View file

@ -369,10 +369,10 @@ export function useTraktIntegration() {
updatePromises.push(
storageService.mergeWithTraktProgress(
id,
type,
item.progress,
item.paused_at,
id,
type,
item.progress,
item.paused_at,
episodeId,
exactTime
)
@ -391,10 +391,10 @@ export function useTraktIntegration() {
updatePromises.push(
storageService.mergeWithTraktProgress(
id,
'movie',
100, // 100% progress for watched items
watchedAt
id,
'movie',
100, // 100% progress for watched items
watchedAt
)
);
}

View file

@ -147,7 +147,7 @@ class StorageService {
// Only notify if we have subscribers
if (this.watchProgressSubscribers.length > 0) {
this.watchProgressSubscribers.forEach(callback => callback());
this.watchProgressSubscribers.forEach(callback => callback());
}
}
@ -394,16 +394,16 @@ class StorageService {
}
}
const updatedProgress: WatchProgress = {
const updatedProgress: WatchProgress = {
...localProgress,
currentTime,
duration,
lastUpdated: traktTimestamp,
traktSynced: true,
traktLastSynced: Date.now(),
traktProgress
};
await this.setWatchProgress(id, type, updatedProgress, episodeId);
lastUpdated: traktTimestamp,
traktSynced: true,
traktLastSynced: Date.now(),
traktProgress
};
await this.setWatchProgress(id, type, updatedProgress, episodeId);
// Only log significant changes
if (progressDiff > 10 || traktProgress === 100) {