feat(audio-level): convert SmallVideo AudioLevelIndicator to React

pull/1695/merge jitsi-meet_2180
Leonard Kim 8 years ago committed by Paweł Domas
parent 8e4864004b
commit 4a1efed4a8
  1. 3
      css/_videolayout_default.scss
  2. 63
      modules/UI/audio_levels/AudioLevels.js
  3. 3
      modules/UI/videolayout/RemoteVideo.js
  4. 60
      modules/UI/videolayout/SmallVideo.js
  5. 83
      react/features/audio-level-indicator/components/AudioLevelIndicator.js
  6. 1
      react/features/audio-level-indicator/components/index.js
  7. 1
      react/features/audio-level-indicator/index.js

@ -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 = 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.updateAudioLevelIndicator = function (lvl) {
AudioLevels.updateThumbnailAudioLevel(this.videoSpanId, lvl);
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…
Cancel
Save