mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
121 lines
3.9 KiB
TypeScript
121 lines
3.9 KiB
TypeScript
import React, { useRef, useEffect, useCallback, forwardRef, useImperativeHandle } from 'react';
|
|
import { View, StyleSheet, requireNativeComponent, Platform, UIManager, findNodeHandle } from 'react-native';
|
|
|
|
// Only available on Android
|
|
const MpvPlayerNative = Platform.OS === 'android'
|
|
? requireNativeComponent<any>('MpvPlayer')
|
|
: null;
|
|
|
|
export interface MpvPlayerRef {
|
|
seek: (positionSeconds: number) => void;
|
|
setAudioTrack: (trackId: number) => void;
|
|
setSubtitleTrack: (trackId: number) => void;
|
|
}
|
|
|
|
export interface MpvPlayerProps {
|
|
source: string;
|
|
headers?: { [key: string]: string };
|
|
paused?: boolean;
|
|
volume?: number;
|
|
rate?: number;
|
|
resizeMode?: 'contain' | 'cover' | 'stretch';
|
|
style?: any;
|
|
onLoad?: (data: { duration: number; width: number; height: number }) => void;
|
|
onProgress?: (data: { currentTime: number; duration: number }) => void;
|
|
onEnd?: () => void;
|
|
onError?: (error: { error: string }) => void;
|
|
onTracksChanged?: (data: { audioTracks: any[]; subtitleTracks: any[] }) => void;
|
|
useHardwareDecoding?: boolean;
|
|
}
|
|
|
|
const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
|
|
const nativeRef = useRef<any>(null);
|
|
|
|
const dispatchCommand = useCallback((commandName: string, args: any[] = []) => {
|
|
if (nativeRef.current && Platform.OS === 'android') {
|
|
const handle = findNodeHandle(nativeRef.current);
|
|
if (handle) {
|
|
UIManager.dispatchViewManagerCommand(
|
|
handle,
|
|
commandName,
|
|
args
|
|
);
|
|
}
|
|
}
|
|
}, []);
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
seek: (positionSeconds: number) => {
|
|
dispatchCommand('seek', [positionSeconds]);
|
|
},
|
|
setAudioTrack: (trackId: number) => {
|
|
dispatchCommand('setAudioTrack', [trackId]);
|
|
},
|
|
setSubtitleTrack: (trackId: number) => {
|
|
dispatchCommand('setSubtitleTrack', [trackId]);
|
|
},
|
|
}), [dispatchCommand]);
|
|
|
|
if (Platform.OS !== 'android' || !MpvPlayerNative) {
|
|
// Fallback for iOS or if native component is not available
|
|
return (
|
|
<View style={[styles.container, props.style, { backgroundColor: 'black' }]} />
|
|
);
|
|
}
|
|
|
|
// Debug logging removed to prevent console spam
|
|
|
|
const handleLoad = (event: any) => {
|
|
console.log('[MpvPlayer] Native onLoad event:', event?.nativeEvent);
|
|
props.onLoad?.(event?.nativeEvent);
|
|
};
|
|
|
|
const handleProgress = (event: any) => {
|
|
props.onProgress?.(event?.nativeEvent);
|
|
};
|
|
|
|
const handleEnd = (event: any) => {
|
|
console.log('[MpvPlayer] Native onEnd event');
|
|
props.onEnd?.();
|
|
};
|
|
|
|
const handleError = (event: any) => {
|
|
console.log('[MpvPlayer] Native onError event:', event?.nativeEvent);
|
|
props.onError?.(event?.nativeEvent);
|
|
};
|
|
|
|
const handleTracksChanged = (event: any) => {
|
|
console.log('[MpvPlayer] Native onTracksChanged event:', event?.nativeEvent);
|
|
props.onTracksChanged?.(event?.nativeEvent);
|
|
};
|
|
|
|
return (
|
|
<MpvPlayerNative
|
|
ref={nativeRef}
|
|
style={[styles.container, props.style]}
|
|
source={props.source}
|
|
headers={props.headers}
|
|
paused={props.paused ?? true}
|
|
volume={props.volume ?? 1.0}
|
|
rate={props.rate ?? 1.0}
|
|
resizeMode={props.resizeMode ?? 'contain'}
|
|
onLoad={handleLoad}
|
|
onProgress={handleProgress}
|
|
onEnd={handleEnd}
|
|
onError={handleError}
|
|
onTracksChanged={handleTracksChanged}
|
|
useHardwareDecoding={props.useHardwareDecoding ?? false}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: 'black',
|
|
},
|
|
});
|
|
|
|
MpvPlayer.displayName = 'MpvPlayer';
|
|
|
|
export default MpvPlayer;
|