Video component reimplemented with hooks

This commit is contained in:
NikolaBorislavovHristov 2019-09-25 17:56:34 +03:00
parent c6a29f5692
commit 7c6fb5a631
2 changed files with 67 additions and 58 deletions

View file

@ -1,77 +1,67 @@
const React = require('react');
const PropTypes = require('prop-types');
const hat = require('hat');
const { HTMLVideo, YouTubeVideo, MPVVideo } = require('stremio-video');
const useVideoImplementation = require('./useVideoImplementation');
class Video extends React.Component {
constructor(props) {
super(props);
this.containerRef = React.createRef();
this.id = `video-${hat()}`;
this.video = null;
}
shouldComponentUpdate() {
return false;
}
componentWillUnmount() {
this.dispatch({ commandName: 'destroy' });
}
selectVideoImplementation = (args) => {
if (args.ipc) {
return MPVVideo;
} else if (args.stream.ytId) {
return YouTubeVideo;
} else {
return HTMLVideo;
}
}
dispatch = (args = {}) => {
if (args.commandName === 'load') {
const { commandArgs = {} } = args;
const Video = this.selectVideoImplementation(commandArgs);
if (this.video === null || this.video.constructor !== Video) {
this.dispatch({ commandName: 'destroy' });
this.video = new Video({
id: this.id,
containerElement: this.containerRef.current,
ipc: commandArgs.ipc
const Video = React.forwardRef(({ className, ...props }, ref) => {
const [onEnded, onError, onPropValue, onPropChanged, onImplementationChanged] = React.useMemo(() => [
props.onEnded,
props.onError,
props.onPropValue,
props.onPropChanged,
props.onImplementationChanged
], []);
const containerElementRef = React.useRef(null);
const videoRef = React.useRef(null);
const id = React.useMemo(() => `video-${hat()}`, []);
const dispatch = React.useCallback((args) => {
if (args && args.commandName === 'load' && args.commandArgs) {
const Video = useVideoImplementation(args.commandArgs.shell, args.commandArgs.stream);
if (typeof Video !== 'function') {
videoRef.current = null;
} else if (videoRef.current === null || videoRef.current.constructor !== Video) {
dispatch({ commandName: 'destroy' });
videoRef.current = new Video({
id: id,
containerElement: containerElementRef.current,
shell: args.commandArgs.shell
});
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.onImplementationChanged(this.video.constructor.manifest);
videoRef.current.on('ended', onEnded);
videoRef.current.on('error', onError);
videoRef.current.on('propValue', onPropValue);
videoRef.current.on('propChanged', onPropChanged);
onImplementationChanged(videoRef.current.constructor.manifest);
}
}
if (this.video !== null) {
if (videoRef.current !== null) {
try {
this.video.dispatch(args);
videoRef.current.dispatch(args);
} catch (e) {
console.error(this.video.constructor.manifest.name, e);
console.error(videoRef.current.constructor.manifest.name, e);
}
}
}
}, []);
React.useImperativeHandle(ref, () => ({ dispatch }));
React.useEffect(() => {
return () => {
dispatch({ commandName: 'destroy' });
};
}, []);
return (
<div ref={containerElementRef} id={id} className={className} />
);
});
render() {
return (
<div ref={this.containerRef} id={this.id} className={this.props.className} />
);
}
}
Video.displayName = 'Video';
Video.propTypes = {
className: PropTypes.string,
onEnded: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
onPropValue: PropTypes.func.isRequired,
onPropChanged: PropTypes.func.isRequired,
onImplementationChanged: PropTypes.func.isRequired
onEnded: PropTypes.func,
onError: PropTypes.func,
onPropValue: PropTypes.func,
onPropChanged: PropTypes.func,
onImplementationChanged: PropTypes.func
};
module.exports = Video;

View file

@ -0,0 +1,19 @@
const { HTMLVideo, YouTubeVideo, MPVVideo } = require('stremio-video');
const useVideoImplementation = (shell, stream) => {
if (shell) {
return MPVVideo;
}
if (stream) {
if (stream.ytId) {
return YouTubeVideo;
} else {
return HTMLVideo;
}
}
return null;
};
module.exports = useVideoImplementation;