Browse Source

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.
master
Leonard Kim 8 years ago
parent
commit
152427e01b

+ 1
- 0
css/_vertical_filmstrip_overrides.scss View File

82
 
82
 
83
                 .toolbar-icon {
83
                 .toolbar-icon {
84
                     float: none;
84
                     float: none;
85
+                    margin: auto;
85
                 }
86
                 }
86
             }
87
             }
87
         }
88
         }

+ 8
- 0
modules/UI/videolayout/RemoteVideo.js View File

2
 
2
 
3
 /* eslint-disable no-unused-vars */
3
 /* eslint-disable no-unused-vars */
4
 import React from 'react';
4
 import React from 'react';
5
+import ReactDOM from 'react-dom';
5
 
6
 
6
 import {
7
 import {
7
     MuteButton,
8
     MuteButton,
515
 
516
 
516
     this.removeAudioLevelIndicator();
517
     this.removeAudioLevelIndicator();
517
 
518
 
519
+    const toolbarContainer
520
+        = this.container.querySelector('.videocontainer__toolbar');
521
+
522
+    if (toolbarContainer) {
523
+        ReactDOM.unmountComponentAtNode(toolbarContainer);
524
+    }
525
+
518
     this.removeConnectionIndicator();
526
     this.removeConnectionIndicator();
519
 
527
 
520
     this.removeDisplayName();
528
     this.removeDisplayName();

+ 30
- 95
modules/UI/videolayout/SmallVideo.js View File

16
     ConnectionIndicator
16
     ConnectionIndicator
17
 } from '../../../react/features/connection-indicator';
17
 } from '../../../react/features/connection-indicator';
18
 import { DisplayName } from '../../../react/features/display-name';
18
 import { DisplayName } from '../../../react/features/display-name';
19
-/* eslint-disable no-unused-vars */
19
+import {
20
+    AudioMutedIndicator,
21
+    ModeratorIndicator,
22
+    VideoMutedIndicator
23
+} from '../../../react/features/filmstrip';
24
+/* eslint-enable no-unused-vars */
20
 
25
 
21
 const logger = require("jitsi-meet-logger").getLogger(__filename);
26
 const logger = require("jitsi-meet-logger").getLogger(__filename);
22
 
27
 
64
 const DISPLAY_AVATAR_WITH_NAME = 4;
69
 const DISPLAY_AVATAR_WITH_NAME = 4;
65
 
70
 
