mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
slider change
This commit is contained in:
parent
6405fd2c71
commit
17339d82a6
3 changed files with 65 additions and 146 deletions
|
|
@ -124,8 +124,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
const [rnVideoAudioTracks, setRnVideoAudioTracks] = useState<Array<{id: number, name: string, language?: string}>>([]);
|
||||
const [rnVideoTextTracks, setRnVideoTextTracks] = useState<Array<{id: number, name: string, language?: string}>>([]);
|
||||
const [isPlayerReady, setIsPlayerReady] = useState(false);
|
||||
const progressAnim = useRef(new Animated.Value(0)).current;
|
||||
const progressBarRef = useRef<View>(null);
|
||||
// Removed progressAnim and progressBarRef - no longer needed with React Native Community Slider
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const isSeeking = useRef(false);
|
||||
const seekDebounceTimer = useRef<NodeJS.Timeout | null>(null);
|
||||
|
|
@ -454,44 +453,29 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
}
|
||||
}, [seekTime, duration]);
|
||||
|
||||
const handleProgressBarTouch = (event: any) => {
|
||||
if (duration > 0) {
|
||||
const { locationX } = event.nativeEvent;
|
||||
processProgressTouch(locationX);
|
||||
// Slider callback functions for React Native Community Slider
|
||||
const handleSliderValueChange = (value: number) => {
|
||||
if (isDragging && duration > 0) {
|
||||
const seekTime = Math.min(value, duration - END_EPSILON);
|
||||
setCurrentTime(seekTime);
|
||||
pendingSeekValue.current = seekTime;
|
||||
}
|
||||
};
|
||||
|
||||
const handleProgressBarDragStart = () => {
|
||||
|
||||
const handleSlidingStart = () => {
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleProgressBarDragMove = (event: any) => {
|
||||
if (!isDragging || !duration || duration <= 0) return;
|
||||
const { locationX } = event.nativeEvent;
|
||||
processProgressTouch(locationX, true);
|
||||
};
|
||||
|
||||
const handleProgressBarDragEnd = () => {
|
||||
|
||||
const handleSlidingComplete = (value: number) => {
|
||||
setIsDragging(false);
|
||||
if (pendingSeekValue.current !== null) {
|
||||
seekToTime(pendingSeekValue.current);
|
||||
if (duration > 0) {
|
||||
const seekTime = Math.min(value, duration - END_EPSILON);
|
||||
seekToTime(seekTime);
|
||||
pendingSeekValue.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const processProgressTouch = (locationX: number, isDragging = false) => {
|
||||
progressBarRef.current?.measure((x, y, width, height, pageX, pageY) => {
|
||||
const percentage = Math.max(0, Math.min(locationX / width, 0.999));
|
||||
const seekTime = Math.min(percentage * duration, duration - END_EPSILON);
|
||||
progressAnim.setValue(percentage);
|
||||
if (isDragging) {
|
||||
pendingSeekValue.current = seekTime;
|
||||
setCurrentTime(seekTime);
|
||||
} else {
|
||||
seekToTime(seekTime);
|
||||
}
|
||||
});
|
||||
};
|
||||
// Removed processProgressTouch - no longer needed with React Native Community Slider
|
||||
|
||||
const handleProgress = (data: any) => {
|
||||
if (isDragging || isSeeking.current) return;
|
||||
|
|
@ -501,12 +485,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
// Update time more frequently for subtitle synchronization (0.1s threshold)
|
||||
if (Math.abs(currentTimeInSeconds - currentTime) > 0.1) {
|
||||
safeSetState(() => setCurrentTime(currentTimeInSeconds));
|
||||
const progressPercent = duration > 0 ? currentTimeInSeconds / duration : 0;
|
||||
Animated.timing(progressAnim, {
|
||||
toValue: progressPercent,
|
||||
duration: 100,
|
||||
useNativeDriver: false,
|
||||
}).start();
|
||||
// Removed progressAnim animation - no longer needed with React Native Community Slider
|
||||
const bufferedTime = data.playableDuration || currentTimeInSeconds;
|
||||
safeSetState(() => setBuffered(bufferedTime));
|
||||
}
|
||||
|
|
@ -1199,12 +1178,9 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
setShowAudioModal={setShowAudioModal}
|
||||
setShowSubtitleModal={setShowSubtitleModal}
|
||||
setShowSourcesModal={setShowSourcesModal}
|
||||
progressBarRef={progressBarRef}
|
||||
progressAnim={progressAnim}
|
||||
handleProgressBarTouch={handleProgressBarTouch}
|
||||
handleProgressBarDragStart={handleProgressBarDragStart}
|
||||
handleProgressBarDragMove={handleProgressBarDragMove}
|
||||
handleProgressBarDragEnd={handleProgressBarDragEnd}
|
||||
onSliderValueChange={handleSliderValueChange}
|
||||
onSlidingStart={handleSlidingStart}
|
||||
onSlidingComplete={handleSlidingComplete}
|
||||
buffered={buffered}
|
||||
formatTime={formatTime}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { logger } from '../../utils/logger';
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { MaterialIcons } from '@expo/vector-icons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import Slider from '@react-native-community/slider';
|
||||
import AndroidVideoPlayer from './AndroidVideoPlayer';
|
||||
import { useTraktAutosync } from '../../hooks/useTraktAutosync';
|
||||
import { useTraktAutosyncSettings } from '../../hooks/useTraktAutosyncSettings';
|
||||
|
|
@ -127,8 +128,7 @@ const VideoPlayer: React.FC = () => {
|
|||
const [vlcAudioTracks, setVlcAudioTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]);
|
||||
const [vlcTextTracks, setVlcTextTracks] = useState<Array<{ id: number, name: string, language?: string }>>([]);
|
||||
const [isPlayerReady, setIsPlayerReady] = useState(false);
|
||||
const progressAnim = useRef(new Animated.Value(0)).current;
|
||||
const progressBarRef = useRef<View>(null);
|
||||
// Removed progressAnim and progressBarRef - no longer needed with React Native Community Slider
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const isSeeking = useRef(false);
|
||||
const seekDebounceTimer = useRef<NodeJS.Timeout | null>(null);
|
||||
|
|
@ -515,44 +515,29 @@ const VideoPlayer: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const handleProgressBarTouch = (event: any) => {
|
||||
if (duration > 0) {
|
||||
const { locationX } = event.nativeEvent;
|
||||
processProgressTouch(locationX);
|
||||
// Slider callback functions for React Native Community Slider
|
||||
const handleSliderValueChange = (value: number) => {
|
||||
if (isDragging && duration > 0) {
|
||||
const seekTime = Math.min(value, duration - END_EPSILON);
|
||||
setCurrentTime(seekTime);
|
||||
pendingSeekValue.current = seekTime;
|
||||
}
|
||||
};
|
||||
|
||||
const handleProgressBarDragStart = () => {
|
||||
const handleSlidingStart = () => {
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleProgressBarDragMove = (event: any) => {
|
||||
if (!isDragging || !duration || duration <= 0) return;
|
||||
const { locationX } = event.nativeEvent;
|
||||
processProgressTouch(locationX, true);
|
||||
};
|
||||
|
||||
const handleProgressBarDragEnd = () => {
|
||||
const handleSlidingComplete = (value: number) => {
|
||||
setIsDragging(false);
|
||||
if (pendingSeekValue.current !== null) {
|
||||
seekToTime(pendingSeekValue.current);
|
||||
if (duration > 0) {
|
||||
const seekTime = Math.min(value, duration - END_EPSILON);
|
||||
seekToTime(seekTime);
|
||||
pendingSeekValue.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const processProgressTouch = (locationX: number, isDragging = false) => {
|
||||
progressBarRef.current?.measure((x, y, width, height, pageX, pageY) => {
|
||||
const percentage = Math.max(0, Math.min(locationX / width, 0.999));
|
||||
const seekTime = Math.min(percentage * duration, duration - END_EPSILON);
|
||||
progressAnim.setValue(percentage);
|
||||
if (isDragging) {
|
||||
pendingSeekValue.current = seekTime;
|
||||
setCurrentTime(seekTime);
|
||||
} else {
|
||||
seekToTime(seekTime);
|
||||
}
|
||||
});
|
||||
};
|
||||
// Removed processProgressTouch - no longer needed with React Native Community Slider
|
||||
|
||||
const handleProgress = (event: any) => {
|
||||
if (isDragging || isSeeking.current) return;
|
||||
|
|
@ -562,12 +547,7 @@ const VideoPlayer: React.FC = () => {
|
|||
// Only update if there's a significant change to avoid unnecessary updates
|
||||
if (Math.abs(currentTimeInSeconds - currentTime) > 0.5) {
|
||||
safeSetState(() => setCurrentTime(currentTimeInSeconds));
|
||||
const progressPercent = duration > 0 ? currentTimeInSeconds / duration : 0;
|
||||
Animated.timing(progressAnim, {
|
||||
toValue: progressPercent,
|
||||
duration: 250,
|
||||
useNativeDriver: false,
|
||||
}).start();
|
||||
// Removed progressAnim animation - no longer needed with React Native Community Slider
|
||||
const bufferedTime = event.bufferTime / 1000 || currentTimeInSeconds;
|
||||
safeSetState(() => setBuffered(bufferedTime));
|
||||
}
|
||||
|
|
@ -1273,12 +1253,9 @@ const VideoPlayer: React.FC = () => {
|
|||
setShowAudioModal={setShowAudioModal}
|
||||
setShowSubtitleModal={setShowSubtitleModal}
|
||||
setShowSourcesModal={setShowSourcesModal}
|
||||
progressBarRef={progressBarRef}
|
||||
progressAnim={progressAnim}
|
||||
handleProgressBarTouch={handleProgressBarTouch}
|
||||
handleProgressBarDragStart={handleProgressBarDragStart}
|
||||
handleProgressBarDragMove={handleProgressBarDragMove}
|
||||
handleProgressBarDragEnd={handleProgressBarDragEnd}
|
||||
onSliderValueChange={handleSliderValueChange}
|
||||
onSlidingStart={handleSlidingStart}
|
||||
onSlidingComplete={handleSlidingComplete}
|
||||
buffered={buffered}
|
||||
formatTime={formatTime}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity, Animated, StyleSheet } from 'react-native';
|
||||
import { View, Text, TouchableOpacity, Animated, StyleSheet, Platform } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import Slider from '@react-native-community/slider';
|
||||
import { styles } from '../utils/playerStyles';
|
||||
import { getTrackDisplayName } from '../utils/playerUtils';
|
||||
|
||||
|
|
@ -31,12 +32,10 @@ interface PlayerControlsProps {
|
|||
setShowAudioModal: (show: boolean) => void;
|
||||
setShowSubtitleModal: (show: boolean) => void;
|
||||
setShowSourcesModal?: (show: boolean) => void;
|
||||
progressBarRef: React.RefObject<View>;
|
||||
progressAnim: Animated.Value;
|
||||
handleProgressBarTouch: (event: any) => void;
|
||||
handleProgressBarDragStart: () => void;
|
||||
handleProgressBarDragMove: (event: any) => void;
|
||||
handleProgressBarDragEnd: () => void;
|
||||
// Slider-specific props
|
||||
onSliderValueChange: (value: number) => void;
|
||||
onSlidingStart: () => void;
|
||||
onSlidingComplete: (value: number) => void;
|
||||
buffered: number;
|
||||
formatTime: (seconds: number) => string;
|
||||
}
|
||||
|
|
@ -67,12 +66,9 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
setShowAudioModal,
|
||||
setShowSubtitleModal,
|
||||
setShowSourcesModal,
|
||||
progressBarRef,
|
||||
progressAnim,
|
||||
handleProgressBarTouch,
|
||||
handleProgressBarDragStart,
|
||||
handleProgressBarDragMove,
|
||||
handleProgressBarDragEnd,
|
||||
onSliderValueChange,
|
||||
onSlidingStart,
|
||||
onSlidingComplete,
|
||||
buffered,
|
||||
formatTime,
|
||||
}) => {
|
||||
|
|
@ -81,55 +77,25 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
style={[StyleSheet.absoluteFill, { opacity: fadeAnim }]}
|
||||
pointerEvents={showControls ? 'auto' : 'none'}
|
||||
>
|
||||
{/* Progress bar with enhanced touch handling */}
|
||||
{/* Progress slider with native iOS slider */}
|
||||
<View style={styles.sliderContainer}>
|
||||
<View
|
||||
style={styles.progressTouchArea}
|
||||
onTouchStart={handleProgressBarDragStart}
|
||||
onTouchMove={handleProgressBarDragMove}
|
||||
onTouchEnd={handleProgressBarDragEnd}
|
||||
>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
onPress={handleProgressBarTouch}
|
||||
style={{width: '100%'}}
|
||||
>
|
||||
<View
|
||||
ref={progressBarRef}
|
||||
style={styles.progressBarContainer}
|
||||
>
|
||||
{/* Buffered Progress */}
|
||||
<View style={[styles.bufferProgress, {
|
||||
width: `${(buffered / (duration || 1)) * 100}%`
|
||||
}]} />
|
||||
{/* Animated Progress */}
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.progressBarFill,
|
||||
{
|
||||
width: progressAnim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['0%', '100%']
|
||||
})
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Progress Thumb - Moved outside the progressBarContainer */}
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.progressThumb,
|
||||
{
|
||||
left: progressAnim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: ['0%', '100%']
|
||||
})
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Slider
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 40,
|
||||
marginHorizontal: 0,
|
||||
}}
|
||||
minimumValue={0}
|
||||
maximumValue={duration || 1}
|
||||
value={currentTime}
|
||||
onValueChange={onSliderValueChange}
|
||||
onSlidingStart={onSlidingStart}
|
||||
onSlidingComplete={onSlidingComplete}
|
||||
minimumTrackTintColor="#FFFFFF"
|
||||
maximumTrackTintColor="rgba(255, 255, 255, 0.3)"
|
||||
thumbTintColor={Platform.OS === 'android' ? '#FFFFFF' : undefined}
|
||||
tapToSeek={Platform.OS === 'ios'}
|
||||
/>
|
||||
<View style={styles.timeDisplay}>
|
||||
<Text style={styles.duration}>{formatTime(currentTime)}</Text>
|
||||
<Text style={styles.duration}>{formatTime(duration)}</Text>
|
||||
|
|
@ -244,4 +210,4 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
export default PlayerControls;
|
||||
export default PlayerControls;
|
||||
Loading…
Reference in a new issue