chore: update basic example
This commit is contained in:
		| @@ -1,8 +1,6 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| import React, { | import React, {Component, createRef} from 'react'; | ||||||
|   Component |  | ||||||
| } from 'react'; |  | ||||||
|  |  | ||||||
| import { | import { | ||||||
|   StyleSheet, |   StyleSheet, | ||||||
| @@ -14,12 +12,11 @@ import { | |||||||
|   ToastAndroid, |   ToastAndroid, | ||||||
| } from 'react-native'; | } 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 { | class VideoPlayer extends Component { | ||||||
|  |  | ||||||
|   state = { |   state = { | ||||||
|     rate: 1, |     rate: 1, | ||||||
|     volume: 1, |     volume: 1, | ||||||
| @@ -46,7 +43,7 @@ class VideoPlayer extends Component { | |||||||
|     showRNVControls: false, |     showRNVControls: false, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   seekerWidth = 0 |   seekerWidth = 0; | ||||||
|  |  | ||||||
|   srcList = [ |   srcList = [ | ||||||
|     require('./broadchurch.mp4'), |     require('./broadchurch.mp4'), | ||||||
| @@ -60,18 +57,16 @@ class VideoPlayer extends Component { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       description: '(hls|live) red bull tv', |       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', |       description: '(mp4|subtitles) demo with sintel Subtitles', | ||||||
|       uri: |       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', | ||||||
|         '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', |       type: 'mpd', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       description: 'invalid URL', |       description: 'invalid URL', | ||||||
|       uri: |       uri: 'mmt://www.youtube.com', | ||||||
|         'mmt://www.youtube.com', |  | ||||||
|       type: 'mpd', |       type: 'mpd', | ||||||
|     }, |     }, | ||||||
|     {description: '(no url) Stopped playback', uri: undefined}, |     {description: '(no url) Stopped playback', uri: undefined}, | ||||||
| @@ -79,14 +74,15 @@ class VideoPlayer extends Component { | |||||||
|       description: '(no view) no View', |       description: '(no view) no View', | ||||||
|       noView: true, |       noView: true, | ||||||
|     }, |     }, | ||||||
|   ] |   ]; | ||||||
|  |  | ||||||
|   video: Video; |   video = createRef<Video>(); | ||||||
|   seekPanResponder: PanResponder | undefined; |   seekPanResponder: PanResponder | undefined; | ||||||
|  |  | ||||||
|   popupInfo = () => { |   popupInfo = () => { | ||||||
|     VideoDecoderProperties.getWidevineLevel().then((widevineLevel: number) => { |     VideoDecoderProperties.getWidevineLevel().then((widevineLevel: number) => { | ||||||
|       VideoDecoderProperties.isHEVCSupported().then((hevcSupported: boolean) => { |       VideoDecoderProperties.isHEVCSupported().then( | ||||||
|  |         (hevcSupported: boolean) => { | ||||||
|           VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then( |           VideoDecoderProperties.isCodecSupported('video/avc', 1920, 1080).then( | ||||||
|             (avcSupported: boolean) => { |             (avcSupported: boolean) => { | ||||||
|               this.toast( |               this.toast( | ||||||
| @@ -99,60 +95,57 @@ class VideoPlayer extends Component { | |||||||
|                   '\n avc: ' + |                   '\n avc: ' + | ||||||
|                   (avcSupported ? '' : 'NOT') + |                   (avcSupported ? '' : 'NOT') + | ||||||
|                   'supported', |                   'supported', | ||||||
|             ) |               ); | ||||||
|             }, |             }, | ||||||
|         ) |           ); | ||||||
|       }) |         }, | ||||||
|     }) |       ); | ||||||
|   } |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   onLoad = (data: any) => { |   onLoad = (data: any) => { | ||||||
|     this.setState({ duration: data.duration, loading: false, }); |     this.setState({duration: data.duration, loading: false}); | ||||||
|     this.onAudioTracks(data) |     this.onAudioTracks(data); | ||||||
|     this.onTextTracks(data) |     this.onTextTracks(data); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   onProgress = (data: any) => { |   onProgress = (data: any) => { | ||||||
|     if (!this.state.seeking) { |     if (!this.state.seeking) { | ||||||
|       const position = this.calculateSeekerPosition() |       const position = this.calculateSeekerPosition(); | ||||||
|       this.setSeekerPosition(position) |       this.setSeekerPosition(position); | ||||||
|     } |     } | ||||||
|     this.setState({ currentTime: data.currentTime }) |     this.setState({currentTime: data.currentTime}); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   onVideoLoadStart = () => { |   onVideoLoadStart = () => { | ||||||
|     console.log('onVideoLoadStart') |     this.setState({isLoading: true}); | ||||||
|     this.setState({ isLoading: true }) |   }; | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   onAudioTracks = (data: any) => { |   onAudioTracks = (data: any) => { | ||||||
|     const selectedTrack = data.audioTracks?.find((x: any) => { |     const selectedTrack = data.audioTracks?.find((x: any) => { | ||||||
|       return x.selected |       return x.selected; | ||||||
|     }) |     }); | ||||||
|     this.setState({ |     this.setState({ | ||||||
|       audioTracks: data.audioTracks, |       audioTracks: data.audioTracks, | ||||||
|     }) |     }); | ||||||
|     if (selectedTrack?.language) { |     if (selectedTrack?.language) { | ||||||
|       this.setState({ |       this.setState({ | ||||||
|         selectedAudioTrack: { |         selectedAudioTrack: { | ||||||
|           type: 'language', |           type: 'language', | ||||||
|           value: selectedTrack?.language, |           value: selectedTrack?.language, | ||||||
|         }, |         }, | ||||||
|       }) |       }); | ||||||
|  |  | ||||||
|     } |  | ||||||
|     } |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   onTextTracks = (data: any) => { |   onTextTracks = (data: any) => { | ||||||
|     const selectedTrack = data.textTracks?.find((x: any) => { |     const selectedTrack = data.textTracks?.find((x: any) => { | ||||||
|       return x.selected |       return x.selected; | ||||||
|     }) |     }); | ||||||
|  |  | ||||||
|     this.setState({ |     this.setState({ | ||||||
|       textTracks: data.textTracks, |       textTracks: data.textTracks, | ||||||
|     }) |     }); | ||||||
|     if (selectedTrack?.language) { |     if (selectedTrack?.language) { | ||||||
|       this.setState({ |       this.setState({ | ||||||
|         textTracks: data, |         textTracks: data, | ||||||
| @@ -160,38 +153,31 @@ class VideoPlayer extends Component { | |||||||
|           type: 'language', |           type: 'language', | ||||||
|           value: selectedTrack?.language, |           value: selectedTrack?.language, | ||||||
|         }, |         }, | ||||||
|       }) |       }); | ||||||
|     } |  | ||||||
|     } |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   onAspectRatio = (data: any) => { |   onAspectRatio = (data: any) => { | ||||||
|     console.log('onAspectRadio called ' + JSON.stringify(data)) |  | ||||||
|     this.setState({ |     this.setState({ | ||||||
|       videoWidth: data.width, |       videoWidth: data.width, | ||||||
|       videoHeight: data.height, |       videoHeight: data.height, | ||||||
|     }) |     }); | ||||||
|   } |   }; | ||||||
|  |  | ||||||
|   onVideoBuffer = (param: any) => { |   onVideoBuffer = (param: any) => { | ||||||
|     console.log('onVideoBuffer') |     this.setState({isLoading: param.isBuffering}); | ||||||
|  |   }; | ||||||
|     this.setState({ isLoading: param.isBuffering }) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   onReadyForDisplay = () => { |   onReadyForDisplay = () => { | ||||||
|     console.log('onReadyForDisplay') |     this.setState({isLoading: false}); | ||||||
|  |   }; | ||||||
|     this.setState({ isLoading: false }) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   onAudioBecomingNoisy = () => { |   onAudioBecomingNoisy = () => { | ||||||
|     this.setState({ paused: true }) |     this.setState({paused: true}); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   onAudioFocusChanged = (event: {hasAudioFocus: boolean}) => { |   onAudioFocusChanged = (event: {hasAudioFocus: boolean}) => { | ||||||
|     this.setState({ paused: !event.hasAudioFocus }) |     this.setState({paused: !event.hasAudioFocus}); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   getCurrentTimePercentage = () => { |   getCurrentTimePercentage = () => { | ||||||
| @@ -202,11 +188,18 @@ class VideoPlayer extends Component { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   renderRateControl(rate: number) { |   renderRateControl(rate: number) { | ||||||
|     const isSelected = (this.state.rate === rate); |     const isSelected = this.state.rate === rate; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({ rate }) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}> |         onPress={() => { | ||||||
|  |           this.setState({rate}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {rate} |           {rate} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
| @@ -214,30 +207,43 @@ class VideoPlayer extends Component { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderResizeModeControl(resizeMode: string) { |   renderResizeModeControl(resizeMode: string) { | ||||||
|     const isSelected = (this.state.resizeMode === resizeMode); |     const isSelected = this.state.resizeMode === resizeMode; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({ resizeMode }) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}> |         onPress={() => { | ||||||
|  |           this.setState({resizeMode}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {resizeMode} |           {resizeMode} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderVolumeControl(volume: number) { |   renderVolumeControl(volume: number) { | ||||||
|     const isSelected = (this.state.volume === volume); |     const isSelected = this.state.volume === volume; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({ volume }) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}> |         onPress={() => { | ||||||
|  |           this.setState({volume}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {volume * 100}% |           {volume * 100}% | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   toast = (visible: boolean, message: string) => { |   toast = (visible: boolean, message: string) => { | ||||||
|     if (visible) { |     if (visible) { | ||||||
|       ToastAndroid.showWithGravityAndOffset( |       ToastAndroid.showWithGravityAndOffset( | ||||||
| @@ -246,35 +252,33 @@ class VideoPlayer extends Component { | |||||||
|         ToastAndroid.BOTTOM, |         ToastAndroid.BOTTOM, | ||||||
|         25, |         25, | ||||||
|         50, |         50, | ||||||
|       ) |       ); | ||||||
|       return null |       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() |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   onError = (err: any) => { | ||||||
|  |     this.toast(true, 'error: ' + err?.error.errorCode); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   onEnd = () => { | ||||||
|  |     this.channelUp(); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   toggleFullscreen() { |   toggleFullscreen() { | ||||||
|     this.setState({ fullscreen: !this.state.fullscreen }) |     this.setState({fullscreen: !this.state.fullscreen}); | ||||||
|   } |   } | ||||||
|   toggleControls() { |   toggleControls() { | ||||||
|     this.setState({ showRNVControls: !this.state.showRNVControls }) |     this.setState({showRNVControls: !this.state.showRNVControls}); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   toggleDecoration() { |   toggleDecoration() { | ||||||
|     this.setState({ decoration: !this.state.decoration }) |     this.setState({decoration: !this.state.decoration}); | ||||||
|     if (this.state.decoration) { |     if (this.state.decoration) { | ||||||
|       this.video.dismissFullscreenPlayer() |       this.video.current?.dismissFullscreenPlayer(); | ||||||
|     } else { |     } else { | ||||||
|       this.video.presentFullscreenPlayer() |       this.video.current?.presentFullscreenPlayer(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -290,86 +294,80 @@ class VideoPlayer extends Component { | |||||||
|       textTracks: [], |       textTracks: [], | ||||||
|       selectedAudioTrack: undefined, |       selectedAudioTrack: undefined, | ||||||
|       selectedTextTrack: undefined, |       selectedTextTrack: undefined, | ||||||
|     }) |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   channelUp() { |   channelUp() { | ||||||
|     console.log('channel up') |     this.goToChannel((this.state.srcListId + 1) % this.srcList.length); | ||||||
|     this.goToChannel((this.state.srcListId + 1) % this.srcList.length) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   channelDown() { |   channelDown() { | ||||||
|     console.log('channel down') |     this.goToChannel( | ||||||
|     this.goToChannel((this.state.srcListId + this.srcList.length - 1) % this.srcList.length) |       (this.state.srcListId + this.srcList.length - 1) % this.srcList.length, | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|     this.initSeekPanResponder() |     this.initSeekPanResponder(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderDecorationsControl() { |   renderDecorationsControl() { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity |       <TouchableOpacity | ||||||
|         onPress={() => { |         onPress={() => { | ||||||
|           this.toggleDecoration() |           this.toggleDecoration(); | ||||||
|         }} |         }}> | ||||||
|       > |  | ||||||
|         <Text style={[styles.controlOption]}>{'decoration'}</Text> |         <Text style={[styles.controlOption]}>{'decoration'}</Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderInfoControl() { |   renderInfoControl() { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity |       <TouchableOpacity | ||||||
|         onPress={() => { |         onPress={() => { | ||||||
|           this.popupInfo() |           this.popupInfo(); | ||||||
|         }} |         }}> | ||||||
|       > |  | ||||||
|         <Text style={[styles.controlOption]}>{'decoderInfo'}</Text> |         <Text style={[styles.controlOption]}>{'decoderInfo'}</Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderFullScreenControl() { |   renderFullScreenControl() { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity |       <TouchableOpacity | ||||||
|         onPress={() => { |         onPress={() => { | ||||||
|           this.toggleFullscreen() |           this.toggleFullscreen(); | ||||||
|         }} |         }}> | ||||||
|       > |  | ||||||
|         <Text style={[styles.controlOption]}>{'fullscreen'}</Text> |         <Text style={[styles.controlOption]}>{'fullscreen'}</Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderPause() { |   renderPause() { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity |       <TouchableOpacity | ||||||
|         onPress={() => { |         onPress={() => { | ||||||
|           this.setState({ paused: !this.state.paused }) |           this.setState({paused: !this.state.paused}); | ||||||
|         }} |         }}> | ||||||
|       > |  | ||||||
|         <Text style={[styles.controlOption]}> |         <Text style={[styles.controlOption]}> | ||||||
|           {this.state.paused ? 'pause' : 'playing'} |           {this.state.paused ? 'pause' : 'playing'} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderRepeatModeControl() { |   renderRepeatModeControl() { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity |       <TouchableOpacity | ||||||
|         onPress={() => { |         onPress={() => { | ||||||
|           this.setState({ loop: !this.state.loop }) |           this.setState({loop: !this.state.loop}); | ||||||
|         }} |         }}> | ||||||
|       > |  | ||||||
|         <Text style={[styles.controlOption]}> |         <Text style={[styles.controlOption]}> | ||||||
|           {this.state.loop ? 'loop enable' : 'loop disable'} |           {this.state.loop ? 'loop enable' : 'loop disable'} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderLeftControl() { |   renderLeftControl() { | ||||||
| @@ -377,14 +375,13 @@ class VideoPlayer extends Component { | |||||||
|       <View> |       <View> | ||||||
|         <TouchableOpacity |         <TouchableOpacity | ||||||
|           onPress={() => { |           onPress={() => { | ||||||
|             this.channelDown() |             this.channelDown(); | ||||||
|           }} |           }}> | ||||||
|         > |  | ||||||
|           <Text style={[styles.leftRightControlOption]}>{'ChDown'}</Text> |           <Text style={[styles.leftRightControlOption]}>{'ChDown'}</Text> | ||||||
|         </TouchableOpacity> |         </TouchableOpacity> | ||||||
|       </View> |       </View> | ||||||
|       // onTimelineUpdated |       // onTimelineUpdated | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderRightControl() { |   renderRightControl() { | ||||||
| @@ -392,13 +389,12 @@ class VideoPlayer extends Component { | |||||||
|       <View> |       <View> | ||||||
|         <TouchableOpacity |         <TouchableOpacity | ||||||
|           onPress={() => { |           onPress={() => { | ||||||
|             this.channelUp() |             this.channelUp(); | ||||||
|           }} |           }}> | ||||||
|         > |  | ||||||
|           <Text style={[styles.leftRightControlOption]}>{'ChUp'}</Text> |           <Text style={[styles.leftRightControlOption]}>{'ChUp'}</Text> | ||||||
|         </TouchableOpacity> |         </TouchableOpacity> | ||||||
|       </View> |       </View> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -415,11 +411,11 @@ class VideoPlayer extends Component { | |||||||
|    */ |    */ | ||||||
|   constrainToSeekerMinMax(val = 0) { |   constrainToSeekerMinMax(val = 0) { | ||||||
|     if (val <= 0) { |     if (val <= 0) { | ||||||
|       return 0 |       return 0; | ||||||
|     } else if (val >= this.seekerWidth) { |     } 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} |    * @param {float} position position in px of seeker handle} | ||||||
|    */ |    */ | ||||||
|   setSeekerPosition(position = 0) { |   setSeekerPosition(position = 0) { | ||||||
|     const state = this.state |     const state = this.state; | ||||||
|     position = this.constrainToSeekerMinMax(position) |     position = this.constrainToSeekerMinMax(position); | ||||||
|  |  | ||||||
|     state.seekerFillWidth = position |     state.seekerFillWidth = position; | ||||||
|     state.seekerPosition = position |     state.seekerPosition = position; | ||||||
|  |  | ||||||
|     if (!state.seeking) { |     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 |    * @return {float} position of seeker handle in px based on currentTime | ||||||
|    */ |    */ | ||||||
|   calculateSeekerPosition() { |   calculateSeekerPosition() { | ||||||
|     const percent = this.state.currentTime / this.state.duration |     const percent = this.state.currentTime / this.state.duration; | ||||||
|     return this.seekerWidth * percent |     return this.seekerWidth * percent; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -461,8 +457,8 @@ class VideoPlayer extends Component { | |||||||
|    * @return {float} time in ms based on seekerPosition. |    * @return {float} time in ms based on seekerPosition. | ||||||
|    */ |    */ | ||||||
|   calculateTimeFromSeekerPosition() { |   calculateTimeFromSeekerPosition() { | ||||||
|     const percent = this.state.seekerPosition / this.seekerWidth |     const percent = this.state.seekerPosition / this.seekerWidth; | ||||||
|     return this.state.duration * percent |     return this.state.duration * percent; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -480,20 +476,20 @@ class VideoPlayer extends Component { | |||||||
|        * position in the onProgress listener. |        * position in the onProgress listener. | ||||||
|        */ |        */ | ||||||
|       onPanResponderGrant: (evt, gestureState) => { |       onPanResponderGrant: (evt, gestureState) => { | ||||||
|         const state = this.state |         const state = this.state; | ||||||
|         // this.clearControlTimeout() |         // this.clearControlTimeout() | ||||||
|         const position = evt.nativeEvent.locationX |         const position = evt.nativeEvent.locationX; | ||||||
|         this.setSeekerPosition(position) |         this.setSeekerPosition(position); | ||||||
|         state.seeking = true |         state.seeking = true; | ||||||
|         this.setState(state) |         this.setState(state); | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|       /** |       /** | ||||||
|        * When panning, update the seekbar position, duh. |        * When panning, update the seekbar position, duh. | ||||||
|        */ |        */ | ||||||
|       onPanResponderMove: (evt, gestureState) => { |       onPanResponderMove: (evt, gestureState) => { | ||||||
|         const position = this.state.seekerOffset + gestureState.dx |         const position = this.state.seekerOffset + gestureState.dx; | ||||||
|         this.setSeekerPosition(position) |         this.setSeekerPosition(position); | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|       /** |       /** | ||||||
| @@ -502,41 +498,43 @@ class VideoPlayer extends Component { | |||||||
|        * onEnd callback |        * onEnd callback | ||||||
|        */ |        */ | ||||||
|       onPanResponderRelease: (evt, gestureState) => { |       onPanResponderRelease: (evt, gestureState) => { | ||||||
|         const time = this.calculateTimeFromSeekerPosition() |         const time = this.calculateTimeFromSeekerPosition(); | ||||||
|         const state = this.state |         const state = this.state; | ||||||
|         if (time >= state.duration && !state.isLoading) { |         if (time >= state.duration && !state.isLoading) { | ||||||
|           state.paused = true |           state.paused = true; | ||||||
|           this.onEnd() |           this.onEnd(); | ||||||
|         } else { |         } else { | ||||||
|           this.video?.seek(time) |           this.video.current?.seek(time); | ||||||
|           state.seeking = false |           state.seeking = false; | ||||||
|         } |         } | ||||||
|         this.setState(state) |         this.setState(state); | ||||||
|       }, |       }, | ||||||
|     }) |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderSeekBar() { |   renderSeekBar() { | ||||||
|     if (!this.seekPanResponder) { |     if (!this.seekPanResponder) { | ||||||
|       return null |       return null; | ||||||
|     } |     } | ||||||
|     return ( |     return ( | ||||||
|       <View |       <View | ||||||
|         style={styles.seekbarContainer} |         style={styles.seekbarContainer} | ||||||
|         {...this.seekPanResponder.panHandlers} |         {...this.seekPanResponder.panHandlers} | ||||||
|         {...styles.generalControls} |         {...styles.generalControls}> | ||||||
|       > |  | ||||||
|         <View |         <View | ||||||
|           style={styles.seekbarTrack} |           style={styles.seekbarTrack} | ||||||
|           onLayout={(event) => (this.seekerWidth = event.nativeEvent.layout.width)} |           onLayout={event => | ||||||
|           pointerEvents={'none'} |             (this.seekerWidth = event.nativeEvent.layout.width) | ||||||
|         > |           } | ||||||
|  |           pointerEvents={'none'}> | ||||||
|           <View |           <View | ||||||
|             style={[ |             style={[ | ||||||
|               styles.seekbarFill, |               styles.seekbarFill, | ||||||
|               { |               { | ||||||
|                 width: |                 width: | ||||||
|                   this.state.seekerFillWidth > 0 ? this.state.seekerFillWidth : 0, |                   this.state.seekerFillWidth > 0 | ||||||
|  |                     ? this.state.seekerFillWidth | ||||||
|  |                     : 0, | ||||||
|                 backgroundColor: '#FFF', |                 backgroundColor: '#FFF', | ||||||
|               }, |               }, | ||||||
|             ]} |             ]} | ||||||
| @@ -546,65 +544,84 @@ class VideoPlayer extends Component { | |||||||
|         <View |         <View | ||||||
|           style={[ |           style={[ | ||||||
|             styles.seekbarHandle, |             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 |           <View | ||||||
|             style={[ |             style={[styles.seekbarCircle, {backgroundColor: '#FFF'}]} | ||||||
|               styles.seekbarCircle, |  | ||||||
|               { backgroundColor: '#FFF' }, |  | ||||||
|             ]} |  | ||||||
|             pointerEvents={'none'} |             pointerEvents={'none'} | ||||||
|           /> |           /> | ||||||
|         </View> |         </View> | ||||||
|       </View> |       </View> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   IndicatorLoadingView() { |   IndicatorLoadingView() { | ||||||
|     if (this.state.isLoading) |     if (this.state.isLoading) | ||||||
|       return <ActivityIndicator color="#3235fd" size="large" style={styles.IndicatorStyle} /> |       return ( | ||||||
|     else return <View /> |         <ActivityIndicator | ||||||
|  |           color="#3235fd" | ||||||
|  |           size="large" | ||||||
|  |           style={styles.IndicatorStyle} | ||||||
|  |         /> | ||||||
|  |       ); | ||||||
|  |     else return <View />; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderTopControl() { |   renderTopControl() { | ||||||
|     return (<> |     return ( | ||||||
|  |       <> | ||||||
|         <Text style={[styles.controlOption]}> |         <Text style={[styles.controlOption]}> | ||||||
|           {this.srcList[this.state.srcListId]?.description || 'local file'} |           {this.srcList[this.state.srcListId]?.description || 'local file'} | ||||||
|         </Text> |         </Text> | ||||||
|         <View> |         <View> | ||||||
|           <TouchableOpacity |           <TouchableOpacity | ||||||
|             onPress={() => { |             onPress={() => { | ||||||
|             this.toggleControls() |               this.toggleControls(); | ||||||
|           }} |             }}> | ||||||
|         > |             <Text style={[styles.leftRightControlOption]}> | ||||||
|           <Text style={[styles.leftRightControlOption]}>{this.state.showRNVControls ? 'Hide controls' : 'Show controls'}</Text> |               {this.state.showRNVControls ? 'Hide controls' : 'Show controls'} | ||||||
|  |             </Text> | ||||||
|           </TouchableOpacity> |           </TouchableOpacity> | ||||||
|         </View> |         </View> | ||||||
|     </>) |       </> | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   renderOverlay() { |   renderOverlay() { | ||||||
|     return ( |     return ( | ||||||
|       <> |       <> | ||||||
|         {this.IndicatorLoadingView()} |         {this.IndicatorLoadingView()} | ||||||
|         <View style={styles.topControls}> |         <View style={styles.topControls}> | ||||||
|           <View style={styles.resizeModeControl}>{this.renderTopControl()}</View> |           <View style={styles.resizeModeControl}> | ||||||
|  |             {this.renderTopControl()} | ||||||
|  |           </View> | ||||||
|         </View> |         </View> | ||||||
|         {!this.state.showRNVControls ? ( |         {!this.state.showRNVControls ? ( | ||||||
|           <> |           <> | ||||||
|             <View style={styles.leftControls}> |             <View style={styles.leftControls}> | ||||||
|               <View style={styles.resizeModeControl}>{this.renderLeftControl()}</View> |               <View style={styles.resizeModeControl}> | ||||||
|             </View><View style={styles.rightControls}> |                 {this.renderLeftControl()} | ||||||
|               <View style={styles.resizeModeControl}>{this.renderRightControl()}</View> |               </View> | ||||||
|             </View><View style={styles.bottomControls}> |             </View> | ||||||
|               <View style={styles.generalControls}> |             <View style={styles.rightControls}> | ||||||
|                 <View style={styles.generalControls}> |               <View style={styles.resizeModeControl}> | ||||||
|                   <View style={styles.resizeModeControl}>{this.renderInfoControl()}</View> |                 {this.renderRightControl()} | ||||||
|  |               </View> | ||||||
|  |             </View> | ||||||
|  |             <View style={styles.bottomControls}> | ||||||
|  |               <View style={styles.generalControls}> | ||||||
|  |                 <View style={styles.generalControls}> | ||||||
|  |                   <View style={styles.resizeModeControl}> | ||||||
|  |                     {this.renderInfoControl()} | ||||||
|  |                   </View> | ||||||
|  |                 </View> | ||||||
|  |                 <View style={styles.resizeModeControl}> | ||||||
|  |                   {this.renderPause()} | ||||||
|                 </View> |                 </View> | ||||||
|                 <View style={styles.resizeModeControl}>{this.renderPause()}</View> |  | ||||||
|                 <View style={styles.resizeModeControl}> |                 <View style={styles.resizeModeControl}> | ||||||
|                   {this.renderRepeatModeControl()} |                   {this.renderRepeatModeControl()} | ||||||
|                 </View> |                 </View> | ||||||
| @@ -646,21 +663,20 @@ class VideoPlayer extends Component { | |||||||
|                     style={styles.picker} |                     style={styles.picker} | ||||||
|                     selectedValue={this.state.selectedAudioTrack?.value} |                     selectedValue={this.state.selectedAudioTrack?.value} | ||||||
|                     onValueChange={(itemValue, itemIndex) => { |                     onValueChange={(itemValue, itemIndex) => { | ||||||
|                       console.log('on audio value change ' + itemValue); |  | ||||||
|                       this.setState({ |                       this.setState({ | ||||||
|                         selectedAudioTrack: { |                         selectedAudioTrack: { | ||||||
|                           type: 'language', |                           type: 'language', | ||||||
|                           value: itemValue, |                           value: itemValue, | ||||||
|                         }, |                         }, | ||||||
|                       }); |                       }); | ||||||
|                     }} |                     }}> | ||||||
|                   > |                     {this.state.audioTracks.map(track => { | ||||||
|                     {this.state.audioTracks.map((track) => { |  | ||||||
|                       return ( |                       return ( | ||||||
|                         <Picker.Item |                         <Picker.Item | ||||||
|                           label={track.language} |                           label={track.language} | ||||||
|                           value={track.language} |                           value={track.language} | ||||||
|                           key={track.language} /> |                           key={track.language} | ||||||
|  |                         /> | ||||||
|                       ); |                       ); | ||||||
|                     })} |                     })} | ||||||
|                   </Picker> |                   </Picker> | ||||||
| @@ -673,45 +689,59 @@ class VideoPlayer extends Component { | |||||||
|                     style={styles.picker} |                     style={styles.picker} | ||||||
|                     selectedValue={this.state.selectedTextTrack?.value} |                     selectedValue={this.state.selectedTextTrack?.value} | ||||||
|                     onValueChange={(itemValue, itemIndex) => { |                     onValueChange={(itemValue, itemIndex) => { | ||||||
|                       console.log('on value change ' + itemValue); |  | ||||||
|                       this.setState({ |                       this.setState({ | ||||||
|                         selectedTextTrack: { |                         selectedTextTrack: { | ||||||
|                           type: 'language', |                           type: 'language', | ||||||
|                           value: itemValue, |                           value: itemValue, | ||||||
|                         }, |                         }, | ||||||
|                       }); |                       }); | ||||||
|                     }} |                     }}> | ||||||
|                   > |  | ||||||
|                     <Picker.Item label={'none'} value={'none'} key={'none'} /> |                     <Picker.Item label={'none'} value={'none'} key={'none'} /> | ||||||
|                     {this.state.textTracks.map((track) => ( |                     {this.state.textTracks.map(track => ( | ||||||
|                       <Picker.Item |                       <Picker.Item | ||||||
|                         label={track.language} |                         label={track.language} | ||||||
|                         value={track.language} |                         value={track.language} | ||||||
|                         key={track.language} /> |                         key={track.language} | ||||||
|  |                       /> | ||||||
|                     ))} |                     ))} | ||||||
|                   </Picker> |                   </Picker> | ||||||
|                 )} |                 )} | ||||||
|               </View> |               </View> | ||||||
|             </View></> |             </View> | ||||||
|         ) : null |  | ||||||
|         } |  | ||||||
|           </> |           </> | ||||||
|     ) |         ) : null} | ||||||
|  |       </> | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderVideoView() { |   renderVideoView() { | ||||||
|     const viewStyle = this.state.fullscreen ? styles.fullScreen : styles.halfScreen |     const viewStyle = this.state.fullscreen | ||||||
|  |       ? styles.fullScreen | ||||||
|  |       : styles.halfScreen; | ||||||
|  |  | ||||||
|     return ( |     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 |         <Video | ||||||
|           ref={(ref: Video) => { |           // paused={this.state.paused} | ||||||
|             this.video = ref |           ref={this.video} | ||||||
|           }} |  | ||||||
|           source={this.srcList[this.state.srcListId]} |           source={this.srcList[this.state.srcListId]} | ||||||
|           style={viewStyle} |           style={viewStyle} | ||||||
|           rate={this.state.rate} |           rate={this.state.rate} | ||||||
|           paused={this.state.paused} |  | ||||||
|           volume={this.state.volume} |           volume={this.state.volume} | ||||||
|           muted={this.state.muted} |           muted={this.state.muted} | ||||||
|           fullscreen={this.state.fullscreen} |           fullscreen={this.state.fullscreen} | ||||||
| @@ -736,21 +766,21 @@ class VideoPlayer extends Component { | |||||||
|           playInBackground={false} |           playInBackground={false} | ||||||
|         /> |         /> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   render() { |   render() { | ||||||
|     return ( |     return ( | ||||||
|       <View style={styles.container}> |       <View style={styles.container}> | ||||||
|         {this.srcList[this.state.srcListId]?.noView ? null : this.renderVideoView()} |         {this.srcList[this.state.srcListId]?.noView | ||||||
|  |           ? null | ||||||
|  |           : this.renderVideoView()} | ||||||
|         {this.renderOverlay()} |         {this.renderOverlay()} | ||||||
|       </View> |       </View> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| const styles = StyleSheet.create({ | const styles = StyleSheet.create({ | ||||||
|   container: { |   container: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
| @@ -890,4 +920,4 @@ const styles = StyleSheet.create({ | |||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| export default VideoPlayer | export default VideoPlayer; | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| import React, { | import React, {Component} from 'react'; | ||||||
|   Component |  | ||||||
| } from 'react'; |  | ||||||
|  |  | ||||||
| import { | import { | ||||||
|   Alert, |   Alert, | ||||||
| @@ -30,7 +28,7 @@ const filterTypes = [ | |||||||
|   FilterType.PROCESS, |   FilterType.PROCESS, | ||||||
|   FilterType.TONAL, |   FilterType.TONAL, | ||||||
|   FilterType.TRANSFER, |   FilterType.TRANSFER, | ||||||
|     FilterType.SEPIA |   FilterType.SEPIA, | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| class VideoPlayer extends Component { | class VideoPlayer extends Component { | ||||||
| @@ -40,7 +38,7 @@ class VideoPlayer extends Component { | |||||||
|     this.onProgress = this.onProgress.bind(this); |     this.onProgress = this.onProgress.bind(this); | ||||||
|     this.onBuffer = this.onBuffer.bind(this); |     this.onBuffer = this.onBuffer.bind(this); | ||||||
|   } |   } | ||||||
|   video = React.createRef(); |   video = React.createRef<Video>(); | ||||||
|  |  | ||||||
|   state = { |   state = { | ||||||
|     rate: 1, |     rate: 1, | ||||||
| @@ -56,7 +54,7 @@ class VideoPlayer extends Component { | |||||||
|     mixWithOthers: null, |     mixWithOthers: null, | ||||||
|     isBuffering: false, |     isBuffering: false, | ||||||
|     filter: FilterType.NONE, |     filter: FilterType.NONE, | ||||||
|     filterEnabled: true |     filterEnabled: true, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   onLoad(data: any) { |   onLoad(data: any) { | ||||||
| @@ -90,19 +88,26 @@ class VideoPlayer extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     this.setState({ |     this.setState({ | ||||||
|       filter: filterTypes[index] |       filter: filterTypes[index], | ||||||
|     }) |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderSkinControl(skin) { |   renderSkinControl(skin: 'custom' | 'native' | 'embed') { | ||||||
|     const isSelected = this.state.skin == skin; |     const isSelected = this.state.skin == skin; | ||||||
|     const selectControls = skin == 'native' || skin == 'embed'; |     const selectControls = skin == 'native' || skin == 'embed'; | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({ |       <TouchableOpacity | ||||||
|  |         onPress={() => { | ||||||
|  |           this.setState({ | ||||||
|             controls: selectControls, |             controls: selectControls, | ||||||
|           skin: skin |             skin: skin, | ||||||
|         }) }}> |           }); | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {skin} |           {skin} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
| @@ -110,77 +115,111 @@ class VideoPlayer extends Component { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderRateControl(rate: number) { |   renderRateControl(rate: number) { | ||||||
|     const isSelected = (this.state.rate == rate); |     const isSelected = this.state.rate == rate; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({rate: rate}) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         onPress={() => { | ||||||
|  |           this.setState({rate: rate}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {rate}x |           {rate}x | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderResizeModeControl(resizeMode: string) { |   renderResizeModeControl(resizeMode: string) { | ||||||
|     const isSelected = (this.state.resizeMode == resizeMode); |     const isSelected = this.state.resizeMode == resizeMode; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         onPress={() => { | ||||||
|  |           this.setState({resizeMode: resizeMode}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {resizeMode} |           {resizeMode} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderVolumeControl(volume: number) { |   renderVolumeControl(volume: number) { | ||||||
|     const isSelected = (this.state.volume == volume); |     const isSelected = this.state.volume == volume; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({volume: volume}) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         onPress={() => { | ||||||
|  |           this.setState({volume: volume}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {volume * 100}% |           {volume * 100}% | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderIgnoreSilentSwitchControl(ignoreSilentSwitch: string) { |   renderIgnoreSilentSwitchControl(ignoreSilentSwitch: string) { | ||||||
|     const isSelected = (this.state.ignoreSilentSwitch == ignoreSilentSwitch); |     const isSelected = this.state.ignoreSilentSwitch == ignoreSilentSwitch; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({ignoreSilentSwitch: ignoreSilentSwitch}) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         onPress={() => { | ||||||
|  |           this.setState({ignoreSilentSwitch: ignoreSilentSwitch}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {ignoreSilentSwitch} |           {ignoreSilentSwitch} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderFullscreenControl(fullscreen: string) { |   renderFullscreenControl(fullscreen: string) { | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { |       <TouchableOpacity | ||||||
|  |         onPress={() => { | ||||||
|           if (fullscreen === 'fullscreen') { |           if (fullscreen === 'fullscreen') { | ||||||
|             this.video.presentFullscreenPlayer() |             this.video.current?.presentFullscreenPlayer(); | ||||||
|           } |           } | ||||||
|         }}> |         }}> | ||||||
|         <Text style={[styles.controlOption]}> |         <Text style={[styles.controlOption]}>{fullscreen}</Text> | ||||||
|           {fullscreen} |  | ||||||
|         </Text> |  | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderMixWithOthersControl(mixWithOthers: string) { |   renderMixWithOthersControl(mixWithOthers: string) { | ||||||
|     const isSelected = (this.state.mixWithOthers == mixWithOthers); |     const isSelected = this.state.mixWithOthers == mixWithOthers; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TouchableOpacity onPress={() => { this.setState({mixWithOthers: mixWithOthers}) }}> |       <TouchableOpacity | ||||||
|         <Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}> |         onPress={() => { | ||||||
|  |           this.setState({mixWithOthers: mixWithOthers}); | ||||||
|  |         }}> | ||||||
|  |         <Text | ||||||
|  |           style={[ | ||||||
|  |             styles.controlOption, | ||||||
|  |             {fontWeight: isSelected ? 'bold' : 'normal'}, | ||||||
|  |           ]}> | ||||||
|           {mixWithOthers} |           {mixWithOthers} | ||||||
|         </Text> |         </Text> | ||||||
|       </TouchableOpacity> |       </TouchableOpacity> | ||||||
|     ) |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderCustomSkin() { |   renderCustomSkin() { | ||||||
| @@ -189,10 +228,24 @@ class VideoPlayer extends Component { | |||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <View style={styles.container}> |       <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 |           <Video | ||||||
|             ref={(ref: Video) => { |             ref={(ref: Video) => { | ||||||
|               this.video = ref |               this.video = ref; | ||||||
|             }} |             }} | ||||||
|             source={require('./broadchurch.mp4')} |             source={require('./broadchurch.mp4')} | ||||||
|             style={styles.fullScreen} |             style={styles.fullScreen} | ||||||
| @@ -206,7 +259,9 @@ class VideoPlayer extends Component { | |||||||
|             onLoad={this.onLoad} |             onLoad={this.onLoad} | ||||||
|             onBuffer={this.onBuffer} |             onBuffer={this.onBuffer} | ||||||
|             onProgress={this.onProgress} |             onProgress={this.onProgress} | ||||||
|             onEnd={() => { Alert.alert('Done!') }} |             onEnd={() => { | ||||||
|  |               Alert.alert('Done!'); | ||||||
|  |             }} | ||||||
|             repeat={true} |             repeat={true} | ||||||
|             filter={this.state.filter} |             filter={this.state.filter} | ||||||
|             filterEnabled={this.state.filterEnabled} |             filterEnabled={this.state.filterEnabled} | ||||||
| @@ -220,21 +275,22 @@ class VideoPlayer extends Component { | |||||||
|               {this.renderSkinControl('native')} |               {this.renderSkinControl('native')} | ||||||
|               {this.renderSkinControl('embed')} |               {this.renderSkinControl('embed')} | ||||||
|             </View> |             </View> | ||||||
|             { |             {this.state.filterEnabled ? ( | ||||||
|               (this.state.filterEnabled) ? |  | ||||||
|               <View style={styles.skinControl}> |               <View style={styles.skinControl}> | ||||||
|                     <TouchableOpacity onPress={() => { |                 <TouchableOpacity | ||||||
|                       this.setFilter(-1) |                   onPress={() => { | ||||||
|  |                     this.setFilter(-1); | ||||||
|                   }}> |                   }}> | ||||||
|                   <Text style={styles.controlOption}>Previous Filter</Text> |                   <Text style={styles.controlOption}>Previous Filter</Text> | ||||||
|                 </TouchableOpacity> |                 </TouchableOpacity> | ||||||
|                     <TouchableOpacity onPress={() => { |                 <TouchableOpacity | ||||||
|                       this.setFilter(1) |                   onPress={() => { | ||||||
|  |                     this.setFilter(1); | ||||||
|                   }}> |                   }}> | ||||||
|                   <Text style={styles.controlOption}>Next Filter</Text> |                   <Text style={styles.controlOption}>Next Filter</Text> | ||||||
|                 </TouchableOpacity> |                 </TouchableOpacity> | ||||||
|                   </View> : null |               </View> | ||||||
|             } |             ) : null} | ||||||
|           </View> |           </View> | ||||||
|           <View style={styles.generalControls}> |           <View style={styles.generalControls}> | ||||||
|             <View style={styles.rateControl}> |             <View style={styles.rateControl}> | ||||||
| @@ -256,8 +312,7 @@ class VideoPlayer extends Component { | |||||||
|             </View> |             </View> | ||||||
|           </View> |           </View> | ||||||
|           <View style={styles.generalControls}> |           <View style={styles.generalControls}> | ||||||
|             { |             {Platform.OS === 'ios' ? ( | ||||||
|               (Platform.OS === 'ios') ? |  | ||||||
|               <> |               <> | ||||||
|                 <View style={styles.ignoreSilentSwitchControl}> |                 <View style={styles.ignoreSilentSwitchControl}> | ||||||
|                   {this.renderIgnoreSilentSwitchControl('ignore')} |                   {this.renderIgnoreSilentSwitchControl('ignore')} | ||||||
| @@ -270,14 +325,18 @@ class VideoPlayer extends Component { | |||||||
|                 <View style={styles.mixWithOthersControl}> |                 <View style={styles.mixWithOthersControl}> | ||||||
|                   {this.renderFullscreenControl('fullscreen')} |                   {this.renderFullscreenControl('fullscreen')} | ||||||
|                 </View> |                 </View> | ||||||
|                 </> : null |               </> | ||||||
|             } |             ) : null} | ||||||
|           </View> |           </View> | ||||||
|  |  | ||||||
|           <View style={styles.trackingControls}> |           <View style={styles.trackingControls}> | ||||||
|             <View style={styles.progress}> |             <View style={styles.progress}> | ||||||
|               <View style={[styles.innerProgressCompleted, {flex: flexCompleted}]} /> |               <View | ||||||
|               <View style={[styles.innerProgressRemaining, {flex: flexRemaining}]} /> |                 style={[styles.innerProgressCompleted, {flex: flexCompleted}]} | ||||||
|  |               /> | ||||||
|  |               <View | ||||||
|  |                 style={[styles.innerProgressRemaining, {flex: flexRemaining}]} | ||||||
|  |               /> | ||||||
|             </View> |             </View> | ||||||
|           </View> |           </View> | ||||||
|         </View> |         </View> | ||||||
| @@ -286,7 +345,10 @@ class VideoPlayer extends Component { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   renderNativeSkin() { |   renderNativeSkin() { | ||||||
|     const videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen; |     const videoStyle = | ||||||
|  |       this.state.skin == 'embed' | ||||||
|  |         ? styles.nativeVideoControls | ||||||
|  |         : styles.fullScreen; | ||||||
|     return ( |     return ( | ||||||
|       <View style={styles.container}> |       <View style={styles.container}> | ||||||
|         <View style={styles.fullScreen}> |         <View style={styles.fullScreen}> | ||||||
| @@ -303,7 +365,9 @@ class VideoPlayer extends Component { | |||||||
|             onLoad={this.onLoad} |             onLoad={this.onLoad} | ||||||
|             onBuffer={this.onBuffer} |             onBuffer={this.onBuffer} | ||||||
|             onProgress={this.onProgress} |             onProgress={this.onProgress} | ||||||
|             onEnd={() => { Alert.alert('Done!') }} |             onEnd={() => { | ||||||
|  |               Alert.alert('Done!'); | ||||||
|  |             }} | ||||||
|             repeat={true} |             repeat={true} | ||||||
|             controls={this.state.controls} |             controls={this.state.controls} | ||||||
|             filter={this.state.filter} |             filter={this.state.filter} | ||||||
| @@ -317,21 +381,22 @@ class VideoPlayer extends Component { | |||||||
|               {this.renderSkinControl('native')} |               {this.renderSkinControl('native')} | ||||||
|               {this.renderSkinControl('embed')} |               {this.renderSkinControl('embed')} | ||||||
|             </View> |             </View> | ||||||
|             { |             {this.state.filterEnabled ? ( | ||||||
|               (this.state.filterEnabled) ? |  | ||||||
|               <View style={styles.skinControl}> |               <View style={styles.skinControl}> | ||||||
|                     <TouchableOpacity onPress={() => { |                 <TouchableOpacity | ||||||
|                       this.setFilter(-1) |                   onPress={() => { | ||||||
|  |                     this.setFilter(-1); | ||||||
|                   }}> |                   }}> | ||||||
|                   <Text style={styles.controlOption}>Previous Filter</Text> |                   <Text style={styles.controlOption}>Previous Filter</Text> | ||||||
|                 </TouchableOpacity> |                 </TouchableOpacity> | ||||||
|                     <TouchableOpacity onPress={() => { |                 <TouchableOpacity | ||||||
|                       this.setFilter(1) |                   onPress={() => { | ||||||
|  |                     this.setFilter(1); | ||||||
|                   }}> |                   }}> | ||||||
|                   <Text style={styles.controlOption}>Next Filter</Text> |                   <Text style={styles.controlOption}>Next Filter</Text> | ||||||
|                 </TouchableOpacity> |                 </TouchableOpacity> | ||||||
|                   </View> : null |               </View> | ||||||
|             } |             ) : null} | ||||||
|           </View> |           </View> | ||||||
|           <View style={styles.generalControls}> |           <View style={styles.generalControls}> | ||||||
|             <View style={styles.rateControl}> |             <View style={styles.rateControl}> | ||||||
| @@ -353,8 +418,7 @@ class VideoPlayer extends Component { | |||||||
|             </View> |             </View> | ||||||
|           </View> |           </View> | ||||||
|           <View style={styles.generalControls}> |           <View style={styles.generalControls}> | ||||||
|             { |             {Platform.OS === 'ios' ? ( | ||||||
|               (Platform.OS === 'ios') ? |  | ||||||
|               <> |               <> | ||||||
|                 <View style={styles.ignoreSilentSwitchControl}> |                 <View style={styles.ignoreSilentSwitchControl}> | ||||||
|                   {this.renderIgnoreSilentSwitchControl('ignore')} |                   {this.renderIgnoreSilentSwitchControl('ignore')} | ||||||
| @@ -364,17 +428,18 @@ class VideoPlayer extends Component { | |||||||
|                   {this.renderMixWithOthersControl('mix')} |                   {this.renderMixWithOthersControl('mix')} | ||||||
|                   {this.renderMixWithOthersControl('duck')} |                   {this.renderMixWithOthersControl('duck')} | ||||||
|                 </View> |                 </View> | ||||||
|                 </> : null |               </> | ||||||
|             } |             ) : null} | ||||||
|           </View> |           </View> | ||||||
|         </View> |         </View> | ||||||
|  |  | ||||||
|       </View> |       </View> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   render() { |   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, |     right: 0, | ||||||
|   }, |   }, | ||||||
|   controls: { |   controls: { | ||||||
|     backgroundColor: "transparent", |     backgroundColor: 'transparent', | ||||||
|     borderRadius: 5, |     borderRadius: 5, | ||||||
|     position: 'absolute', |     position: 'absolute', | ||||||
|     bottom: 44, |     bottom: 44, | ||||||
| @@ -439,24 +504,24 @@ const styles = StyleSheet.create({ | |||||||
|     flex: 1, |     flex: 1, | ||||||
|     flexDirection: 'row', |     flexDirection: 'row', | ||||||
|     alignItems: 'center', |     alignItems: 'center', | ||||||
|     justifyContent: 'center' |     justifyContent: 'center', | ||||||
|   }, |   }, | ||||||
|   ignoreSilentSwitchControl: { |   ignoreSilentSwitchControl: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|     flexDirection: 'row', |     flexDirection: 'row', | ||||||
|     alignItems: 'center', |     alignItems: 'center', | ||||||
|     justifyContent: 'center' |     justifyContent: 'center', | ||||||
|   }, |   }, | ||||||
|   mixWithOthersControl: { |   mixWithOthersControl: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|     flexDirection: 'row', |     flexDirection: 'row', | ||||||
|     alignItems: 'center', |     alignItems: 'center', | ||||||
|     justifyContent: 'center' |     justifyContent: 'center', | ||||||
|   }, |   }, | ||||||
|   controlOption: { |   controlOption: { | ||||||
|     alignSelf: 'center', |     alignSelf: 'center', | ||||||
|     fontSize: 11, |     fontSize: 11, | ||||||
|     color: "white", |     color: 'white', | ||||||
|     paddingLeft: 2, |     paddingLeft: 2, | ||||||
|     paddingRight: 2, |     paddingRight: 2, | ||||||
|     lineHeight: 12, |     lineHeight: 12, | ||||||
| @@ -472,4 +537,4 @@ const styles = StyleSheet.create({ | |||||||
|     justifyContent: 'center', |     justifyContent: 'center', | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
| export default VideoPlayer | export default VideoPlayer; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user