66
 function SmallVideo(VideoLayout) {
71
 function SmallVideo(VideoLayout) {
72
+    this._isModerator = false;
67
     this.isAudioMuted = false;
73
     this.isAudioMuted = false;
68
     this.hasAvatar = false;
74
     this.hasAvatar = false;
69
     this.isVideoMuted = false;
75
     this.isVideoMuted = false;
270
  * or hidden
276
  * or hidden
271
  */
277
  */
272
 SmallVideo.prototype.showAudioIndicator = function (isMuted) {
278
 SmallVideo.prototype.showAudioIndicator = function (isMuted) {
273
-    let mutedIndicator = this.getAudioMutedIndicator();
274
-
275
-    UIUtil.setVisible(mutedIndicator, isMuted);
276
-
277
     this.isAudioMuted = isMuted;
279
     this.isAudioMuted = isMuted;
278
-};
279
-
280
-/**
281
- * Returns the audio muted indicator jquery object. If it doesn't exists -
282
- * creates it.
283
- *
284
- * @returns {HTMLElement} the audio muted indicator
285
- */
286
-SmallVideo.prototype.getAudioMutedIndicator = function () {
287
-    let selector = '#' + this.videoSpanId + ' .audioMuted';
288
-    let audioMutedSpan = document.querySelector(selector);
289
-
290
-    if (audioMutedSpan) {
291
-        return audioMutedSpan;
292
-    }
293
-
294
-    audioMutedSpan = document.createElement('span');
295
-    audioMutedSpan.className = 'audioMuted toolbar-icon';
296
-
297
-    UIUtil.setTooltip(audioMutedSpan,
298
-        "videothumbnail.mute",
299
-        "top");
300
-
301
-    let mutedIndicator = document.createElement('i');
302
-    mutedIndicator.className = 'icon-mic-disabled';
303
-    audioMutedSpan.appendChild(mutedIndicator);
304
-
305
-    this.container
306
-        .querySelector('.videocontainer__toolbar')
307
-        .appendChild(audioMutedSpan);
308
-
309
-    return audioMutedSpan;
280
+    this.updateStatusBar();
310
 };
281
 };
311
 
282
 
312
 /**
283
 /**
320
     this.isVideoMuted = isMuted;
291
     this.isVideoMuted = isMuted;
321
     this.updateView();
292
     this.updateView();
322
 
293
 
323
-    let element = this.getVideoMutedIndicator();
324
-
325
-    UIUtil.setVisible(element, isMuted);
294
+    this.updateStatusBar();
326
 };
295
 };
327
 
296
 
328
 /**
297
 /**
329
- * Returns the video muted indicator jquery object. If it doesn't exists -
330
- * creates it.
298
+ * Create or updates the ReactElement for displaying status indicators about
299
+ * audio mute, video mute, and moderator status.
331
  *
300
  *
332
- * @returns {jQuery|HTMLElement} the video muted indicator
301
+ * @returns {void}
333
  */
302
  */
334
-SmallVideo.prototype.getVideoMutedIndicator = function () {
335
-    var selector = '#' + this.videoSpanId + ' .videoMuted';
336
-    var videoMutedSpan = document.querySelector(selector);
337
-
338
-    if (videoMutedSpan) {
339
-        return videoMutedSpan;
340
-    }
341
-
342
-    videoMutedSpan = document.createElement('span');
343
-    videoMutedSpan.className = 'videoMuted toolbar-icon';
344
-
345
-    this.container
346
-        .querySelector('.videocontainer__toolbar')
347
-        .appendChild(videoMutedSpan);
348
-
349
-    var mutedIndicator = document.createElement('i');
350
-    mutedIndicator.className = 'icon-camera-disabled';
351
-
352
-    UIUtil.setTooltip(mutedIndicator,
353
-        "videothumbnail.videomute",
354
-        "top");
303
+SmallVideo.prototype.updateStatusBar = function () {
304
+    const statusBarContainer
305
+        = this.container.querySelector('.videocontainer__toolbar');
355
 
306
 
356
-    videoMutedSpan.appendChild(mutedIndicator);
357
-
358
-    return videoMutedSpan;
307
+    /* jshint ignore:start */
308
+    ReactDOM.render(
309
+        <div>
310
+            { this.isAudioMuted ? <AudioMutedIndicator /> : null }
311
+            { this.isVideoMuted ? <VideoMutedIndicator /> : null }
312
+            { this._isModerator
313
+                && !interfaceConfig.DISABLE_FOCUS_INDICATOR
314
+                    ? <ModeratorIndicator /> : null }
315
+        </div>,
316
+        statusBarContainer);
317
+    /* jshint ignore:end */
359
 };
318
 };
360
 
319
 
361
 /**
320
 /**
362
  * Adds the element indicating the moderator(owner) of the conference.
321
  * Adds the element indicating the moderator(owner) of the conference.
363
  */
322
  */
364
 SmallVideo.prototype.addModeratorIndicator = function () {
323
 SmallVideo.prototype.addModeratorIndicator = function () {
365
-
366
-    // Don't create moderator indicator if DISABLE_FOCUS_INDICATOR is true
367
-    if (interfaceConfig.DISABLE_FOCUS_INDICATOR)
368
-        return false;
369
-
370
-    // Show moderator indicator
371
-    var indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');
372
-
373
-    if (indicatorSpan.length) {
374
-        return;
375
-    }
376
-
377
-    indicatorSpan = document.createElement('span');
378
-    indicatorSpan.className = 'focusindicator toolbar-icon right';
379
-
380
-    this.container
381
-        .querySelector('.videocontainer__toolbar')
382
-        .appendChild(indicatorSpan);
383
-
384
-    var moderatorIndicator = document.createElement('i');
385
-    moderatorIndicator.className = 'icon-star';
386
-
387
-    UIUtil.setTooltip(moderatorIndicator,
388
-        "videothumbnail.moderator",
389
-        "top-left");
390
-
391
-    indicatorSpan.appendChild(moderatorIndicator);
324
+    this._isModerator = true;
325
+    this.updateStatusBar();
392
 };
326
 };
393
 
327
 
394
 /**
328
 /**
456
  * Removes the element indicating the moderator(owner) of the conference.
390
  * Removes the element indicating the moderator(owner) of the conference.
457
  */
391
  */
458
 SmallVideo.prototype.removeModeratorIndicator = function () {
392
 SmallVideo.prototype.removeModeratorIndicator = function () {
459
-    $('#' + this.videoSpanId + ' .focusindicator').remove();
393
+    this._isModerator = false;
394
+    this.updateStatusBar();
460
 };
395
 };
461
 
396
 
462
 /**
397
 /**

+ 1
- 0
react/features/filmstrip/components/_.web.js View File

1
+export * from './web';

+ 2
- 0
react/features/filmstrip/components/index.js View File

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

+ 24
- 0
react/features/filmstrip/components/web/AudioMutedIndicator.js View File

1
+import BaseIndicator from './BaseIndicator';
2
+
3
+/**
4
+ * React {@code Component} for showing an audio muted icon with a tooltip.
5
+ *
6
+ * @extends BaseIndicator
7
+ */
8
+class AudioMutedIndicator extends BaseIndicator {
9
+    /**
10
+     * Initializes a new AudioMutedIcon instance.
11
+     *
12
+     * @param {Object} props - The read-only React Component props with which
13
+     * the new instance is to be initialized.
14
+     */
15
+    constructor(props) {
16
+        super(props);
17
+
18
+        this._classNames = 'audioMuted toolbar-icon';
19
+        this._iconClass = 'icon-mic-disabled';
20
+        this._tooltipKey = 'videothumbnail.mute';
21
+    }
22
+}
23
+
24
+export default AudioMutedIndicator;

+ 110
- 0
react/features/filmstrip/components/web/BaseIndicator.js View File

1
+import React, { Component } from 'react';
2
+
3
+import UIUtil from '../../../../../modules/UI/util/UIUtil';
4
+
5
+/**
6
+ * React {@code Component} for showing an icon with a tooltip.
7
+ *
8
+ * @extends Component
9
+ */
10
+class BaseIndicator extends Component {
11
+    /**
12
+     * Initializes a new {@code BaseIndicator} instance.
13
+     *
14
+     * @param {Object} props - The read-only properties with which the new
15
+     * instance is to be initialized.
16
+     */
17
+    constructor(props) {
18
+        super(props);
19
+
20
+        /**
21
+         * The CSS classes to apply to the root HTML element of the component.
22
+         *
23
+         * @type {string}
24
+         */
25
+        this._classNames = '';
26
+
27
+        /**
28
+         * The CSS class which will display an icon.
29
+         *
30
+         * @type {string}
31
+         */
32
+        this._iconClass = '';
33
+
34
+        /**
35
+         * An internal reference to the HTML element at the top of the
36
+         * component's DOM hierarchy. The reference is needed for attaching a
37
+         * tooltip.
38
+         *
39
+         * @type {HTMLElement}
40
+         */
41
+        this._rootElement = null;
42
+
43
+        /**
44
+         * The translation key for the text to display in the tooltip.
45
+         *
46
+         * @type {string}
47
+         */
48
+        this._tooltipKey = '';
49
+
50
+        // Bind event handler so it is only bound once for every instance.
51
+        this._setRootElementRef = this._setRootElementRef.bind(this);
52
+    }
53
+
54
+    /**
55
+     * Sets a tooltip which will display when hovering over the component.
56
+     *
57
+     * @inheritdoc
58
+     * @returns {void}
59
+     */
60
+    componentDidMount() {
61
+        this._setTooltip();
62
+    }
63
+
64
+    /**
65
+     * Implements React's {@link Component#render()}.
66
+     *
67
+     * @inheritdoc
68
+     * @returns {ReactElement}
69
+     */
70
+    render() {
71
+        return (
72
+            <span className = { this._classNames }>
73
+                <i
74
+                    className = { this._iconClass }
75
+                    ref = { this._setRootElementRef } />
76
+            </span>
77
+        );
78
+    }
79
+
80
+    /**
81
+     * Sets the internal reference to the root HTML element for the component.
82
+     *
83
+     * @param {HTMLIconElement} element - The root HTML element of the
84
+     * component.
85
+     * @private
86
+     * @returns {void}
87
+     */
88
+    _setRootElementRef(element) {
89
+        this._rootElement = element;
90
+    }
91
+
92
+    /**
93
+     * Associate the component as a tooltip trigger so a tooltip may display on
94
+     * hover.
95
+     *
96
+     * @private
97
+     * @returns {void}
98
+     */
99
+    _setTooltip() {
100
+        // TODO Replace UIUtil with an AtlasKit component when a suitable one
101
+        // becomes available for tooltips.
102
+        UIUtil.setTooltip(
103
+            this._rootElement,
104
+            this._tooltipKey,
105
+            'top'
106
+        );
107
+    }
108
+}
109
+
110
+export default BaseIndicator;

+ 24
- 0
react/features/filmstrip/components/web/ModeratorIndicator.js View File

1
+import BaseIndicator from './BaseIndicator';
2
+
3
+/**
4
+ * React {@code Component} for showing a moderator icon with a tooltip.
5
+ *
6
+ * @extends BaseIndicator
7
+ */
8
+class ModeratorIndicator extends BaseIndicator {
9
+    /**
10
+     * Initializes a new ModeratorIndicator instance.
11
+     *
12
+     * @param {Object} props - The read-only React Component props with which
13
+     * the new instance is to be initialized.
14
+     */
15
+    constructor(props) {
16
+        super(props);
17
+
18
+        this._classNames = 'focusindicator toolbar-icon right';
19
+        this._iconClass = 'icon-star';
20
+        this._tooltipKey = 'videothumbnail.moderator';
21
+    }
22
+}
23
+
24
+export default ModeratorIndicator;

+ 24
- 0
react/features/filmstrip/components/web/VideoMutedIndicator.js View File

1
+import BaseIndicator from './BaseIndicator';
2
+
3
+/**
4
+ * React {@code Component} for showing a video muted icon with a tooltip.
5
+ *
6
+ * @extends BaseIndicator
7
+ */
8
+class VideoMutedIndicator extends BaseIndicator {
9
+    /**
10
+     * Initializes a new VideoMutedIndicator instance.
11
+     *
12
+     * @param {Object} props - The read-only React Component props with which
13
+     * the new instance is to be initialized.
14
+     */
15
+    constructor(props) {
16
+        super(props);
17
+
18
+        this._classNames = 'videoMuted toolbar-icon';
19
+        this._iconClass = 'icon-camera-disabled';
20
+        this._tooltipKey = 'videothumbnail.videomute';
21
+    }
22
+}
23
+
24
+export default VideoMutedIndicator;

+ 3
- 0
react/features/filmstrip/components/web/index.js View File

1
+export { default as AudioMutedIndicator } from './AudioMutedIndicator';
2
+export { default as ModeratorIndicator } from './ModeratorIndicator';
3
+export { default as VideoMutedIndicator } from './VideoMutedIndicator';

Loading…
Cancel
Save