Sfoglia il codice sorgente

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

j8
Leonard Kim 8 anni fa
parent
commit
4a1efed4a8

+ 2
- 1
css/_videolayout_default.scss Vedi File

@@ -318,7 +318,8 @@
318 318
 /**
319 319
  * Audio indicator on video thumbnails.
320 320
  */
321
-.videocontainer>span.audioindicator {
321
+.videocontainer>span.audioindicator,
322
+.videocontainer>.audioindicator-container {
322 323
     position: absolute;
323 324
     display: inline-block;
324 325
     left: 6px;

+ 0
- 63
modules/UI/audio_levels/AudioLevels.js Vedi File

@@ -6,69 +6,6 @@ import UIUtil from "../util/UIUtil";
6 6
  * Responsible for drawing audio levels.
7 7
  */
8 8
 const AudioLevels = {
9
-
10
-    /**
11
-     * The number of dots.
12
-     *
13
-     * IMPORTANT: functions below assume that this is an odd number.
14
-     */
15
-    _AUDIO_LEVEL_DOTS: 5,
16
-
17
-    /**
18
-     * Creates the audio level indicator span element.
19
-     *
20
-     * IMPORTANT: This function assumes that the number of dots is an
21
-     * odd number.
22
-     *
23
-     * @return {Element} the document element representing audio levels
24
-     */
25
-    createThumbnailAudioLevelIndicator() {
26
-
27
-        let audioSpan = document.createElement('span');
28
-        audioSpan.className = 'audioindicator';
29
-
30
-        this.sideDotsCount = Math.floor(this._AUDIO_LEVEL_DOTS/2);
31
-
32
-        for (let i = 0; i < this._AUDIO_LEVEL_DOTS; i++) {
33
-            let audioDot = document.createElement('span');
34
-
35
-            // The median index will be equal to the number of dots on each
36
-            // side.
37
-            if (i === this.sideDotsCount)
38
-                audioDot.className = "audiodot-middle";
39
-            else
40
-                audioDot.className = (i < this.sideDotsCount)
41
-                                    ? "audiodot-top"
42
-                                    : "audiodot-bottom";
43
-
44
-            audioSpan.appendChild(audioDot);
45
-        }
46
-        return audioSpan;
47
-    },
48
-
49
-    /**
50
-     * Updates the audio level UI for the given id.
51
-     *
52
-     * @param {string} id id of the user for whom we draw the audio level
53
-     * @param {number} audioLevel the newAudio level to render
54
-     */
55
-    updateThumbnailAudioLevel (id, audioLevel) {
56
-
57
-        // First make sure we are sensitive enough.
58
-        audioLevel *= 1.2;
59
-        audioLevel = Math.min(audioLevel, 1);
60
-
61
-        // Let's now stretch the audio level over the number of dots we have.
62
-        let stretchedAudioLevel = (this.sideDotsCount + 1) * audioLevel;
63
-        let dotLevel = 0.0;
64
-
65
-        for (let i = 0; i < (this.sideDotsCount + 1); i++) {
66
-
67
-            dotLevel = Math.min(1, Math.max(0, (stretchedAudioLevel - i)));
68
-            this._setDotLevel(id, i, dotLevel);
69
-        }
70
-    },
71
-
72 9
     /**
73 10
      * Fills the dot(s) with the specified "index", with as much opacity as
74 11
      * indicated by "opacity".

+ 3
- 0
modules/UI/videolayout/RemoteVideo.js Vedi File

@@ -516,6 +516,9 @@ RemoteVideo.prototype.updateConnectionStatusIndicator = function () {
516 516
  */
517 517
 RemoteVideo.prototype.remove = function () {
518 518
     logger.log("Remove thumbnail", this.id);
519
+
520
+    this.removeAudioLevelIndicator();
521
+
519 522
     this.removeConnectionIndicator();
520 523
     // Make sure that the large video is updated if are removing its
521 524
     // corresponding small video.

+ 53
- 7
modules/UI/videolayout/SmallVideo.js Vedi File

@@ -1,10 +1,18 @@
1 1
 /* global $, APP, JitsiMeetJS, interfaceConfig */
2
+
3
+/* eslint-disable no-unused-vars */
4
+import React from 'react';
5
+import ReactDOM from 'react-dom';
6
+
7
+import { AudioLevelIndicator }
8
+    from '../../../react/features/audio-level-indicator';
9
+/* eslint-enable no-unused-vars */
10
+
2 11
 const logger = require("jitsi-meet-logger").getLogger(__filename);
3 12
 
4 13
 import Avatar from "../avatar/Avatar";
5 14
 import UIUtil from "../util/UIUtil";
6 15
 import UIEvents from "../../../service/UI/UIEvents";
7
-import AudioLevels from "../audio_levels/AudioLevels";
8 16
 
9 17
 const RTCUIHelper = JitsiMeetJS.util.RTCUIHelper;
10 18
 
@@ -341,25 +349,63 @@ SmallVideo.prototype.addModeratorIndicator = function () {
341 349
 
342 350
 /**
343 351
  * Adds the element indicating the audio level of the participant.
352
+ *
353
+ * @returns {void}
344 354
  */
345 355
 SmallVideo.prototype.addAudioLevelIndicator = function () {
346
-    var audioSpan = $('#' + this.videoSpanId + ' .audioindicator');
356
+    let audioLevelContainer = this._getAudioLevelContainer();
347 357
 
348
-    if (audioSpan.length) {
358
+    if (audioLevelContainer) {
349 359
         return;
350 360
     }
351 361
 
352
-    this.container.appendChild(
353
-        AudioLevels.createThumbnailAudioLevelIndicator());
362
+    audioLevelContainer = document.createElement('span');
363
+    audioLevelContainer.className = 'audioindicator-container';
364
+    this.container.appendChild(audioLevelContainer);
365
+
366
+    this.updateAudioLevelIndicator();
367
+};
368
+
369
+/**
370
+ * Removes the element indicating the audio level of the participant.
371
+ *
372
+ * @returns {void}
373
+ */
374
+SmallVideo.prototype.removeAudioLevelIndicator = function () {
375
+    const audioLevelContainer = this._getAudioLevelContainer();
376
+
377
+    if (audioLevelContainer) {
378
+        ReactDOM.unmountComponentAtNode(audioLevelContainer);
379
+    }
354 380
 };
355 381
 
356 382
 /**
357 383
  * Updates the audio level for this small video.
358 384
  *
359 385
  * @param lvl the new audio level to set
386
+ * @returns {void}
387
+ */
388
+SmallVideo.prototype.updateAudioLevelIndicator = function (lvl = 0) {
389
+    const audioLevelContainer = this._getAudioLevelContainer();
390
+
391
+    if (audioLevelContainer) {
392
+        /* jshint ignore:start */
393
+        ReactDOM.render(
394
+            <AudioLevelIndicator
395
+                audioLevel = { lvl }/>,
396
+            audioLevelContainer);
397
+        /* jshint ignore:end */
398
+    }
399
+};
400
+
401
+/**
402
+ * Queries the component's DOM for the element that should be the parent to the
403
+ * AudioLevelIndicator.
404
+ *
405
+ * @returns {HTMLElement} The DOM element that holds the AudioLevelIndicator.
360 406
  */
361
-SmallVideo.prototype.updateAudioLevelIndicator = function (lvl) {
362
-    AudioLevels.updateThumbnailAudioLevel(this.videoSpanId, lvl);
407
+SmallVideo.prototype._getAudioLevelContainer = function () {
408
+    return this.container.querySelector('.audioindicator-container');
363 409
 };
364 410
 
365 411
 /**

+ 83
- 0
react/features/audio-level-indicator/components/AudioLevelIndicator.js Vedi File

@@ -0,0 +1,83 @@
1
+import React, { Component } from 'react';
2
+
3
+/**
4
+ * The number of dots to display in AudioLevelIndicator.
5
+ *
6
+ * IMPORTANT: AudioLevelIndicator assumes that this is an odd number.
7
+ */
8
+const AUDIO_LEVEL_DOTS = 5;
9
+
10
+/**
11
+ * The index of the dot that is at the direct middle of all other dots.
12
+ */
13
+const CENTER_DOT_INDEX = Math.floor(AUDIO_LEVEL_DOTS / 2);
14
+
15
+/**
16
+ * Creates a ReactElement responsible for drawing audio levels.
17
+ *
18
+ * @extends {Component}
19
+ */
20
+class AudioLevelIndicator extends Component {
21
+    /**
22
+     * {@code AudioLevelIndicator}'s property types.
23
+     *
24
+     * @static
25
+     */
26
+    static propTypes = {
27
+        /**
28
+         * The current audio level to display. The value should be a number
29
+         * between 0 and 1.
30
+         *
31
+         * @type {number}
32
+         */
33
+        audioLevel: React.PropTypes.number
34
+    };
35
+
36
+    /**
37
+     * Implements React's {@link Component#render()}.
38
+     *
39
+     * @inheritdoc
40
+     * @returns {ReactElement}
41
+     */
42
+    render() {
43
+        // First make sure we are sensitive enough.
44
+        const audioLevel = Math.min(this.props.audioLevel * 1.2, 1);
45
+
46
+        // Let's now stretch the audio level over the number of dots we have.
47
+        const stretchedAudioLevel = AUDIO_LEVEL_DOTS * audioLevel;
48
+
49
+        const audioLevelDots = [];
50
+
51
+        for (let i = 0; i < AUDIO_LEVEL_DOTS; i++) {
52
+            const distanceFromCenter = CENTER_DOT_INDEX - i;
53
+            const audioLevelFromCenter
54
+                = stretchedAudioLevel - Math.abs(distanceFromCenter);
55
+            const cappedOpacity = Math.min(
56
+                1, Math.max(0, audioLevelFromCenter));
57
+            let className;
58
+
59
+            if (distanceFromCenter === 0) {
60
+                className = 'audiodot-middle';
61
+            } else if (distanceFromCenter < 0) {
62
+                className = 'audiodot-top';
63
+            } else {
64
+                className = 'audiodot-bottom';
65
+            }
66
+
67
+            audioLevelDots.push(
68
+                <span
69
+                    className = { className }
70
+                    key = { i }
71
+                    style = {{ opacity: cappedOpacity }} />
72
+            );
73
+        }
74
+
75
+        return (
76
+            <span className = 'audioindicator in-react'>
77
+                { audioLevelDots }
78
+            </span>
79
+        );
80
+    }
81
+}
82
+
83
+export default AudioLevelIndicator;

+ 1
- 0
react/features/audio-level-indicator/components/index.js Vedi File

@@ -0,0 +1 @@
1
+export { default as AudioLevelIndicator } from './AudioLevelIndicator';

+ 1
- 0
react/features/audio-level-indicator/index.js Vedi File

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

Loading…
Annulla
Salva