feat(audio-level): convert SmallVideo AudioLevelIndicator to React
This commit is contained in:
parent
8e4864004b
commit
4a1efed4a8
|
@ -318,7 +318,8 @@
|
|||
/**
|
||||
* Audio indicator on video thumbnails.
|
||||
*/
|
||||
.videocontainer>span.audioindicator {
|
||||
.videocontainer>span.audioindicator,
|
||||
.videocontainer>.audioindicator-container {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
left: 6px;
|
||||
|
|
|
@ -6,69 +6,6 @@ import UIUtil from "../util/UIUtil";
|
|||
* Responsible for drawing audio levels.
|
||||
*/
|
||||
const AudioLevels = {
|
||||
|
||||
/**
|
||||
* The number of dots.
|
||||
*
|
||||
* IMPORTANT: functions below assume that this is an odd number.
|
||||
*/
|
||||
_AUDIO_LEVEL_DOTS: 5,
|
||||
|
||||
/**
|
||||
* Creates the audio level indicator span element.
|
||||
*
|
||||
* IMPORTANT: This function assumes that the number of dots is an
|
||||
* odd number.
|
||||
*
|
||||
* @return {Element} the document element representing audio levels
|
||||
*/
|
||||
createThumbnailAudioLevelIndicator() {
|
||||
|
||||
let audioSpan = document.createElement('span');
|
||||
audioSpan.className = 'audioindicator';
|
||||
|
||||
this.sideDotsCount = Math.floor(this._AUDIO_LEVEL_DOTS/2);
|
||||
|
||||
for (let i = 0; i < this._AUDIO_LEVEL_DOTS; i++) {
|
||||
let audioDot = document.createElement('span');
|
||||
|
||||
// The median index will be equal to the number of dots on each
|
||||
// side.
|
||||
if (i === this.sideDotsCount)
|
||||
audioDot.className = "audiodot-middle";
|
||||
else
|
||||
audioDot.className = (i < this.sideDotsCount)
|
||||
? "audiodot-top"
|
||||
: "audiodot-bottom";
|
||||
|
||||
audioSpan.appendChild(audioDot);
|
||||
}
|
||||
return audioSpan;
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the audio level UI for the given id.
|
||||
*
|
||||
* @param {string} id id of the user for whom we draw the audio level
|
||||
* @param {number} audioLevel the newAudio level to render
|
||||
*/
|
||||
updateThumbnailAudioLevel (id, audioLevel) {
|
||||
|
||||
// First make sure we are sensitive enough.
|
||||
audioLevel *= 1.2;
|
||||
audioLevel = Math.min(audioLevel, 1);
|
||||
|
||||
// Let's now stretch the audio level over the number of dots we have.
|
||||
let stretchedAudioLevel = (this.sideDotsCount + 1) * audioLevel;
|
||||
let dotLevel = 0.0;
|
||||
|
||||
for (let i = 0; i < (this.sideDotsCount + 1); i++) {
|
||||
|
||||
dotLevel = Math.min(1, Math.max(0, (stretchedAudioLevel - i)));
|
||||
this._setDotLevel(id, i, dotLevel);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills the dot(s) with the specified "index", with as much opacity as
|
||||
* indicated by "opacity".
|
||||
|
|
|
@ -516,6 +516,9 @@ RemoteVideo.prototype.updateConnectionStatusIndicator = function () {
|
|||
*/
|
||||
RemoteVideo.prototype.remove = function () {
|
||||
logger.log("Remove thumbnail", this.id);
|
||||
|
||||
this.removeAudioLevelIndicator();
|
||||
|
||||
this.removeConnectionIndicator();
|
||||
// Make sure that the large video is updated if are removing its
|
||||
// corresponding small video.
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
/* global $, APP, JitsiMeetJS, interfaceConfig */
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import { AudioLevelIndicator }
|
||||
from '../../../react/features/audio-level-indicator';
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
import Avatar from "../avatar/Avatar";
|
||||
import UIUtil from "../util/UIUtil";
|
||||
import UIEvents from "../../../service/UI/UIEvents";
|
||||
import AudioLevels from "../audio_levels/AudioLevels";
|
||||
|
||||
const RTCUIHelper = JitsiMeetJS.util.RTCUIHelper;
|
||||
|
||||
|
@ -341,25 +349,63 @@ SmallVideo.prototype.addModeratorIndicator = function () {
|
|||
|
||||
/**
|
||||
* Adds the element indicating the audio level of the participant.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
SmallVideo.prototype.addAudioLevelIndicator = function () {
|
||||
var audioSpan = $('#' + this.videoSpanId + ' .audioindicator');
|
||||
let audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioSpan.length) {
|
||||
if (audioLevelContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.container.appendChild(
|
||||
AudioLevels.createThumbnailAudioLevelIndicator());
|
||||
audioLevelContainer = document.createElement('span');
|
||||
audioLevelContainer.className = 'audioindicator-container';
|
||||
this.container.appendChild(audioLevelContainer);
|
||||
|
||||
this.updateAudioLevelIndicator();
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element indicating the audio level of the participant.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
SmallVideo.prototype.removeAudioLevelIndicator = function () {
|
||||
const audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioLevelContainer) {
|
||||
ReactDOM.unmountComponentAtNode(audioLevelContainer);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the audio level for this small video.
|
||||
*
|
||||
* @param lvl the new audio level to set
|
||||
* @returns {void}
|
||||
*/
|
||||
SmallVideo.prototype.updateAudioLevelIndicator = function (lvl) {
|
||||
AudioLevels.updateThumbnailAudioLevel(this.videoSpanId, lvl);
|
||||
SmallVideo.prototype.updateAudioLevelIndicator = function (lvl = 0) {
|
||||
const audioLevelContainer = this._getAudioLevelContainer();
|
||||
|
||||
if (audioLevelContainer) {
|
||||
/* jshint ignore:start */
|
||||
ReactDOM.render(
|
||||
<AudioLevelIndicator
|
||||
audioLevel = { lvl }/>,
|
||||
audioLevelContainer);
|
||||
/* jshint ignore:end */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Queries the component's DOM for the element that should be the parent to the
|
||||
* AudioLevelIndicator.
|
||||
*
|
||||
* @returns {HTMLElement} The DOM element that holds the AudioLevelIndicator.
|
||||
*/
|
||||
SmallVideo.prototype._getAudioLevelContainer = function () {
|
||||
return this.container.querySelector('.audioindicator-container');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
/**
|
||||
* The number of dots to display in AudioLevelIndicator.
|
||||
*
|
||||
* IMPORTANT: AudioLevelIndicator assumes that this is an odd number.
|
||||
*/
|
||||
const AUDIO_LEVEL_DOTS = 5;
|
||||
|
||||
/**
|
||||
* The index of the dot that is at the direct middle of all other dots.
|
||||
*/
|
||||
const CENTER_DOT_INDEX = Math.floor(AUDIO_LEVEL_DOTS / 2);
|
||||
|
||||
/**
|
||||
* Creates a ReactElement responsible for drawing audio levels.
|
||||
*
|
||||
* @extends {Component}
|
||||
*/
|
||||
class AudioLevelIndicator extends Component {
|
||||
/**
|
||||
* {@code AudioLevelIndicator}'s property types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The current audio level to display. The value should be a number
|
||||
* between 0 and 1.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
audioLevel: React.PropTypes.number
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
// First make sure we are sensitive enough.
|
||||
const audioLevel = Math.min(this.props.audioLevel * 1.2, 1);
|
||||
|
||||
// Let's now stretch the audio level over the number of dots we have.
|
||||
const stretchedAudioLevel = AUDIO_LEVEL_DOTS * audioLevel;
|
||||
|
||||
const audioLevelDots = [];
|
||||
|
||||
for (let i = 0; i < AUDIO_LEVEL_DOTS; i++) {
|
||||
const distanceFromCenter = CENTER_DOT_INDEX - i;
|
||||
const audioLevelFromCenter
|
||||
= stretchedAudioLevel - Math.abs(distanceFromCenter);
|
||||
const cappedOpacity = Math.min(
|
||||
1, Math.max(0, audioLevelFromCenter));
|
||||
let className;
|
||||
|
||||
if (distanceFromCenter === 0) {
|
||||
className = 'audiodot-middle';
|
||||
} else if (distanceFromCenter < 0) {
|
||||
className = 'audiodot-top';
|
||||
} else {
|
||||
className = 'audiodot-bottom';
|
||||
}
|
||||
|
||||
audioLevelDots.push(
|
||||
<span
|
||||
className = { className }
|
||||
key = { i }
|
||||
style = {{ opacity: cappedOpacity }} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span className = 'audioindicator in-react'>
|
||||
{ audioLevelDots }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AudioLevelIndicator;
|
|
@ -0,0 +1 @@
|
|||
export { default as AudioLevelIndicator } from './AudioLevelIndicator';
|
|
@ -0,0 +1 @@
|
|||
export * from './components';
|
Loading…
Reference in New Issue