'use strict'; import React, {FC, useCallback, useRef, useState} from 'react'; import {TouchableOpacity, View} from 'react-native'; import Video, { AudioTrack, OnAudioTracksData, OnLoadData, OnProgressData, OnTextTracksData, OnVideoAspectRatioData, TextTrack, OnBufferData, OnAudioFocusChangedData, OnVideoErrorData, VideoRef, OnTextTrackDataChangedData, OnSeekData, OnPlaybackStateChangedData, OnPlaybackRateChangeData, OnVideoTracksData, SelectedVideoTrackType, BufferingStrategyType, ReactVideoSource, SelectedTrackType, TextTracks, ResizeMode, VideoTrack, SelectedTrack, SelectedVideoTrack, } from 'react-native-video'; import styles from './styles'; import {AdditionalSourceInfo} from './types'; import {bufferConfig, srcList, textTracksSelectionBy} from './constants'; import {Overlay, toast} from './components'; type AdditionnalSourceInfo = { textTracks: TextTracks; adTagUrl: string; description: string; noView: boolean; }; type Props = NonNullable; const VideoPlayer: FC = ({}) => { const [rate, setRate] = useState(1); const [volume, setVolume] = useState(1); const [muted, setMuted] = useState(false); const [resizeMode, setResizeMode] = useState(ResizeMode.CONTAIN); const [duration, setDuration] = useState(0); const [currentTime, setCurrentTime] = useState(0); const [_, setVideoSize] = useState({videoWidth: 0, videoHeight: 0}); const [paused, setPaused] = useState(false); const [fullscreen, setFullscreen] = useState(true); const [decoration, setDecoration] = useState(true); const [isLoading, setIsLoading] = useState(false); const [audioTracks, setAudioTracks] = useState([]); const [textTracks, setTextTracks] = useState([]); const [videoTracks, setVideoTracks] = useState([]); const [selectedAudioTrack, setSelectedAudioTrack] = useState< SelectedTrack | undefined >(undefined); const [selectedTextTrack, setSelectedTextTrack] = useState< SelectedTrack | undefined >(undefined); const [selectedVideoTrack, setSelectedVideoTrack] = useState({ type: SelectedVideoTrackType.AUTO, }); const [srcListId, setSrcListId] = useState(0); const [repeat, setRepeat] = useState(false); const [controls, setControls] = useState(false); const [useCache, setUseCache] = useState(false); const [poster, setPoster] = useState(undefined); const [showNotificationControls, setShowNotificationControls] = useState(false); const [isSeeking, setIsSeeking] = useState(false); const videoRef = useRef(null); const viewStyle = fullscreen ? styles.fullScreen : styles.halfScreen; const currentSrc = srcList[srcListId]; const additional = currentSrc as AdditionalSourceInfo; const onAudioTracks = (data: OnAudioTracksData) => { const selectedTrack = data.audioTracks?.find((x: AudioTrack) => { return x.selected; }); if (selectedTrack?.index) { setAudioTracks(data.audioTracks); setSelectedAudioTrack({ type: SelectedTrackType.INDEX, value: selectedTrack.index, }); } else { setAudioTracks(data.audioTracks); } }; const onVideoTracks = (data: OnVideoTracksData) => { console.log('onVideoTracks', data.videoTracks); setVideoTracks(data.videoTracks); }; const onTextTracks = (data: OnTextTracksData) => { const selectedTrack = data.textTracks?.find((x: TextTrack) => { return x?.selected; }); if (selectedTrack?.language) { setTextTracks(data.textTracks); if (textTracksSelectionBy === 'index') { setSelectedTextTrack({ type: SelectedTrackType.INDEX, value: selectedTrack?.index, }); } else { setSelectedTextTrack({ type: SelectedTrackType.LANGUAGE, value: selectedTrack?.language, }); } } else { setTextTracks(data.textTracks); } }; const onLoad = (data: OnLoadData) => { setDuration(data.duration); onAudioTracks(data); onTextTracks(data); onVideoTracks(data); }; const onProgress = (data: OnProgressData) => { setCurrentTime(data.currentTime); }; const onSeek = (data: OnSeekData) => { setCurrentTime(data.currentTime); setIsSeeking(false); }; const onVideoLoadStart = () => { console.log('onVideoLoadStart'); setIsLoading(true); }; const onTextTrackDataChanged = (data: OnTextTrackDataChangedData) => { console.log(`Subtitles: ${JSON.stringify(data, null, 2)}`); }; const onAspectRatio = (data: OnVideoAspectRatioData) => { console.log('onAspectRadio called ' + JSON.stringify(data)); setVideoSize({videoWidth: data.width, videoHeight: data.height}); }; const onVideoBuffer = (param: OnBufferData) => { console.log('onVideoBuffer'); setIsLoading(param.isBuffering); }; const onReadyForDisplay = () => { console.log('onReadyForDisplay'); setIsLoading(false); }; const onAudioBecomingNoisy = () => { setPaused(true); }; const onAudioFocusChanged = (event: OnAudioFocusChangedData) => { setPaused(!event.hasAudioFocus); }; const onError = (err: OnVideoErrorData) => { console.log(JSON.stringify(err)); toast(true, 'error: ' + JSON.stringify(err)); }; const onEnd = () => { if (!repeat) { channelUp(); } }; const onPlaybackRateChange = (data: OnPlaybackRateChangeData) => { console.log('onPlaybackRateChange', data); }; const onPlaybackStateChanged = (data: OnPlaybackStateChangedData) => { console.log('onPlaybackStateChanged', data); }; const goToChannel = (channel: number) => { setSrcListId(channel); setDuration(0); setCurrentTime(0); setVideoSize({videoWidth: 0, videoHeight: 0}); setIsLoading(false); setAudioTracks([]); setTextTracks([]); setSelectedAudioTrack(undefined); setSelectedTextTrack(undefined); setSelectedVideoTrack({ type: SelectedVideoTrackType.AUTO, }); }; const channelUp = useCallback(() => { console.log('channel up'); goToChannel((srcListId + 1) % srcList.length); }, [srcListId]); const channelDown = useCallback(() => { console.log('channel down'); goToChannel((srcListId + srcList.length - 1) % srcList.length); }, [srcListId]); return ( {(srcList[srcListId] as AdditionalSourceInfo)?.noView ? null : ( )} ); }; export default VideoPlayer;