chore: update basic example

This commit is contained in:
KrzysztofMoch 2023-09-18 16:20:14 +02:00
parent e7276922a2
commit c991a0e8f7
2 changed files with 462 additions and 367 deletions

View File

@ -1,8 +1,6 @@
'use strict';
import React, {
Component
} from 'react';
import React, {Component, createRef} from 'react';
import {
StyleSheet,
@ -14,12 +12,11 @@ import {
ToastAndroid,
} from 'react-native';
import { Picker } from '@react-native-picker/picker'
import {Picker} from '@react-native-picker/picker';
import Video, { VideoDecoderProperties, TextTrackType } from 'react-native-video';
import Video, {TextTrackType, VideoDecoderProperties} from 'react-native-video';
class VideoPlayer extends Component {
state = {
rate: 1,
volume: 1,
@ -46,7 +43,7 @@ class VideoPlayer extends Component {
showRNVControls: false,
};
seekerWidth = 0
seekerWidth = 0;
srcList = [
require('./broadchurch.mp4'),
@ -60,99 +57,95 @@ class VideoPlayer extends Component {
},
{
description: '(hls|live) red bull tv',
uri: 'https://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_928.m3u8'
uri: 'https://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_928.m3u8',
},
{
description: '(mp4|subtitles) demo with sintel Subtitles',
uri:
'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0',
uri: 'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0',
type: 'mpd',
},
{
description: 'invalid URL',
uri:
'mmt://www.youtube.com',
uri: 'mmt://www.youtube.com',
type: 'mpd',
},
{ description: '(no url) Stopped playback', uri: undefined },
{description: '(no url) Stopped playback', uri: undefined},
{
description: '(no view) no View',
noView: true,
},
]
];
video: Video;
video = createRef<Video>();
seekPanResponder: PanResponder | undefined;
popupInfo = () => {
VideoDecoderProperties.getWidevineLevel().then((widevineLevel: number) => {
VideoDecoderProperties.isHEVCSupported().then((hevcSupported: boolean) => {
VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then(
(avcSupported: boolean) => {
this.toast(
true,
'Widevine level: ' +
widevineLevel +
'\n hevc: ' +
(hevcSupported ? '' : 'NOT') +
'supported' +
'\n avc: ' +
(avcSupported ? '' : 'NOT') +
'supported',
)
},
)
})
})
}
VideoDecoderProperties.isHEVCSupported().then(
(hevcSupported: boolean) => {
VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then(
(avcSupported: boolean) => {
this.toast(
true,
'Widevine level: ' +
widevineLevel +
'\n hevc: ' +
(hevcSupported ? '' : 'NOT') +
'supported' +
'\n avc: ' +
(avcSupported ? '' : 'NOT') +
'supported',
);
},
);
},
);
});
};
onLoad = (data: any) => {
this.setState({ duration: data.duration, loading: false, });
this.onAudioTracks(data)
this.onTextTracks(data)
this.setState({duration: data.duration, loading: false});
this.onAudioTracks(data);
this.onTextTracks(data);
};
onProgress = (data: any) => {
if (!this.state.seeking) {
const position = this.calculateSeekerPosition()
this.setSeekerPosition(position)
const position = this.calculateSeekerPosition();
this.setSeekerPosition(position);
}
this.setState({ currentTime: data.currentTime })
this.setState({currentTime: data.currentTime});
};
onVideoLoadStart = () => {
console.log('onVideoLoadStart')
this.setState({ isLoading: true })
}
this.setState({isLoading: true});
};
onAudioTracks = (data: any) => {
const selectedTrack = data.audioTracks?.find((x: any) => {
return x.selected
})
return x.selected;
});
this.setState({
audioTracks: data.audioTracks,
})
});
if (selectedTrack?.language) {
this.setState({
selectedAudioTrack: {
type: 'language',
value: selectedTrack?.language,
},
})
});
}
}
};
onTextTracks = (data: any) => {
const selectedTrack = data.textTracks?.find((x: any) => {
return x.selected
})
return x.selected;
});
this.setState({
textTracks: data.textTracks,
})
});
if (selectedTrack?.language) {
this.setState({
textTracks: data,
@ -160,38 +153,31 @@ class VideoPlayer extends Component {
type: 'language',
value: selectedTrack?.language,
},
})
});
}
}
};
onAspectRatio = (data: any) => {
console.log('onAspectRadio called ' + JSON.stringify(data))
this.setState({
videoWidth: data.width,
videoHeight: data.height,
})
}
onVideoBuffer = (param: any) => {
console.log('onVideoBuffer')
this.setState({ isLoading: param.isBuffering })
}
onReadyForDisplay = () => {
console.log('onReadyForDisplay')
this.setState({ isLoading: false })
}
onAudioBecomingNoisy = () => {
this.setState({ paused: true })
});
};
onAudioFocusChanged = (event: { hasAudioFocus: boolean }) => {
this.setState({ paused: !event.hasAudioFocus })
onVideoBuffer = (param: any) => {
this.setState({isLoading: param.isBuffering});
};
onReadyForDisplay = () => {
this.setState({isLoading: false});
};
onAudioBecomingNoisy = () => {
this.setState({paused: true});
};
onAudioFocusChanged = (event: {hasAudioFocus: boolean}) => {
this.setState({paused: !event.hasAudioFocus});
};
getCurrentTimePercentage = () => {
@ -202,11 +188,18 @@ class VideoPlayer extends Component {
};
renderRateControl(rate: number) {
const isSelected = (this.state.rate === rate);
const isSelected = this.state.rate === rate;
return (
<TouchableOpacity onPress={() => { this.setState({ rate }) }}>
<Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
<TouchableOpacity
onPress={() => {
this.setState({rate});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{rate}
</Text>
</TouchableOpacity>
@ -214,30 +207,43 @@ class VideoPlayer extends Component {
}
renderResizeModeControl(resizeMode: string) {
const isSelected = (this.state.resizeMode === resizeMode);
const isSelected = this.state.resizeMode === resizeMode;
return (
<TouchableOpacity onPress={() => { this.setState({ resizeMode }) }}>
<Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
<TouchableOpacity
onPress={() => {
this.setState({resizeMode});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{resizeMode}
</Text>
</TouchableOpacity>
)
);
}
renderVolumeControl(volume: number) {
const isSelected = (this.state.volume === volume);
const isSelected = this.state.volume === volume;
return (
<TouchableOpacity onPress={() => { this.setState({ volume }) }}>
<Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
<TouchableOpacity
onPress={() => {
this.setState({volume});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{volume * 100}%
</Text>
</TouchableOpacity>
)
);
}
toast = (visible: boolean, message: string) => {
if (visible) {
ToastAndroid.showWithGravityAndOffset(
@ -246,35 +252,33 @@ class VideoPlayer extends Component {
ToastAndroid.BOTTOM,
25,
50,
)
return null
);
return null;
}
return null
}
onError = (err: any) => {
console.log(JSON.stringify(err?.error.errorCode))
this.toast(true, 'error: ' + err?.error.errorCode)
}
onEnd = () => {
this.channelUp()
return null;
};
onError = (err: any) => {
this.toast(true, 'error: ' + err?.error.errorCode);
};
onEnd = () => {
this.channelUp();
};
toggleFullscreen() {
this.setState({ fullscreen: !this.state.fullscreen })
this.setState({fullscreen: !this.state.fullscreen});
}
toggleControls() {
this.setState({ showRNVControls: !this.state.showRNVControls })
this.setState({showRNVControls: !this.state.showRNVControls});
}
toggleDecoration() {
this.setState({ decoration: !this.state.decoration })
this.setState({decoration: !this.state.decoration});
if (this.state.decoration) {
this.video.dismissFullscreenPlayer()
this.video.current?.dismissFullscreenPlayer();
} else {
this.video.presentFullscreenPlayer()
this.video.current?.presentFullscreenPlayer();
}
}
@ -290,86 +294,80 @@ class VideoPlayer extends Component {
textTracks: [],
selectedAudioTrack: undefined,
selectedTextTrack: undefined,
})
});
}
channelUp() {
console.log('channel up')
this.goToChannel((this.state.srcListId + 1) % this.srcList.length)
this.goToChannel((this.state.srcListId + 1) % this.srcList.length);
}
channelDown() {
console.log('channel down')
this.goToChannel((this.state.srcListId + this.srcList.length - 1) % this.srcList.length)
this.goToChannel(
(this.state.srcListId + this.srcList.length - 1) % this.srcList.length,
);
}
componentDidMount() {
this.initSeekPanResponder()
this.initSeekPanResponder();
}
renderDecorationsControl() {
return (
<TouchableOpacity
onPress={() => {
this.toggleDecoration()
}}
>
this.toggleDecoration();
}}>
<Text style={[styles.controlOption]}>{'decoration'}</Text>
</TouchableOpacity>
)
);
}
renderInfoControl() {
return (
<TouchableOpacity
onPress={() => {
this.popupInfo()
}}
>
this.popupInfo();
}}>
<Text style={[styles.controlOption]}>{'decoderInfo'}</Text>
</TouchableOpacity>
)
);
}
renderFullScreenControl() {
return (
<TouchableOpacity
onPress={() => {
this.toggleFullscreen()
}}
>
this.toggleFullscreen();
}}>
<Text style={[styles.controlOption]}>{'fullscreen'}</Text>
</TouchableOpacity>
)
);
}
renderPause() {
return (
<TouchableOpacity
onPress={() => {
this.setState({ paused: !this.state.paused })
}}
>
this.setState({paused: !this.state.paused});
}}>
<Text style={[styles.controlOption]}>
{this.state.paused ? 'pause' : 'playing'}
</Text>
</TouchableOpacity>
)
);
}
renderRepeatModeControl() {
return (
<TouchableOpacity
onPress={() => {
this.setState({ loop: !this.state.loop })
}}
>
this.setState({loop: !this.state.loop});
}}>
<Text style={[styles.controlOption]}>
{this.state.loop ? 'loop enable' : 'loop disable'}
</Text>
</TouchableOpacity>
)
);
}
renderLeftControl() {
@ -377,14 +375,13 @@ class VideoPlayer extends Component {
<View>
<TouchableOpacity
onPress={() => {
this.channelDown()
}}
>
this.channelDown();
}}>
<Text style={[styles.leftRightControlOption]}>{'ChDown'}</Text>
</TouchableOpacity>
</View>
// onTimelineUpdated
)
);
}
renderRightControl() {
@ -392,13 +389,12 @@ class VideoPlayer extends Component {
<View>
<TouchableOpacity
onPress={() => {
this.channelUp()
}}
>
this.channelUp();
}}>
<Text style={[styles.leftRightControlOption]}>{'ChUp'}</Text>
</TouchableOpacity>
</View>
)
);
}
/**
@ -415,11 +411,11 @@ class VideoPlayer extends Component {
*/
constrainToSeekerMinMax(val = 0) {
if (val <= 0) {
return 0
return 0;
} else if (val >= this.seekerWidth) {
return this.seekerWidth
return this.seekerWidth;
}
return val
return val;
}
/**
@ -430,17 +426,17 @@ class VideoPlayer extends Component {
* @param {float} position position in px of seeker handle}
*/
setSeekerPosition(position = 0) {
const state = this.state
position = this.constrainToSeekerMinMax(position)
const state = this.state;
position = this.constrainToSeekerMinMax(position);
state.seekerFillWidth = position
state.seekerPosition = position
state.seekerFillWidth = position;
state.seekerPosition = position;
if (!state.seeking) {
state.seekerOffset = position
state.seekerOffset = position;
}
this.setState(state)
this.setState(state);
}
/**
@ -450,8 +446,8 @@ class VideoPlayer extends Component {
* @return {float} position of seeker handle in px based on currentTime
*/
calculateSeekerPosition() {
const percent = this.state.currentTime / this.state.duration
return this.seekerWidth * percent
const percent = this.state.currentTime / this.state.duration;
return this.seekerWidth * percent;
}
/**
@ -461,8 +457,8 @@ class VideoPlayer extends Component {
* @return {float} time in ms based on seekerPosition.
*/
calculateTimeFromSeekerPosition() {
const percent = this.state.seekerPosition / this.seekerWidth
return this.state.duration * percent
const percent = this.state.seekerPosition / this.seekerWidth;
return this.state.duration * percent;
}
/**
@ -480,20 +476,20 @@ class VideoPlayer extends Component {
* position in the onProgress listener.
*/
onPanResponderGrant: (evt, gestureState) => {
const state = this.state
const state = this.state;
// this.clearControlTimeout()
const position = evt.nativeEvent.locationX
this.setSeekerPosition(position)
state.seeking = true
this.setState(state)
const position = evt.nativeEvent.locationX;
this.setSeekerPosition(position);
state.seeking = true;
this.setState(state);
},
/**
* When panning, update the seekbar position, duh.
*/
onPanResponderMove: (evt, gestureState) => {
const position = this.state.seekerOffset + gestureState.dx
this.setSeekerPosition(position)
const position = this.state.seekerOffset + gestureState.dx;
this.setSeekerPosition(position);
},
/**
@ -502,41 +498,43 @@ class VideoPlayer extends Component {
* onEnd callback
*/
onPanResponderRelease: (evt, gestureState) => {
const time = this.calculateTimeFromSeekerPosition()
const state = this.state
const time = this.calculateTimeFromSeekerPosition();
const state = this.state;
if (time >= state.duration && !state.isLoading) {
state.paused = true
this.onEnd()
state.paused = true;
this.onEnd();
} else {
this.video?.seek(time)
state.seeking = false
this.video.current?.seek(time);
state.seeking = false;
}
this.setState(state)
this.setState(state);
},
})
});
}
renderSeekBar() {
if (!this.seekPanResponder) {
return null
return null;
}
return (
<View
style={styles.seekbarContainer}
{...this.seekPanResponder.panHandlers}
{...styles.generalControls}
>
{...styles.generalControls}>
<View
style={styles.seekbarTrack}
onLayout={(event) => (this.seekerWidth = event.nativeEvent.layout.width)}
pointerEvents={'none'}
>
onLayout={event =>
(this.seekerWidth = event.nativeEvent.layout.width)
}
pointerEvents={'none'}>
<View
style={[
styles.seekbarFill,
{
width:
this.state.seekerFillWidth > 0 ? this.state.seekerFillWidth : 0,
this.state.seekerFillWidth > 0
? this.state.seekerFillWidth
: 0,
backgroundColor: '#FFF',
},
]}
@ -546,65 +544,84 @@ class VideoPlayer extends Component {
<View
style={[
styles.seekbarHandle,
{ left: this.state.seekerPosition > 0 ? this.state.seekerPosition : 0 },
{
left:
this.state.seekerPosition > 0 ? this.state.seekerPosition : 0,
},
]}
pointerEvents={'none'}
>
pointerEvents={'none'}>
<View
style={[
styles.seekbarCircle,
{ backgroundColor: '#FFF' },
]}
style={[styles.seekbarCircle, {backgroundColor: '#FFF'}]}
pointerEvents={'none'}
/>
</View>
</View>
)
);
}
IndicatorLoadingView() {
if (this.state.isLoading)
return <ActivityIndicator color="#3235fd" size="large" style={styles.IndicatorStyle} />
else return <View />
return (
<ActivityIndicator
color="#3235fd"
size="large"
style={styles.IndicatorStyle}
/>
);
else return <View />;
}
renderTopControl() {
return (<>
<Text style={[styles.controlOption]}>
{this.srcList[this.state.srcListId]?.description || 'local file'}
</Text>
<View >
<TouchableOpacity
onPress={() => {
this.toggleControls()
}}
>
<Text style={[styles.leftRightControlOption]}>{this.state.showRNVControls ? 'Hide controls' : 'Show controls'}</Text>
</TouchableOpacity>
</View>
</>)
return (
<>
<Text style={[styles.controlOption]}>
{this.srcList[this.state.srcListId]?.description || 'local file'}
</Text>
<View>
<TouchableOpacity
onPress={() => {
this.toggleControls();
}}>
<Text style={[styles.leftRightControlOption]}>
{this.state.showRNVControls ? 'Hide controls' : 'Show controls'}
</Text>
</TouchableOpacity>
</View>
</>
);
}
renderOverlay() {
return (
<>
{this.IndicatorLoadingView()}
<View style={styles.topControls}>
<View style={styles.resizeModeControl}>{this.renderTopControl()}</View>
<View style={styles.resizeModeControl}>
{this.renderTopControl()}
</View>
</View>
{!this.state.showRNVControls ? (
<>
<View style={styles.leftControls}>
<View style={styles.resizeModeControl}>{this.renderLeftControl()}</View>
</View><View style={styles.rightControls}>
<View style={styles.resizeModeControl}>{this.renderRightControl()}</View>
</View><View style={styles.bottomControls}>
<View style={styles.resizeModeControl}>
{this.renderLeftControl()}
</View>
</View>
<View style={styles.rightControls}>
<View style={styles.resizeModeControl}>
{this.renderRightControl()}
</View>
</View>
<View style={styles.bottomControls}>
<View style={styles.generalControls}>
<View style={styles.generalControls}>
<View style={styles.resizeModeControl}>{this.renderInfoControl()}</View>
<View style={styles.resizeModeControl}>
{this.renderInfoControl()}
</View>
</View>
<View style={styles.resizeModeControl}>
{this.renderPause()}
</View>
<View style={styles.resizeModeControl}>{this.renderPause()}</View>
<View style={styles.resizeModeControl}>
{this.renderRepeatModeControl()}
</View>
@ -646,21 +663,20 @@ class VideoPlayer extends Component {
style={styles.picker}
selectedValue={this.state.selectedAudioTrack?.value}
onValueChange={(itemValue, itemIndex) => {
console.log('on audio value change ' + itemValue);
this.setState({
selectedAudioTrack: {
type: 'language',
value: itemValue,
},
});
}}
>
{this.state.audioTracks.map((track) => {
}}>
{this.state.audioTracks.map(track => {
return (
<Picker.Item
label={track.language}
value={track.language}
key={track.language} />
key={track.language}
/>
);
})}
</Picker>
@ -673,45 +689,59 @@ class VideoPlayer extends Component {
style={styles.picker}
selectedValue={this.state.selectedTextTrack?.value}
onValueChange={(itemValue, itemIndex) => {
console.log('on value change ' + itemValue);
this.setState({
selectedTextTrack: {
type: 'language',
value: itemValue,
},
});
}}
>
}}>
<Picker.Item label={'none'} value={'none'} key={'none'} />
{this.state.textTracks.map((track) => (
{this.state.textTracks.map(track => (
<Picker.Item
label={track.language}
value={track.language}
key={track.language} />
key={track.language}
/>
))}
</Picker>
)}
</View>
</View></>
) : null
}
</View>
</>
) : null}
</>
)
);
}
renderVideoView() {
const viewStyle = this.state.fullscreen ? styles.fullScreen : styles.halfScreen
const viewStyle = this.state.fullscreen
? styles.fullScreen
: styles.halfScreen;
return (
<TouchableOpacity style={viewStyle}>
<TouchableOpacity
style={viewStyle}
onPress={() => {
if (!this.video.current) {
return;
}
const {paused} = this.state;
const {pause, play, setPlayerStatus} = this.video.current;
const shouldPlay = paused === true || paused === undefined;
shouldPlay ? play() : pause();
// OR setPlayerStatus(shouldPlay);
this.setState({paused: !shouldPlay});
}}>
<Video
ref={(ref: Video) => {
this.video = ref
}}
// paused={this.state.paused}
ref={this.video}
source={this.srcList[this.state.srcListId]}
style={viewStyle}
rate={this.state.rate}
paused={this.state.paused}
volume={this.state.volume}
muted={this.state.muted}
fullscreen={this.state.fullscreen}
@ -736,21 +766,21 @@ class VideoPlayer extends Component {
playInBackground={false}
/>
</TouchableOpacity>
)
);
}
render() {
return (
<View style={styles.container}>
{this.srcList[this.state.srcListId]?.noView ? null : this.renderVideoView()}
{this.srcList[this.state.srcListId]?.noView
? null
: this.renderVideoView()}
{this.renderOverlay()}
</View>
)
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
@ -890,4 +920,4 @@ const styles = StyleSheet.create({
},
});
export default VideoPlayer
export default VideoPlayer;

