Video component refactored / HTMLVideo and YouTubeVideo combined

This commit is contained in:
NikolaBorislavovHristov 2018-11-21 17:45:47 +02:00
parent c3c361755a
commit c86793d7d7
9 changed files with 57 additions and 84 deletions

View file

@ -1,7 +1,5 @@
import React, { Component, Fragment } from 'react';
import classnames from 'classnames';
import ReactHTMLVideo from './stremio-video/ReactHTMLVideo';
import ReactYouTubeVideo from './stremio-video/ReactYouTubeVideo';
import Video from './Video';
import ControlBar from './ControlBar';
import styles from './styles';
@ -12,7 +10,7 @@ class Player extends Component {
this.videoRef = React.createRef();
this.state = {
videoComponent: null,
videoImplementation: null,
paused: null,
time: null,
duration: null,
@ -22,8 +20,8 @@ class Player extends Component {
componentDidMount() {
this.prepareStream()
.then(({ source, videoComponent }) => {
this.setState({ videoComponent }, () => {
.then(({ source, videoImplementation }) => {
this.setState({ videoImplementation }, () => {
this.videoRef.current.dispatch('command', 'load', {
source: source
});
@ -35,7 +33,7 @@ class Player extends Component {
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.videoComponent !== this.state.videoComponent ||
return nextState.videoImplementation !== this.state.videoImplementation ||
nextState.paused !== this.state.paused ||
nextState.time !== this.state.time ||
nextState.duration !== this.state.duration ||
@ -45,11 +43,15 @@ class Player extends Component {
prepareStream = () => {
return new Promise((resolve, reject) => {
// YT.ready(() => {
resolve({
source: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
videoComponent: ReactHTMLVideo
});
// resolve({
// source: 'J2z5uzqxJNU',
// videoImplementation: 'YouTube'
// });
// });
resolve({
source: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
videoImplementation: 'HTML'
});
});
}
@ -96,14 +98,15 @@ class Player extends Component {
}
renderVideo() {
if (this.state.videoComponent === null) {
if (this.state.videoImplementation === null) {
return null;
}
return (
<Fragment>
<this.state.videoComponent
<Video
ref={this.videoRef}
implementation={this.state.videoImplementation}
className={styles['layer']}
onEnded={this.onEnded}
onError={this.onError}

View file

@ -1,8 +1,10 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import HTMLVideo from './HTMLVideo';
import HTMLVideo from './stremio-video/HTMLVideo';
import YouTubeVideo from './stremio-video/YouTubeVideo';
import styles from './styles';
class ReactHTMLVideo extends Component {
class Video extends Component {
constructor(props) {
super(props);
@ -10,7 +12,7 @@ class ReactHTMLVideo extends Component {
}
componentDidMount() {
this.video = new HTMLVideo(this.videoRef.current);
this.video = new Video.implementations[this.props.implementation](this.videoRef.current);
this.video.on('ended', this.props.onEnded);
this.video.on('error', this.props.onError);
this.video.on('propValue', this.props.onPropValue);
@ -32,21 +34,44 @@ class ReactHTMLVideo extends Component {
try {
this.video && this.video.dispatch(...args);
} catch (e) {
console.error('HTMLVideo', e);
console.error(Video.implementations[this.props.implementation].manifest.name, e);
}
}
render() {
renderHTMLVideo() {
return (
<video ref={this.videoRef} className={this.props.className} />
<div className={this.props.className}>
<video ref={this.videoRef} className={styles['html-video']} />
</div>
);
}
renderYouTubeVideo() {
return (
<div className={this.props.className}>
<div ref={this.videoRef} />
</div>
);
}
render() {
switch (this.props.implementation) {
case 'HTML':
return this.renderHTMLVideo();
case 'YouTube':
return this.renderYouTubeVideo();
}
}
}
ReactHTMLVideo.manifest = HTMLVideo.manifest;
Video.implementations = {
'HTML': HTMLVideo,
'YouTube': YouTubeVideo
};
ReactHTMLVideo.propTypes = {
Video.propTypes = {
className: PropTypes.string,
implementation: PropTypes.oneOf(Object.keys(Video.implementations)).isRequired,
onEnded: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
onPropValue: PropTypes.func.isRequired,
@ -54,4 +79,4 @@ ReactHTMLVideo.propTypes = {
observedProps: PropTypes.arrayOf(PropTypes.string).isRequired
};
export default ReactHTMLVideo;
export default Video;

View file

@ -0,0 +1,3 @@
import Video from './Video';
export default Video;

View file

@ -0,0 +1,4 @@
.html-video {
width: 100%;
height: 100%;
}

View file

@ -1,57 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import YouTubeVideo from './YouTubeVideo';
class ReactYouTubeVideo extends Component {
constructor(props) {
super(props);
this.videoContainerRef = React.createRef();
}
componentDidMount() {
this.video = new YouTubeVideo(this.videoContainerRef.current);
this.video.on('ended', this.props.onEnded);
this.video.on('error', this.props.onError);
this.video.on('propValue', this.props.onPropValue);
this.video.on('propChanged', this.props.onPropChanged);
this.props.observedProps.forEach((propName) => {
this.dispatch('observeProp', propName);
});
}
componentWillUnmount() {
this.dispatch('stop');
}
shouldComponentUpdate() {
return false;
}
dispatch = (...args) => {
try {
this.video && this.video.dispatch(...args);
} catch (e) {
console.error('YouTubeVideo', e);
}
}
render() {
return (
<div ref={this.videoContainerRef} className={this.props.className} />
);
}
}
ReactYouTubeVideo.manifest = YouTubeVideo.manifest;
ReactYouTubeVideo.propTypes = {
className: PropTypes.string,
onEnded: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
onPropValue: PropTypes.func.isRequired,
onPropChanged: PropTypes.func.isRequired,
observedProps: PropTypes.arrayOf(PropTypes.string).isRequired
};
export default ReactYouTubeVideo;

View file

@ -11,9 +11,4 @@
right: 0;
bottom: 0;
}
video.layer {
width: 100%;
height: 100%;
}
}