chore(example/basic): refactor state variable (#3949)

* refactor: basic example from class component to functional component

* refactor: toast component path

* refactor: bufferConfig prop

* refacotr: import component path

* fix: seekbar issue on iOS

* refactor: state variable

* chore: refactor overlay component according to new state structure
This commit is contained in:
Seyed Mostafa Hasani 2024-07-08 11:24:32 +03:30 committed by GitHub
parent 7562669fd6
commit a3ecc0108c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 305 additions and 266 deletions

View File

@ -1,6 +1,6 @@
'use strict';
import React, {FC, useRef, useState} from 'react';
import React, {FC, useCallback, useRef, useState} from 'react';
import {TouchableOpacity, View} from 'react-native';
@ -25,24 +25,55 @@ import Video, {
BufferingStrategyType,
ReactVideoSource,
SelectedTrackType,
ResizeMode,
VideoTrack,
SelectedTrack,
SelectedVideoTrack,
} from 'react-native-video';
import styles from './styles';
import {AdditionalSourceInfo} from './types';
import {
bufferConfig,
defaultValue,
srcList,
textTracksSelectionBy,
} from './constants';
import {bufferConfig, srcList, textTracksSelectionBy} from './constants';
import {Overlay, toast} from './components';
type Props = NonNullable<unknown>;
const VideoPlayer: FC<Props> = ({}) => {
const [state, setState] = useState(defaultValue);
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<AudioTrack[]>([]);
const [textTracks, setTextTracks] = useState<TextTrack[]>([]);
const [videoTracks, setVideoTracks] = useState<VideoTrack[]>([]);
const [selectedAudioTrack, setSelectedAudioTrack] = useState<
SelectedTrack | undefined
>(undefined);
const [selectedTextTrack, setSelectedTextTrack] = useState<
SelectedTrack | undefined
>(undefined);
const [selectedVideoTrack, setSelectedVideoTrack] =
useState<SelectedVideoTrack>({
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<string | undefined>(undefined);
const [showNotificationControls, setShowNotificationControls] =
useState(false);
const [isSeeking, setIsSeeking] = useState(false);
const videoRef = useRef<VideoRef>(null);
const viewStyle = state.fullscreen ? styles.fullScreen : styles.halfScreen;
const currentSrc = srcList[state.srcListId];
const viewStyle = fullscreen ? styles.fullScreen : styles.halfScreen;
const currentSrc = srcList[srcListId];
const additional = currentSrc as AdditionalSourceInfo;
const onAudioTracks = (data: OnAudioTracksData) => {
@ -50,28 +81,19 @@ const VideoPlayer: FC<Props> = ({}) => {
return x.selected;
});
if (selectedTrack?.index) {
setState({
...state,
audioTracks: data.audioTracks,
selectedAudioTrack: {
setAudioTracks(data.audioTracks);
setSelectedAudioTrack({
type: SelectedTrackType.INDEX,
value: selectedTrack?.index,
},
value: selectedTrack.index,
});
} else {
setState({
...state,
audioTracks: data.audioTracks,
});
setAudioTracks(data.audioTracks);
}
};
const onVideoTracks = (data: OnVideoTracksData) => {
console.log('onVideoTracks', data.videoTracks);
setState({
...state,
videoTracks: data.videoTracks,
});
setVideoTracks(data.videoTracks);
};
const onTextTracks = (data: OnTextTracksData) => {
@ -80,46 +102,42 @@ const VideoPlayer: FC<Props> = ({}) => {
});
if (selectedTrack?.language) {
setState({
...state,
textTracks: data.textTracks,
selectedTextTrack:
textTracksSelectionBy === 'index'
? {
setTextTracks(data.textTracks);
if (textTracksSelectionBy === 'index') {
setSelectedTextTrack({
type: SelectedTrackType.INDEX,
value: selectedTrack?.index,
}
: {
type: SelectedTrackType.LANGUAGE,
value: selectedTrack?.language,
},
});
} else {
setState({
...state,
textTracks: data.textTracks,
setSelectedTextTrack({
type: SelectedTrackType.LANGUAGE,
value: selectedTrack?.language,
});
}
} else {
setTextTracks(data.textTracks);
}
};
const onLoad = (data: OnLoadData) => {
setDuration(data.duration);
onAudioTracks(data);
onTextTracks(data);
onVideoTracks(data);
setState({...state, duration: data.duration});
};
const onProgress = (data: OnProgressData) => {
setState({...state, currentTime: data.currentTime});
setCurrentTime(data.currentTime);
};
const onSeek = (data: OnSeekData) => {
setState({...state, currentTime: data.currentTime, isSeeking: false});
setCurrentTime(data.currentTime);
setIsSeeking(false);
};
const onVideoLoadStart = () => {
console.log('onVideoLoadStart');
setState({...state, isLoading: true});
setIsLoading(true);
};
const onTextTrackDataChanged = (data: OnTextTrackDataChangedData) => {
@ -128,29 +146,25 @@ const VideoPlayer: FC<Props> = ({}) => {
const onAspectRatio = (data: OnVideoAspectRatioData) => {
console.log('onAspectRadio called ' + JSON.stringify(data));
setState({
...state,
videoWidth: data.width,
videoHeight: data.height,
});
setVideoSize({videoWidth: data.width, videoHeight: data.height});
};
const onVideoBuffer = (param: OnBufferData) => {
console.log('onVideoBuffer');
setState({...state, isLoading: param.isBuffering});
setIsLoading(param.isBuffering);
};
const onReadyForDisplay = () => {
console.log('onReadyForDisplay');
setState({...state, isLoading: false});
setIsLoading(false);
};
const onAudioBecomingNoisy = () => {
setState({...state, paused: true});
setPaused(true);
};
const onAudioFocusChanged = (event: OnAudioFocusChangedData) => {
setState({...state, paused: !event.hasAudioFocus});
setPaused(!event.hasAudioFocus);
};
const onError = (err: OnVideoErrorData) => {
@ -159,7 +173,7 @@ const VideoPlayer: FC<Props> = ({}) => {
};
const onEnd = () => {
if (!state.loop) {
if (!repeat) {
channelUp();
}
};
@ -173,53 +187,49 @@ const VideoPlayer: FC<Props> = ({}) => {
};
const goToChannel = (channel: number) => {
setState({
...state,
srcListId: channel,
duration: 0.0,
currentTime: 0.0,
videoWidth: 0,
videoHeight: 0,
isLoading: false,
audioTracks: [],
textTracks: [],
selectedAudioTrack: undefined,
selectedTextTrack: undefined,
selectedVideoTrack: {
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 = () => {
const channelUp = useCallback(() => {
console.log('channel up');
goToChannel((state.srcListId + 1) % srcList.length);
};
goToChannel((srcListId + 1) % srcList.length);
}, [srcListId]);
const channelDown = () => {
const channelDown = useCallback(() => {
console.log('channel down');
goToChannel((state.srcListId + srcList.length - 1) % srcList.length);
};
goToChannel((srcListId + srcList.length - 1) % srcList.length);
}, [srcListId]);
return (
<View style={styles.container}>
{(srcList[state.srcListId] as AdditionalSourceInfo)?.noView ? null : (
{(srcList[srcListId] as AdditionalSourceInfo)?.noView ? null : (
<TouchableOpacity style={viewStyle}>
<Video
showNotificationControls={state.showNotificationControls}
showNotificationControls={showNotificationControls}
ref={videoRef}
source={currentSrc as ReactVideoSource}
textTracks={additional?.textTracks}
adTagUrl={additional?.adTagUrl}
drm={additional?.drm}
style={viewStyle}
rate={state.rate}
paused={state.paused}
volume={state.volume}
muted={state.muted}
fullscreen={state.fullscreen}
controls={state.showRNVControls}
resizeMode={state.resizeMode}
rate={rate}
paused={paused}
volume={volume}
muted={muted}
fullscreen={fullscreen}
controls={controls}
resizeMode={resizeMode}
onLoad={onLoad}
onAudioTracks={onAudioTracks}
onTextTracks={onTextTracks}
@ -236,17 +246,17 @@ const VideoPlayer: FC<Props> = ({}) => {
onReadyForDisplay={onReadyForDisplay}
onBuffer={onVideoBuffer}
onSeek={onSeek}
repeat={state.loop}
selectedTextTrack={state.selectedTextTrack}
selectedAudioTrack={state.selectedAudioTrack}
selectedVideoTrack={state.selectedVideoTrack}
repeat={repeat}
selectedTextTrack={selectedTextTrack}
selectedAudioTrack={selectedAudioTrack}
selectedVideoTrack={selectedVideoTrack}
playInBackground={false}
bufferConfig={{
...bufferConfig,
cacheSizeMB: state.useCache ? 200 : 0,
cacheSizeMB: useCache ? 200 : 0,
}}
preventsDisplaySleepDuringVideoPlayback={true}
poster={state.poster}
poster={poster}
onPlaybackRateChange={onPlaybackRateChange}
onPlaybackStateChanged={onPlaybackStateChanged}
bufferingStrategy={BufferingStrategyType.DEFAULT}
@ -257,9 +267,46 @@ const VideoPlayer: FC<Props> = ({}) => {
<Overlay
channelDown={channelDown}
channelUp={channelUp}
setState={setState}
state={state}
ref={videoRef}
videoTracks={videoTracks}
selectedVideoTrack={selectedVideoTrack}
setSelectedTextTrack={setSelectedTextTrack}
audioTracks={audioTracks}
controls={controls}
resizeMode={resizeMode}
textTracks={textTracks}
selectedTextTrack={selectedTextTrack}
selectedAudioTrack={selectedAudioTrack}
setSelectedAudioTrack={setSelectedAudioTrack}
setSelectedVideoTrack={setSelectedVideoTrack}
currentTime={currentTime}
setMuted={setMuted}
muted={muted}
fullscreen={fullscreen}
duration={duration}
decoration={decoration}
paused={paused}
volume={volume}
setControls={setControls}
poster={poster}
setDecoration={setDecoration}
rate={rate}
setFullscreen={setFullscreen}
setPaused={setPaused}
isLoading={isLoading}
isSeeking={isSeeking}
setIsSeeking={setIsSeeking}
repeat={repeat}
setRepeat={setRepeat}
setPoster={setPoster}
setRate={setRate}
setResizeMode={setResizeMode}
setShowNotificationControls={setShowNotificationControls}
showNotificationControls={showNotificationControls}
setUseCache={setUseCache}
setVolume={setVolume}
useCache={useCache}
srcListId={srcListId}
/>
</View>
);

View File

@ -13,13 +13,17 @@ import MultiValueControl, {
MultiValueControlPropType,
} from '../MultiValueControl.tsx';
import {
AudioTrack,
ResizeMode,
SelectedTrack,
SelectedTrackType,
SelectedVideoTrack,
SelectedVideoTrackType,
TextTrack,
VideoDecoderProperties,
VideoRef,
VideoTrack,
} from 'react-native-video';
import {StateType} from '../types';
import {
toast,
Seeker,
@ -32,12 +36,91 @@ import {
type Props = {
channelDown: () => void;
channelUp: () => void;
setState: (value: StateType) => void;
state: StateType;
fullscreen: boolean;
setFullscreen: (value: boolean) => void;
controls: boolean;
setControls: (value: boolean) => void;
decoration: boolean;
setDecoration: (value: boolean) => void;
showNotificationControls: boolean;
setShowNotificationControls: (value: boolean) => void;
selectedAudioTrack: SelectedTrack | undefined;
setSelectedAudioTrack: (value: SelectedTrack | undefined) => void;
selectedTextTrack: SelectedTrack | undefined;
setSelectedTextTrack: (value: SelectedTrack | undefined) => void;
selectedVideoTrack: SelectedVideoTrack;
setSelectedVideoTrack: (value: SelectedVideoTrack) => void;
setIsSeeking: (value: boolean) => void;
rate: number;
setRate: (value: number) => void;
volume: number;
setVolume: (value: number) => void;
resizeMode: ResizeMode;
setResizeMode: (value: ResizeMode) => void;
isLoading: boolean;
srcListId: number;
useCache: boolean;
setUseCache: (value: boolean) => void;
paused: boolean;
setPaused: (value: boolean) => void;
repeat: boolean;
setRepeat: (value: boolean) => void;
poster: string | undefined;
setPoster: (value: string | undefined) => void;
muted: boolean;
setMuted: (value: boolean) => void;
currentTime: number;
duration: number;
isSeeking: boolean;
audioTracks: AudioTrack[];
textTracks: TextTrack[];
videoTracks: VideoTrack[];
};
const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
const {state, setState, channelUp, channelDown} = props;
const {
channelUp,
channelDown,
setFullscreen,
fullscreen,
setControls,
controls,
setDecoration,
decoration,
setShowNotificationControls,
showNotificationControls,
setSelectedAudioTrack,
setSelectedTextTrack,
setSelectedVideoTrack,
setIsSeeking,
rate,
setRate,
volume,
setVolume,
resizeMode,
setResizeMode,
isLoading,
srcListId,
setUseCache,
useCache,
paused,
setPaused,
setRepeat,
repeat,
setPoster,
poster,
setMuted,
muted,
duration,
isSeeking,
currentTime,
textTracks,
videoTracks,
audioTracks,
selectedAudioTrack,
selectedVideoTrack,
selectedTextTrack,
} = props;
const popupInfo = useCallback(() => {
VideoDecoderProperties.getWidevineLevel().then((widevineLevel: number) => {
VideoDecoderProperties.isHEVCSupported().then((hevc: string) => {
@ -59,82 +142,62 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
}, []);
const toggleFullscreen = () => {
setState({...state, fullscreen: !state.fullscreen});
setFullscreen(!fullscreen);
};
const toggleControls = () => {
setState({...state, showRNVControls: !state.showRNVControls});
setControls(!controls);
};
const toggleDecoration = () => {
setState({...state, decoration: !state.decoration});
setDecoration(!decoration);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref.current?.setFullScreen(!state.decoration);
ref.current?.setFullScreen(!decoration);
};
const toggleShowNotificationControls = () => {
setState({
...state,
showNotificationControls: !state.showNotificationControls,
});
setShowNotificationControls(!showNotificationControls);
};
const onSelectedAudioTrackChange = (itemValue: string) => {
console.log('on audio value change ' + itemValue);
if (itemValue === 'none') {
setState({
...state,
selectedAudioTrack: {
setSelectedAudioTrack({
type: SelectedTrackType.DISABLED,
},
});
} else {
setState({
...state,
selectedAudioTrack: {
setSelectedAudioTrack({
type: SelectedTrackType.INDEX,
value: itemValue,
},
});
}
};
const onSelectedTextTrackChange = (itemValue: string) => {
console.log('on value change ' + itemValue);
setState({
...state,
selectedTextTrack: {
type:
const type =
textTracksSelectionBy === 'index'
? SelectedTrackType.INDEX
: SelectedTrackType.LANGUAGE,
value: itemValue,
},
});
: SelectedTrackType.LANGUAGE;
setSelectedTextTrack({type, value: itemValue});
};
const onSelectedVideoTrackChange = (itemValue: string) => {
console.log('on value change ' + itemValue);
if (itemValue === undefined || itemValue === 'auto') {
setState({
...state,
selectedVideoTrack: {
setSelectedVideoTrack({
type: SelectedVideoTrackType.AUTO,
},
});
} else {
setState({
...state,
selectedVideoTrack: {
setSelectedVideoTrack({
type: SelectedVideoTrackType.INDEX,
value: itemValue,
},
});
}
};
const videoSeek = (position: number) => {
setState({...state, isSeeking: true});
setIsSeeking(true);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref.current?.seek(position);
@ -142,33 +205,45 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
const onRateSelected = (value: MultiValueControlPropType) => {
if (typeof value === 'number') {
setState({...state, rate: value});
}
};
const onVolumeSelected = (value: MultiValueControlPropType) => {
if (typeof value === 'number') {
setState({...state, volume: value});
}
};
const onResizeModeSelected = (value: MultiValueControlPropType) => {
if (typeof value === 'object') {
setState({...state, resizeMode: value});
setRate(value);
}
};
const onVolumeSelected = (value: MultiValueControlPropType) => {
if (typeof value === 'number') {
setVolume(value);
}
};
const onResizeModeSelected = (value: MultiValueControlPropType) => {
if (typeof value === 'object') {
setResizeMode(value);
}
};
const toggleCache = () => setUseCache(!useCache);
const togglePause = () => setPaused(!paused);
const toggleRepeat = () => setRepeat(!repeat);
const togglePoster = () => setPoster(poster ? undefined : samplePoster);
const toggleMuted = () => setMuted(!muted);
return (
<>
<Indicator isLoading={state.isLoading} />
<Indicator isLoading={isLoading} />
<View style={styles.topControls}>
<View style={styles.resizeModeControl}>
<TopControl
srcListId={state.srcListId}
showRNVControls={state.showRNVControls}
srcListId={srcListId}
showRNVControls={controls}
toggleControls={toggleControls}
/>
</View>
</View>
{!state.showRNVControls ? (
{!controls ? (
<>
<View style={styles.leftControls}>
<ToggleControl onPress={channelDown} text="ChDown" />
@ -182,46 +257,35 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
<View style={styles.generalControls}>
<ToggleControl onPress={popupInfo} text="decoderInfo" />
<ToggleControl
isSelected={state.useCache}
onPress={() => {
setState({...state, useCache: !state.useCache});
}}
isSelected={useCache}
onPress={toggleCache}
selectedText="enable cache"
unselectedText="disable cache"
/>
</View>
) : null}
<ToggleControl
isSelected={state.paused}
onPress={() => {
setState({...state, paused: !state.paused});
}}
isSelected={paused}
onPress={togglePause}
selectedText="pause"
unselectedText="playing"
/>
<ToggleControl
isSelected={state.loop}
onPress={() => {
setState({...state, loop: !state.loop});
}}
isSelected={repeat}
onPress={toggleRepeat}
selectedText="loop enable"
unselectedText="loop disable"
/>
<ToggleControl onPress={toggleFullscreen} text="fullscreen" />
<ToggleControl onPress={toggleDecoration} text="decoration" />
<ToggleControl
isSelected={!!state.poster}
onPress={() => {
setState({
...state,
poster: state.poster ? undefined : samplePoster,
});
}}
isSelected={!!poster}
onPress={togglePoster}
selectedText="poster"
unselectedText="no poster"
/>
<ToggleControl
isSelected={state.showNotificationControls}
isSelected={showNotificationControls}
onPress={toggleShowNotificationControls}
selectedText="hide notification controls"
unselectedText="show notification controls"
@ -232,13 +296,13 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
<MultiValueControl
values={[0, 0.25, 0.5, 1.0, 1.5, 2.0]}
onPress={onRateSelected}
selected={state.rate}
selected={rate}
/>
{/* shall be replaced by slider */}
<MultiValueControl
values={[0.5, 1, 1.5]}
onPress={onVolumeSelected}
selected={state.volume}
selected={volume}
/>
<MultiValueControl
values={[
@ -247,18 +311,16 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
ResizeMode.STRETCH,
]}
onPress={onResizeModeSelected}
selected={state.resizeMode}
selected={resizeMode}
/>
<ToggleControl
isSelected={state.muted}
onPress={() => {
setState({...state, muted: !state.muted});
}}
isSelected={muted}
onPress={toggleMuted}
text="muted"
/>
{isIos ? (
<ToggleControl
isSelected={state.paused}
isSelected={paused}
onPress={() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
@ -276,27 +338,27 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
) : null}
</View>
<Seeker
currentTime={state.currentTime}
duration={state.duration}
isLoading={state.isLoading}
currentTime={currentTime}
duration={duration}
isLoading={isLoading}
videoSeek={prop => videoSeek(prop)}
isUISeeking={state.isSeeking}
isUISeeking={isSeeking}
/>
<View style={styles.generalControls}>
<AudioTrackSelector
audioTracks={state.audioTracks}
selectedAudioTrack={state.selectedAudioTrack}
audioTracks={audioTracks}
selectedAudioTrack={selectedAudioTrack}
onValueChange={onSelectedAudioTrackChange}
/>
<TextTrackSelector
textTracks={state.textTracks}
selectedTextTrack={state.selectedTextTrack}
textTracks={textTracks}
selectedTextTrack={selectedTextTrack}
onValueChange={onSelectedTextTrackChange}
textTracksSelectionBy={textTracksSelectionBy}
/>
<VideoTrackSelector
videoTracks={state.videoTracks}
selectedVideoTrack={state.selectedVideoTrack}
videoTracks={videoTracks}
selectedVideoTrack={selectedVideoTrack}
onValueChange={onSelectedVideoTrackChange}
/>
</View>

View File

@ -2,11 +2,9 @@ import {
BufferConfig,
DRMType,
ISO639_1,
ResizeMode,
SelectedVideoTrackType,
TextTrackType,
} from 'react-native-video';
import {SampleVideoSource, StateType} from '../types';
import {SampleVideoSource} from '../types';
import {localeVideo} from '../assets';
import {Platform} from 'react-native';
@ -159,36 +157,6 @@ export const srcList: SampleVideoSource[] = srcAllPlatformList.concat(
isAndroid ? srcAndroidList : srcIosList,
);
export const defaultValue: StateType = {
rate: 1,
volume: 1,
muted: false,
resizeMode: ResizeMode.CONTAIN,
duration: 0.0,
currentTime: 0.0,
videoWidth: 0,
videoHeight: 0,
paused: false,
fullscreen: true,
decoration: true,
isLoading: false,
audioTracks: [],
textTracks: [],
videoTracks: [],
selectedAudioTrack: undefined,
selectedTextTrack: undefined,
selectedVideoTrack: {
type: SelectedVideoTrackType.AUTO,
},
srcListId: 0,
loop: false,
showRNVControls: false,
useCache: false,
poster: undefined,
showNotificationControls: false,
isSeeking: false,
};
export const bufferConfig: BufferConfig = {
minBufferMs: 15000,
maxBufferMs: 50000,
@ -197,4 +165,4 @@ export const bufferConfig: BufferConfig = {
live: {
targetOffsetMs: 500,
},
}
};

View File

@ -1,14 +1,4 @@
import {
AudioTrack,
Drm,
ReactVideoSource,
ResizeMode,
SelectedTrack,
SelectedVideoTrack,
TextTrack,
TextTracks,
VideoTrack,
} from 'react-native-video';
import {Drm, ReactVideoSource, TextTracks} from 'react-native-video';
export type AdditionalSourceInfo = {
textTracks: TextTracks;
@ -19,31 +9,3 @@ export type AdditionalSourceInfo = {
};
export type SampleVideoSource = ReactVideoSource | AdditionalSourceInfo;
export interface StateType {
rate: number;
volume: number;
muted: boolean;
resizeMode: ResizeMode;
duration: number;
currentTime: number;
videoWidth: number;
videoHeight: number;
paused: boolean;
fullscreen: boolean;
decoration: boolean;
isLoading: boolean;
audioTracks: Array<AudioTrack>;
textTracks: Array<TextTrack>;
videoTracks: Array<VideoTrack>;
selectedAudioTrack: SelectedTrack | undefined;
selectedTextTrack: SelectedTrack | undefined;
selectedVideoTrack: SelectedVideoTrack;
srcListId: number;
loop: boolean;
showRNVControls: boolean;
useCache: boolean;
poster?: string;
showNotificationControls: boolean;
isSeeking: boolean;
}