View File

@ -1,7 +1,5 @@
'use strict';
import React, {
Component
} from 'react';
import React, {Component} from 'react';
import {
Alert,
@ -12,25 +10,25 @@ import {
View,
} from 'react-native';
import Video,{FilterType} from 'react-native-video';
import Video, {FilterType} from 'react-native-video';
const filterTypes = [
FilterType.NONE,
FilterType.INVERT,
FilterType.MONOCHROME,
FilterType.POSTERIZE,
FilterType.FALSE,
FilterType.MAXIMUMCOMPONENT,
FilterType.MINIMUMCOMPONENT,
FilterType.CHROME,
FilterType.FADE,
FilterType.INSTANT,
FilterType.MONO,
FilterType.NOIR,
FilterType.PROCESS,
FilterType.TONAL,
FilterType.TRANSFER,
FilterType.SEPIA
FilterType.NONE,
FilterType.INVERT,
FilterType.MONOCHROME,
FilterType.POSTERIZE,
FilterType.FALSE,
FilterType.MAXIMUMCOMPONENT,
FilterType.MINIMUMCOMPONENT,
FilterType.CHROME,
FilterType.FADE,
FilterType.INSTANT,
FilterType.MONO,
FilterType.NOIR,
FilterType.PROCESS,
FilterType.TONAL,
FilterType.TRANSFER,
FilterType.SEPIA,
];
class VideoPlayer extends Component {
@ -40,7 +38,7 @@ class VideoPlayer extends Component {
this.onProgress = this.onProgress.bind(this);
this.onBuffer = this.onBuffer.bind(this);
}
video = React.createRef();
video = React.createRef<Video>();
state = {
rate: 1,
@ -56,7 +54,7 @@ class VideoPlayer extends Component {
mixWithOthers: null,
isBuffering: false,
filter: FilterType.NONE,
filterEnabled: true
filterEnabled: true,
};
onLoad(data: any) {
@ -68,8 +66,8 @@ class VideoPlayer extends Component {
this.setState({currentTime: data.currentTime});
}
onBuffer({ isBuffering }: { isBuffering: boolean }) {
this.setState({ isBuffering });
onBuffer({isBuffering}: {isBuffering: boolean}) {
this.setState({isBuffering});
}
getCurrentTimePercentage() {
@ -90,19 +88,26 @@ class VideoPlayer extends Component {
}
this.setState({
filter: filterTypes[index]
})
filter: filterTypes[index],
});
}
renderSkinControl(skin) {
renderSkinControl(skin: 'custom' | 'native' | 'embed') {
const isSelected = this.state.skin == skin;
const selectControls = skin == 'native' || skin == 'embed';
return (
<TouchableOpacity onPress={() => { this.setState({
controls: selectControls,
skin: skin
}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({
controls: selectControls,
skin: skin,
});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{skin}
</Text>
</TouchableOpacity>
@ -110,77 +115,111 @@ class VideoPlayer extends Component {
}
renderRateControl(rate: number) {
const isSelected = (this.state.rate == rate);
const isSelected = this.state.rate == rate;
return (
<TouchableOpacity onPress={() => { this.setState({rate: rate}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({rate: rate});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{rate}x
</Text>
</TouchableOpacity>
)
);
}
renderResizeModeControl(resizeMode: string) {
const isSelected = (this.state.resizeMode == resizeMode);
const isSelected = this.state.resizeMode == resizeMode;
return (
<TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({resizeMode: resizeMode});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{resizeMode}
</Text>
</TouchableOpacity>
)
);
}
renderVolumeControl(volume: number) {
const isSelected = (this.state.volume == volume);
const isSelected = this.state.volume == volume;
return (
<TouchableOpacity onPress={() => { this.setState({volume: volume}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({volume: volume});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{volume * 100}%
</Text>
</TouchableOpacity>
)
);
}
renderIgnoreSilentSwitchControl(ignoreSilentSwitch: string) {
const isSelected = (this.state.ignoreSilentSwitch == ignoreSilentSwitch);
const isSelected = this.state.ignoreSilentSwitch == ignoreSilentSwitch;
return (
<TouchableOpacity onPress={() => { this.setState({ignoreSilentSwitch: ignoreSilentSwitch}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({ignoreSilentSwitch: ignoreSilentSwitch});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{ignoreSilentSwitch}
</Text>
</TouchableOpacity>
)
);
}
renderFullscreenControl(fullscreen: string) {
return (
<TouchableOpacity onPress={() => {
<TouchableOpacity
onPress={() => {
if (fullscreen === 'fullscreen') {
this.video.presentFullscreenPlayer()
this.video.current?.presentFullscreenPlayer();
}
}}>
<Text style={[styles.controlOption]}>
{fullscreen}
</Text>
<Text style={[styles.controlOption]}>{fullscreen}</Text>
</TouchableOpacity>
)
);
}
renderMixWithOthersControl(mixWithOthers: string) {
const isSelected = (this.state.mixWithOthers == mixWithOthers);
const isSelected = this.state.mixWithOthers == mixWithOthers;
return (
<TouchableOpacity onPress={() => { this.setState({mixWithOthers: mixWithOthers}) }}>
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
<TouchableOpacity
onPress={() => {
this.setState({mixWithOthers: mixWithOthers});
}}>
<Text
style={[
styles.controlOption,
{fontWeight: isSelected ? 'bold' : 'normal'},
]}>
{mixWithOthers}
</Text>
</TouchableOpacity>
)
);
}
renderCustomSkin() {
@ -189,10 +228,24 @@ class VideoPlayer extends Component {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.fullScreen} onPress={() => {this.setState({paused: !this.state.paused})}}>
<TouchableOpacity
style={styles.fullScreen}
onPress={() => {
if (!this.video.current) {
return;
}
const {play, pause, setPlayerStatus} = this.video.current;
const shouldPlay = !this.state.paused;
shouldPlay ? play() : pause();
// OR setPlayerStatus(shouldPlay)
this.setState({paused: shouldPlay});
}}>
<Video
ref={(ref: Video) => {
this.video = ref
this.video = ref;
}}
source={require('./broadchurch.mp4')}
style={styles.fullScreen}
@ -206,7 +259,9 @@ class VideoPlayer extends Component {
onLoad={this.onLoad}
onBuffer={this.onBuffer}
onProgress={this.onProgress}
onEnd={() => { Alert.alert('Done!') }}
onEnd={() => {
Alert.alert('Done!');
}}
repeat={true}
filter={this.state.filter}
filterEnabled={this.state.filterEnabled}
@ -220,21 +275,22 @@ class VideoPlayer extends Component {
{this.renderSkinControl('native')}
{this.renderSkinControl('embed')}
</View>
{
(this.state.filterEnabled) ?
<View style={styles.skinControl}>
<TouchableOpacity onPress={() => {
this.setFilter(-1)
}}>
<Text style={styles.controlOption}>Previous Filter</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
this.setFilter(1)
}}>
<Text style={styles.controlOption}>Next Filter</Text>
</TouchableOpacity>
</View> : null
}
{this.state.filterEnabled ? (
<View style={styles.skinControl}>
<TouchableOpacity
onPress={() => {
this.setFilter(-1);
}}>
<Text style={styles.controlOption}>Previous Filter</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.setFilter(1);
}}>
<Text style={styles.controlOption}>Next Filter</Text>
</TouchableOpacity>
</View>
) : null}
</View>
<View style={styles.generalControls}>
<View style={styles.rateControl}>
@ -256,28 +312,31 @@ class VideoPlayer extends Component {
</View>
</View>
<View style={styles.generalControls}>
{
(Platform.OS === 'ios') ?
<>
<View style={styles.ignoreSilentSwitchControl}>
{this.renderIgnoreSilentSwitchControl('ignore')}
{this.renderIgnoreSilentSwitchControl('obey')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderMixWithOthersControl('mix')}
{this.renderMixWithOthersControl('duck')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderFullscreenControl('fullscreen')}
</View>
</> : null
}
{Platform.OS === 'ios' ? (
<>
<View style={styles.ignoreSilentSwitchControl}>
{this.renderIgnoreSilentSwitchControl('ignore')}
{this.renderIgnoreSilentSwitchControl('obey')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderMixWithOthersControl('mix')}
{this.renderMixWithOthersControl('duck')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderFullscreenControl('fullscreen')}
</View>
</>
) : null}
</View>
<View style={styles.trackingControls}>
<View style={styles.progress}>
<View style={[styles.innerProgressCompleted, {flex: flexCompleted}]} />
<View style={[styles.innerProgressRemaining, {flex: flexRemaining}]} />
<View
style={[styles.innerProgressCompleted, {flex: flexCompleted}]}
/>
<View
style={[styles.innerProgressRemaining, {flex: flexRemaining}]}
/>
</View>
</View>
</View>
@ -286,7 +345,10 @@ class VideoPlayer extends Component {
}
renderNativeSkin() {
const videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen;
const videoStyle =
this.state.skin == 'embed'
? styles.nativeVideoControls
: styles.fullScreen;
return (
<View style={styles.container}>
<View style={styles.fullScreen}>
@ -303,7 +365,9 @@ class VideoPlayer extends Component {
onLoad={this.onLoad}
onBuffer={this.onBuffer}
onProgress={this.onProgress}
onEnd={() => { Alert.alert('Done!') }}
onEnd={() => {
Alert.alert('Done!');
}}
repeat={true}
controls={this.state.controls}
filter={this.state.filter}
@ -317,21 +381,22 @@ class VideoPlayer extends Component {
{this.renderSkinControl('native')}
{this.renderSkinControl('embed')}
</View>
{
(this.state.filterEnabled) ?
<View style={styles.skinControl}>
<TouchableOpacity onPress={() => {
this.setFilter(-1)
}}>
<Text style={styles.controlOption}>Previous Filter</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
this.setFilter(1)
}}>
<Text style={styles.controlOption}>Next Filter</Text>
</TouchableOpacity>
</View> : null
}
{this.state.filterEnabled ? (
<View style={styles.skinControl}>
<TouchableOpacity
onPress={() => {
this.setFilter(-1);
}}>
<Text style={styles.controlOption}>Previous Filter</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.setFilter(1);
}}>
<Text style={styles.controlOption}>Next Filter</Text>
</TouchableOpacity>
</View>
) : null}
</View>
<View style={styles.generalControls}>
<View style={styles.rateControl}>
@ -353,28 +418,28 @@ class VideoPlayer extends Component {
</View>
</View>
<View style={styles.generalControls}>
{
(Platform.OS === 'ios') ?
<>
<View style={styles.ignoreSilentSwitchControl}>
{this.renderIgnoreSilentSwitchControl('ignore')}
{this.renderIgnoreSilentSwitchControl('obey')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderMixWithOthersControl('mix')}
{this.renderMixWithOthersControl('duck')}
</View>
</> : null
}
{Platform.OS === 'ios' ? (
<>
<View style={styles.ignoreSilentSwitchControl}>
{this.renderIgnoreSilentSwitchControl('ignore')}
{this.renderIgnoreSilentSwitchControl('obey')}
</View>
<View style={styles.mixWithOthersControl}>
{this.renderMixWithOthersControl('mix')}
{this.renderMixWithOthersControl('duck')}
</View>
</>
) : null}
</View>
</View>
</View>
);
}
render() {
return this.state.controls ? this.renderNativeSkin() : this.renderCustomSkin();
return this.state.controls
? this.renderNativeSkin()
: this.renderCustomSkin();
}
}
@ -393,7 +458,7 @@ const styles = StyleSheet.create({
right: 0,
},
controls: {
backgroundColor: "transparent",
backgroundColor: 'transparent',
borderRadius: 5,
position: 'absolute',
bottom: 44,
@ -439,24 +504,24 @@ const styles = StyleSheet.create({
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
ignoreSilentSwitchControl: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
mixWithOthersControl: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
controlOption: {
alignSelf: 'center',
fontSize: 11,
color: "white",
color: 'white',
paddingLeft: 2,
paddingRight: 2,
lineHeight: 12,
@ -472,4 +537,4 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
});
export default VideoPlayer
export default VideoPlayer;