Procházet zdrojové kódy

added some documentation (jsdocs)

j8
isymchych před 9 roky
rodič
revize
6b98fd52ea

+ 66
- 11
conference.js Zobrazit soubor

17
 
17
 
18
 let room, connection, localTracks, localAudio, localVideo, roomLocker;
18
 let room, connection, localTracks, localAudio, localVideo, roomLocker;
19
 
19
 
20
+/**
21
+ * Known custom conference commands.
22
+ */
20
 const Commands = {
23
 const Commands = {
21
     CONNECTION_QUALITY: "stats",
24
     CONNECTION_QUALITY: "stats",
22
     EMAIL: "email",
25
     EMAIL: "email",
26
     STOP_PREZI: "stop-prezi"
29
     STOP_PREZI: "stop-prezi"
27
 };
30
 };
28
 
31
 
32
+/**
33
+ * Open Connection. When authentication failed it shows auth dialog.
34
+ * @returns Promise<JitsiConnection>
35
+ */
29
 function connect() {
36
 function connect() {
30
     return openConnection({retry: true}).catch(function (err) {
37
     return openConnection({retry: true}).catch(function (err) {
31
         if (err === ConnectionErrors.PASSWORD_REQUIRED) {
38
         if (err === ConnectionErrors.PASSWORD_REQUIRED) {
37
     });
44
     });
38
 }
45
 }
39
 
46
 
40
-const addTrack = (track) => {
47
+/**
48
+ * Add local track to the conference and shares
49
+ * video type with other users if its video track.
50
+ * @param {JitsiLocalTrack} track local track
51
+ */
52
+function addTrack (track) {
41
     room.addTrack(track);
53
     room.addTrack(track);
54
+
42
     if (track.isAudioTrack()) {
55
     if (track.isAudioTrack()) {
43
         return;
56
         return;
44
     }
57
     }
50
             xmlns: 'http://jitsi.org/jitmeet/video'
63
             xmlns: 'http://jitsi.org/jitmeet/video'
51
         }
64
         }
52
     });
65
     });
53
-};
66
+}
54
 
67
 
55
-// share email with other users
56
-const sendEmail = (email) => {
68
+/**
69
+ * Share email with other users.
70
+ * @param {string} email new email
71
+ */
72
+function sendEmail (email) {
57
     room.sendCommand(Commands.EMAIL, {
73
     room.sendCommand(Commands.EMAIL, {
58
         value: email,
74
         value: email,
59
         attributes: {
75
         attributes: {
60
             id: room.myUserId()
76
             id: room.myUserId()
61
         }
77
         }
62
     });
78
     });
63
-};
64
-
79
+}
65
 
80
 
66
-const unload = () => {
81
+/**
82
+ * Leave the conference and close connection.
83
+ */
84
+function unload () {
67
     room.leave();
85
     room.leave();
68
     connection.disconnect();
86
     connection.disconnect();
69
-};
87
+}
70
 
88
 
71
-const getDisplayName = (id) => {
89
+/**
90
+ * Get user nickname by user id.
91
+ * @param {string} id user id
92
+ * @returns {string?} user nickname or undefined if user is unknown.
93
+ */
94
+function getDisplayName (id) {
72
     if (APP.conference.isLocalId(id)) {
95
     if (APP.conference.isLocalId(id)) {
73
         return APP.settings.getDisplayName();
96
         return APP.settings.getDisplayName();
74
     }
97
     }
77
     if (participant && participant.getDisplayName()) {
100
     if (participant && participant.getDisplayName()) {
78
         return participant.getDisplayName();
101
         return participant.getDisplayName();
79
     }
102
     }
80
-};
103
+}
81
 
104
 
82
 class ConferenceConnector {
105
 class ConferenceConnector {
83
     constructor(resolve, reject) {
106
     constructor(resolve, reject) {
151
     isModerator: false,
174
     isModerator: false,
152
     audioMuted: false,
175
     audioMuted: false,
153
     videoMuted: false,
176
     videoMuted: false,
177
+    /**
178
+     * Open new connection and join to the conference.
179
+     * @param {object} options
180
+     * @param {string} roomName name of the conference
181
+     * @returns {Promise}
182
+     */
154
     init(options) {
183
     init(options) {
155
         this.roomName = options.roomName;
184
         this.roomName = options.roomName;
156
         JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
185
         JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
173
             });
202
             });
174
         });
203
         });
175
     },
204
     },
205
+    /**
206
+     * Create local tracks of specified types.
207
+     * If we cannot obtain required tracks it will return empty array.
208
+     * @param {string[]} devices required track types ('audio', 'video' etc.)
209
+     * @returns {Promise<JitsiLocalTrack[]>}
210
+     */
176
     createLocalTracks (...devices) {
211
     createLocalTracks (...devices) {
177
         return JitsiMeetJS.createLocalTracks({
212
         return JitsiMeetJS.createLocalTracks({
178
             // copy array to avoid mutations inside library
213
             // copy array to avoid mutations inside library
184
             return Promise.reject(err);
219
             return Promise.reject(err);
185
         });
220
         });
186
     },
221
     },
222
+    /**
223
+     * Check if id is id of the local user.
224
+     * @param {string} id id to check
225
+     * @returns {boolean}
226
+     */
187
     isLocalId (id) {
227
     isLocalId (id) {
188
         return this.localId === id;
228
         return this.localId === id;
189
     },
229
     },
217
     toggleVideoMuted () {
257
     toggleVideoMuted () {
218
         this.muteVideo(!this.videoMuted);
258
         this.muteVideo(!this.videoMuted);
219
     },
259
     },
260
+    /**
261
+     * Retrieve list of conference participants (without local user).
262
+     * @returns {JitsiParticipant[]}
263
+     */
220
     listMembers () {
264
     listMembers () {
221
         return room.getParticipants();
265
         return room.getParticipants();
222
     },
266
     },
267
+    /**
268
+     * Retrieve list of ids of conference participants (without local user).
269
+     * @returns {string[]}
270
+     */
223
     listMembersIds () {
271
     listMembersIds () {
224
         return room.getParticipants().map(p => p.getId());
272
         return room.getParticipants().map(p => p.getId());
225
     },
273
     },
274
+    /**
275
+     * Check if SIP is supported.
276
+     * @returns {boolean}
277
+     */
226
     sipGatewayEnabled () {
278
     sipGatewayEnabled () {
227
         return room.isSIPCallingSupported();
279
         return room.isSIPCallingSupported();
228
     },
280
     },
279
     /**
331
     /**
280
      * Will check for number of remote particiapnts that have at least one
332
      * Will check for number of remote particiapnts that have at least one
281
      * remote track.
333
      * remote track.
282
-     * @return boolean whether we have enough participants with remote streams
334
+     * @return {boolean} whether we have enough participants with remote streams
283
      */
335
      */
284
     checkEnoughParticipants (number) {
336
     checkEnoughParticipants (number) {
285
         var participants = this._room.getParticipants();
337
         var participants = this._room.getParticipants();
336
         }
388
         }
337
         return options;
389
         return options;
338
     },
390
     },
