From d66764471fb6b00dde6cb8852c25bd8c2bdfc295 Mon Sep 17 00:00:00 2001 From: tapframe Date: Tue, 8 Jul 2025 17:19:21 +0530 Subject: [PATCH] Remove SkiaProgressSlider from PlayerControls and refactor progress handling for improved touch interaction. Update AndroidVideoPlayer and VideoPlayer components to eliminate seekToTime prop and adjust subtitle handling. --- src/components/player/AndroidVideoPlayer.tsx | 1 - src/components/player/VideoPlayer.tsx | 15 +- .../player/controls/PlayerControls.tsx | 104 ++++---- .../player/controls/SkiaProgressSlider.tsx | 226 ------------------ 4 files changed, 53 insertions(+), 293 deletions(-) delete mode 100644 src/components/player/controls/SkiaProgressSlider.tsx diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index 894536b..be64877 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -1195,7 +1195,6 @@ const AndroidVideoPlayer: React.FC = () => { handleProgressBarDragEnd={handleProgressBarDragEnd} buffered={buffered} formatTime={formatTime} - seekToTime={seekToTime} /> { const [currentSubtitle, setCurrentSubtitle] = useState(''); const [subtitleSize, setSubtitleSize] = useState(DEFAULT_SUBTITLE_SIZE); const [useCustomSubtitles, setUseCustomSubtitles] = useState(false); - const [subtitleBackground, setSubtitleBackground] = useState(true); // Add missing state const [isLoadingSubtitles, setIsLoadingSubtitles] = useState(false); const [availableSubtitles, setAvailableSubtitles] = useState([]); const [showSubtitleLanguageModal, setShowSubtitleLanguageModal] = useState(false); @@ -904,20 +903,14 @@ const VideoPlayer: React.FC = () => { }, []); const increaseSubtitleSize = () => { - const newSize = Math.min(subtitleSize + 2, 40); - setSubtitleSize(newSize); + const newSize = Math.min(subtitleSize + 2, 32); saveSubtitleSize(newSize); }; const decreaseSubtitleSize = () => { - const newSize = Math.max(subtitleSize - 2, 12); - setSubtitleSize(newSize); + const newSize = Math.max(subtitleSize - 2, 8); saveSubtitleSize(newSize); }; - - const toggleSubtitleBackground = () => { - setSubtitleBackground(prev => !prev); - }; useEffect(() => { if (pendingSeek && isPlayerReady && isVideoLoaded && duration > 0) { @@ -1211,7 +1204,6 @@ const VideoPlayer: React.FC = () => { handleProgressBarDragEnd={handleProgressBarDragEnd} buffered={buffered} formatTime={formatTime} - seekToTime={seekToTime} /> { currentSubtitle={currentSubtitle} subtitleSize={subtitleSize} zoomScale={zoomScale} - subtitleBackground={subtitleBackground} /> { selectedTextTrack={selectedTextTrack} useCustomSubtitles={useCustomSubtitles} subtitleSize={subtitleSize} - subtitleBackground={subtitleBackground} fetchAvailableSubtitles={fetchAvailableSubtitles} loadWyzieSubtitle={loadWyzieSubtitle} selectTextTrack={selectTextTrack} increaseSubtitleSize={increaseSubtitleSize} decreaseSubtitleSize={decreaseSubtitleSize} - toggleSubtitleBackground={toggleSubtitleBackground} /> void; buffered: number; formatTime: (seconds: number) => string; - seekToTime?: (time: number) => void; } -const { width: screenWidth } = Dimensions.get('window'); - export const PlayerControls: React.FC = ({ showControls, fadeAnim, @@ -79,61 +75,63 @@ export const PlayerControls: React.FC = ({ handleProgressBarDragEnd, buffered, formatTime, - seekToTime, }) => { - // State for tracking preview time during dragging - const [previewTime, setPreviewTime] = useState(null); - const [isDragging, setIsDragging] = useState(false); - - // Calculate slider width based on screen width minus padding - const sliderWidth = screenWidth - 40; // 20px padding on each side - - const handleSeek = (time: number) => { - if (seekToTime) { - seekToTime(time); - } - }; - - const handleSeekPreview = (time: number) => { - setPreviewTime(time); - }; - - const handleSeekStart = () => { - setIsDragging(true); - handleProgressBarDragStart(); - }; - - const handleSeekEnd = (time: number) => { - setIsDragging(false); - setPreviewTime(null); - handleProgressBarDragEnd(); - handleSeek(time); - }; - - // Determine which time to display (preview time while dragging, otherwise current time) - const displayTime = isDragging && previewTime !== null ? previewTime : currentTime; - return ( - {/* Progress bar with Skia slider */} + {/* Progress bar with enhanced touch handling */} - + + + + {/* Buffered Progress */} + + {/* Animated Progress */} + + + + {/* Progress Thumb - Moved outside the progressBarContainer */} + + + - - {formatTime(displayTime)} - + {formatTime(currentTime)} {formatTime(duration)} diff --git a/src/components/player/controls/SkiaProgressSlider.tsx b/src/components/player/controls/SkiaProgressSlider.tsx deleted file mode 100644 index 49df3a5..0000000 --- a/src/components/player/controls/SkiaProgressSlider.tsx +++ /dev/null @@ -1,226 +0,0 @@ -import React, { useMemo, useEffect } from 'react'; -import { View, Dimensions } from 'react-native'; -import { - Canvas, - RoundedRect, - Circle, - Group, - Shadow, -} from '@shopify/react-native-skia'; -import { - Gesture, - GestureDetector, - GestureHandlerRootView, -} from 'react-native-gesture-handler'; -import Animated, { - useSharedValue, - useAnimatedStyle, - withSpring, - runOnJS, - interpolate, -} from 'react-native-reanimated'; - -interface SkiaProgressSliderProps { - currentTime: number; - duration: number; - buffered: number; - onSeek: (time: number) => void; - onSeekStart?: () => void; - onSeekEnd?: (time: number) => void; - onSeekPreview?: (time: number) => void; // New callback for preview time - width: number; - height?: number; - thumbSize?: number; - progressColor?: string; - backgroundColor?: string; - bufferedColor?: string; -} - -export const SkiaProgressSlider: React.FC = ({ - currentTime, - duration, - buffered, - onSeek, - onSeekStart, - onSeekEnd, - onSeekPreview, - width, - height = 4, - thumbSize = 16, - progressColor = '#E50914', - backgroundColor = 'rgba(255, 255, 255, 0.2)', - bufferedColor = 'rgba(255, 255, 255, 0.4)', -}) => { - const progress = useSharedValue(0); - const isDragging = useSharedValue(false); - const thumbScale = useSharedValue(1); - const progressWidth = useSharedValue(0); - const previewTimeValue = useSharedValue(0); - - // Add padding to account for thumb size - const trackPadding = thumbSize / 2; - const trackWidth = width - (trackPadding * 2); - - // Update progress when currentTime changes - useEffect(() => { - if (!isDragging.value && duration > 0) { - const newProgress = (currentTime / duration); - progress.value = newProgress; - progressWidth.value = newProgress * trackWidth; - } - }, [currentTime, duration, trackWidth]); - - // Calculate buffered width - const bufferedWidth = useMemo(() => { - return duration > 0 ? (buffered / duration) * trackWidth : 0; - }, [buffered, duration, trackWidth]); - - // Handle seeking with proper coordinate mapping - const seekToPosition = (gestureX: number, isPreview: boolean = false) => { - 'worklet'; - // Map gesture coordinates to track coordinates - const trackX = gestureX - trackPadding; - const clampedX = Math.max(0, Math.min(trackX, trackWidth)); - - const newProgress = clampedX / trackWidth; - progress.value = newProgress; - progressWidth.value = clampedX; - - const seekTime = newProgress * duration; - previewTimeValue.value = seekTime; - - if (isPreview && onSeekPreview) { - runOnJS(onSeekPreview)(seekTime); - } else if (!isPreview) { - runOnJS(onSeek)(seekTime); - } - }; - - // Pan gesture for dragging - const panGesture = Gesture.Pan() - .onBegin((e) => { - 'worklet'; - isDragging.value = true; - thumbScale.value = withSpring(1.2, { damping: 15, stiffness: 400 }); - // Process the initial touch position immediately - seekToPosition(e.x, true); - if (onSeekStart) { - runOnJS(onSeekStart)(); - } - }) - .onUpdate((e) => { - 'worklet'; - seekToPosition(e.x, true); // Use preview mode during dragging - }) - .onFinalize((e) => { - 'worklet'; - isDragging.value = false; - thumbScale.value = withSpring(1, { damping: 15, stiffness: 400 }); - - // Use the exact same preview time for the final seek to ensure consistency - if (onSeekEnd) { - runOnJS(onSeekEnd)(previewTimeValue.value); - } - - // Final seek when drag ends - use the same calculation as preview - runOnJS(onSeek)(previewTimeValue.value); - }); - - // Tap gesture for seeking - const tapGesture = Gesture.Tap() - .onEnd((e) => { - 'worklet'; - seekToPosition(e.x, false); // Direct seek on tap - }); - - const composedGesture = Gesture.Simultaneous(tapGesture, panGesture); - - // Animated styles for thumb - const animatedThumbStyle = useAnimatedStyle(() => { - const thumbX = progress.value * trackWidth + trackPadding; - - return { - transform: [ - { translateX: thumbX - thumbSize / 2 }, - { scale: thumbScale.value } - ], - }; - }); - - // Animated style for progress width - const animatedProgressStyle = useAnimatedStyle(() => { - return { - width: progressWidth.value, - }; - }); - - return ( - - - - - - {/* Background track */} - - - {/* Buffered progress */} - {bufferedWidth > 0 && ( - - )} - - - - {/* Current progress - using regular view for animation */} - - - {/* Animated thumb */} - - - - - ); -}; \ No newline at end of file