mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-29 05:48:45 +00:00
added buffer indicator
This commit is contained in:
parent
fd9cc1ac52
commit
de576915d5
4 changed files with 44 additions and 14 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useRef, useEffect, useMemo, useCallback, useState } from 'react';
|
||||
import { View, StyleSheet, Platform, Animated, ToastAndroid } from 'react-native';
|
||||
import { View, StyleSheet, Platform, Animated, ToastAndroid, ActivityIndicator } from 'react-native';
|
||||
import { toast } from '@backpackapp-io/react-native-toast';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
|
||||
|
|
@ -787,7 +787,9 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
modals.setErrorDetails(displayError);
|
||||
modals.setShowErrorModal(true);
|
||||
}}
|
||||
onBuffer={(buf) => playerState.setIsBuffering(buf.isBuffering)}
|
||||
onBuffer={(buf) => {
|
||||
playerState.setIsBuffering(buf.isBuffering);
|
||||
}}
|
||||
onTracksChanged={(data) => {
|
||||
console.log('[AndroidVideoPlayer] onTracksChanged:', data);
|
||||
if (data?.audioTracks) {
|
||||
|
|
@ -879,6 +881,13 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
formatTime={formatTime}
|
||||
/>
|
||||
|
||||
{/* Buffering Indicator (Visible when controls are hidden) */}
|
||||
{playerState.isBuffering && !playerState.showControls && (
|
||||
<View style={[StyleSheet.absoluteFill, { justifyContent: 'center', alignItems: 'center', zIndex: 15 }]}>
|
||||
<ActivityIndicator size="large" color="#FFFFFF" />
|
||||
</View>
|
||||
)}
|
||||
|
||||
<PlayerControls
|
||||
showControls={playerState.showControls}
|
||||
fadeAnim={fadeAnim}
|
||||
|
|
@ -926,6 +935,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
playerBackend={useExoPlayer ? 'ExoPlayer' : 'MPV'}
|
||||
onSwitchToMPV={handleManualSwitchToMPV}
|
||||
useExoPlayer={useExoPlayer}
|
||||
isBuffering={playerState.isBuffering}
|
||||
/>
|
||||
|
||||
<SpeedActivatedOverlay
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { View, StatusBar, StyleSheet, Animated, Dimensions } from 'react-native';
|
||||
import { View, StatusBar, StyleSheet, Animated, Dimensions, ActivityIndicator } from 'react-native';
|
||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import axios from 'axios';
|
||||
|
|
@ -745,10 +745,16 @@ const KSPlayerCore: React.FC = () => {
|
|||
await traktAutosync.handlePlaybackEnd(duration, duration, 'ended');
|
||||
}}
|
||||
onError={handleError}
|
||||
onBuffer={setIsBuffering}
|
||||
onBuffer={(b) => {
|
||||
setIsBuffering(b);
|
||||
}}
|
||||
onReadyForDisplay={() => setIsPlayerReady(true)}
|
||||
onPlaybackStalled={() => setIsBuffering(true)}
|
||||
onPlaybackResume={() => setIsBuffering(false)}
|
||||
onPlaybackStalled={() => {
|
||||
setIsBuffering(true);
|
||||
}}
|
||||
onPlaybackResume={() => {
|
||||
setIsBuffering(false);
|
||||
}}
|
||||
screenWidth={screenDimensions.width}
|
||||
screenHeight={screenDimensions.height}
|
||||
customVideoStyles={{ width: '100%', height: '100%' }}
|
||||
|
|
@ -817,6 +823,13 @@ const KSPlayerCore: React.FC = () => {
|
|||
{/* UI Controls */}
|
||||
{isVideoLoaded && (
|
||||
<View pointerEvents="box-none" style={StyleSheet.absoluteFill}>
|
||||
{/* Buffering Indicator (Visible when controls are hidden) */}
|
||||
{isBuffering && !showControls && (
|
||||
<View style={[StyleSheet.absoluteFill, { justifyContent: 'center', alignItems: 'center', zIndex: 15 }]}>
|
||||
<ActivityIndicator size="large" color="#FFFFFF" />
|
||||
</View>
|
||||
)}
|
||||
|
||||
<PlayerControls
|
||||
showControls={showControls}
|
||||
fadeAnim={fadeAnim}
|
||||
|
|
@ -871,6 +884,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
isAirPlayActive={isAirPlayActive}
|
||||
allowsAirPlay={allowsAirPlay}
|
||||
onAirPlayPress={() => ksPlayerRef.current?.showAirPlayPicker()}
|
||||
isBuffering={isBuffering}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity, Animated, StyleSheet, Platform, Dimensions } from 'react-native';
|
||||
import { View, Text, TouchableOpacity, Animated, StyleSheet, Platform, Dimensions, ActivityIndicator } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import Feather from 'react-native-vector-icons/Feather';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
|
|
@ -54,6 +54,7 @@ interface PlayerControlsProps {
|
|||
// MPV Switch (Android only)
|
||||
onSwitchToMPV?: () => void;
|
||||
useExoPlayer?: boolean;
|
||||
isBuffering?: boolean;
|
||||
}
|
||||
|
||||
export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
||||
|
|
@ -98,6 +99,7 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
onAirPlayPress,
|
||||
onSwitchToMPV,
|
||||
useExoPlayer,
|
||||
isBuffering = false,
|
||||
}) => {
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -463,7 +465,7 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
<TouchableOpacity
|
||||
onPress={handlePlayPauseWithAnimation}
|
||||
activeOpacity={0.7}
|
||||
style={{ marginHorizontal: buttonSpacing }}
|
||||
disabled={isBuffering}
|
||||
>
|
||||
<View style={[styles.playButtonCircle, { width: playButtonSize, height: playButtonSize }]}>
|
||||
<Animated.View style={[
|
||||
|
|
@ -479,11 +481,15 @@ export const PlayerControls: React.FC<PlayerControlsProps> = ({
|
|||
transform: [{ scale: playIconScale }],
|
||||
opacity: playIconOpacity
|
||||
}}>
|
||||
<Ionicons
|
||||
name={paused ? "play" : "pause"}
|
||||
size={playIconSizeCalculated}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
{isBuffering ? (
|
||||
<ActivityIndicator size="large" color="#FFFFFF" />
|
||||
) : (
|
||||
<Ionicons
|
||||
name={paused ? "play" : "pause"}
|
||||
size={playIconSizeCalculated}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
)}
|
||||
</Animated.View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const qualityPadH = isTV ? 10 : isLargeTablet ? 9 : isTablet ? 8 : 8;
|
|||
const qualityPadV = isTV ? 4 : isLargeTablet ? 3 : isTablet ? 3 : 2;
|
||||
const qualityRadius = isTV ? 6 : isLargeTablet ? 5 : isTablet ? 4 : 4;
|
||||
const qualityTextFont = isTV ? 13 : isLargeTablet ? 12 : isTablet ? 11 : 11;
|
||||
const controlsGap = isTV ? 56 : isLargeTablet ? 48 : isTablet ? 44 : 40;
|
||||
const controlsGap = isTV ? 140 : isLargeTablet ? 110 : isTablet ? 90 : 70;
|
||||
const controlsTranslateY = isTV ? -48 : isLargeTablet ? -42 : isTablet ? -36 : -30;
|
||||
const skipTextFont = isTV ? 14 : isLargeTablet ? 13 : isTablet ? 12 : 12;
|
||||
const sliderBottom = isTV ? 60 : isLargeTablet ? 50 : isTablet ? 45 : 35;
|
||||
|
|
|
|||
Loading…
Reference in a new issue