added buffer indicator

This commit is contained in:
tapframe 2026-01-27 00:41:53 +05:30
parent fd9cc1ac52
commit de576915d5
4 changed files with 44 additions and 14 deletions

View file

@ -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

View file

@ -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>
)}

View file

@ -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>

View file

@ -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;