391
+    /**
392
+     * Setup interaction between conference and UI.
393
+     */
339
     _setupListeners () {
394
     _setupListeners () {
340
         // add local streams when joined to the conference
395
         // add local streams when joined to the conference
341
         room.on(ConferenceEvents.CONFERENCE_JOINED, () => {
396
         room.on(ConferenceEvents.CONFERENCE_JOINED, () => {

+ 25
- 0
connection.js Zobrazit soubor

5
 const ConnectionEvents = JitsiMeetJS.events.connection;
5
 const ConnectionEvents = JitsiMeetJS.events.connection;
6
 const ConnectionErrors = JitsiMeetJS.errors.connection;
6
 const ConnectionErrors = JitsiMeetJS.errors.connection;
7
 
7
 
8
+/**
9
+ * Try to open connection using provided credentials.
10
+ * @param {string} [id]
11
+ * @param {string} [password]
12
+ * @returns {Promise<JitsiConnection>} connection if
13
+ * everything is ok, else error.
14
+ */
8
 function connect(id, password) {
15
 function connect(id, password) {
9
     let connection = new JitsiMeetJS.JitsiConnection(null, null, config);
16
     let connection = new JitsiMeetJS.JitsiConnection(null, null, config);
10
 
17
 
42
     });
49
     });
43
 }
50
 }
44
 
51
 
52
+/**
53
+ * Show Authentication Dialog and try to connect with new credentials.
54
+ * If failed to connect because of PASSWORD_REQUIRED error
55
+ * then ask for password again.
56
+ * @returns {Promise<JitsiConnection>}
57
+ */
45
 function requestAuth() {
58
 function requestAuth() {
46
     return new Promise(function (resolve, reject) {
59
     return new Promise(function (resolve, reject) {
47
         let authDialog = LoginDialog.showAuthDialog(
60
         let authDialog = LoginDialog.showAuthDialog(
62
     });
75
     });
63
 }
76
 }
64
 
77
 
78
+/**
79
+ * Open JitsiConnection using provided credentials.
80
+ * If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
81
+ *
82
+ * @param {object} options
83
+ * @param {string} [options.id]
84
+ * @param {string} [options.password]
85
+ * @param {boolean} [retry] if we should show auth dialog
86
+ * on PASSWORD_REQUIRED error.
87
+ *
88
+ * @returns {Promise<JitsiConnection>}
89
+ */
65
 export function openConnection({id, password, retry}) {
90
 export function openConnection({id, password, retry}) {
66
     return connect(id, password).catch(function (err) {
91
     return connect(id, password).catch(function (err) {
67
         if (!retry) {
92
         if (!retry) {

+ 175
- 3
modules/UI/UI.js Zobrazit soubor

31
 let preziManager;
31
 let preziManager;
32
 let etherpadManager;
32
 let etherpadManager;
33
 
33
 
34
+/**
35
+ * Prompt user for nickname.
36
+ */
34
 function promptDisplayName() {
37
 function promptDisplayName() {
35
     let nickRequiredMsg = APP.translation.translateString("dialog.displayNameRequired");
38
     let nickRequiredMsg = APP.translation.translateString("dialog.displayNameRequired");
36
     let defaultNickMsg = APP.translation.translateString(
39
     let defaultNickMsg = APP.translation.translateString(
76
     );
79
     );
77
 }
80
 }
78
 
81
 
82
+/**
83
+ * Initialize chat.
84
+ */
79
 function setupChat() {
85
 function setupChat() {
80
     Chat.init(eventEmitter);
86
     Chat.init(eventEmitter);
81
     $("#toggle_smileys").click(function() {
87
     $("#toggle_smileys").click(function() {
83
     });
89
     });
84
 }
90
 }
85
 
91
 
92
+/**
93
+ * Initialize toolbars.
94
+ */
86
 function setupToolbars() {
95
 function setupToolbars() {
87
     Toolbar.init(eventEmitter);
96
     Toolbar.init(eventEmitter);
88
     Toolbar.setupButtonsFromConfig();
97
     Toolbar.setupButtonsFromConfig();
113
     }
122
     }
114
 }
123
 }
115
 
124
 
125
+/**
126
+ * Notify user that server has shut down.
127
+ */
116
 UI.notifyGracefulShudown = function () {
128
 UI.notifyGracefulShudown = function () {
117
     messageHandler.openMessageDialog(
129
     messageHandler.openMessageDialog(
118
         'dialog.serviceUnavailable',
130
         'dialog.serviceUnavailable',
120
     );
132
     );
121
 };
133
 };
122
 
134
 
135
+/**
136
+ * Notify user that reservation error happened.
137
+ */
123
 UI.notifyReservationError = function (code, msg) {
138
 UI.notifyReservationError = function (code, msg) {
124
     var title = APP.translation.generateTranslationHTML(
139
     var title = APP.translation.generateTranslationHTML(
125
         "dialog.reservationError");
140
         "dialog.reservationError");
135
     );
150
     );
136
 };
151
 };
137
 
152
 
153
+/**
154
+ * Notify user that he has been kicked from the server.
155
+ */
138
 UI.notifyKicked = function () {
156
 UI.notifyKicked = function () {
139
     messageHandler.openMessageDialog("dialog.sessTerminated", "dialog.kickMessage");
157
     messageHandler.openMessageDialog("dialog.sessTerminated", "dialog.kickMessage");
140
 };
158
 };
141
 
159
 
160
+/**
161
+ * Notify user that Jitsi Videobridge is not accessible.
162
+ */
142
 UI.notifyBridgeDown = function () {
163
 UI.notifyBridgeDown = function () {
143
     messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
164
     messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
144
 };
165
 };
145
 
166
 
167
+/**
168
+ * Change nickname for the user.
169
+ * @param {string} id user id
170
+ * @param {string} displayName new nickname
171
+ */
146
 UI.changeDisplayName = function (id, displayName) {
172
 UI.changeDisplayName = function (id, displayName) {
147
     ContactList.onDisplayNameChange(id, displayName);
173
     ContactList.onDisplayNameChange(id, displayName);
148
     SettingsMenu.onDisplayNameChange(id, displayName);
174
     SettingsMenu.onDisplayNameChange(id, displayName);
153
     }
179
     }
154
 };
180
 };
155
 
181
 
182
+/**
183
+ * Intitialize conference UI.
184
+ */
156
 UI.initConference = function () {
185
 UI.initConference = function () {
157
     var id = APP.conference.localId;
186
     var id = APP.conference.localId;
158
     Toolbar.updateRoomUrl(window.location.href);
187
     Toolbar.updateRoomUrl(window.location.href);
186
     VideoLayout.mucJoined();
215
     VideoLayout.mucJoined();
187
 };
216
 };
188
 
217
 
218
+/**
219
+ * Setup some UI event listeners.
220
+ */
189
 function registerListeners() {
221
 function registerListeners() {
190
     UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
222
     UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
191
         UI.setUserAvatar(APP.conference.localId, email);
223
         UI.setUserAvatar(APP.conference.localId, email);
214
     UI.addListener(UIEvents.TOGGLE_FILM_STRIP, UI.toggleFilmStrip);
246
     UI.addListener(UIEvents.TOGGLE_FILM_STRIP, UI.toggleFilmStrip);
215
 }
247
 }
216
 
248
 
249
+/**
250
+ * Setup some DOM event listeners.
251
+ */
217
 function bindEvents() {
252
 function bindEvents() {
218
     function onResize() {
253
     function onResize() {
219
         PanelToggler.resizeChat();
254
         PanelToggler.resizeChat();
341
 };
376
 };
342
 
377
 
343
 
378
 
379
+/**
380
+ * Show local stream on UI.
381
+ * @param {JitsiTrack} track stream to show
382
+ */
344
 UI.addLocalStream = function (track) {
383
 UI.addLocalStream = function (track) {
345
     switch (track.getType()) {
384
     switch (track.getType()) {
346
     case 'audio':
385
     case 'audio':
356
 };
395
 };
357
 
396
 
358
 
397
 
359
-UI.addRemoteStream = function (stream) {
360
-    VideoLayout.onRemoteStreamAdded(stream);
398
+/**
399
+ * Show remote stream on UI.
400
+ * @param {JitsiTrack} track stream to show
401
+ */
402
+UI.addRemoteStream = function (track) {
403
+    VideoLayout.onRemoteStreamAdded(track);
361
 };
404
 };
362
 
405
 
363
 function chatAddError(errorMessage, originalText) {
406
 function chatAddError(errorMessage, originalText) {
364
     return Chat.chatAddError(errorMessage, originalText);
407
     return Chat.chatAddError(errorMessage, originalText);
365
 }
408
 }
366
 
409
 
410
+/**
411
+ * Update chat subject.
412
+ * @param {string} subject new chat subject
413
+ */
367
 UI.setSubject = function (subject) {
414
 UI.setSubject = function (subject) {
368
     Chat.setSubject(subject);
415
     Chat.setSubject(subject);
369
 };
416
 };
370
 
417
 
418
+/**
419
+ * Setup and show Etherpad.
420
+ * @param {string} name etherpad id
421
+ */
371
 UI.initEtherpad = function (name) {
422
 UI.initEtherpad = function (name) {
372
     if (etherpadManager || !config.etherpad_base || !name) {
423
     if (etherpadManager || !config.etherpad_base || !name) {
373
         return;
424
         return;
377
     Toolbar.showEtherpadButton();
428
     Toolbar.showEtherpadButton();
378
 };
429
 };
379
 
430
 
431
+/**
432
+ * Show user on UI.
433
+ * @param {string} id user id
434
+ * @param {string} displayName user nickname
435
+ */
380
 UI.addUser = function (id, displayName) {
436
 UI.addUser = function (id, displayName) {
381
     ContactList.addContact(id);
437
     ContactList.addContact(id);
382
 
438
 
395
     VideoLayout.addParticipantContainer(id);
451
     VideoLayout.addParticipantContainer(id);
396
 };
452
 };
397
 
453
 
454
+/**
455
+ * Remove user from UI.
456
+ * @param {string} id   user id
457
+ * @param {string} displayName user nickname
458
+ */
398
 UI.removeUser = function (id, displayName) {
459
 UI.removeUser = function (id, displayName) {
399
     ContactList.removeContact(id);
460
     ContactList.removeContact(id);
400
 
461
 
415
 //     VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status);
476
 //     VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status);
416
 // }
477
 // }
417
 
478
 
479
+/**
480
+ * Update videotype for specified user.
481
+ * @param {string} id user id
482
+ * @param {string} newVideoType new videotype
483
+ */
418
 UI.onPeerVideoTypeChanged = (id, newVideoType) => {
484
 UI.onPeerVideoTypeChanged = (id, newVideoType) => {
419
     VideoLayout.onVideoTypeChanged(id, newVideoType);
485
     VideoLayout.onVideoTypeChanged(id, newVideoType);
420
 };
486
 };
421
 
487
 
488
+/**
489
+ * Update local user role and show notification if user is moderator.
490
+ * @param {boolean} isModerator if local user is moderator or not
491
+ */
422
 UI.updateLocalRole = function (isModerator) {
492
 UI.updateLocalRole = function (isModerator) {
423
     VideoLayout.showModeratorIndicator();
493
     VideoLayout.showModeratorIndicator();
424
 
494
 
462
 };
532
 };
463
 
533
 
464
 
534
 
535
+/**
536
+ * Toggles smileys in the chat.
537
+ */
465
 UI.toggleSmileys = function () {
538
 UI.toggleSmileys = function () {
466
     Chat.toggleSmileys();
539
     Chat.toggleSmileys();
467
 };
540
 };
468
 
541
 
542
+/**
543
+ * Get current settings.
544
+ * @returns {object} settings
545
+ */
469
 UI.getSettings = function () {
546
 UI.getSettings = function () {
470
     return Settings.getSettings();
547
     return Settings.getSettings();
471
 };
548
 };
472
 
549
 
550
+/**
551
+ * Toggles film strip.
552
+ */
473
 UI.toggleFilmStrip = function () {
553
 UI.toggleFilmStrip = function () {
474
     BottomToolbar.toggleFilmStrip();
554
     BottomToolbar.toggleFilmStrip();
475
 };
555
 };
476
 
556
 
557
+/**
558
+ * Toggles chat panel.
559
+ */
477
 UI.toggleChat = function () {
560
 UI.toggleChat = function () {
478
     PanelToggler.toggleChat();
561
     PanelToggler.toggleChat();
479
 };
562
 };
480
 
563
 
564
+/**
565
+ * Toggles contact list panel.
566
+ */
481
 UI.toggleContactList = function () {
567
 UI.toggleContactList = function () {
482
     PanelToggler.toggleContactList();
568
     PanelToggler.toggleContactList();
483
 };
569
 };
499
     return VideoLayout.showMore(jid);
585
     return VideoLayout.showMore(jid);
500
 };
586
 };
501
 
587
 
588
+// FIXME check if someone user this
502
 UI.showLoginPopup = function(callback) {
589
 UI.showLoginPopup = function(callback) {
503
     console.log('password is required');
590
     console.log('password is required');
504
     var message = '<h2 data-i18n="dialog.passwordRequired">';
591
     var message = '<h2 data-i18n="dialog.passwordRequired">';
569
     ToolbarToggler.dockToolbar(isDock);
656
     ToolbarToggler.dockToolbar(isDock);
570
 };
657
 };
571
 
658
 
659
+/**
660
+ * Update user avatar.
661
+ * @param {string} id user id
662
+ * @param {stirng} email user email
663
+ */
572
 UI.setUserAvatar = function (id, email) {
664
 UI.setUserAvatar = function (id, email) {
573
     // update avatar
665
     // update avatar
574
     Avatar.setUserAvatar(id, email);
666
     Avatar.setUserAvatar(id, email);
582
     }
674
     }
583
 };
675
 };
584
 
676
 
677
+/**
678
+ * Notify user that connection failed.
679
+ * @param {string} stropheErrorMsg raw Strophe error message
680
+ */
585
 UI.notifyConnectionFailed = function (stropheErrorMsg) {
681
 UI.notifyConnectionFailed = function (stropheErrorMsg) {
586
     var title = APP.translation.generateTranslationHTML(
682
     var title = APP.translation.generateTranslationHTML(
587
         "dialog.error");
683
         "dialog.error");
600
     );
696
     );
601
 };
697
 };
602
 
698
 
699
+/**
700
+ * Notify user that he need to install Firefox extension to share screen.
701
+ * @param {stirng} url extension url
702
+ */
603
 UI.notifyFirefoxExtensionRequired = function (url) {
703
 UI.notifyFirefoxExtensionRequired = function (url) {
604
     messageHandler.openMessageDialog(
704
     messageHandler.openMessageDialog(
605
         "dialog.extensionRequired",
705
         "dialog.extensionRequired",
611
     );
711
     );
612
 };
712
 };
613
 
713
 
714
+/**
715
+ * Notify user that he was automatically muted when joned the conference.
716
+ */
614
 UI.notifyInitiallyMuted = function () {
717
 UI.notifyInitiallyMuted = function () {
615
     messageHandler.notify(
718
     messageHandler.notify(
616
         null, "notify.mutedTitle", "connected", "notify.muted", null, {timeOut: 120000}
719
         null, "notify.mutedTitle", "connected", "notify.muted", null, {timeOut: 120000}
617
     );
720
     );
618
 };
721
 };
619
 
722
 
723
+/**
724
+ * Mark user as dominant speaker.
725
+ * @param {string} id user id
726
+ */
620
 UI.markDominantSpeaker = function (id) {
727
 UI.markDominantSpeaker = function (id) {
621
     VideoLayout.onDominantSpeakerChanged(id);
728
     VideoLayout.onDominantSpeakerChanged(id);
622
 };
729
 };
625
     VideoLayout.onLastNEndpointsChanged(ids, []);
732
     VideoLayout.onLastNEndpointsChanged(ids, []);
626
 };
733
 };
627
 
734
 
735
+/**
736
+ * Update audio level visualization for specified user.
737
+ * @param {string} id user id
738
+ * @param {number} lvl audio level
739
+ */
628
 UI.setAudioLevel = function (id, lvl) {
740
 UI.setAudioLevel = function (id, lvl) {
629
     VideoLayout.setAudioLevel(id, lvl);
741
     VideoLayout.setAudioLevel(id, lvl);
630
 };
742
 };
631
 
743
 
744
+/**
745
+ * Update state of desktop sharing buttons.
746
+ * @param {boolean} isSharingScreen if user is currently sharing his screen
747
+ */
632
 UI.updateDesktopSharingButtons = function (isSharingScreen) {
748
 UI.updateDesktopSharingButtons = function (isSharingScreen) {
633
     Toolbar.changeDesktopSharingButtonState(isSharingScreen);
749
     Toolbar.changeDesktopSharingButtonState(isSharingScreen);
634
 };
750
 };
635
 
751
 
752
+/**
753
+ * Hide connection quality statistics from UI.
754
+ */
636
 UI.hideStats = function () {
755
 UI.hideStats = function () {
637
     VideoLayout.hideStats();
756
     VideoLayout.hideStats();
638
 };
757
 };
639
 
758
 
759
+/**
760
+ * Update local connection quality statistics.
761
+ * @param {number} percent
762
+ * @param {object} stats
763
+ */
640
 UI.updateLocalStats = function (percent, stats) {
764
 UI.updateLocalStats = function (percent, stats) {
641
     VideoLayout.updateLocalConnectionStats(percent, stats);
765
     VideoLayout.updateLocalConnectionStats(percent, stats);
642
 };
766
 };
643
 
767
 
768
+/**
769
+ * Update connection quality statistics for remote user.
770
+ * @param {string} id user id
771
+ * @param {number} percent
772
+ * @param {object} stats
773
+ */
644
 UI.updateRemoteStats = function (id, percent, stats) {
774
 UI.updateRemoteStats = function (id, percent, stats) {
645
     VideoLayout.updateConnectionStats(id, percent, stats);
775
     VideoLayout.updateConnectionStats(id, percent, stats);
646
 };
776
 };
647
 
777
 
778
+/**
779
+ * Mark video as interrupted or not.
780
+ * @param {boolean} interrupted if video is interrupted
781
+ */
648
 UI.markVideoInterrupted = function (interrupted) {
782
 UI.markVideoInterrupted = function (interrupted) {
649
     if (interrupted) {
783
     if (interrupted) {
650
         VideoLayout.onVideoInterrupted();
784
         VideoLayout.onVideoInterrupted();
653
     }
787
     }
654
 };
788
 };
655
 
789
 
790
+/**
791
+ * Mark room as locked or not.
792
+ * @param {boolean} locked if room is locked.
793
+ */
656
 UI.markRoomLocked = function (locked) {
794
 UI.markRoomLocked = function (locked) {
657
     if (locked) {
795
     if (locked) {
658
         Toolbar.lockLockButton();
796
         Toolbar.lockLockButton();
661
     }
799
     }
662
 };
800
 };
663
 
801
 
802
+/**
803
+ * Add chat message.
804
+ * @param {string} from user id
805
+ * @param {string} displayName user nickname
806
+ * @param {string} message message text
807
+ * @param {number} stamp timestamp when message was created
808
+ */
664
 UI.addMessage = function (from, displayName, message, stamp) {
809
 UI.addMessage = function (from, displayName, message, stamp) {
665
     Chat.updateChatConversation(from, displayName, message, stamp);
810
     Chat.updateChatConversation(from, displayName, message, stamp);
666
 };
811
 };
672
 
817
 
673
 /**
818
 /**
674
  * Invite participants to conference.
819
  * Invite participants to conference.
820
+ * @param {string} roomUrl
821
+ * @param {string} conferenceName
822
+ * @param {string} key
823
+ * @param {string} nick
675
  */
824
  */
676
 UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) {
825
 UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) {
677
     let keyText = "";
826
     let keyText = "";
710
     window.open(`mailto:?subject=${subject}&body=${body}`, '_blank');
859
     window.open(`mailto:?subject=${subject}&body=${body}`, '_blank');
711
 };
860
 };
712
 
861
 
862
+/**
863
+ * Show user feedback dialog if its required or just show "thank you" dialog.
864
+ * @returns {Promise} when dialog is closed.
865
+ */
713
 UI.requestFeedback = function () {
866
 UI.requestFeedback = function () {
714
     return new Promise(function (resolve, reject) {
867
     return new Promise(function (resolve, reject) {
715
         if (Feedback.isEnabled()) {
868
         if (Feedback.isEnabled()) {
736
     });
889
     });
737
 };
890
 };
738
 
891
 
892
+/**
893
+ * Request recording token from the user.
894
+ * @returns {Promise}
895
+ */
739
 UI.requestRecordingToken = function () {
896
 UI.requestRecordingToken = function () {
740
     let msg = APP.translation.generateTranslationHTML("dialog.recordingToken");
897
     let msg = APP.translation.generateTranslationHTML("dialog.recordingToken");
741
     let token = APP.translation.translateString("dialog.token");
898
     let token = APP.translation.translateString("dialog.token");
769
     messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
926
     messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
770
 };
927
 };
771
 
928
 
929
+/**
930
+ * Updates auth info on the UI.
931
+ * @param {boolean} isAuthEnabled if authentication is enabled
932
+ * @param {string} [login] current login
933
+ */
772
 UI.updateAuthInfo = function (isAuthEnabled, login) {
934
 UI.updateAuthInfo = function (isAuthEnabled, login) {
773
     let loggedIn = !!login;
935
     let loggedIn = !!login;
774
 
936
 
782
     }
944
     }
783
 };
945
 };
784
 
946
 
947
+/**
948
+ * Show Prezi from the user.
949
+ * @param {string} userId user id
950
+ * @param {string} url Prezi url
951
+ * @param {number} slide slide to show
952
+ */
785
 UI.showPrezi = function (userId, url, slide) {
953
 UI.showPrezi = function (userId, url, slide) {
786
     preziManager.showPrezi(userId, url, slide);
954
     preziManager.showPrezi(userId, url, slide);
787
 };
955
 };
788
 
956
 
957
+/**
958
+ * Stop showing Prezi from the user.
959
+ * @param {string} userId user id
960
+ */
789
 UI.stopPrezi = function (userId) {
961
 UI.stopPrezi = function (userId) {
790
   if (preziManager.isSharing(userId)) {
962
   if (preziManager.isSharing(userId)) {
791
       preziManager.removePrezi(userId);
963
       preziManager.removePrezi(userId);
798
 
970
 
799
 /**
971
 /**
800
  * Returns the id of the current video shown on large.
972
  * Returns the id of the current video shown on large.
801
- * Currently used by tests (troture).
973
+ * Currently used by tests (torture).
802
  */
974
  */
803
 UI.getLargeVideoID = function () {
975
 UI.getLargeVideoID = function () {
804
     return VideoLayout.getLargeVideoID();
976
     return VideoLayout.getLargeVideoID();

+ 24
- 0
modules/UI/authentication/AuthHandler.js Zobrazit soubor

10
 let externalAuthWindow;
10
 let externalAuthWindow;
11
 let authRequiredDialog;
11
 let authRequiredDialog;
12
 
12
 
13
+/**
14
+ * Authenticate using external service or just focus
15
+ * external auth window if there is one already.
16
+ *
17
+ * @param {JitsiConference} room
18
+ * @param {string} [lockPassword] password to use if the conference is locked
19
+ */
13
 function doExternalAuth (room, lockPassword) {
20
 function doExternalAuth (room, lockPassword) {
14
     if (externalAuthWindow) {
21
     if (externalAuthWindow) {
15
         externalAuthWindow.focus();
22
         externalAuthWindow.focus();
32
     }
39
     }
33
 }
40
 }
34
 
41
 
42
+/**
43
+ * Authenticate on the server.
44
+ * @param {JitsiConference} room
45
+ * @param {string} [lockPassword] password to use if the conference is locked
46
+ */
35
 function doXmppAuth (room, lockPassword) {
47
 function doXmppAuth (room, lockPassword) {
36
     let loginDialog = LoginDialog.showAuthDialog(function (id, password) {
48
     let loginDialog = LoginDialog.showAuthDialog(function (id, password) {
37
         // auth "on the fly":
49
         // auth "on the fly":
83
     });
95
     });
84
 }
96
 }
85
 
97
 
98
+/**
99
+ * Authenticate for the conference.
100
+ * Uses external service for auth if conference supports that.
101
+ * @param {JitsiConference} room
102
+ * @param {string} [lockPassword] password to use if the conference is locked
103
+ */
86
 function authenticate (room, lockPassword) {
104
 function authenticate (room, lockPassword) {
87
     if (room.isExternalAuthEnabled()) {
105
     if (room.isExternalAuthEnabled()) {
88
         doExternalAuth(room, lockPassword);
106
         doExternalAuth(room, lockPassword);
91
     }
109
     }
92
 }
110
 }
93
 
111
 
112
+/**
113
+ * Notify user that authentication is required to create the conference.
114
+ */
94
 function requireAuth(roomName) {
115
 function requireAuth(roomName) {
95
     if (authRequiredDialog) {
116
     if (authRequiredDialog) {
96
         return;
117
         return;
101
     );
122
     );
102
 }
123
 }
103
 
124
 
125
+/**
126
+ * Close auth-related dialogs if there are any.
127
+ */
104
 function closeAuth() {
128
 function closeAuth() {
105
     if (externalAuthWindow) {
129
     if (externalAuthWindow) {
106
         externalAuthWindow.close();
130
         externalAuthWindow.close();

+ 55
- 7
modules/UI/authentication/LoginDialog.js Zobrazit soubor

2
 
2
 
3
 var messageHandler = require('../util/MessageHandler');
3
 var messageHandler = require('../util/MessageHandler');
4
 
4
 
5
+/**
6
+ * Build html for "password required" dialog.
7
+ * @returns {string} html string
8
+ */
5
 function getPasswordInputHtml() {
9
 function getPasswordInputHtml() {
6
     let placeholder = config.hosts.authdomain
10
     let placeholder = config.hosts.authdomain
7
         ? "user identity"
11
         ? "user identity"
13
         <h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
17
         <h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
14
         <input name="username" type="text" placeholder=${placeholder} autofocus>
18
         <input name="username" type="text" placeholder=${placeholder} autofocus>
15
         <input name="password" type="password"
19
         <input name="password" type="password"
16
-    data-i18n="[placeholder]dialog.userPassword"
17
-    placeholder="user password">
20
+               data-i18n="[placeholder]dialog.userPassword"
21
+               placeholder="user password">
18
         `;
22
         `;
19
 }
23
 }
20
 
24
 
25
+/**
26
+ * Convert provided id to jid if it's not jid yet.
27
+ * @param {string} id user id or jid
28
+ * @returns {string} jid
29
+ */
21
 function toJid(id) {
30
 function toJid(id) {
22
     if (id.indexOf("@") >= 0) {
31
     if (id.indexOf("@") >= 0) {
23
         return id;
32
         return id;
33
     return jid;
42
     return jid;
34
 }
43
 }
35
 
44
 
45
+/**
46
+ * Generate cancel button config for the dialog.
47
+ * @returns {Object}
48
+ */
36
 function cancelButton() {
49
 function cancelButton() {
37
     return {
50
     return {
38
         title: APP.translation.generateTranslationHTML("dialog.Cancel"),
51
         title: APP.translation.generateTranslationHTML("dialog.Cancel"),
40
     };
53
     };
41
 }
54
 }
42
 
55
 
43
-function Dialog(successCallback, cancelCallback) {
56
+/**
57
+ * Auth dialog for JitsiConnection which supports retries.
58
+ * If no cancelCallback provided then there will be
59
+ * no cancel button on the dialog.
60
+ *
61
+ * @class LoginDialog
62
+ * @constructor
63
+ *
64
+ * @param {function(jid, password)} successCallback
65
+ * @param {function} [cancelCallback] callback to invoke if user canceled.
66
+ */
67
+function LoginDialog(successCallback, cancelCallback) {
44
     let loginButtons = [{
68
     let loginButtons = [{
45
         title: APP.translation.generateTranslationHTML("dialog.Ok"),
69
         title: APP.translation.generateTranslationHTML("dialog.Ok"),
46
         value: true
70
         value: true
118
         connDialog.goToState('finished');
142
         connDialog.goToState('finished');
119
     };
143
     };
120
 
144
 
145
+    /**
146
+     *  Show message as connection status.
147
+     * @param {string} message
148
+     */
121
     this.displayConnectionStatus = function (message) {
149
     this.displayConnectionStatus = function (message) {
122
         let connectingState = connDialog.getState('connecting');
150
         let connectingState = connDialog.getState('connecting');
123
 
151
 
133
     };
161
     };
134
 }
162
 }
135
 
163
 
136
-const LoginDialog = {
164
+export default {
137
 
165
 
166
+    /**
167
+     * Show new auth dialog for JitsiConnection.
168
+     *
169
+     * @param {function(jid, password)} successCallback
170
+     * @param {function} [cancelCallback] callback to invoke if user canceled.
171
+     *
172
+     * @returns {LoginDialog}
173
+     */
138
     showAuthDialog: function (successCallback, cancelCallback) {
174
     showAuthDialog: function (successCallback, cancelCallback) {
139
-        return new Dialog(successCallback, cancelCallback);
175
+        return new LoginDialog(successCallback, cancelCallback);
140
     },
176
     },
141
 
177
 
178
+    /**
179
+     * Show notification that external auth is required (using provided url).
180
+     * @param {string} url URL to use for external auth.
181
+     * @param {function} callback callback to invoke when auth popup is closed.
182
+     * @returns auth dialog
183
+     */
142
     showExternalAuthDialog: function (url, callback) {
184
     showExternalAuthDialog: function (url, callback) {
143
         var dialog = messageHandler.openCenteredPopup(
185
         var dialog = messageHandler.openCenteredPopup(
144
             url, 910, 660,
186
             url, 910, 660,
153
         return dialog;
195
         return dialog;
154
     },
196
     },
155
 
197
 
198
+    /**
199
+     * Show notification that authentication is required
200
+     * to create the conference, so he should authenticate or wait for a host.
201
+     * @param {string} roomName name of the conference
202
+     * @param {function} onAuthNow callback to invoke if
203
+     * user want to authenticate.
204
+     * @returns dialog
205
+     */
156
     showAuthRequiredDialog: function (roomName, onAuthNow) {
206
     showAuthRequiredDialog: function (roomName, onAuthNow) {
157
         var title = APP.translation.generateTranslationHTML(
207
         var title = APP.translation.generateTranslationHTML(
158
             "dialog.WaitingForHost"
208
             "dialog.WaitingForHost"
184
         );
234
         );
185
     }
235
     }
186
 };
236
 };
187
-
188
-export default LoginDialog;

+ 48
- 4
modules/UI/authentication/RoomLocker.js Zobrazit soubor

4
 //FIXME:
4
 //FIXME:
5
 import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
5
 import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
6
 
6
 
7
+/**
8
+ * Show dialog which asks user for new password for the conference.
9
+ * @returns {Promise<string>} password or nothing if user canceled
10
+ */
7
 function askForNewPassword () {
11
 function askForNewPassword () {
8
     let passMsg = APP.translation.generateTranslationHTML("dialog.passwordMsg");
12
     let passMsg = APP.translation.generateTranslationHTML("dialog.passwordMsg");
9
     let yourPassMsg = APP.translation.translateString("dialog.yourPassword");
13
     let yourPassMsg = APP.translation.translateString("dialog.yourPassword");
30
     });
34
     });
31
 }
35
 }
32
 
36
 
37
+/**
38
+ * Show dialog which asks for required conference password.
39
+ * @returns {Promise<string>} password or nothing if user canceled
40
+ */
33
 function askForPassword () {
41
 function askForPassword () {
34
     let passRequiredMsg = APP.translation.translateString(
42
     let passRequiredMsg = APP.translation.translateString(
35
         "dialog.passwordRequired"
43
         "dialog.passwordRequired"
58
     });
66
     });
59
 }
67
 }
60
 
68
 
69
+/**
70
+ * Show dialog which asks if user want remove password from the conference.
71
+ * @returns {Promise}
72
+ */
61
 function askToUnlock () {
73
 function askToUnlock () {
62
     return new Promise(function (resolve, reject) {
74
     return new Promise(function (resolve, reject) {
63
         messageHandler.openTwoButtonDialog(
75
         messageHandler.openTwoButtonDialog(
74
     });
86
     });
75
 }
87
 }
76
 
88
 
77
-function notifyPasswordNotSupported (err) {
78
-    console.warn('setting password failed', err);
89
+/**
90
+ * Show notification that user cannot set password for the conference
91
+ * because server doesn't support that.
92
+ */
93
+function notifyPasswordNotSupported () {
94
+    console.warn('room passwords not supported');
79
     messageHandler.showError("dialog.warning", "dialog.passwordNotSupported");
95
     messageHandler.showError("dialog.warning", "dialog.passwordNotSupported");
80
 }
96
 }
81
 
97
 
82
-function notifyPasswordFailed() {
83
-    console.warn('room passwords not supported');
98
+/**
99
+ * Show notification that setting password for the conference failed.
100
+ * @param {Error} err error
101
+ */
102
+function notifyPasswordFailed(err) {
103
+    console.warn('setting password failed', err);
84
     messageHandler.showError("dialog.lockTitle", "dialog.lockMessage");
104
     messageHandler.showError("dialog.lockTitle", "dialog.lockMessage");
85
 }
105
 }
86
 
106
 
87
 const ConferenceErrors = JitsiMeetJS.errors.conference;
107
 const ConferenceErrors = JitsiMeetJS.errors.conference;
88
 
108
 
109
+/**
110
+ * Create new RoomLocker for the conference.
111
+ * It allows to set or remove password for the conference,
112
+ * or ask for required password.
113
+ * @returns {RoomLocker}
114
+ */
89
 export default function createRoomLocker (room) {
115
 export default function createRoomLocker (room) {
90
     let password;
116
     let password;
91
 
117
 
103
         });
129
         });
104
     }
130
     }
105
 
131
 
132
+    /**
133
+     * @class RoomLocker
134
+     */
106
     return {
135
     return {
107
         get isLocked () {
136
         get isLocked () {
108
             return !!password;
137
             return !!password;
112
             return password;
141
             return password;
113
         },
142
         },
114
 
143
 
144
+        /**
145
+         * Allows to remove password from the conference (asks user first).
146
+         * @returns {Promise}
147
+         */
115
         askToUnlock () {
148
         askToUnlock () {
116
             return askToUnlock().then(function () {
149
             return askToUnlock().then(function () {
117
                 return lock();
150
                 return lock();
120
             });
153
             });
121
         },
154
         },
122
 
155
 
156
+        /**
157
+         * Allows to set password for the conference.
158
+         * It asks user for new password and locks the room.
159
+         * @returns {Promise}
160
+         */
123
         askToLock () {
161
         askToLock () {
124
             return askForNewPassword().then(function (newPass) {
162
             return askForNewPassword().then(function (newPass) {
125
                 return lock(newPass);
163
                 return lock(newPass);
128
             });
166
             });
129
         },
167
         },
130
 
168
 
169
+        /**
170
+         * Asks user for required conference password.
171
+         */
131
         requirePassword () {
172
         requirePassword () {
132
             return askForPassword().then(function (newPass) {
173
             return askForPassword().then(function (newPass) {
133
                 password = newPass;
174
                 password = newPass;
134
             });
175
             });
135
         },
176
         },
136
 
177
 
178
+        /**
179
+         * Show notification that to set/remove password user must be moderator.
180
+         */
137
         notifyModeratorRequired () {
181
         notifyModeratorRequired () {
138
             if (password) {
182
             if (password) {
139
                 messageHandler.openMessageDialog(null, "dialog.passwordError");
183
                 messageHandler.openMessageDialog(null, "dialog.passwordError");

+ 22
- 0
modules/UI/etherpad/Etherpad.js Zobrazit soubor

6
 import SidePanelToggler from "../side_pannels/SidePanelToggler";
6
 import SidePanelToggler from "../side_pannels/SidePanelToggler";
7
 import BottomToolbar from '../toolbars/BottomToolbar';
7
 import BottomToolbar from '../toolbars/BottomToolbar';
8
 
8
 
9
+/**
10
+ * Etherpad options.
11
+ */
9
 const options = $.param({
12
 const options = $.param({
10
     showControns: true,
13
     showControns: true,
11
     showChat: false,
14
     showChat: false,
40
     };
43
     };
41
 }
44
 }
42
 
45
 
46
+/**
47
+ * Default Etherpad frame width.
48
+ */
43
 const DEFAULT_WIDTH = 640;
49
 const DEFAULT_WIDTH = 640;
50
+/**
51
+ * Default Etherpad frame height.
52
+ */
44
 const DEFAULT_HEIGHT = 480;
53
 const DEFAULT_HEIGHT = 480;
45
 
54
 
46
 const EtherpadContainerType = "etherpad";
55
 const EtherpadContainerType = "etherpad";
47
 
56
 
57
+/**
58
+ * Container for Etherpad iframe.
59
+ */
48
 class Etherpad extends LargeContainer {
60
 class Etherpad extends LargeContainer {
49
     constructor (domain, name) {
61
     constructor (domain, name) {
50
         super();
62
         super();
123
     }
135
     }
124
 }
136
 }
125
 
137
 
138
+/**
139
+ * Manager of the Etherpad frame.
140
+ */
126
 export default class EtherpadManager {
141
 export default class EtherpadManager {
127
     constructor (domain, name) {
142
     constructor (domain, name) {
128
         if (!domain || !name) {
143
         if (!domain || !name) {
138
         return !!this.etherpad;
153
         return !!this.etherpad;
139
     }
154
     }
140
 
155
 
156
+    /**
157
+     * Create new Etherpad frame.
158
+     */
141
     openEtherpad () {
159
     openEtherpad () {
142
         this.etherpad = new Etherpad(this.domain, this.name);
160
         this.etherpad = new Etherpad(this.domain, this.name);
143
         VideoLayout.addLargeVideoContainer(
161
         VideoLayout.addLargeVideoContainer(
146
         );
164
         );
147
     }
165
     }
148
 
166
 
167
+    /**
168
+     * Toggle Etherpad frame visibility.
169
+     * Open new Etherpad frame if there is no Etherpad frame yet.
170
+     */
149
     toggleEtherpad () {
171
     toggleEtherpad () {
150
         if (!this.isOpen) {
172
         if (!this.isOpen) {
151
             this.openEtherpad();
173
             this.openEtherpad();

+ 71
- 0
modules/UI/prezi/Prezi.js Zobrazit soubor

11
 import SidePanelToggler from "../side_pannels/SidePanelToggler";
11
 import SidePanelToggler from "../side_pannels/SidePanelToggler";
12
 import BottomToolbar from '../toolbars/BottomToolbar';
12
 import BottomToolbar from '../toolbars/BottomToolbar';
13
 
13
 
14
+/**
15
+ * Example of Prezi link.
16
+ */
14
 const defaultPreziLink = "http://prezi.com/wz7vhjycl7e6/my-prezi";
17
 const defaultPreziLink = "http://prezi.com/wz7vhjycl7e6/my-prezi";
15
 const alphanumRegex = /^[a-z0-9-_\/&\?=;]+$/i;
18
 const alphanumRegex = /^[a-z0-9-_\/&\?=;]+$/i;
19
+/**
20
+ * Default aspect ratio for Prezi frame.
21
+ */
16
 const aspectRatio = 16.0 / 9.0;
22
 const aspectRatio = 16.0 / 9.0;
17
 
23
 
24
+/**
25
+ * Default Prezi frame width.
26
+ */
18
 const DEFAULT_WIDTH = 640;
27
 const DEFAULT_WIDTH = 640;
28
+/**
29
+ * Default Prezi frame height.
30
+ */
19
 const DEFAULT_HEIGHT = 480;
31
 const DEFAULT_HEIGHT = 480;
20
 
32
 
21
 /**
33
 /**
22
  * Indicates if the given string is an alphanumeric string.
34
  * Indicates if the given string is an alphanumeric string.
23
  * Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the
35
  * Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the
24
  * purpose of checking URIs.
36
  * purpose of checking URIs.
37
+ * @param {string} unsafeText string to check
38
+ * @returns {boolean}
25
  */
39
  */
26
 function isAlphanumeric(unsafeText) {
40
 function isAlphanumeric(unsafeText) {
27
     return alphanumRegex.test(unsafeText);
41
     return alphanumRegex.test(unsafeText);
29
 
43
 
30
 /**
44
 /**
31
  * Returns the presentation id from the given url.
45
  * Returns the presentation id from the given url.
46
+ * @param {string} url Prezi link
47
+ * @returns {string} presentation id
32
  */
48
  */
33
 function getPresentationId (url) {
49
 function getPresentationId (url) {
34
     let presId = url.substring(url.indexOf("prezi.com/") + 10);
50
     let presId = url.substring(url.indexOf("prezi.com/") + 10);
35
     return presId.substring(0, presId.indexOf('/'));
51
     return presId.substring(0, presId.indexOf('/'));
36
 }
52
 }
37
 
53
 
54
+/**
55
+ * Checks if given string is Prezi url.
56
+ * @param {string} url string to check.
57
+ * @returns {boolean}
58
+ */
38
 function isPreziLink(url) {
59
 function isPreziLink(url) {
39
     if (url.indexOf('http://prezi.com/') !== 0 && url.indexOf('https://prezi.com/') !== 0) {
60
     if (url.indexOf('http://prezi.com/') !== 0 && url.indexOf('https://prezi.com/') !== 0) {
40
         return false;
61
         return false;
48
     return true;
69
     return true;
49
 }
70
 }
50
 
71
 
72
+/**
73
+ * Notify user that other user if already sharing Prezi.
74
+ */
51
 function notifyOtherIsSharingPrezi() {
75
 function notifyOtherIsSharingPrezi() {
52
     messageHandler.openMessageDialog(
76
     messageHandler.openMessageDialog(
53
         "dialog.sharePreziTitle",
77
         "dialog.sharePreziTitle",
55
     );
79
     );
56
 }
80
 }
57
 
81
 
82
+/**
83
+ * Ask user if he want to close Prezi he's sharing.
84
+ */
58
 function proposeToClosePrezi() {
85
 function proposeToClosePrezi() {
59
     return new Promise(function (resolve, reject) {
86
     return new Promise(function (resolve, reject) {
60
         messageHandler.openTwoButtonDialog(
87
         messageHandler.openTwoButtonDialog(
76
     });
103
     });
77
 }
104
 }
78
 
105
 
106
+/**
107
+ * Ask user for Prezi url to share with others.
108
+ * Dialog validates client input to allow only Prezi urls.
109
+ */
79
 function requestPreziLink() {
110
 function requestPreziLink() {
80
     const title = APP.translation.generateTranslationHTML("dialog.sharePreziTitle");
111
     const title = APP.translation.generateTranslationHTML("dialog.sharePreziTitle");
81
     const cancelButton = APP.translation.generateTranslationHTML("dialog.Cancel");
112
     const cancelButton = APP.translation.generateTranslationHTML("dialog.Cancel");
154
 
185
 
155
 export const PreziContainerType = "prezi";
186
 export const PreziContainerType = "prezi";
156
 
187
 
188
+/**
189
+ * Container for Prezi iframe.
190
+ */
157
 class PreziContainer extends LargeContainer {
191
 class PreziContainer extends LargeContainer {
158
 
192
 
159
     constructor ({preziId, isMy, slide, onSlideChanged}) {
193
     constructor ({preziId, isMy, slide, onSlideChanged}) {
187
         });
221
         });
188
     }
222
     }
189
 
223
 
224
+    /**
225
+     * Change Prezi slide.
226
+     * @param {number} slide slide to show
227
+     */
190
     goToSlide (slide) {
228
     goToSlide (slide) {
191
         if (this.preziPlayer.getCurrentStep() === slide) {
229
         if (this.preziPlayer.getCurrentStep() === slide) {
192
             return;
230
             return;
204
         }
242
         }
205
     }
243
     }
206
 
244
 
245
+    /**
246
+     * Show or hide "reload presentation" button.
247
+     * @param {boolean} show
248
+     */
207
     showReloadBtn (show) {
249
     showReloadBtn (show) {
208
         this.reloadBtn.css('display', show ? 'inline-block' : 'none');
250
         this.reloadBtn.css('display', show ? 'inline-block' : 'none');
209
     }
251
     }
256
         this.$iframe.width(width).height(height);
298
         this.$iframe.width(width).height(height);
257
     }
299
     }
258
 
300
 
301
+    /**
302
+     * Close Prezi frame.
303
+     */
259
     close () {
304
     close () {
260
         this.showReloadBtn(false);
305
         this.showReloadBtn(false);
261
         this.preziPlayer.destroy();
306
         this.preziPlayer.destroy();
263
     }
308
     }
264
 }
309
 }
265
 
310
 
311
+/**
312
+ * Manager of Prezi frames.
313
+ */
266
 export default class PreziManager {
314
 export default class PreziManager {
267
     constructor (emitter) {
315
     constructor (emitter) {
268
         this.emitter = emitter;
316
         this.emitter = emitter;
282
         return this.userId === APP.conference.localId;
330
         return this.userId === APP.conference.localId;
283
     }
331
     }
284
 
332
 
333
+    /**
334
+     * Check if user is currently sharing.
335
+     * @param {string} id user id to check for
336
+     */
285
     isSharing (id) {
337
     isSharing (id) {
286
         return this.userId === id;
338
         return this.userId === id;
287
     }
339
     }
302
         }
354
         }
303
     }
355
     }
304
 
356
 
357
+    /**
358
+     * Reload current Prezi frame.
359
+     */
305
     reloadPresentation () {
360
     reloadPresentation () {
306
         if (!this.prezi) {
361
         if (!this.prezi) {
307
             return;
362
             return;
310
         iframe.src = iframe.src;
365
         iframe.src = iframe.src;
311
     }
366
     }
312
 
367
 
368
+    /**
369
+     * Show Prezi. Create new Prezi if there is no Prezi yet.
370
+     * @param {string} id owner id
371
+     * @param {string} url Prezi url
372
+     * @param {number} slide slide to show
373
+     */
313
     showPrezi (id, url, slide) {
374
     showPrezi (id, url, slide) {
314
         if (!this.isPresenting) {
375
         if (!this.isPresenting) {
315
             this.createPrezi(id, url, slide);
376
             this.createPrezi(id, url, slide);
324
         }
385
         }
325
     }
386
     }
326
 
387
 
388
+    /**
389
+     * Create new Prezi frame..
390
+     * @param {string} id owner id
391
+     * @param {string} url Prezi url
392
+     * @param {number} slide slide to show
393
+     */
327
     createPrezi (id, url, slide) {
394
     createPrezi (id, url, slide) {
328
         console.log("presentation added", url);
395
         console.log("presentation added", url);
329
 
396
 
354
         VideoLayout.showLargeVideoContainer(PreziContainerType, true);
421
         VideoLayout.showLargeVideoContainer(PreziContainerType, true);
355
     }
422
     }
356
 
423
 
424
+    /**
425
+     * Close Prezi.
426
+     * @param {string} id owner id
427
+     */
357
     removePrezi (id) {
428
     removePrezi (id) {
358
         if (this.userId !== id) {
429
         if (this.userId !== id) {
359
             throw new Error(`cannot close presentation from ${this.userId} instead of ${id}`);
430
             throw new Error(`cannot close presentation from ${this.userId} instead of ${id}`);

+ 17
- 0
modules/UI/videolayout/LargeContainer.js Zobrazit soubor

1
 
1
 
2
+/**
3
+ * Base class for all Large containers which we can show.
4
+ */
2
 export default class LargeContainer {
5
 export default class LargeContainer {
3
 
6
 
4
     /**
7
     /**
8
+     * Show this container.
5
      * @returns Promise
9
      * @returns Promise
6
      */
10
      */
7
     show () {
11
     show () {
8
     }
12
     }
9
 
13
 
10
     /**
14
     /**
15
+     * Hide this container.
11
      * @returns Promise
16
      * @returns Promise
12
      */
17
      */
13
     hide () {
18
     hide () {
14
     }
19
     }
15
 
20
 
21
+    /**
22
+     * Resize this container.
23
+     * @param {number} containerWidth available width
24
+     * @param {number} containerHeight available height
25
+     * @param {boolean} animate if container should animate it's resize process
26
+     */
16
     resize (containerWidth, containerHeight, animate) {
27
     resize (containerWidth, containerHeight, animate) {
17
     }
28
     }
18
 
29
 
30
+    /**
31
+     * Handler for "hover in" events.
32
+     */
19
     onHoverIn (e) {
33
     onHoverIn (e) {
20
     }
34
     }
21
 
35
 
36
+    /**
37
+     * Handler for "hover out" events.
38
+     */
22
     onHoverOut (e) {
39
     onHoverOut (e) {
23
     }
40
     }
24
 }
41
 }

+ 86
- 1
modules/UI/videolayout/LargeVideo.js Zobrazit soubor

11
 
11
 
12
 const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE;
12
 const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE;
13
 
13
 
14
+/**
15
+ * Get stream id.
16
+ * @param {JitsiTrack?} stream
17
+ */
14
 function getStreamId(stream) {
18
 function getStreamId(stream) {
15
     if(!stream)
19
     if(!stream)
16
         return;
20
         return;
147
 
151
 
148
 export const VideoContainerType = "video";
152
 export const VideoContainerType = "video";
149
 
153
 
154
+/**
155
+ * Container for user video.
156
+ */
150
 class VideoContainer extends LargeContainer {
157
 class VideoContainer extends LargeContainer {
151
     // FIXME: With Temasys we have to re-select everytime
158
     // FIXME: With Temasys we have to re-select everytime
152
     get $video () {
159
     get $video () {
174
         this.$video.on('play', onPlay);
181
         this.$video.on('play', onPlay);
175
     }
182
     }
176
 
183
 
184
+    /**
185
+     * Get size of video element.
186
+     * @returns {{width, height}}
187
+     */
177
     getStreamSize () {
188
     getStreamSize () {
178
         let video = this.$video[0];
189
         let video = this.$video[0];
179
         return {
190
         return {
182
         };
193
         };
183
     }
194
     }
184
 
195
 
196
+    /**
197
+     * Calculate optimal video size for specified container size.
198
+     * @param {number} containerWidth container width
199
+     * @param {number} containerHeight container height
200
+     * @returns {{availableWidth, availableHeight}}
201
+     */
185
     getVideoSize (containerWidth, containerHeight) {
202
     getVideoSize (containerWidth, containerHeight) {
186
         let { width, height } = this.getStreamSize();
203
         let { width, height } = this.getStreamSize();
187
         if (this.stream && this.isScreenSharing()) {
204
         if (this.stream && this.isScreenSharing()) {
197
         }
214
         }
198
     }
215
     }
199
 
216
 
217
+    /**
218
+     * Calculate optimal video position (offset for top left corner)
219
+     * for specified video size and container size.
220
+     * @param {number} width video width
221
+     * @param {number} height video height
222
+     * @param {number} containerWidth container width
223
+     * @param {number} containerHeight container height
224
+     * @returns {{horizontalIndent, verticalIndent}}
225
+     */
200
     getVideoPosition (width, height, containerWidth, containerHeight) {
226
     getVideoPosition (width, height, containerWidth, containerHeight) {
201
         if (this.stream && this.isScreenSharing()) {
227
         if (this.stream && this.isScreenSharing()) {
202
             return getDesktopVideoPosition( width,
228
             return getDesktopVideoPosition( width,
238
         });
264
         });
239
     }
265
     }
240
 
266
 
267
+    /**
268
+     * Update video stream.
269
+     * @param {JitsiTrack?} stream new stream
270
+     * @param {string} videoType video type
271
+     */
241
     setStream (stream, videoType) {
272
     setStream (stream, videoType) {
242
         this.stream = stream;
273
         this.stream = stream;
243
         this.videoType = videoType;
274
         this.videoType = videoType;
250
         });
281
         });
251
     }
282
     }
252
 
283
 
284
+    /**
285
+     * Check if current video stream is screen sharing.
286
+     * @returns {boolean}
287
+     */
253
     isScreenSharing () {
288
     isScreenSharing () {
254
         return this.videoType === 'desktop';
289
         return this.videoType === 'desktop';
255
     }
290
     }
256
 
291
 
292
+    /**
293
+     * Show or hide user avatar.
294
+     * @param {boolean} show
295
+     */
257
     showAvatar (show) {
296
     showAvatar (show) {
258
         this.$avatar.css("visibility", show ? "visible" : "hidden");
297
         this.$avatar.css("visibility", show ? "visible" : "hidden");
259
     }
298
     }
289
     }
328
     }
290
 }
329
 }
291
 
330
 
292
-
331
+/**
332
+ * Manager for all Large containers.
333
+ */
293
 export default class LargeVideoManager {
334
 export default class LargeVideoManager {
294
     constructor () {
335
     constructor () {
295
         this.containers = {};
336
         this.containers = {};
356
         return this.videoContainer.id;
397
         return this.videoContainer.id;
357
     }
398
     }
358
 
399
 
400
+     /**
401
+     * Update large video.
402
+     * Switches to large video even if previously other container was visible.
403
+     * @param {JitsiTrack?} stream new stream
404
+     * @param {string?} videoType new video type
405
+     * @returns {Promise}
406
+     */
359
     updateLargeVideo (smallVideo, videoType, largeVideoUpdatedCallBack) {
407
     updateLargeVideo (smallVideo, videoType, largeVideoUpdatedCallBack) {
360
         let id = getStreamId(smallVideo.stream);
408
         let id = getStreamId(smallVideo.stream);
361
 
409
 
380
         });
428
         });
381
     }
429
     }
382
 
430
 
431
+    /**
432
+     * Update container size optionally taking side bar size into account.
433
+     * @param {boolean} isSideBarVisible if side bar is visible.
434
+     */
383
     updateContainerSize (isSideBarVisible) {
435
     updateContainerSize (isSideBarVisible) {
384
         this.width = UIUtil.getAvailableVideoWidth(isSideBarVisible);
436
         this.width = UIUtil.getAvailableVideoWidth(isSideBarVisible);
385
         this.height = window.innerHeight;
437
         this.height = window.innerHeight;
386
     }
438
     }
387
 
439
 
440
+    /**
441
+     * Resize Large container of specified type.
442
+     * @param {string} type type of container which should be resized.
443
+     * @param {boolean} [animate=false] if resize process should be animated.
444
+     */
388
     resizeContainer (type, animate = false) {
445
     resizeContainer (type, animate = false) {
389
         let container = this.getContainer(type);
446
         let container = this.getContainer(type);
390
         container.resize(this.width, this.height, animate);
447
         container.resize(this.width, this.height, animate);
391
     }
448
     }
392
 
449
 
450
+    /**
451
+     * Resize all Large containers.
452
+     * @param {boolean} animate if resize process should be animated.
453
+     */
393
     resize (animate) {
454
     resize (animate) {
394
         // resize all containers
455
         // resize all containers
395
         Object.keys(this.containers)
456
         Object.keys(this.containers)
420
         $("#dominantSpeakerAvatar").attr('src', avatarUrl);
481
         $("#dominantSpeakerAvatar").attr('src', avatarUrl);
421
     }
482
     }
422
 
483
 
484
+    /**
485
+     * Show avatar on Large video container or not.
486
+     * @param {boolean} show
487
+     */
423
     showAvatar (show) {
488
     showAvatar (show) {
424
         show ? this.videoContainer.hide() : this.videoContainer.show();
489
         show ? this.videoContainer.hide() : this.videoContainer.show();
425
         this.videoContainer.showAvatar(show);
490
         this.videoContainer.showAvatar(show);
426
     }
491
     }
427
 
492
 
493
+    /**
494
+     * Add container of specified type.
495
+     * @param {string} type container type
496
+     * @param {LargeContainer} container container to add.
497
+     */
428
     addContainer (type, container) {
498
     addContainer (type, container) {
429
         if (this.containers[type]) {
499
         if (this.containers[type]) {
430
             throw new Error(`container of type ${type} already exist`);
500
             throw new Error(`container of type ${type} already exist`);
434
         this.resizeContainer(type);
504
         this.resizeContainer(type);
435
     }
505
     }
436
 
506
 
507
+    /**
508
+     * Get Large container of specified type.
509
+     * @param {string} type container type.
510
+     * @returns {LargeContainer}
511
+     */
437
     getContainer (type) {
512
     getContainer (type) {
438
         let container = this.containers[type];
513
         let container = this.containers[type];
439
 
514
 
444
         return container;
519
         return container;
445
     }
520
     }
446
 
521
 
522
+    /**
523
+     * Remove Large container of specified type.
524
+     * @param {string} type container type.
525
+     */
447
     removeContainer (type) {
526
     removeContainer (type) {
448
         if (!this.containers[type]) {
527
         if (!this.containers[type]) {
449
             throw new Error(`container of type ${type} doesn't exist`);
528
             throw new Error(`container of type ${type} doesn't exist`);
452
         delete this.containers[type];
531
         delete this.containers[type];
453
     }
532
     }
454
 
533
 
534
+    /**
535
+     * Show Large container of specified type.
536
+     * Does nothing if such container is already visible.
537
+     * @param {string} type container type.
538
+     * @returns {Promise}
539
+     */
455
     showContainer (type) {
540
     showContainer (type) {
456
         if (this.state === type) {
541
         if (this.state === type) {
457
             return Promise.resolve();
542
             return Promise.resolve();

+ 1
- 1
modules/UI/videolayout/VideoLayout.js Zobrazit soubor

997
                     // update current small video and the old one
997
                     // update current small video and the old one
998
                     smallVideo.updateView();
998
                     smallVideo.updateView();
999
                     oldSmallVideo && oldSmallVideo.updateView();
999
                     oldSmallVideo && oldSmallVideo.updateView();
1000
-                });
1000
+            });
1001
 
1001
 
1002
         } else if (currentId) {
1002
         } else if (currentId) {
1003
             let currentSmallVideo = this.getSmallVideo(currentId);
1003
             let currentSmallVideo = this.getSmallVideo(currentId);

Načítá se…
Zrušit
Uložit