fix(device-selection): do not reuse tracks in previews
Device selection has live previews that reuse the current local audio and video tracks for the sake of internet explorer. This means when the local video was muted, device selection would show a muted message. It is preferred to show a live preview even when muted. The changes include: - Passing device ids into DeviceSelectionDialog, not tracks. - Setting default selected devices to use for live previews. - Removing all checks in DeviceSelectionDialog involving local tracks. - Catching and displaying errors when creating a live video preview.
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
const VIDEO_MUTE_CLASS = 'video-muted';
|
||||
const VIDEO_ERROR_CLASS = 'video-preview-has-error';
|
||||
|
||||
/**
|
||||
* React component for displaying video. This component defers to lib-jitsi-meet
|
||||
@@ -17,12 +17,18 @@ class VideoInputPreview extends Component {
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* An error message to display instead of a preview. Displaying an error
|
||||
* will take priority over displaying a video preview.
|
||||
*/
|
||||
error: React.PropTypes.string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: React.PropTypes.func,
|
||||
|
||||
/*
|
||||
/**
|
||||
* The JitsiLocalTrack to display.
|
||||
*/
|
||||
track: React.PropTypes.object
|
||||
@@ -37,9 +43,37 @@ class VideoInputPreview extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
/**
|
||||
* The internal reference to the DOM/HTML element intended for showing
|
||||
* error messages.
|
||||
*
|
||||
* @private
|
||||
* @type {HTMLDivElement}
|
||||
*/
|
||||
this._errorElement = null;
|
||||
|
||||
/**
|
||||
* The internal reference to topmost DOM/HTML element backing the React
|
||||
* {@code Component}. Accessed directly for toggling a classname to
|
||||
* indicate an error is present so styling can be changed to display it.
|
||||
*
|
||||
* @private
|
||||
* @type {HTMLDivElement}
|
||||
*/
|
||||
this._rootElement = null;
|
||||
|
||||
/**
|
||||
* 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._setErrorElement = this._setErrorElement.bind(this);
|
||||
this._setRootElement = this._setRootElement.bind(this);
|
||||
this._setVideoElement = this._setVideoElement.bind(this);
|
||||
}
|
||||
@@ -51,7 +85,11 @@ class VideoInputPreview extends Component {
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._attachTrack(this.props.track);
|
||||
if (this.props.error) {
|
||||
this._updateErrorView(this.props.error);
|
||||
} else {
|
||||
this._attachTrack(this.props.track);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,9 +118,9 @@ class VideoInputPreview extends Component {
|
||||
autoPlay = { true }
|
||||
className = 'video-input-preview-display flipVideoX'
|
||||
ref = { this._setVideoElement } />
|
||||
<div className = 'video-input-preview-muted'>
|
||||
{ this.props.t('deviceSelection.currentlyVideoMuted') }
|
||||
</div>
|
||||
<div
|
||||
className = 'video-input-preview-error'
|
||||
ref = { this._setErrorElement } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -99,8 +137,15 @@ class VideoInputPreview extends Component {
|
||||
* @returns {void}
|
||||
*/
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.track !== this.props.track) {
|
||||
const hasNewTrack = nextProps.track !== this.props.track;
|
||||
|
||||
if (hasNewTrack || nextProps.error) {
|
||||
this._detachTrack(this.props.track);
|
||||
this._updateErrorView(nextProps.error);
|
||||
}
|
||||
|
||||
// Never attempt to show the new track if there is an error present.
|
||||
if (hasNewTrack && !nextProps.error) {
|
||||
this._attachTrack(nextProps.track);
|
||||
}
|
||||
|
||||
@@ -123,17 +168,9 @@ class VideoInputPreview extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not attempt to display a preview if the track is muted, as the
|
||||
// library will simply return a falsy value for the element anyway.
|
||||
if (track.isMuted()) {
|
||||
this._showMuteOverlay(true);
|
||||
} else {
|
||||
this._showMuteOverlay(false);
|
||||
const updatedVideoElement = track.attach(this._videoElement);
|
||||
|
||||
const updatedVideoElement = track.attach(this._videoElement);
|
||||
|
||||
this._setVideoElement(updatedVideoElement);
|
||||
}
|
||||
this._setVideoElement(updatedVideoElement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,6 +196,19 @@ class VideoInputPreview extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an instance variable for the component's element intended for
|
||||
* displaying error messages. The element will be accessed directly to
|
||||
* display an error message.
|
||||
*
|
||||
* @param {Object} element - DOM element intended for displaying errors.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setErrorElement(element) {
|
||||
this._errorElement = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component's root element.
|
||||
*
|
||||
@@ -183,20 +233,22 @@ class VideoInputPreview extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or removes a class to the component's parent node to indicate mute
|
||||
* status.
|
||||
* Adds or removes a class to the component's parent node to indicate an
|
||||
* error has occurred. Also sets the error text.
|
||||
*
|
||||
* @param {boolean} shouldShow - True if the mute class should be added and
|
||||
* false if the class should be removed.
|
||||
* @param {string} error - The error message to display. If falsy, error
|
||||
* message display will be hidden.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_showMuteOverlay(shouldShow) {
|
||||
if (shouldShow) {
|
||||
this._rootElement.classList.add(VIDEO_MUTE_CLASS);
|
||||
_updateErrorView(error) {
|
||||
if (error) {
|
||||
this._rootElement.classList.add(VIDEO_ERROR_CLASS);
|
||||
} else {
|
||||
this._rootElement.classList.remove(VIDEO_MUTE_CLASS);
|
||||
this._rootElement.classList.remove(VIDEO_ERROR_CLASS);
|
||||
}
|
||||
|
||||
this._errorElement.innerText = error || '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user