feat(small-video): convert the "toolbar" to react

Move display of audio muted, video muted, and moderator icons,
which make up the elements of the small video toolbar, into React
Components.
This commit is contained in:
Leonard Kim 2017-06-19 11:01:44 -05:00 committed by yanas
parent 573aa168ea
commit 152427e01b
10 changed files with 227 additions and 95 deletions

View File

@ -82,6 +82,7 @@
.toolbar-icon {
float: none;
margin: auto;
}
}
}

View File

@ -2,6 +2,7 @@
/* eslint-disable no-unused-vars */
import React from 'react';
import ReactDOM from 'react-dom';
import {
MuteButton,
@ -515,6 +516,13 @@ RemoteVideo.prototype.remove = function () {
this.removeAudioLevelIndicator();
const toolbarContainer
= this.container.querySelector('.videocontainer__toolbar');
if (toolbarContainer) {
ReactDOM.unmountComponentAtNode(toolbarContainer);
}
this.removeConnectionIndicator();
this.removeDisplayName();

View File

@ -16,7 +16,12 @@ import {
ConnectionIndicator
} from '../../../react/features/connection-indicator';
import { DisplayName } from '../../../react/features/display-name';
/* eslint-disable no-unused-vars */
import {
AudioMutedIndicator,
ModeratorIndicator,
VideoMutedIndicator
} from '../../../react/features/filmstrip';
/* eslint-enable no-unused-vars */
const logger = require("jitsi-meet-logger").getLogger(__filename);
@ -64,6 +69,7 @@ const DISPLAY_VIDEO_WITH_NAME = 3;
const DISPLAY_AVATAR_WITH_NAME = 4;
function SmallVideo(VideoLayout) {
this._isModerator = false;
this.isAudioMuted = false;
this.hasAvatar = false;
this.isVideoMuted = false;
@ -270,43 +276,8 @@ SmallVideo.prototype.updateConnectionStatus = function (connectionStatus) {
* or hidden
*/
SmallVideo.prototype.showAudioIndicator = function (isMuted) {
let mutedIndicator = this.getAudioMutedIndicator();
UIUtil.setVisible(mutedIndicator, isMuted);
this.isAudioMuted = isMuted;
};
/**
* Returns the audio muted indicator jquery object. If it doesn't exists -
* creates it.
*
* @returns {HTMLElement} the audio muted indicator
*/
SmallVideo.prototype.getAudioMutedIndicator = function () {
let selector = '#' + this.videoSpanId + ' .audioMuted';
let audioMutedSpan = document.querySelector(selector);
if (audioMutedSpan) {
return audioMutedSpan;
}
audioMutedSpan = document.createElement('span');
audioMutedSpan.className = 'audioMuted toolbar-icon';
UIUtil.setTooltip(audioMutedSpan,
"videothumbnail.mute",
"top");
let mutedIndicator = document.createElement('i');
mutedIndicator.className = 'icon-mic-disabled';
audioMutedSpan.appendChild(mutedIndicator);
this.container
.querySelector('.videocontainer__toolbar')
.appendChild(audioMutedSpan);
return audioMutedSpan;
this.updateStatusBar();
};
/**
@ -320,75 +291,38 @@ SmallVideo.prototype.setVideoMutedView = function(isMuted) {
this.isVideoMuted = isMuted;
this.updateView();
let element = this.getVideoMutedIndicator();
UIUtil.setVisible(element, isMuted);
this.updateStatusBar();
};
/**
* Returns the video muted indicator jquery object. If it doesn't exists -
* creates it.
* Create or updates the ReactElement for displaying status indicators about
* audio mute, video mute, and moderator status.
*
* @returns {jQuery|HTMLElement} the video muted indicator
* @returns {void}
*/
SmallVideo.prototype.getVideoMutedIndicator = function () {
var selector = '#' + this.videoSpanId + ' .videoMuted';
var videoMutedSpan = document.querySelector(selector);
SmallVideo.prototype.updateStatusBar = function () {
const statusBarContainer
= this.container.querySelector('.videocontainer__toolbar');
if (videoMutedSpan) {
return videoMutedSpan;
}
videoMutedSpan = document.createElement('span');
videoMutedSpan.className = 'videoMuted toolbar-icon';
this.container
.querySelector('.videocontainer__toolbar')
.appendChild(videoMutedSpan);
var mutedIndicator = document.createElement('i');
mutedIndicator.className = 'icon-camera-disabled';
UIUtil.setTooltip(mutedIndicator,
"videothumbnail.videomute",
"top");
videoMutedSpan.appendChild(mutedIndicator);
return videoMutedSpan;
/* jshint ignore:start */
ReactDOM.render(
<div>
{ this.isAudioMuted ? <AudioMutedIndicator /> : null }
{ this.isVideoMuted ? <VideoMutedIndicator /> : null }
{ this._isModerator
&& !interfaceConfig.DISABLE_FOCUS_INDICATOR
? <ModeratorIndicator /> : null }
</div>,
statusBarContainer);
/* jshint ignore:end */
};
/**
* Adds the element indicating the moderator(owner) of the conference.
*/
SmallVideo.prototype.addModeratorIndicator = function () {
// Don't create moderator indicator if DISABLE_FOCUS_INDICATOR is true
if (interfaceConfig.DISABLE_FOCUS_INDICATOR)
return false;
// Show moderator indicator
var indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');
if (indicatorSpan.length) {
return;
}
indicatorSpan = document.createElement('span');
indicatorSpan.className = 'focusindicator toolbar-icon right';
this.container
.querySelector('.videocontainer__toolbar')
.appendChild(indicatorSpan);
var moderatorIndicator = document.createElement('i');
moderatorIndicator.className = 'icon-star';
UIUtil.setTooltip(moderatorIndicator,
"videothumbnail.moderator",
"top-left");
indicatorSpan.appendChild(moderatorIndicator);
this._isModerator = true;
this.updateStatusBar();
};
/**
@ -456,7 +390,8 @@ SmallVideo.prototype._getAudioLevelContainer = function () {
* Removes the element indicating the moderator(owner) of the conference.
*/
SmallVideo.prototype.removeModeratorIndicator = function () {
$('#' + this.videoSpanId + ' .focusindicator').remove();
this._isModerator = false;
this.updateStatusBar();
};
/**

View File

@ -0,0 +1 @@
export * from './web';

View File

@ -1 +1,3 @@
export * from './_';
export { default as Filmstrip } from './Filmstrip';

View File

@ -0,0 +1,24 @@
import BaseIndicator from './BaseIndicator';
/**
* React {@code Component} for showing an audio muted icon with a tooltip.
*
* @extends BaseIndicator
*/
class AudioMutedIndicator extends BaseIndicator {
/**
* Initializes a new AudioMutedIcon instance.
*
* @param {Object} props - The read-only React Component props with which
* the new instance is to be initialized.
*/
constructor(props) {
super(props);
this._classNames = 'audioMuted toolbar-icon';
this._iconClass = 'icon-mic-disabled';
this._tooltipKey = 'videothumbnail.mute';
}
}
export default AudioMutedIndicator;

View File

@ -0,0 +1,110 @@
import React, { Component } from 'react';
import UIUtil from '../../../../../modules/UI/util/UIUtil';
/**
* React {@code Component} for showing an icon with a tooltip.
*
* @extends Component
*/
class BaseIndicator extends Component {
/**
* Initializes a new {@code BaseIndicator} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
/**
* The CSS classes to apply to the root HTML element of the component.
*
* @type {string}
*/
this._classNames = '';
/**
* The CSS class which will display an icon.
*
* @type {string}
*/
this._iconClass = '';
/**
* An internal reference to the HTML element at the top of the
* component's DOM hierarchy. The reference is needed for attaching a
* tooltip.
*
* @type {HTMLElement}
*/
this._rootElement = null;
/**
* The translation key for the text to display in the tooltip.
*
* @type {string}
*/
this._tooltipKey = '';
// Bind event handler so it is only bound once for every instance.
this._setRootElementRef = this._setRootElementRef.bind(this);
}
/**
* Sets a tooltip which will display when hovering over the component.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
this._setTooltip();
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<span className = { this._classNames }>
<i
className = { this._iconClass }
ref = { this._setRootElementRef } />
</span>
);
}
/**
* Sets the internal reference to the root HTML element for the component.
*
* @param {HTMLIconElement} element - The root HTML element of the
* component.
* @private
* @returns {void}
*/
_setRootElementRef(element) {
this._rootElement = element;
}
/**
* Associate the component as a tooltip trigger so a tooltip may display on
* hover.
*
* @private
* @returns {void}
*/
_setTooltip() {
// TODO Replace UIUtil with an AtlasKit component when a suitable one
// becomes available for tooltips.
UIUtil.setTooltip(
this._rootElement,
this._tooltipKey,
'top'
);
}
}
export default BaseIndicator;

View File

@ -0,0 +1,24 @@
import BaseIndicator from './BaseIndicator';
/**
* React {@code Component} for showing a moderator icon with a tooltip.
*
* @extends BaseIndicator
*/
class ModeratorIndicator extends BaseIndicator {
/**
* Initializes a new ModeratorIndicator instance.
*
* @param {Object} props - The read-only React Component props with which
* the new instance is to be initialized.
*/
constructor(props) {
super(props);
this._classNames = 'focusindicator toolbar-icon right';
this._iconClass = 'icon-star';
this._tooltipKey = 'videothumbnail.moderator';
}
}
export default ModeratorIndicator;

View File

@ -0,0 +1,24 @@
import BaseIndicator from './BaseIndicator';
/**
* React {@code Component} for showing a video muted icon with a tooltip.
*
* @extends BaseIndicator
*/
class VideoMutedIndicator extends BaseIndicator {
/**
* Initializes a new VideoMutedIndicator instance.
*
* @param {Object} props - The read-only React Component props with which
* the new instance is to be initialized.
*/
constructor(props) {
super(props);
this._classNames = 'videoMuted toolbar-icon';
this._iconClass = 'icon-camera-disabled';
this._tooltipKey = 'videothumbnail.videomute';
}
}
export default VideoMutedIndicator;

View File

@ -0,0 +1,3 @@
export { default as AudioMutedIndicator } from './AudioMutedIndicator';
export { default as ModeratorIndicator } from './ModeratorIndicator';
export { default as VideoMutedIndicator } from './VideoMutedIndicator';