import PropTypes from 'prop-types'; import React, { Component } from 'react'; /** * Component that renders a video element for a passed in video track. * * @extends Component */ class Video extends Component { /** * Default values for {@code Video} component's properties. * * @static */ static defaultProps = { className: '', id: '' }; /** * {@code Video} component's property types. * * @static */ static propTypes = { /** * CSS classes to add to the video element. */ className: PropTypes.string, /** * The value of the id attribute of the video. Used by the torture tests * to locate video elements. */ id: PropTypes.string, /** * Optional callback to invoke once the video starts playing. */ onVideoPlaying: PropTypes.func, /** * The JitsiLocalTrack to display. */ videoTrack: PropTypes.object }; /** * Initializes a new {@code Video} instance. * * @param {Object} props - The read-only properties with which the new * instance is to be initialized. */ constructor(props) { super(props); /** * The internal reference to the DOM/HTML element intended for * displaying a video. This element may be an HTML video element or a * temasys video object. * * @private * @type {HTMLVideoElement|Object} */ this._videoElement = null; // Bind event handlers so they are only bound once for every instance. this._onVideoPlaying = this._onVideoPlaying.bind(this); this._setVideoElement = this._setVideoElement.bind(this); } /** * Invokes the library for rendering the video on initial display. Sets the * volume level to zero to ensure no sound plays. * * @inheritdoc * @returns {void} */ componentDidMount() { // Add these attributes directly onto the video element so temasys can // use them when converting the video to an object. this._videoElement.volume = 0; this._videoElement.onplaying = this._onVideoPlaying; this._attachTrack(this.props.videoTrack); } /** * Remove any existing associations between the current video track and the * component's video element. * * @inheritdoc * @returns {void} */ componentWillUnmount() { this._detachTrack(this.props.videoTrack); } /** * Updates the video display only if a new track is added. This component's * updating is blackboxed from React to prevent re-rendering of video * element, as the lib uses track.attach(videoElement) instead. Also, * re-rendering cannot be used with temasys, which replaces video elements * with an object. * * @inheritdoc * @returns {boolean} - False is always returned to blackbox this component. * from React. */ shouldComponentUpdate(nextProps) { const currentJitsiTrack = this.props.videoTrack && this.props.videoTrack.jitsiTrack; const nextJitsiTrack = nextProps.videoTrack && nextProps.videoTrack.jitsiTrack; if (currentJitsiTrack !== nextJitsiTrack) { this._detachTrack(this.props.videoTrack); this._attachTrack(nextProps.videoTrack); } return false; } /** * Renders the video element. * * @override * @returns {ReactElement} */ render() { // The wrapping div is necessary because temasys will replace the video // with an object but react will keep expecting the video element. The // div gives a constant element for react to keep track of. return (