Parcourir la source

Merge pull request #593 from jitsi/custom-role-recorder-view

Add custom-role to presence and special view for Recorders
j8
hristoterezov il y a 9 ans
Parent
révision
a8aa62b075

+ 58
- 54
conference.js Voir le fichier

@@ -21,16 +21,6 @@ const TrackErrors = JitsiMeetJS.errors.track;
21 21
 
22 22
 let room, connection, localAudio, localVideo, roomLocker;
23 23
 
24
-/**
25
- * Known custom conference commands.
26
- */
27
-const Commands = {
28
-    CONNECTION_QUALITY: "stats",
29
-    EMAIL: "email",
30
-    ETHERPAD: "etherpad",
31
-    SHARED_VIDEO: "shared-video"
32
-};
33
-
34 24
 import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/LargeVideo";
35 25
 
36 26
 /**
@@ -52,10 +42,11 @@ function connect(roomName) {
52 42
 
53 43
 /**
54 44
  * Share email with other users.
45
+ * @param emailCommand the email command
55 46
  * @param {string} email new email
56 47
  */
57
-function sendEmail (email) {
58
-    room.sendCommand(Commands.EMAIL, {
48
+function sendEmail (emailCommand, email) {
49
+    room.sendCommand(emailCommand, {
59 50
         value: email,
60 51
         attributes: {
61 52
             id: room.myUserId()
@@ -507,32 +498,6 @@ export default {
507 498
     getLogs () {
508 499
         return room.getLogs();
509 500
     },
510
-    _createRoom (localTracks) {
511
-        room = connection.initJitsiConference(APP.conference.roomName,
512
-            this._getConferenceOptions());
513
-        this.localId = room.myUserId();
514
-        localTracks.forEach((track) => {
515
-            if (track.isAudioTrack()) {
516
-                this.useAudioStream(track);
517
-            } else if (track.isVideoTrack()) {
518
-                this.useVideoStream(track);
519
-            }
520
-        });
521
-        roomLocker = createRoomLocker(room);
522
-        this._room = room; // FIXME do not use this
523
-
524
-        let email = APP.settings.getEmail();
525
-        email && sendEmail(email);
526
-
527
-        let nick = APP.settings.getDisplayName();
528
-        if (config.useNicks && !nick) {
529
-            nick = APP.UI.askForNickname();
530
-            APP.settings.setDisplayName(nick);
531
-        }
532
-        nick && room.setDisplayName(nick);
533
-
534
-        this._setupListeners();
535
-    },
536 501
 
537 502
     /**
538 503
      * Exposes a Command(s) API on this instance. It is necessitated by (1) the
@@ -544,20 +509,30 @@ export default {
544 509
      * API of this instance.
545 510
      */
546 511
     commands: {
512
+        /**
513
+         * Known custom conference commands.
514
+         */
515
+        defaults: {
516
+            CONNECTION_QUALITY: "stats",
517
+            EMAIL: "email",
518
+            ETHERPAD: "etherpad",
519
+            SHARED_VIDEO: "shared-video",
520
+            CUSTOM_ROLE: "custom-role"
521
+        },
547 522
         /**
548 523
          * Receives notifications from other participants about commands aka
549 524
          * custom events (sent by sendCommand or sendCommandOnce methods).
550 525
          * @param command {String} the name of the command
551 526
          * @param handler {Function} handler for the command
552 527
          */
553
-        addCommandListener () {
528
+            addCommandListener () {
554 529
             room.addCommandListener.apply(room, arguments);
555 530
         },
556 531
         /**
557 532
          * Removes command.
558 533
          * @param name {String} the name of the command.
559 534
          */
560
-        removeCommand () {
535
+            removeCommand () {
561 536
             room.removeCommand.apply(room, arguments);
562 537
         },
563 538
         /**
@@ -565,7 +540,7 @@ export default {
565 540
          * @param name {String} the name of the command.
566 541
          * @param values {Object} with keys and values that will be sent.
567 542
          */
568
-        sendCommand () {
543
+            sendCommand () {
569 544
             room.sendCommand.apply(room, arguments);
570 545
         },
571 546
         /**
@@ -573,9 +548,36 @@ export default {
573 548
          * @param name {String} the name of the command.
574 549
          * @param values {Object} with keys and values that will be sent.
575 550
          */
576
-        sendCommandOnce () {
551
+            sendCommandOnce () {
577 552
             room.sendCommandOnce.apply(room, arguments);
578
-        },
553
+        }
554
+    },
555
+
556
+    _createRoom (localTracks) {
557
+        room = connection.initJitsiConference(APP.conference.roomName,
558
+            this._getConferenceOptions());
559
+        this.localId = room.myUserId();
560
+        localTracks.forEach((track) => {
561
+            if (track.isAudioTrack()) {
562
+                this.useAudioStream(track);
563
+            } else if (track.isVideoTrack()) {
564
+                this.useVideoStream(track);
565
+            }
566
+        });
567
+        roomLocker = createRoomLocker(room);
568
+        this._room = room; // FIXME do not use this
569
+
570
+        let email = APP.settings.getEmail();
571
+        email && sendEmail(this.commands.defaults.EMAIL, email);
572
+
573
+        let nick = APP.settings.getDisplayName();
574
+        if (config.useNicks && !nick) {
575
+            nick = APP.UI.askForNickname();
576
+            APP.settings.setDisplayName(nick);
577
+        }
578
+        nick && room.setDisplayName(nick);
579
+
580
+        this._setupListeners();
579 581
     },
580 582
 
581 583
     _getConferenceOptions() {
@@ -916,7 +918,8 @@ export default {
916 918
                 APP.UI.updateLocalStats(percent, stats);
917 919
 
918 920
                 // send local stats to other users
919
-                room.sendCommandOnce(Commands.CONNECTION_QUALITY, {
921
+                room.sendCommandOnce(this.commands.defaults.CONNECTION_QUALITY,
922
+                {
920 923
                     children: ConnectionQuality.convertToMUCStats(stats),
921 924
                     attributes: {
922 925
                         xmlns: 'http://jitsi.org/jitmeet/stats'
@@ -926,8 +929,9 @@ export default {
926 929
         );
927 930
 
928 931
         // listen to remote stats
929
-        room.addCommandListener(Commands.CONNECTION_QUALITY,(values, from) => {
930
-            ConnectionQuality.updateRemoteStats(from, values);
932
+        room.addCommandListener(this.commands.defaults.CONNECTION_QUALITY,
933
+            (values, from) => {
934
+                ConnectionQuality.updateRemoteStats(from, values);
931 935
         });
932 936
 
933 937
         ConnectionQuality.addListener(CQEvents.REMOTESTATS_UPDATED,
@@ -935,7 +939,7 @@ export default {
935 939
                 APP.UI.updateRemoteStats(id, percent, stats);
936 940
             });
937 941
 
938
-        room.addCommandListener(Commands.ETHERPAD, ({value}) => {
942
+        room.addCommandListener(this.commands.defaults.ETHERPAD, ({value}) => {
939 943
             APP.UI.initEtherpad(value);
940 944
         });
941 945
 
@@ -948,9 +952,9 @@ export default {
948 952
 
949 953
             APP.settings.setEmail(email);
950 954
             APP.UI.setUserAvatar(room.myUserId(), email);
951
-            sendEmail(email);
955
+            sendEmail(this.commands.defaults.EMAIL, email);
952 956
         });
953
-        room.addCommandListener(Commands.EMAIL, (data) => {
957
+        room.addCommandListener(this.commands.defaults.EMAIL, (data) => {
954 958
             APP.UI.setUserAvatar(data.attributes.id, data.value);
955 959
         });
956 960
 
@@ -1095,8 +1099,8 @@ export default {
1095 1099
             // send start and stop commands once, and remove any updates
1096 1100
             // that had left
1097 1101
             if (state === 'stop' || state === 'start' || state === 'playing') {
1098
-                room.removeCommand(Commands.SHARED_VIDEO);
1099
-                room.sendCommandOnce(Commands.SHARED_VIDEO, {
1102
+                room.removeCommand(this.commands.defaults.SHARED_VIDEO);
1103
+                room.sendCommandOnce(this.commands.defaults.SHARED_VIDEO, {
1100 1104
                     value: url,
1101 1105
                     attributes: {
1102 1106
                         state: state,
@@ -1108,8 +1112,8 @@ export default {
1108 1112
             else {
1109 1113
                 // in case of paused, in order to allow late users to join
1110 1114
                 // paused
1111
-                room.removeCommand(Commands.SHARED_VIDEO);
1112
-                room.sendCommand(Commands.SHARED_VIDEO, {
1115
+                room.removeCommand(this.commands.defaults.SHARED_VIDEO);
1116
+                room.sendCommand(this.commands.defaults.SHARED_VIDEO, {
1113 1117
                     value: url,
1114 1118
                     attributes: {
1115 1119
                         state: state,
@@ -1120,7 +1124,7 @@ export default {
1120 1124
             }
1121 1125
         });
1122 1126
         room.addCommandListener(
1123
-            Commands.SHARED_VIDEO, ({value, attributes}, id) => {
1127
+            this.commands.defaults.SHARED_VIDEO, ({value, attributes}, id) => {
1124 1128
 
1125 1129
                 if (attributes.state === 'stop') {
1126 1130
                     APP.UI.stopSharedVideo(id, attributes);

+ 30
- 2
modules/UI/Feedback.js Voir le fichier

@@ -69,6 +69,21 @@ function _toggleFeedbackIcon() {
69 69
     $('#feedbackButtonDiv').toggleClass("hidden");
70 70
 }
71 71
 
72
+/**
73
+ * Shows / hides the feedback button.
74
+ * @param {show} set to {true} to show the feedback button or to  {false}
75
+ * to hide it
76
+ * @private
77
+ */
78
+function _showFeedbackButton (show) {
79
+    var feedbackButton = $("#feedbackButtonDiv");
80
+
81
+    if (show)
82
+        feedbackButton.css("display", "block");
83
+    else
84
+        feedbackButton.css("display", "none");
85
+}
86
+
72 87
 /**
73 88
  * Defines all methods in connection to the Feedback window.
74 89
  *
@@ -85,11 +100,15 @@ var Feedback = {
85 100
      * @param emitter the EventEmitter to associate with the Feedback.
86 101
      */
87 102
     init: function (emitter) {
103
+        // Initialise to enabled.
104
+        this.enabled = true;
105
+
88 106
         // CallStats is the way we send feedback, so we don't have to initialise
89 107
         // if callstats isn't enabled.
90 108
         if (!APP.conference.isCallstatsEnabled())
91 109
             return;
92
-        $("#feedbackButtonDiv").css("display", "block");
110
+
111
+        _showFeedbackButton(true);
93 112
         $("#feedbackButton").click(function (event) {
94 113
             Feedback.openFeedbackWindow();
95 114
         });
@@ -100,13 +119,22 @@ var Feedback = {
100 119
             _toggleFeedbackIcon();
101 120
         });
102 121
     },
122
+    /**
123
+     * Enables/ disabled the feedback feature.
124
+     */
125
+    enableFeedback: function (enable) {
126
+        if (this.enabled !== enable)
127
+            _showFeedbackButton(enable);
128
+        this.enabled = enable;
129
+    },
130
+
103 131
     /**
104 132
      * Indicates if the feedback functionality is enabled.
105 133
      *
106 134
      * @return true if the feedback functionality is enabled, false otherwise.
107 135
      */
108 136
     isEnabled: function() {
109
-        return APP.conference.isCallstatsEnabled();
137
+        return this.enabled && APP.conference.isCallstatsEnabled();
110 138
     },
111 139
     /**
112 140
      * Opens the feedback window.

+ 13
- 4
modules/UI/UI.js Voir le fichier

@@ -29,6 +29,8 @@ var JitsiPopover = require("./util/JitsiPopover");
29 29
 var Feedback = require("./Feedback");
30 30
 
31 31
 import FollowMe from "../FollowMe";
32
+import Recorder from "../recorder/Recorder";
33
+
32 34
 
33 35
 var eventEmitter = new EventEmitter();
34 36
 UI.eventEmitter = eventEmitter;
@@ -42,7 +44,8 @@ let followMeHandler;
42 44
  * Prompt user for nickname.
43 45
  */
44 46
 function promptDisplayName() {
45
-    let nickRequiredMsg = APP.translation.translateString("dialog.displayNameRequired");
47
+    let nickRequiredMsg
48
+        = APP.translation.translateString("dialog.displayNameRequired");
46 49
     let defaultNickMsg = APP.translation.translateString(
47 50
         "defaultNickname", {name: "Jane Pink"}
48 51
     );
@@ -110,8 +113,8 @@ function setupToolbars() {
110 113
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
111 114
  */
112 115
 function toggleFullScreen () {
113
-    let isNotFullScreen = !document.fullscreenElement &&    // alternative standard method
114
-
116
+                            // alternative standard method
117
+    let isNotFullScreen = !document.fullscreenElement &&
115 118
             !document.mozFullScreenElement && // current working methods
116 119
         !document.webkitFullscreenElement &&
117 120
         !document.msFullscreenElement;
@@ -124,7 +127,8 @@ function toggleFullScreen () {
124 127
         } else if (document.documentElement.mozRequestFullScreen) {
125 128
             document.documentElement.mozRequestFullScreen();
126 129
         } else if (document.documentElement.webkitRequestFullscreen) {
127
-            document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
130
+            document.documentElement
131
+                .webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
128 132
         }
129 133
     } else {
130 134
         if (document.exitFullscreen) {
@@ -238,6 +242,11 @@ UI.initConference = function () {
238 242
     //if local role changes buttons state will be again updated
239 243
     UI.updateLocalRole(false);
240 244
 
245
+    // Initialise the recorder handler. We're doing this explicitly before
246
+    // calling showToolbar, because the recorder may want to disable all
247
+    // toolbars.
248
+    new Recorder(APP.conference, UI);
249
+
241 250
     // Once we've joined the muc show the toolbar
242 251
     ToolbarToggler.showToolbar();
243 252
 

+ 39
- 2
modules/UI/recording/Recording.js Voir le fichier

@@ -133,6 +133,13 @@ function _requestRecordingToken () {
133 133
     });
134 134
 }
135 135
 
136
+/**
137
+ * Shows a prompt dialog to the user when they have toggled off the recording.
138
+ *
139
+ * @param recordingType the recording type
140
+ * @returns {Promise}
141
+ * @private
142
+ */
136 143
 function _showStopRecordingPrompt (recordingType) {
137 144
     var title;
138 145
     var message;
@@ -167,6 +174,12 @@ function _showStopRecordingPrompt (recordingType) {
167 174
     });
168 175
 }
169 176
 
177
+/**
178
+ * Moves the element given by {selector} to the top right corner of the screen.
179
+ * @param selector the selector for the element to move
180
+ * @param move {true} to move the element, {false} to move it back to its intial
181
+ * position
182
+ */
170 183
 function moveToCorner(selector, move) {
171 184
     let moveToCornerClass = "moveToCorner";
172 185
 
@@ -176,6 +189,12 @@ function moveToCorner(selector, move) {
176 189
         selector.removeClass(moveToCornerClass);
177 190
 }
178 191
 
192
+/**
193
+ * The status of the recorder.
194
+ * FIXME: Those constants should come from the library.
195
+ * @type {{ON: string, OFF: string, AVAILABLE: string,
196
+ * UNAVAILABLE: string, PENDING: string}}
197
+ */
179 198
 var Status = {
180 199
     ON: "on",
181 200
     OFF: "off",
@@ -184,6 +203,11 @@ var Status = {
184 203
     PENDING: "pending"
185 204
 };
186 205
 
206
+/**
207
+ * Manages the recording user interface and user experience.
208
+ * @type {{init, initRecordingButton, showRecordingButton, updateRecordingState,
209
+ * setRecordingButtonState, checkAutoRecord}}
210
+ */
187 211
 var Recording = {
188 212
     /**
189 213
      * Initializes the recording UI.
@@ -196,6 +220,9 @@ var Recording = {
196 220
         this.initRecordingButton(recordingType);
197 221
     },
198 222
 
223
+    /**
224
+     * Initialise the recording button.
225
+     */
199 226
     initRecordingButton(recordingType) {
200 227
         let selector = $('#toolbar_button_record');
201 228
 
@@ -261,7 +288,10 @@ var Recording = {
261 288
         });
262 289
     },
263 290
 
264
-    // Shows or hides the 'recording' button.
291
+    /**
292
+     * Shows or hides the 'recording' button.
293
+     * @param show {true} to show the recording button, {false} to hide it
294
+     */
265 295
     showRecordingButton (show) {
266 296
         if (_isRecordingButtonEnabled() && show) {
267 297
             $('#toolbar_button_record').css({display: "inline-block"});
@@ -270,6 +300,10 @@ var Recording = {
270 300
         }
271 301
     },
272 302
 
303
+    /**
304
+     * Updates the recording state UI.
305
+     * @param recordingState gives us the current recording state
306
+     */
273 307
     updateRecordingState(recordingState) {
274 308
         // I'm the recorder, so I don't want to see any UI related to states.
275 309
         if (config.iAmRecorder)
@@ -282,7 +316,10 @@ var Recording = {
282 316
         this.setRecordingButtonState(recordingState);
283 317
     },
284 318
 
285
-    // Sets the state of the recording button
319
+    /**
320
+     * Sets the state of the recording button.
321
+     * @param recordingState gives us the current recording state
322
+     */
286 323
     setRecordingButtonState (recordingState) {
287 324
         let buttonSelector = $('#toolbar_button_record');
288 325
         let labelSelector = $('#recordingLabel');

+ 20
- 1
modules/UI/toolbars/BottomToolbar.js Voir le fichier

@@ -12,8 +12,27 @@ const defaultBottomToolbarButtons = {
12 12
 const BottomToolbar = {
13 13
     init () {
14 14
         this.toolbar = $('#bottomToolbar');
15
-    },
16 15
 
16
+        // The bottom toolbar is enabled by default.
17
+        this.enabled = true;
18
+    },
19
+    /**
20
+     * Enables / disables the bottom toolbar.
21
+     * @param {e} set to {true} to enable the bottom toolbar or {false}
22
+     * to disable it
23
+     */
24
+    enable (e) {
25
+        this.enabled = e;
26
+        if (!e && this.isVisible())
27
+            this.hide(false);
28
+    },
29
+    /**
30
+     * Indicates if the bottom toolbar is currently enabled.
31
+     * @return {this.enabled}
32
+     */
33
+    isEnabled() {
34
+        return this.enabled;
35
+    },
17 36
     setupListeners (emitter) {
18 37
         UIUtil.hideDisabledButtons(defaultBottomToolbarButtons);
19 38
 

+ 71
- 5
modules/UI/toolbars/Toolbar.js Voir le fichier

@@ -171,6 +171,9 @@ function showSipNumberInput () {
171 171
 const Toolbar = {
172 172
     init (eventEmitter) {
173 173
         emitter = eventEmitter;
174
+        // The toolbar is enabled by default.
175
+        this.enabled = true;
176
+        this.toolbarSelector = $("#header");
174 177
 
175 178
         UIUtil.hideDisabledButtons(defaultToolbarButtons);
176 179
 
@@ -178,14 +181,31 @@ const Toolbar = {
178 181
             buttonId => $(`#${buttonId}`).click(buttonHandlers[buttonId])
179 182
         );
180 183
     },
181
-
184
+    /**
185
+     * Enables / disables the toolbar.
186
+     * @param {e} set to {true} to enable the toolbar or {false}
187
+     * to disable it
188
+     */
189
+    enable (e) {
190
+        this.enabled = e;
191
+        if (!e && this.isVisible())
192
+            this.hide(false);
193
+    },
194
+    /**
195
+     * Indicates if the bottom toolbar is currently enabled.
196
+     * @return {this.enabled}
197
+     */
198
+    isEnabled() {
199
+        return this.enabled;
200
+    },
182 201
     /**
183 202
      * Updates the room invite url.
184 203
      */
185 204
     updateRoomUrl (newRoomUrl) {
186 205
         roomUrl = newRoomUrl;
187 206
 
188
-        // If the invite dialog has been already opened we update the information.
207
+        // If the invite dialog has been already opened we update the
208
+        // information.
189 209
         let inviteLink = document.getElementById('inviteLinkRef');
190 210
         if (inviteLink) {
191 211
             inviteLink.value = roomUrl;
@@ -244,14 +264,16 @@ const Toolbar = {
244 264
     // checks whether desktop sharing is enabled and whether
245 265
     // we have params to start automatically sharing
246 266
     checkAutoEnableDesktopSharing () {
247
-        if (UIUtil.isButtonEnabled('desktop') && config.autoEnableDesktopSharing) {
267
+        if (UIUtil.isButtonEnabled('desktop')
268
+            && config.autoEnableDesktopSharing) {
248 269
             emitter.emit(UIEvents.TOGGLE_SCREENSHARING);
249 270
         }
250 271
     },
251 272
 
252 273
     // Shows or hides SIP calls button
253 274
     showSipCallButton (show) {
254
-        if (APP.conference.sipGatewayEnabled() && UIUtil.isButtonEnabled('sip') && show) {
275
+        if (APP.conference.sipGatewayEnabled()
276
+            && UIUtil.isButtonEnabled('sip') && show) {
255 277
             $('#toolbar_button_sip').css({display: "inline-block"});
256 278
         } else {
257 279
             $('#toolbar_button_sip').css({display: "none"});
@@ -331,7 +353,51 @@ const Toolbar = {
331 353
      * @param {boolean} muted if icon should look like muted or not
332 354
      */
333 355
     markAudioIconAsMuted (muted) {
334
-        $('#toolbar_button_mute').toggleClass("icon-microphone", !muted).toggleClass("icon-mic-disabled", muted);
356
+        $('#toolbar_button_mute').toggleClass("icon-microphone",
357
+            !muted).toggleClass("icon-mic-disabled", muted);
358
+    },
359
+
360
+    /**
361
+     * Indicates if the toolbar is currently hovered.
362
+     * @return {true} if the toolbar is currently hovered, {false} otherwise
363
+     */
364
+    isHovered() {
365
+        this.toolbarSelector.find('*').each(function () {
366
+            let id = $(this).attr('id');
367
+            if ($(`#${id}:hover`).length > 0) {
368
+                return true;
369
+            }
370
+        });
371
+        if ($("#bottomToolbar:hover").length > 0) {
372
+            return true;
373
+        }
374
+        return false;
375
+    },
376
+
377
+    /**
378
+     * Returns true if this toolbar is currently visible, or false otherwise.
379
+     * @return <tt>true</tt> if currently visible, <tt>false</tt> - otherwise
380
+     */
381
+    isVisible() {
382
+        return this.toolbarSelector.is(":visible");
383
+    },
384
+
385
+    /**
386
+     * Hides the toolbar with animation or not depending on the animate
387
+     * parameter.
388
+     */
389
+    hide() {
390
+        this.toolbarSelector.hide(
391
+            "slide", { direction: "up", duration: 300});
392
+    },
393
+
394
+    /**
395
+     * Shows the toolbar with animation or not depending on the animate
396
+     * parameter.
397
+     */
398
+    show() {
399
+        this.toolbarSelector.show(
400
+            "slide", { direction: "up", duration: 300});
335 401
     }
336 402
 };
337 403
 

+ 19
- 29
modules/UI/toolbars/ToolbarToggler.js Voir le fichier

@@ -2,6 +2,7 @@
2 2
 
3 3
 import UIUtil from '../util/UIUtil';
4 4
 import BottomToolbar from './BottomToolbar';
5
+import Toolbar from './Toolbar';
5 6
 import FilmStrip from '../videolayout/FilmStrip.js';
6 7
 
7 8
 let toolbarTimeoutObject;
@@ -16,10 +17,6 @@ function showDesktopSharingButton() {
16 17
     }
17 18
 }
18 19
 
19
-function isToolbarVisible () {
20
-    return $('#header').is(':visible');
21
-}
22
-
23 20
 /**
24 21
  * Hides the toolbar.
25 22
  */
@@ -28,25 +25,13 @@ function hideToolbar() {
28 25
         return;
29 26
     }
30 27
 
31
-    let header = $("#header");
32
-    let isToolbarHover = false;
33
-    header.find('*').each(function () {
34
-        let id = $(this).attr('id');
35
-        if ($(`#${id}:hover`).length > 0) {
36
-            isToolbarHover = true;
37
-        }
38
-    });
39
-    if ($("#bottomToolbar:hover").length > 0) {
40
-        isToolbarHover = true;
41
-    }
42
-
43 28
     clearTimeout(toolbarTimeoutObject);
44 29
     toolbarTimeoutObject = null;
45 30
 
46
-    if (isToolbarHover) {
31
+    if (Toolbar.isHovered()) {
47 32
         toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
48 33
     } else {
49
-        header.hide("slide", { direction: "up", duration: 300});
34
+        Toolbar.hide();
50 35
         $('#subject').animate({top: "-=40"}, 300);
51 36
         if (!FilmStrip.isFilmStripVisible()) {
52 37
             BottomToolbar.hide(true);
@@ -59,18 +44,23 @@ const ToolbarToggler = {
59 44
      * Shows the main toolbar.
60 45
      */
61 46
     showToolbar () {
62
-        // if we are a recorder we do not want to show the toolbar
63
-        if (interfaceConfig.filmStripOnly || config.iAmRecorder) {
47
+        if (interfaceConfig.filmStripOnly) {
64 48
             return;
65 49
         }
66
-        let header = $("#header");
67
-        if (!header.is(':visible') || !BottomToolbar.isVisible()) {
68
-            header.show("slide", { direction: "up", duration: 300});
50
+
51
+        var updateTimeout = false;
52
+        if (Toolbar.isEnabled() && !Toolbar.isVisible()) {
53
+            Toolbar.show();
69 54
             $('#subject').animate({top: "+=40"}, 300);
70
-            if (!BottomToolbar.isVisible()) {
71
-                BottomToolbar.show(true);
72
-            }
55
+            updateTimeout = true;
56
+        }
73 57
 
58
+        if (BottomToolbar.isEnabled() && !BottomToolbar.isVisible()) {
59
+            BottomToolbar.show(true);
60
+            updateTimeout = true;
61
+        }
62
+
63
+        if (updateTimeout) {
74 64
             if (toolbarTimeoutObject) {
75 65
                 clearTimeout(toolbarTimeoutObject);
76 66
                 toolbarTimeoutObject = null;
@@ -89,13 +79,13 @@ const ToolbarToggler = {
89 79
      * @param isDock indicates what operation to perform
90 80
      */
91 81
     dockToolbar (isDock) {
92
-        if (interfaceConfig.filmStripOnly) {
82
+        if (interfaceConfig.filmStripOnly || !Toolbar.isEnabled()) {
93 83
             return;
94 84
         }
95 85
 
96 86
         if (isDock) {
97 87
             // First make sure the toolbar is shown.
98
-            if (!isToolbarVisible()) {
88
+            if (!Toolbar.isVisible()) {
99 89
                 this.showToolbar();
100 90
             }
101 91
 
@@ -103,7 +93,7 @@ const ToolbarToggler = {
103 93
             clearTimeout(toolbarTimeoutObject);
104 94
             toolbarTimeoutObject = null;
105 95
         } else {
106
-            if (isToolbarVisible()) {
96
+            if (Toolbar.isVisible()) {
107 97
                 toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
108 98
             } else {
109 99
                 this.showToolbar();

+ 18
- 0
modules/UI/videolayout/SmallVideo.js Voir le fichier

@@ -50,7 +50,25 @@ SmallVideo.prototype.showDisplayName = function(isShow) {
50 50
     }
51 51
 };
52 52
 
53
+/**
54
+ * Enables / disables the device availability icons for this small video.
55
+ * @param {enable} set to {true} to enable and {false} to disable
56
+ */
57
+SmallVideo.prototype.enableDeviceAvailabilityIcons = function (enable) {
58
+    if (typeof enable === "undefined")
59
+        return;
60
+
61
+    this.deviceAvailabilityIconsEnabled = enable;
62
+};
63
+
64
+/**
65
+ * Sets the device "non" availability icons.
66
+ * @param devices the devices, which will be checked for availability
67
+ */
53 68
 SmallVideo.prototype.setDeviceAvailabilityIcons = function (devices) {
69
+    if (!this.deviceAvailabilityIconsEnabled)
70
+        return;
71
+
54 72
     if(!this.container)
55 73
         return;
56 74
 

+ 19
- 0
modules/UI/videolayout/VideoLayout.js Voir le fichier

@@ -196,6 +196,25 @@ var VideoLayout = {
196 196
         video.setDeviceAvailabilityIcons(devices);
197 197
     },
198 198
 
199
+    /**
200
+     * Enables/disables device availability icons for the given participant id.
201
+     * The default value is {true}.
202
+     * @param id the identifier of the participant
203
+     * @param enable {true} to enable device availability icons
204
+     */
205
+    enableDeviceAvailabilityIcons (id, enable) {
206
+        let video;
207
+        if (APP.conference.isLocalId(id)) {
208
+            video = localVideoThumbnail;
209
+        }
210
+        else if (remoteVideos[id]) {
211
+            video = remoteVideos[id];
212
+        }
213
+
214
+        if (video)
215
+            video.enableDeviceAvailabilityIcons(enable);
216
+    },
217
+
199 218
     /**
200 219
      * Checks if removed video is currently displayed and tries to display
201 220
      * another one instead.

+ 100
- 0
modules/recorder/Recorder.js Voir le fichier

@@ -0,0 +1,100 @@
1
+/* global config, APP */
2
+/*
3
+ * Copyright @ 2015 Atlassian Pty Ltd
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ *     http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+import VideoLayout from '../UI/videolayout/VideoLayout';
18
+import Feedback from '../UI/Feedback.js';
19
+import Toolbar from '../UI/toolbars/Toolbar';
20
+import BottomToolbar from '../UI/toolbars/BottomToolbar';
21
+
22
+const _RECORDER_CUSTOM_ROLE = "recorder-role";
23
+
24
+class Recorder {
25
+    /**
26
+     * Initializes a new {Recorder} instance.
27
+     *
28
+     * @param conference the {conference} which is to transport
29
+     * {Recorder}-related information between participants
30
+     * @param UI the {UI} which is the source (model/state) to be sent to
31
+     * remote participants if the local participant is the moderator or the
32
+     * destination (model/state) to receive from the remote moderator if the
33
+     * local participant is not the moderator
34
+     */
35
+    constructor (conference, UI) {
36
+        this._conference = conference;
37
+        this._UI = UI;
38
+
39
+        // If I am a recorder then I publish my recorder custom role to notify
40
+        // everyone.
41
+        if (config.iAmRecorder) {
42
+            VideoLayout.enableDeviceAvailabilityIcons(conference.localId, true);
43
+            this._publishMyRecorderRole();
44
+            Feedback.enableFeedback(false);
45
+            Toolbar.enable(false);
46
+            BottomToolbar.enable(false);
47
+        }
48
+
49
+        // Listen to "CUSTOM_ROLE" commands.
50
+        this._conference.commands.addCommandListener(
51
+            this._conference.commands.defaults.CUSTOM_ROLE,
52
+            this._onCustomRoleCommand.bind(this));
53
+    }
54
+
55
+    /**
56
+     * Publish the recorder custom role.
57
+     * @private
58
+     */
59
+    _publishMyRecorderRole () {
60
+        var conference = this._conference;
61
+
62
+        var commands = conference.commands;
63
+
64
+        commands.removeCommand(commands.defaults.CUSTOM_ROLE);
65
+        var self = this;
66
+        commands.sendCommandOnce(
67
+            commands.defaults.CUSTOM_ROLE,
68
+            {
69
+                attributes: {
70
+                    recorderRole: true
71
+                }
72
+            });
73
+    }
74
+
75
+    /**
76
+     * Notifies this instance about a &qout;Custom Role&qout; command (delivered
77
+     * by the Command(s) API of {this._conference}).
78
+     *
79
+     * @param attributes the attributes {Object} carried by the command
80
+     * @param id the identifier of the participant who issued the command. A
81
+     * notable idiosyncrasy of the Command(s) API to be mindful of here is that
82
+     * the command may be issued by the local participant.
83
+     */
84
+    _onCustomRoleCommand ({ attributes }, id) {
85
+        // We require to know who issued the command because (1) only a
86
+        // moderator is allowed to send commands and (2) a command MUST be
87
+        // issued by a defined commander.
88
+        if (typeof id === 'undefined'
89
+            || this._conference.isLocalId(id)
90
+            || !attributes.recorderRole)
91
+            return;
92
+
93
+        var isRecorder = (attributes.recorderRole == 'true');
94
+
95
+        if (isRecorder)
96
+            VideoLayout.enableDeviceAvailabilityIcons(id, isRecorder);
97
+    }
98
+}
99
+
100
+export default Recorder;

Chargement…
Annuler
Enregistrer