Browse Source

Adds a side panel toggler, settings menu, avatars, uuids.

master
fo 10 years ago
parent
commit
1d4177faeb
23 changed files with 785 additions and 370 deletions
  1. 53
    11
      app.js
  2. 138
    0
      avatar.js
  3. 2
    22
      bottom_toolbar.js
  4. 12
    130
      chat.js
  5. 31
    123
      contact_list.js
  6. 1
    0
      css/contact_list.css
  7. 4
    0
      css/font.css
  8. 1
    6
      css/main.css
  9. 45
    0
      css/settingsmenu.css
  10. 19
    5
      css/videolayout_default.css
  11. BIN
      fonts/jitsi.eot
  12. 1
    0
      fonts/jitsi.svg
  13. BIN
      fonts/jitsi.ttf
  14. BIN
      fonts/jitsi.woff
  15. 42
    7
      fonts/selection.json
  16. 33
    16
      index.html
  17. 3
    1
      interface_config.js
  18. 6
    4
      media_stream.js
  19. 14
    0
      muc.js
  20. 83
    0
      settings_menu.js
  21. 245
    0
      side_panel_toggler.js
  22. 3
    5
      util.js
  23. 49
    40
      videolayout.js

+ 53
- 11
app.js View File

11
 var roomUrl = null;
11
 var roomUrl = null;
12
 var roomName = null;
12
 var roomName = null;
13
 var ssrc2jid = {};
13
 var ssrc2jid = {};
14
-var mediaStreams = [];
14
+var mediaStreams = {};
15
 var bridgeIsDown = false;
15
 var bridgeIsDown = false;
16
 
16
 
17
 /**
17
 /**
99
         localVideo = connection.jingle.localVideo;
99
         localVideo = connection.jingle.localVideo;
100
     }
100
     }
101
     connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
101
     connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
102
-
103
-    if (nickname) {
104
-        connection.emuc.addDisplayNameToPresence(nickname);
102
+    
103
+    var email = SettingsMenu.getEmail();
104
+    var displayName = SettingsMenu.getDisplayName();
105
+    if(email) {
106
+        connection.emuc.addEmailToPresence(email);
107
+    } else {
108
+        connection.emuc.addUserIdToPresence(SettingsMenu.getUID());
109
+    }
110
+    if(displayName) {
111
+        connection.emuc.addDisplayNameToPresence(displayName);
105
     }
112
     }
106
 
113
 
107
     if (connection.disco) {
114
     if (connection.disco) {
335
     // NOTE(gp) now that we have simulcast, a media stream can have more than 1
342
     // NOTE(gp) now that we have simulcast, a media stream can have more than 1
336
     // ssrc. We should probably take that into account in our MediaStream
343
     // ssrc. We should probably take that into account in our MediaStream
337
     // wrapper.
344
     // wrapper.
338
-    mediaStreams.push(new MediaStream(data, sid, thessrc));
345
+    var mediaStream = new MediaStream(data, sid, thessrc);
346
+    var jid = data.peerjid || connection.emuc.myroomjid;
347
+    if(!mediaStreams[jid]) {
348
+        mediaStreams[jid] = {};
349
+    }
350
+    mediaStreams[jid][mediaStream.type] = mediaStream;
339
 
351
 
340
     var container;
352
     var container;
341
     var remotes = document.getElementById('remoteVideos');
353
     var remotes = document.getElementById('remoteVideos');
369
                                             data.stream,
381
                                             data.stream,
370
                                             data.peerjid,
382
                                             data.peerjid,
371
                                             thessrc);
383
                                             thessrc);
384
+        if(isVideo && container.id !== 'mixedstream')
385
+             videoSrcToSsrc[$(container).find('>video')[0].src] = thessrc;
372
     }
386
     }
373
 
387
 
374
     // an attempt to work around https://github.com/jitsi/jitmeet/issues/32
388
     // an attempt to work around https://github.com/jitsi/jitmeet/issues/32
699
     VideoLayout.showFocusIndicator();
713
     VideoLayout.showFocusIndicator();
700
 
714
 
701
     // Add myself to the contact list.
715
     // Add myself to the contact list.
702
-    ContactList.addContact(jid);
716
+    ContactList.addContact(jid, SettingsMenu.getEmail() || SettingsMenu.getUID());
703
 
717
 
704
     // Once we've joined the muc show the toolbar
718
     // Once we've joined the muc show the toolbar
705
     ToolbarToggler.showToolbar();
719
     ToolbarToggler.showToolbar();
721
     console.log('is focus? ' + (focus ? 'true' : 'false'));
735
     console.log('is focus? ' + (focus ? 'true' : 'false'));
722
 
736
 
723
     // Add Peer's container
737
     // Add Peer's container
724
-    VideoLayout.ensurePeerContainerExists(jid);
738
+    var id = $(pres).find('>userID').text();
739
+    var email = $(pres).find('>email');
740
+    if(email.length > 0) {
741
+        id = email.text();
742
+    }
743
+    VideoLayout.ensurePeerContainerExists(jid,id);
725
 
744
 
726
     if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantJoined"))
745
     if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantJoined"))
727
     {
746
     {
879
             "Jitsi Videobridge is currently unavailable. Please try again later!");
898
             "Jitsi Videobridge is currently unavailable. Please try again later!");
880
     }
899
     }
881
 
900
 
901
+    var id = $(pres).find('>userID').text();
902
+    var email = $(pres).find('>email');
903
+    if(email.length > 0) {
904
+        id = email.text();
905
+    }
906
+    Avatar.setUserAvatar(jid, id);
907
+
882
 });
908
 });
883
 
909
 
884
 $(document).bind('presence.status.muc', function (event, jid, info, pres) {
910
 $(document).bind('presence.status.muc', function (event, jid, info, pres) {
1358
         "showMethod": "fadeIn",
1384
         "showMethod": "fadeIn",
1359
         "hideMethod": "fadeOut",
1385
         "hideMethod": "fadeOut",
1360
         "reposition": function() {
1386
         "reposition": function() {
1361
-            if(Chat.isVisible() || ContactList.isVisible()) {
1362
-                $("#toast-container").addClass("toast-bottom-right-center");
1387
+            if(PanelToggler.isVisible()) {
1388
+                $("#toast-container").addClass("notification-bottom-right-center");
1363
             } else {
1389
             } else {
1364
-                $("#toast-container").removeClass("toast-bottom-right-center");
1390
+                $("#toast-container").removeClass("notification-bottom-right-center");
1365
             }
1391
             }
1366
         },
1392
         },
1367
         "newestOnTop": false
1393
         "newestOnTop": false
1368
-    }
1394
+    };
1369
 
1395
 
1396
+    $('#settingsmenu>input').keyup(function(event){
1397
+        if(event.keyCode === 13) {//enter
1398
+            SettingsMenu.update();
1399
+        }
1400
+    })
1370
 
1401
 
1371
 });
1402
 });
1372
 
1403
 
1661
     );
1692
     );
1662
 
1693
 
1663
 }
1694
 }
1695
+
1696
+$(document).on('videomuted.muc', function(event, jid, value) {
1697
+    if(mediaStreams[jid] && mediaStreams[jid][MediaStream.VIDEO_TYPE]) {
1698
+        var stream = mediaStreams[jid][MediaStream.VIDEO_TYPE];
1699
+        var isMuted = (value === "true");
1700
+        if (isMuted != stream.muted) {
1701
+            stream.muted = isMuted;
1702
+            Avatar.showUserAvatar(jid, isMuted);
1703
+        }
1704
+    }
1705
+});

+ 138
- 0
avatar.js View File

1
+var Avatar = (function(my) {
2
+    var users = {};
3
+    var activeSpeakerJid;
4
+    /**
5
+     * Sets the user's avatar in the settings menu(if local user), contact list
6
+     * and thumbnail
7
+     * @param jid jid of the user
8
+     * @param id email or userID to be used as a hash
9
+     */
10
+    my.setUserAvatar = function(jid, id) {
11
+        if(id) {
12
+            if(users[jid] === id) {
13
+                return;
14
+            }
15
+            users[jid] = id;
16
+        }
17
+        var url = getGravatarUrl(users[jid]);
18
+        var resourceJid = Strophe.getResourceFromJid(jid);
19
+        var thumbnail = $('#participant_' + resourceJid);
20
+        var avatar = $('#avatar_' + resourceJid);
21
+
22
+        // set the avatar in the settings menu if it is local user and get the
23
+        // local video container
24
+        if(jid === connection.emuc.myroomjid) {
25
+            $('#avatar').get(0).src = url;
26
+            thumbnail = $('#localVideoContainer');
27
+        }
28
+
29
+        // set the avatar in the contact list
30
+        var contact = $('#' + resourceJid + '>img');
31
+        if(contact && contact.length > 0) {
32
+            contact.get(0).src = url;
33
+        }
34
+
35
+        // set the avatar in the thumbnail
36
+        if(avatar && avatar.length > 0) {
37
+            avatar[0].src = url;
38
+        } else {
39
+            if (thumbnail && thumbnail.length > 0) {
40
+                avatar = document.createElement('img');
41
+                avatar.id = 'avatar_' + resourceJid;
42
+                avatar.className = 'userAvatar';
43
+                avatar.src = url;
44
+                thumbnail.append(avatar);
45
+            }
46
+        }
47
+
48
+        //if the user is the current active speaker - update the active speaker
49
+        // avatar
50
+        if(jid === activeSpeakerJid) {
51
+            Avatar.updateActiveSpeakerAvatarSrc(jid);
52
+        }
53
+    };
54
+
55
+    /**
56
+     * Hides or shows the user's avatar
57
+     * @param jid jid of the user
58
+     * @param show whether we should show the avatar or not
59
+     * video because there is no dominant speaker and no focused speaker
60
+     */
61
+    my.showUserAvatar = function(jid, show) {
62
+        if(users[jid]) {
63
+            var resourceJid = Strophe.getResourceFromJid(jid);
64
+            var video = $('#participant_' + resourceJid + '>video');
65
+            var avatar = $('#avatar_' + resourceJid);
66
+
67
+            if(jid === connection.emuc.myroomjid) {
68
+                video = $('#localVideoWrapper>video');
69
+            }
70
+            if(show === undefined || show === null) {
71
+                show = isUserMuted(jid);
72
+            }
73
+
74
+            //if the user is the currently focused, the dominant speaker or if
75
+            //there is no focused and no dominant speaker
76
+            if (activeSpeakerJid === jid) {
77
+                setVisibility($("#largeVideo"), !show);
78
+                setVisibility($('#activeSpeakerAvatar'), show);
79
+                setVisibility(avatar, false);
80
+                setVisibility(video, false);
81
+            } else {
82
+                if (video && video.length > 0) {
83
+                    setVisibility(video, !show);
84
+                    setVisibility(avatar, show);
85
+                }
86
+            }
87
+        }
88
+    };
89
+
90
+    /**
91
+     * Updates the src of the active speaker avatar
92
+     * @param jid of the current active speaker
93
+     */
94
+    my.updateActiveSpeakerAvatarSrc = function(jid) {
95
+        if(!jid) {
96
+            if (focusedVideoSrc) {
97
+                jid = getJidFromVideoSrc(focusedVideoSrc);
98
+            } else {
99
+                jid = connection.emuc.findJidFromResource(
100
+                    VideoLayout.getDominantSpeakerResourceJid());
101
+            }
102
+        }
103
+        var avatar = $("#activeSpeakerAvatar")[0];
104
+        var url = getGravatarUrl(users[jid],
105
+            interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE);
106
+        if(jid === activeSpeakerJid && avatar.src === url) {
107
+            return;
108
+        }
109
+        activeSpeakerJid = jid;
110
+        var isMuted = isUserMuted(jid);
111
+        if(jid && isMuted !== null) {
112
+            avatar.src = url;
113
+            setVisibility($("#largeVideo"), !isMuted);
114
+            Avatar.showUserAvatar(jid, isMuted);
115
+        }
116
+    };
117
+
118
+    function setVisibility(selector, show) {
119
+        if (selector && selector.length > 0) {
120
+            selector.css("visibility", show ? "visible" : "hidden");
121
+        }
122
+    }
123
+
124
+    function isUserMuted(jid) {
125
+        if(!mediaStreams[jid] || !mediaStreams[jid][MediaStream.VIDEO_TYPE]) {
126
+            return null;
127
+        }
128
+        return mediaStreams[jid][MediaStream.VIDEO_TYPE].muted;
129
+    }
130
+
131
+    function getGravatarUrl(email, size) {
132
+        return 'https://www.gravatar.com/avatar/' +
133
+            (email ? MD5.hexdigest(email.trim().toLowerCase()) : SettingsMenu.getUID()) +
134
+            "?d=retro&size=" + (size || "30");
135
+    }
136
+
137
+    return my;
138
+}(Avatar || {}));

+ 2
- 22
bottom_toolbar.js View File

1
 var BottomToolbar = (function (my) {
1
 var BottomToolbar = (function (my) {
2
     my.toggleChat = function() {
2
     my.toggleChat = function() {
3
-        if (ContactList.isVisible()) {
4
-            buttonClick("#contactListButton", "active");
5
-            $('#contactlist').css('z-index', 4);
6
-            setTimeout(function() {
7
-                $('#contactlist').css('display', 'none');
8
-                $('#contactlist').css('z-index', 5);
9
-            }, 500);
10
-        }
11
-
12
-        Chat.toggleChat();
13
-
14
-        buttonClick("#chatBottomButton", "active");
3
+        PanelToggler.toggleChat();
15
     };
4
     };
16
 
5
 
17
     my.toggleContactList = function() {
6
     my.toggleContactList = function() {
18
-        if (Chat.isVisible()) {
19
-            buttonClick("#chatBottomButton", "active");
20
-            setTimeout(function() {
21
-                $('#chatspace').css('display', 'none');
22
-            }, 500);
23
-        }
24
-
25
-        buttonClick("#contactListButton", "active");
26
-
27
-        ContactList.toggleContactList();
7
+        PanelToggler.toggleContactList();
28
     };
8
     };
29
 
9
 
30
     my.toggleFilmStrip = function() {
10
     my.toggleFilmStrip = function() {

+ 12
- 130
chat.js View File

57
 
57
 
58
         var onTextAreaResize = function () {
58
         var onTextAreaResize = function () {
59
             resizeChatConversation();
59
             resizeChatConversation();
60
-            scrollChatToBottom();
60
+            Chat.scrollChatToBottom();
61
         };
61
         };
62
         $('#usermsg').autosize({callback: onTextAreaResize});
62
         $('#usermsg').autosize({callback: onTextAreaResize});
63
 
63
 
144
         }
144
         }
145
     };
145
     };
146
 
146
 
147
-    /**
148
-     * Opens / closes the chat area.
149
-     */
150
-    my.toggleChat = function () {
151
-        var chatspace = $('#chatspace');
152
-        var videospace = $('#videospace');
153
-
154
-        var chatSize = (Chat.isVisible()) ? [0, 0] : Chat.getChatSize();
155
-        var videospaceWidth = window.innerWidth - chatSize[0];
156
-        var videospaceHeight = window.innerHeight;
157
-        var videoSize
158
-            = getVideoSize(null, null, videospaceWidth, videospaceHeight);
159
-        var videoWidth = videoSize[0];
160
-        var videoHeight = videoSize[1];
161
-        var videoPosition = getVideoPosition(videoWidth,
162
-                                             videoHeight,
163
-                                             videospaceWidth,
164
-                                             videospaceHeight);
165
-        var horizontalIndent = videoPosition[0];
166
-        var verticalIndent = videoPosition[1];
167
-
168
-        var thumbnailSize = VideoLayout.calculateThumbnailSize(videospaceWidth);
169
-        var thumbnailsWidth = thumbnailSize[0];
170
-        var thumbnailsHeight = thumbnailSize[1];
171
-        var completeFunction = Chat.isVisible() ?
172
-            function() {} : function () {
173
-                                scrollChatToBottom();
174
-                                chatspace.trigger('shown');
175
-                            };
176
-
177
-        videospace.animate({right: chatSize[0],
178
-                            width: videospaceWidth,
179
-                            height: videospaceHeight},
180
-                            {queue: false,
181
-                            duration: 500,
182
-                            complete: completeFunction});
183
-
184
-        $('#remoteVideos').animate({height: thumbnailsHeight},
185
-                                    {queue: false,
186
-                                    duration: 500});
187
-
188
-        $('#remoteVideos>span').animate({height: thumbnailsHeight,
189
-                                        width: thumbnailsWidth},
190
-                                        {queue: false,
191
-                                        duration: 500,
192
-                                        complete: function() {
193
-                                            $(document).trigger(
194
-                                                    "remotevideo.resized",
195
-                                                    [thumbnailsWidth,
196
-                                                     thumbnailsHeight]);
197
-                                        }});
198
-
199
-        $('#largeVideoContainer').animate({ width: videospaceWidth,
200
-                                            height: videospaceHeight},
201
-                                            {queue: false,
202
-                                             duration: 500
203
-                                            });
204
-
205
-        $('#largeVideo').animate({  width: videoWidth,
206
-                                    height: videoHeight,
207
-                                    top: verticalIndent,
208
-                                    bottom: verticalIndent,
209
-                                    left: horizontalIndent,
210
-                                    right: horizontalIndent},
211
-                                    {   queue: false,
212
-                                        duration: 500
213
-                                    }
214
-        );
215
-
216
-        if (Chat.isVisible()) {
217
-            $("#toast-container").animate({right: '5px'},
218
-                                {queue: false,
219
-                                duration: 500});
220
-            chatspace.hide("slide", { direction: "right",
221
-                                            queue: false,
222
-                                            duration: 500});
223
 
147
 
224
-        }
225
-        else {
226
-            // Undock the toolbar when the chat is shown and if we're in a 
227
-            // video mode.
228
-            if (VideoLayout.isLargeVideoVisible()) {
229
-                ToolbarToggler.dockToolbar(false);
230
-            }
231
-
232
-
233
-            $("#toast-container").animate({right: (chatSize[0] + 5) + 'px'},
234
-                {queue: false,
235
-                    duration: 500});
236
-            chatspace.show("slide", { direction: "right",
237
-                                            queue: false,
238
-                                            duration: 500,
239
-                                            complete: function () {
240
-                                                // Request the focus in the nickname field or the chat input field.
241
-                                                if ($('#nickname').css('visibility') === 'visible') {
242
-                                                    $('#nickinput').focus();
243
-                                                } else {
244
-                                                    $('#usermsg').focus();
245
-                                                }
246
-                                            }
247
-            });
248
-
249
-            Chat.resizeChat();
250
-        }
251
-
252
-    };
253
 
148
 
254
     /**
149
     /**
255
      * Sets the chat conversation mode.
150
      * Sets the chat conversation mode.
268
      * Resizes the chat area.
163
      * Resizes the chat area.
269
      */
164
      */
270
     my.resizeChat = function () {
165
     my.resizeChat = function () {
271
-        var chatSize = Chat.getChatSize();
166
+        var chatSize = PanelToggler.getPanelSize();
272
 
167
 
273
         $('#chatspace').width(chatSize[0]);
168
         $('#chatspace').width(chatSize[0]);
274
         $('#chatspace').height(chatSize[1]);
169
         $('#chatspace').height(chatSize[1]);
276
         resizeChatConversation();
171
         resizeChatConversation();
277
     };
172
     };
278
 
173
 
279
-    /**
280
-     * Returns the size of the chat.
281
-     */
282
-    my.getChatSize = function () {
283
-        var availableHeight = window.innerHeight;
284
-        var availableWidth = window.innerWidth;
285
-
286
-        var chatWidth = 200;
287
-        if (availableWidth * 0.2 < 200)
288
-            chatWidth = availableWidth * 0.2;
289
-
290
-        return [chatWidth, availableHeight];
291
-    };
292
-
293
     /**
174
     /**
294
      * Indicates if the chat is currently visible.
175
      * Indicates if the chat is currently visible.
295
      */
176
      */
309
         $('#usermsg').focus();
190
         $('#usermsg').focus();
310
     };
191
     };
311
 
192
 
193
+    /**
194
+     * Scrolls chat to the bottom.
195
+     */
196
+    my.scrollChatToBottom = function() {
197
+        setTimeout(function () {
198
+            $('#chatconversation').scrollTop(
199
+                $('#chatconversation')[0].scrollHeight);
200
+        }, 5);
201
+    };
202
+
312
     /**
203
     /**
313
      * Adds the smileys container to the chat
204
      * Adds the smileys container to the chat
314
      */
205
      */
426
         }
317
         }
427
     }
318
     }
428
 
319
 
429
-    /**
430
-     * Scrolls chat to the bottom.
431
-     */
432
-    function scrollChatToBottom() {
433
-        setTimeout(function () {
434
-            $('#chatconversation').scrollTop(
435
-                    $('#chatconversation')[0].scrollHeight);
436
-        }, 5);
437
-    }
438
 
320
 
439
     /**
321
     /**
440
      * Returns the current time in the format it is shown to the user
322
      * Returns the current time in the format it is shown to the user

+ 31
- 123
contact_list.js View File

20
      * Adds a contact for the given peerJid if such doesn't yet exist.
20
      * Adds a contact for the given peerJid if such doesn't yet exist.
21
      *
21
      *
22
      * @param peerJid the peerJid corresponding to the contact
22
      * @param peerJid the peerJid corresponding to the contact
23
+     * @param id the user's email or userId used to get the user's avatar
23
      */
24
      */
24
-    my.ensureAddContact = function(peerJid) {
25
+    my.ensureAddContact = function(peerJid, id) {
25
         var resourceJid = Strophe.getResourceFromJid(peerJid);
26
         var resourceJid = Strophe.getResourceFromJid(peerJid);
26
 
27
 
27
         var contact = $('#contactlist>ul>li[id="' + resourceJid + '"]');
28
         var contact = $('#contactlist>ul>li[id="' + resourceJid + '"]');
28
 
29
 
29
         if (!contact || contact.length <= 0)
30
         if (!contact || contact.length <= 0)
30
-            ContactList.addContact(peerJid);
31
+            ContactList.addContact(peerJid,id);
31
     };
32
     };
32
 
33
 
33
     /**
34
     /**
34
      * Adds a contact for the given peer jid.
35
      * Adds a contact for the given peer jid.
35
      *
36
      *
36
      * @param peerJid the jid of the contact to add
37
      * @param peerJid the jid of the contact to add
38
+     * @param id the email or userId of the user
37
      */
39
      */
38
-    my.addContact = function(peerJid) {
40
+    my.addContact = function(peerJid, id) {
39
         var resourceJid = Strophe.getResourceFromJid(peerJid);
41
         var resourceJid = Strophe.getResourceFromJid(peerJid);
40
 
42
 
41
         var contactlist = $('#contactlist>ul');
43
         var contactlist = $('#contactlist>ul');
51
             }
53
             }
52
         };
54
         };
53
 
55
 
54
-        newContact.appendChild(createAvatar());
56
+        newContact.appendChild(createAvatar(id));
55
         newContact.appendChild(createDisplayNameParagraph("Participant"));
57
         newContact.appendChild(createDisplayNameParagraph("Participant"));
56
 
58
 
57
         var clElement = contactlist.get(0);
59
         var clElement = contactlist.get(0);
87
         }
89
         }
88
     };
90
     };
89
 
91
 
90
-    /**
91
-     * Opens / closes the contact list area.
92
-     */
93
-    my.toggleContactList = function () {
94
-        var contactlist = $('#contactlist');
95
-        var videospace = $('#videospace');
96
-
97
-        var chatSize = (ContactList.isVisible()) ? [0, 0] : Chat.getChatSize();
98
-        var videospaceWidth = window.innerWidth - chatSize[0];
99
-        var videospaceHeight = window.innerHeight;
100
-        var videoSize
101
-            = getVideoSize(null, null, videospaceWidth, videospaceHeight);
102
-        var videoWidth = videoSize[0];
103
-        var videoHeight = videoSize[1];
104
-        var videoPosition = getVideoPosition(videoWidth,
105
-                                             videoHeight,
106
-                                             videospaceWidth,
107
-                                             videospaceHeight);
108
-        var horizontalIndent = videoPosition[0];
109
-        var verticalIndent = videoPosition[1];
110
-
111
-        var thumbnailSize = VideoLayout.calculateThumbnailSize(videospaceWidth);
112
-        var thumbnailsWidth = thumbnailSize[0];
113
-        var thumbnailsHeight = thumbnailSize[1];
114
-        var completeFunction = ContactList.isVisible() ?
115
-            function() {} : function () { contactlist.trigger('shown');};
116
-
117
-        videospace.animate({right: chatSize[0],
118
-                            width: videospaceWidth,
119
-                            height: videospaceHeight},
120
-                            {queue: false,
121
-                            duration: 500,
122
-                            complete: completeFunction
123
-                            });
124
-
125
-        $('#remoteVideos').animate({height: thumbnailsHeight},
126
-                                    {queue: false,
127
-                                    duration: 500});
128
-
129
-        $('#remoteVideos>span').animate({height: thumbnailsHeight,
130
-                                        width: thumbnailsWidth},
131
-                                        {queue: false,
132
-                                        duration: 500,
133
-                                        complete: function() {
134
-                                            $(document).trigger(
135
-                                                    "remotevideo.resized",
136
-                                                    [thumbnailsWidth,
137
-                                                     thumbnailsHeight]);
138
-                                        }});
139
-
140
-        $('#largeVideoContainer').animate({ width: videospaceWidth,
141
-                                            height: videospaceHeight},
142
-                                            {queue: false,
143
-                                             duration: 500
144
-                                            });
145
-
146
-        $('#largeVideo').animate({  width: videoWidth,
147
-                                    height: videoHeight,
148
-                                    top: verticalIndent,
149
-                                    bottom: verticalIndent,
150
-                                    left: horizontalIndent,
151
-                                    right: horizontalIndent},
152
-                                    {   queue: false,
153
-                                        duration: 500
154
-                                    });
155
-
156
-        if (ContactList.isVisible()) {
157
-            $("#toast-container").animate({right: '12px'},
158
-                {queue: false,
159
-                    duration: 500});
160
-            $('#contactlist').hide("slide", { direction: "right",
161
-                                            queue: false,
162
-                                            duration: 500});
163
-        } else {
164
-            // Undock the toolbar when the chat is shown and if we're in a 
165
-            // video mode.
166
-            if (VideoLayout.isLargeVideoVisible())
167
-                ToolbarToggler.dockToolbar(false);
168
-
169
-
170
-            $("#toast-container").animate({right: '212px'},
171
-                {queue: false,
172
-                    duration: 500});
173
-            $('#contactlist').show("slide", { direction: "right",
174
-                                            queue: false,
175
-                                            duration: 500});
92
+    my.setVisualNotification = function(show, stopGlowingIn) {
93
+        var glower = $('#contactListButton');
94
+        function stopGlowing() {
95
+            window.clearInterval(notificationInterval);
96
+            notificationInterval = false;
97
+            glower.removeClass('glowing');
98
+            if(!ContactList.isVisible()) {
99
+                glower.removeClass('active');
100
+            }
101
+        }
176
 
102
 
177
-            //stop the glowing of the contact list icon
178
-            setVisualNotification(false);
103
+        if (show && !notificationInterval) {
104
+            notificationInterval = window.setInterval(function () {
105
+                glower.toggleClass('active glowing');
106
+            }, 800);
107
+        }
108
+        else if (!show && notificationInterval) {
109
+            stopGlowing();
110
+        }
111
+        if(stopGlowingIn) {
112
+            setTimeout(stopGlowing, stopGlowingIn);
179
         }
113
         }
180
     };
114
     };
181
 
115
 
191
             $("#numberOfParticipants").text('');
125
             $("#numberOfParticipants").text('');
192
             numberOfContacts += delta;
126
             numberOfContacts += delta;
193
         } else if(numberOfContacts !== 0 && !ContactList.isVisible()) {
127
         } else if(numberOfContacts !== 0 && !ContactList.isVisible()) {
194
-            setVisualNotification(true);
128
+            ContactList.setVisualNotification(true);
195
             numberOfContacts += delta;
129
             numberOfContacts += delta;
196
             $("#numberOfParticipants").text(numberOfContacts);
130
             $("#numberOfParticipants").text(numberOfContacts);
197
         }
131
         }
198
-    };
132
+    }
199
 
133
 
200
     /**
134
     /**
201
      * Creates the avatar element.
135
      * Creates the avatar element.
202
      * 
136
      * 
203
      * @return the newly created avatar element
137
      * @return the newly created avatar element
204
      */
138
      */
205
-    function createAvatar() {
206
-        var avatar = document.createElement('i');
139
+    function createAvatar(id) {
140
+        var avatar = document.createElement('img');
207
         avatar.className = "icon-avatar avatar";
141
         avatar.className = "icon-avatar avatar";
142
+        avatar.src = "https://www.gravatar.com/avatar/" + id + "?d=retro&size=30";
208
 
143
 
209
         return avatar;
144
         return avatar;
210
     }
145
     }
221
         return p;
156
         return p;
222
     }
157
     }
223
 
158
 
224
-    /**
225
-     * Shows/hides a visual notification, indicating that a new user has joined
226
-     * the conference.
227
-     */
228
-    function setVisualNotification(show, stopGlowingIn) {
229
-        var glower = $('#contactListButton');
230
-        function stopGlowing() {
231
-            window.clearInterval(notificationInterval);
232
-            notificationInterval = false;
233
-            glower.removeClass('glowing');
234
-            if(!ContactList.isVisible()) {
235
-                glower.removeClass('active');
236
-            }
237
-        }
238
-
239
-        if (show && !notificationInterval) {
240
-            notificationInterval = window.setInterval(function () {
241
-                glower.toggleClass('active glowing');
242
-            }, 800);
243
-        }
244
-        else if (!show && notificationInterval) {
245
-            stopGlowing();
246
-        }
247
-        if(stopGlowingIn) {
248
-            setTimeout(stopGlowing, stopGlowingIn);
249
-        }
250
-    }
251
 
159
 
252
     /**
160
     /**
253
      * Indicates that the display name has changed.
161
      * Indicates that the display name has changed.

+ 1
- 0
css/contact_list.css View File

34
     margin-right: 10px;
34
     margin-right: 10px;
35
     vertical-align: middle;
35
     vertical-align: middle;
36
     font-size: 22pt;
36
     font-size: 22pt;
37
+    border-radius: 20px;
37
 }
38
 }
38
 
39
 
39
 #contactlist .clickable {
40
 #contactlist .clickable {

+ 4
- 0
css/font.css View File

112
 .icon-connection:before {
112
 .icon-connection:before {
113
     line-height: normal;
113
     line-height: normal;
114
     content: "\e61a";
114
     content: "\e61a";
115
+}
116
+
117
+.icon-settings:before {
118
+    content: "\e61b";
115
 }
119
 }

+ 1
- 6
css/main.css View File

13
     overflow-x: hidden;
13
     overflow-x: hidden;
14
 }
14
 }
15
 
15
 
16
-#chatspace,
17
-#contactlist {
16
+.right-panel {
18
     display:none;
17
     display:none;
19
     position:absolute;
18
     position:absolute;
20
     float: right;
19
     float: right;
38
     display:none;
37
     display:none;
39
 }
38
 }
40
 
39
 
41
-#settingsButton {
42
-    visibility: hidden;
43
-}
44
-
45
 .toolbar_span {
40
 .toolbar_span {
46
     display: inline-block;
41
     display: inline-block;
47
     position: relative;
42
     position: relative;

+ 45
- 0
css/settingsmenu.css View File

1
+#settingsmenu {
2
+    background: black;
3
+    color: #00ccff;
4
+}
5
+
6
+#settingsmenu input {
7
+    margin-top: 10px;
8
+    margin-left: 10%;
9
+    width: 80%;
10
+    font-size: 14px;
11
+    background: #3a3a3a;
12
+    border: none;
13
+    box-shadow: none;
14
+    color: #a7a7a7;
15
+}
16
+
17
+#settingsmenu .arrow-up {
18
+    width: 0;
19
+    height: 0;
20
+    border-left: 5px solid transparent;
21
+    border-right: 5px solid transparent;
22
+    border-bottom: 5px solid #3a3a3a;
23
+    position: relative;
24
+    top: 10px;
25
+    margin-left: auto;
26
+    margin-right: auto;
27
+}
28
+
29
+#settingsmenu button {
30
+    width: 36%;
31
+    left: 32%;
32
+    padding: 0;
33
+    margin-top: 10px;
34
+}
35
+
36
+#settingsmenu #avatar {
37
+    width: 24%;
38
+    left: 38%;
39
+    border-radius: 25px;
40
+    position: relative;
41
+}
42
+
43
+#settingsmenu .icon-settings {
44
+    padding: 34px;
45
+}

+ 19
- 5
css/videolayout_default.css View File

35
 
35
 
36
 #remoteVideos .videocontainer {
36
 #remoteVideos .videocontainer {
37
     display: inline-block;
37
     display: inline-block;
38
-    background-image:url(../images/avatar1.png);
38
+    background-color: black;
39
+    background-repeat: no-repeat;
40
+    background-position: 45;
39
     background-size: contain;
41
     background-size: contain;
40
     border-radius:8px;
42
     border-radius:8px;
41
     border: 2px solid #212425;
43
     border: 2px solid #212425;
115
     height: 100%;
117
     height: 100%;
116
 }
118
 }
117
 
119
 
118
-.dominantspeaker {
119
-    background: #000 !important;
120
-}
121
-
122
 #etherpad,
120
 #etherpad,
123
 #presentation {
121
 #presentation {
124
     text-align: center;
122
     text-align: center;
378
 #mixedstream {
376
 #mixedstream {
379
     display:none !important;
377
     display:none !important;
380
 }
378
 }
379
+
380
+#activeSpeakerAvatar {
381
+    visibility: hidden;
382
+    width: 100px;
383
+    height: 100px;
384
+    margin: auto;
385
+    position: relative;
386
+    border-radius: 50px;
387
+}
388
+
389
+.userAvatar {
390
+    height: 100%;
391
+    position: absolute;
392
+    left: 35px;
393
+    border-radius: 200px;
394
+}

BIN
fonts/jitsi.eot View File


+ 1
- 0
fonts/jitsi.svg View File

34
 <glyph unicode="&#xe618;" d="M797.086 112.301c-0.059 0.163-0.119 0.328-0.16 0.485-71.399-45.638-151.782-69.931-234.023-69.931-0.013 0-0.021 0-0.028 0-122.52 0-237.501 52.772-315.469 144.741-99.778 117.698-134.252 329.954-73.022 427.789 4.004-1.662 7.875-3.233 11.68-4.773 13.585-5.511 26.413-10.716 42.305-19.096 6.063-3.202 12.338-4.812 18.673-4.812 11.714 0 22.6 5.648 29.848 15.486 7.815 10.617 10.313 24.778 6.538 36.951l-3.525 11.41c-10.687 34.59-21.723 70.354-34.211 105.078-9.983 27.765-22.399 62.327-59.226 62.327-12.057 0-26.037-3.656-46.73-12.204-44.294-18.319-71.058-29.961-114.534-49.81-15.102-6.887-25.234-22.698-25.203-39.343 0.028-15.842 8.992-29.337 23.975-36.115 18.208-8.257 30.536-13.716 43.468-19.447l10.687-4.753c-101.938-259.102 24.803-526.458 211.314-639.212 83.497-50.474 178.5-77.14 274.769-77.14h0.041c102.72 0 205.561 31.099 284.501 85.198-31.729 28.803-45.566 69.167-51.671 87.171zM1098.203 210.090c-18.113 8.577-30.356 14.258-43.221 20.244l-10.496 4.892c106.448 257.268-15.569 526.801-200.067 642.788-85.36 53.663-183.123 82.032-282.716 82.032-104.848 0-206.41-30.593-285.967-86.165l-5.385-3.764c31.597-27.564 45.86-66.788 52.917-86.41 72.926 47.94 155.675 73.409 239.895 73.409 125.407 0 242.142-54.785 320.294-150.316 97.683-119.447 128.439-332.255 65.498-429.015-3.989 1.736-7.815 3.385-11.624 4.998-13.471 5.759-26.204 11.18-41.954 19.821-6.203 3.424-12.645 5.155-19.212 5.155-11.585 0-22.399-5.558-29.69-15.267-7.813-10.434-10.478-24.432-6.966-36.515l3.279-11.301c10.096-34.845 20.531-70.857 32.412-105.842 9.588-28.238 21.514-63.382 59.179-63.382 11.843 0 25.577 3.424 45.881 11.399 44.351 17.439 71.319 28.601 115.409 47.777 15.19 6.623 25.601 22.252 25.859 38.894 0.281 15.822-8.445 29.499-23.325 36.569z" horiz-adv-x="1122" />
34
 <glyph unicode="&#xe618;" d="M797.086 112.301c-0.059 0.163-0.119 0.328-0.16 0.485-71.399-45.638-151.782-69.931-234.023-69.931-0.013 0-0.021 0-0.028 0-122.52 0-237.501 52.772-315.469 144.741-99.778 117.698-134.252 329.954-73.022 427.789 4.004-1.662 7.875-3.233 11.68-4.773 13.585-5.511 26.413-10.716 42.305-19.096 6.063-3.202 12.338-4.812 18.673-4.812 11.714 0 22.6 5.648 29.848 15.486 7.815 10.617 10.313 24.778 6.538 36.951l-3.525 11.41c-10.687 34.59-21.723 70.354-34.211 105.078-9.983 27.765-22.399 62.327-59.226 62.327-12.057 0-26.037-3.656-46.73-12.204-44.294-18.319-71.058-29.961-114.534-49.81-15.102-6.887-25.234-22.698-25.203-39.343 0.028-15.842 8.992-29.337 23.975-36.115 18.208-8.257 30.536-13.716 43.468-19.447l10.687-4.753c-101.938-259.102 24.803-526.458 211.314-639.212 83.497-50.474 178.5-77.14 274.769-77.14h0.041c102.72 0 205.561 31.099 284.501 85.198-31.729 28.803-45.566 69.167-51.671 87.171zM1098.203 210.090c-18.113 8.577-30.356 14.258-43.221 20.244l-10.496 4.892c106.448 257.268-15.569 526.801-200.067 642.788-85.36 53.663-183.123 82.032-282.716 82.032-104.848 0-206.41-30.593-285.967-86.165l-5.385-3.764c31.597-27.564 45.86-66.788 52.917-86.41 72.926 47.94 155.675 73.409 239.895 73.409 125.407 0 242.142-54.785 320.294-150.316 97.683-119.447 128.439-332.255 65.498-429.015-3.989 1.736-7.815 3.385-11.624 4.998-13.471 5.759-26.204 11.18-41.954 19.821-6.203 3.424-12.645 5.155-19.212 5.155-11.585 0-22.399-5.558-29.69-15.267-7.813-10.434-10.478-24.432-6.966-36.515l3.279-11.301c10.096-34.845 20.531-70.857 32.412-105.842 9.588-28.238 21.514-63.382 59.179-63.382 11.843 0 25.577 3.424 45.881 11.399 44.351 17.439 71.319 28.601 115.409 47.777 15.19 6.623 25.601 22.252 25.859 38.894 0.281 15.822-8.445 29.499-23.325 36.569z" horiz-adv-x="1122" />
35
 <glyph unicode="&#xe619;" d="M46.993 961.7c461.234 0 553.793 0 1015.024 0 35.919 0 53.356-25.959 53.356-57.959-0.581-303.259-0.325-606.488-0.449-909.809 0-43.984-13.203-57.058-57.703-57.058-443.072-0.126-556.453-0.126-999.553 0-44.534 0-57.799 13.009-57.799 57.058-0.098 303.257 0.485 608.072-0.093 911.329-0.034 26.21 11.301 53.761 47.217 56.439zM311.405 450.298c0-119.045-0.072-172.168 0.057-291.249 0.036-50.043 11.208-61.050 62.12-61.050 233.352 0 137.075 0 370.522 0 47.075 0 59.249 11.982 59.249 58.095 0.126 239.111 0.126 346.338 0 585.389 0 48.138-10.687 58.991-57.768 58.991-235.323 0.101-140.844 0.101-376.157 0-47.044 0-57.93-11.043-57.966-58.89-0.129-119.109-0.057-172.209-0.057-291.287zM153.944 838.566c-74.929-0.062-66.687 5.958-66.845-66.685-0.201-63.95-7.054-63.534 62.528-63.372 72.999 0.194 67.201-3.764 67.302 67.554 0 67.722 4.087 62.595-62.985 62.502zM963.644 838.566c-71.159-0.034-65.56 6.185-65.751-65.364-0.129-67.302-4.508-64.693 64.528-64.693 73.089 0 65.299-2.031 65.299 66.238-0.003 68.646 6.956 63.911-64.076 63.818zM216.828 122.408c0.359 73.094 4.639 66.914-67.358 67.17-68.104 0.191-62.569 2.763-62.407-63.31 0.129-73.476-6.954-66.52 67.074-66.649 66.042-0.065 63.142-6.056 62.691 62.789zM1027.718 124.4c0.134 68.334 6.443 65.304-63.297 65.178-70.132-0.132-66.656 5.793-66.527-65.304 0.129-70.645-4.384-64.721 63.756-64.657 71.995 0.132 66.202-6.698 66.068 64.783zM1027.718 342.077c0 70.55 7.219 66.842-67.485 66.522-0.898 0-1.873 0-2.838 0-59.375 0-59.375 0-59.375-58.023 0-77.922-6.443-69.936 69.293-70.196 66.076-0.387 60.539-3.091 60.405 61.697zM151.307 489.873c68.295-0.163 65.815-5.568 65.624 62.982-0.194 71.128 4.895 64.917-66.014 65.010-69.905 0.101-63.813 4.704-63.885-63.978-0.062-67.431-5.7-64.463 64.275-64.014zM961.263 489.873c72.511-0.258 66.589-4.603 66.455 64.494 0 68.558 6.185 63.537-64.267 63.498-70.196-0.028-65.686 6.053-65.498-65.493 0.132-62.5 0.067-62.5 63.31-62.5zM150.399 280.38c71.004 0 66.659-6.567 66.466 64.528-0.163 63.694-0.036 63.501-65.013 63.756-70.805 0.258-64.822 2.673-64.822-63.756 0.036-69.167-5.919-64.788 63.369-64.528z" horiz-adv-x="1115" />
35
 <glyph unicode="&#xe619;" d="M46.993 961.7c461.234 0 553.793 0 1015.024 0 35.919 0 53.356-25.959 53.356-57.959-0.581-303.259-0.325-606.488-0.449-909.809 0-43.984-13.203-57.058-57.703-57.058-443.072-0.126-556.453-0.126-999.553 0-44.534 0-57.799 13.009-57.799 57.058-0.098 303.257 0.485 608.072-0.093 911.329-0.034 26.21 11.301 53.761 47.217 56.439zM311.405 450.298c0-119.045-0.072-172.168 0.057-291.249 0.036-50.043 11.208-61.050 62.12-61.050 233.352 0 137.075 0 370.522 0 47.075 0 59.249 11.982 59.249 58.095 0.126 239.111 0.126 346.338 0 585.389 0 48.138-10.687 58.991-57.768 58.991-235.323 0.101-140.844 0.101-376.157 0-47.044 0-57.93-11.043-57.966-58.89-0.129-119.109-0.057-172.209-0.057-291.287zM153.944 838.566c-74.929-0.062-66.687 5.958-66.845-66.685-0.201-63.95-7.054-63.534 62.528-63.372 72.999 0.194 67.201-3.764 67.302 67.554 0 67.722 4.087 62.595-62.985 62.502zM963.644 838.566c-71.159-0.034-65.56 6.185-65.751-65.364-0.129-67.302-4.508-64.693 64.528-64.693 73.089 0 65.299-2.031 65.299 66.238-0.003 68.646 6.956 63.911-64.076 63.818zM216.828 122.408c0.359 73.094 4.639 66.914-67.358 67.17-68.104 0.191-62.569 2.763-62.407-63.31 0.129-73.476-6.954-66.52 67.074-66.649 66.042-0.065 63.142-6.056 62.691 62.789zM1027.718 124.4c0.134 68.334 6.443 65.304-63.297 65.178-70.132-0.132-66.656 5.793-66.527-65.304 0.129-70.645-4.384-64.721 63.756-64.657 71.995 0.132 66.202-6.698 66.068 64.783zM1027.718 342.077c0 70.55 7.219 66.842-67.485 66.522-0.898 0-1.873 0-2.838 0-59.375 0-59.375 0-59.375-58.023 0-77.922-6.443-69.936 69.293-70.196 66.076-0.387 60.539-3.091 60.405 61.697zM151.307 489.873c68.295-0.163 65.815-5.568 65.624 62.982-0.194 71.128 4.895 64.917-66.014 65.010-69.905 0.101-63.813 4.704-63.885-63.978-0.062-67.431-5.7-64.463 64.275-64.014zM961.263 489.873c72.511-0.258 66.589-4.603 66.455 64.494 0 68.558 6.185 63.537-64.267 63.498-70.196-0.028-65.686 6.053-65.498-65.493 0.132-62.5 0.067-62.5 63.31-62.5zM150.399 280.38c71.004 0 66.659-6.567 66.466 64.528-0.163 63.694-0.036 63.501-65.013 63.756-70.805 0.258-64.822 2.673-64.822-63.756 0.036-69.167-5.919-64.788 63.369-64.528z" horiz-adv-x="1115" />
36
 <glyph unicode="&#xe61a;" d="M3.881 146.835h220.26v-210.835h-220.26v210.835zM308.817 350.143h220.27v-414.143h-220.27v414.143zM613.764 553.412h220.268v-617.412h-220.268v617.412zM918.685 756.715h220.265v-820.715h-220.265v820.715zM1223.629 960h220.263v-1024h-220.263v1024z" horiz-adv-x="1444" />
36
 <glyph unicode="&#xe61a;" d="M3.881 146.835h220.26v-210.835h-220.26v210.835zM308.817 350.143h220.27v-414.143h-220.27v414.143zM613.764 553.412h220.268v-617.412h-220.268v617.412zM918.685 756.715h220.265v-820.715h-220.265v820.715zM1223.629 960h220.263v-1024h-220.263v1024z" horiz-adv-x="1444" />
37
+<glyph unicode="&#xe61b;" d="M526.071 234.749c-28.637-30.869-56.465-60.861-84.282-90.859-51.578-55.636-103.047-111.376-154.842-166.832-7.606-8.135-15.958-16.1-25.317-22.012-28.075-17.708-58.31-18.090-88.472-6.492-59.84 23.028-80.004 90.727-59.734 139.234 5.413 12.95 13.721 23.601 23.709 33.173 70.256 67.351 140.506 134.717 210.76 202.077 15.638 14.993 31.264 29.995 47.364 45.45-9.302 9.529-18.386 18.833-27.451 28.137-12.122 12.442-13.234 20.28-5.067 35.498 4.735 8.816 4.789 8.878-2.627 16.198-20.012 19.72-40.168 39.198-63.498 55.188-27.167 18.624-57.161 24.233-89.083 19.849-53.402-7.328-91.609-38.372-121.413-81.046-12.774-18.299-15.365-40.313-17.517-61.875-3.23-32.245-2.415-64.479 2.209-96.597 1.654-11.515-3.863-16.539-13.835-11.175-8.306 4.448-16.095 11.048-22.115 18.353-15.574 18.89-22.223 42.042-27.474 65.395-12.955 57.652-8.86 114.49 12.191 169.495 32.345 84.537 79.743 159.571 145.953 221.932 13.659 12.857 176.841 180.564 202.944 207.021 7.493 7.599 14.895 7.635 22.393 0.028 43.009-43.641 85.985-87.316 128.927-131.029 8.117-8.267 8.019-15.097-0.222-23.49-26.339-26.834-52.726-53.627-79.106-80.419-6.244-6.334-97.34-82.437-73.027-128.816 22.693-25.090 46.196-49.449 69.575-73.904 1.189-1.238 4.686-1.386 6.523-0.632 3.63 1.499 6.848 3.997 10.248 6.066 9.745 5.94 19.545 4.918 27.812-3.083 11.755-11.381 23.405-22.858 35.392-34.59 4.807 4.575 9.939 9.41 15.027 14.294 27.128 26.039 54.272 52.071 81.351 78.146 16.413 15.778 18.652 28.418 11.038 49.658-10.473 29.221-14.356 59.677-13.85 90.624 1.017 61.045 20.438 115.334 61.003 161.416 32.825 37.286 72.054 64.311 121.643 74.325 35.227 7.101 69.139 4.513 100.663-14.026 6.365-3.752 11.908-9.007 17.455-14.005 3.491-3.125 3.153-6.236-0.565-9.98-42.503-42.885-84.772-86.013-127.154-129.035-12.442-12.638-12.356-23.167 0.196-35.914 40.344-40.978 80.597-82.050 120.936-123.052 10.076-10.233 19.537-10.021 29.504 0.134 43.195 44.077 86.449 88.090 129.706 132.118 1.21 1.233 2.572 2.322 5.135 4.624 5.491-5.893 11.895-10.924 15.961-17.406 19.452-30.944 22.608-64.83 17.073-100.25-14.253-91.080-97.188-175.638-197.712-190.123-39.977-5.764-79.372-2.562-118.067 9.031-5.898 1.775-11.541 4.629-17.538 5.829-12.47 2.474-23.872-0.366-32.74-9.877-30.921-33.168-61.674-66.484-92.474-99.758-0.73-0.805-1.349-1.718-0.181-1.099 8.992-10.006 17.354-20.662 27.061-29.94 81.064-77.54 164.91-151.986 250.882-224.063 9.936-8.347 10.274-15.695 1.040-25.1-42.338-43.068-84.689-86.111-127.059-129.154-9.413-9.575-16.846-9.152-25.291 1.295-76.686 94.78-156.8 186.609-239.707 276.002-1.334 1.453-2.562 3.029-4.257 5.042z" horiz-adv-x="1105" />
37
 </font></defs></svg>
38
 </font></defs></svg>

BIN
fonts/jitsi.ttf View File


BIN
fonts/jitsi.woff View File


+ 42
- 7
fonts/selection.json View File

1
 {
1
 {
2
 	"IcoMoonType": "selection",
2
 	"IcoMoonType": "selection",
3
 	"icons": [
3
 	"icons": [
4
+		{
5
+			"icon": {
6
+				"paths": [
7
+					"M526.071 725.251c-28.637 30.869-56.465 60.861-84.282 90.859-51.578 55.636-103.047 111.376-154.842 166.832-7.606 8.135-15.958 16.1-25.317 22.012-28.075 17.708-58.31 18.090-88.472 6.492-59.84-23.028-80.004-90.727-59.734-139.234 5.413-12.95 13.721-23.601 23.709-33.173 70.256-67.351 140.506-134.717 210.76-202.077 15.638-14.993 31.264-29.995 47.364-45.45-9.302-9.529-18.386-18.833-27.451-28.137-12.122-12.442-13.234-20.28-5.067-35.498 4.735-8.816 4.789-8.878-2.627-16.198-20.012-19.72-40.168-39.198-63.498-55.188-27.167-18.624-57.161-24.233-89.083-19.849-53.402 7.328-91.609 38.372-121.413 81.046-12.774 18.299-15.365 40.313-17.517 61.875-3.23 32.245-2.415 64.479 2.209 96.597 1.654 11.515-3.863 16.539-13.835 11.175-8.306-4.448-16.095-11.048-22.115-18.353-15.574-18.89-22.223-42.042-27.474-65.395-12.955-57.652-8.86-114.49 12.191-169.495 32.345-84.537 79.743-159.571 145.953-221.932 13.659-12.857 176.841-180.564 202.944-207.021 7.493-7.599 14.895-7.635 22.393-0.028 43.009 43.641 85.985 87.316 128.927 131.029 8.117 8.267 8.019 15.097-0.222 23.49-26.339 26.834-52.726 53.627-79.106 80.419-6.244 6.334-97.34 82.437-73.027 128.816 22.693 25.090 46.196 49.449 69.575 73.904 1.189 1.238 4.686 1.386 6.523 0.632 3.63-1.499 6.848-3.997 10.248-6.066 9.745-5.94 19.545-4.918 27.812 3.083 11.755 11.381 23.405 22.858 35.392 34.59 4.807-4.575 9.939-9.41 15.027-14.294 27.128-26.039 54.272-52.071 81.351-78.146 16.413-15.778 18.652-28.418 11.038-49.658-10.473-29.221-14.356-59.677-13.85-90.624 1.017-61.045 20.438-115.334 61.003-161.416 32.825-37.286 72.054-64.311 121.643-74.325 35.227-7.101 69.139-4.513 100.663 14.026 6.365 3.752 11.908 9.007 17.455 14.005 3.491 3.125 3.153 6.236-0.565 9.98-42.503 42.885-84.772 86.013-127.154 129.035-12.442 12.638-12.356 23.167 0.196 35.914 40.344 40.978 80.597 82.050 120.936 123.052 10.076 10.233 19.537 10.021 29.504-0.134 43.195-44.077 86.449-88.090 129.706-132.118 1.21-1.233 2.572-2.322 5.135-4.624 5.491 5.893 11.895 10.924 15.961 17.406 19.452 30.944 22.608 64.83 17.073 100.25-14.253 91.080-97.188 175.638-197.712 190.123-39.977 5.764-79.372 2.562-118.067-9.031-5.898-1.775-11.541-4.629-17.538-5.829-12.47-2.474-23.872 0.366-32.74 9.877-30.921 33.168-61.674 66.484-92.474 99.758-0.73 0.805-1.349 1.718-0.181 1.099 8.992 10.006 17.354 20.662 27.061 29.94 81.064 77.54 164.91 151.986 250.882 224.063 9.936 8.347 10.274 15.695 1.040 25.1-42.338 43.068-84.689 86.111-127.059 129.154-9.413 9.575-16.846 9.152-25.291-1.295-76.686-94.78-156.8-186.609-239.707-276.002-1.334-1.453-2.562-3.029-4.257-5.042z"
8
+				],
9
+				"attrs": [
10
+					{
11
+						"opacity": 1,
12
+						"visibility": false
13
+					}
14
+				],
15
+				"width": 1105,
16
+				"grid": 0,
17
+				"tags": [
18
+					"settings"
19
+				]
20
+			},
21
+			"attrs": [
22
+				{
23
+					"opacity": 1,
24
+					"visibility": false
25
+				}
26
+			],
27
+			"properties": {
28
+				"order": 1,
29
+				"id": 33,
30
+				"prevSize": 32,
31
+				"code": 58907,
32
+				"name": "settings"
33
+			},
34
+			"setIdx": 0,
35
+			"iconIdx": 0
36
+		},
4
 		{
37
 		{
5
 			"icon": {
38
 			"icon": {
6
 				"paths": [
39
 				"paths": [
7
 					"M1223.129 242.783l-180.128 175.796v-217.716c0-74.673-59.512-135.496-132.599-135.496h-634.716c-73.084 0-132.596 60.823-132.596 135.496v609.237c0 74.673 59.512 135.496 132.596 135.496h634.716c73.084 0 132.599-60.82 132.599-135.496v-172.679l193.45 153.712c48.784 35.558 96.695-5.178 96.695-40.424v-483.533c-0.003-35.248-55.897-71.306-110.017-24.393zM601.169 760.065c-141.111 0-255.524-114.411-255.524-255.521s114.411-255.521 255.524-255.521c141.108 0 255.519 114.411 255.519 255.521-0 141.113-114.408 255.521-255.519 255.521z",
40
 					"M1223.129 242.783l-180.128 175.796v-217.716c0-74.673-59.512-135.496-132.599-135.496h-634.716c-73.084 0-132.596 60.823-132.596 135.496v609.237c0 74.673 59.512 135.496 132.596 135.496h634.716c73.084 0 132.599-60.82 132.599-135.496v-172.679l193.45 153.712c48.784 35.558 96.695-5.178 96.695-40.424v-483.533c-0.003-35.248-55.897-71.306-110.017-24.393zM601.169 760.065c-141.111 0-255.524-114.411-255.524-255.521s114.411-255.521 255.524-255.521c141.108 0 255.519 114.411 255.519 255.521-0 141.113-114.408 255.521-255.519 255.521z",
8
 					"M599.045 359.751c-80.474 0-145.727 65.253-145.727 145.729 0 80.471 65.25 145.727 145.727 145.727s145.729-65.256 145.729-145.727c0-80.474-65.253-145.729-145.729-145.729z"
41
 					"M599.045 359.751c-80.474 0-145.727 65.253-145.727 145.729 0 80.471 65.25 145.727 145.727 145.727s145.729-65.256 145.729-145.727c0-80.474-65.253-145.729-145.729-145.729z"
9
 				],
42
 				],
43
+				"width": 1334,
10
 				"attrs": [
44
 				"attrs": [
11
 					{
45
 					{
12
 						"opacity": 1,
46
 						"opacity": 1,
17
 						"visibility": false
51
 						"visibility": false
18
 					}
52
 					}
19
 				],
53
 				],
20
-				"width": 1334,
21
-				"grid": 0,
22
 				"tags": [
54
 				"tags": [
23
 					"webCam"
55
 					"webCam"
24
-				]
56
+				],
57
+				"grid": 0
25
 			},
58
 			},
26
 			"attrs": [
59
 			"attrs": [
27
 				{
60
 				{
714
 				"ligatures": ""
747
 				"ligatures": ""
715
 			},
748
 			},
716
 			"setIdx": 0,
749
 			"setIdx": 0,
717
-			"iconIdx": 26
750
+			"iconIdx": 25
718
 		},
751
 		},
719
 		{
752
 		{
720
 			"icon": {
753
 			"icon": {
740
 				"ligatures": ""
773
 				"ligatures": ""
741
 			},
774
 			},
742
 			"setIdx": 0,
775
 			"setIdx": 0,
743
-			"iconIdx": 27
776
+			"iconIdx": 26
744
 		},
777
 		},
745
 		{
778
 		{
746
 			"icon": {
779
 			"icon": {
765
 				"ligatures": ""
798
 				"ligatures": ""
766
 			},
799
 			},
767
 			"setIdx": 0,
800
 			"setIdx": 0,
768
-			"iconIdx": 28
801
+			"iconIdx": 27
769
 		}
802
 		}
770
 	],
803
 	],
771
 	"height": 1024,
804
 	"height": 1024,
775
 	"preferences": {
808
 	"preferences": {
776
 		"showGlyphs": true,
809
 		"showGlyphs": true,
777
 		"showQuickUse": true,
810
 		"showQuickUse": true,
811
+		"showQuickUse2": true,
778
 		"showSVGs": true,
812
 		"showSVGs": true,
779
 		"fontPref": {
813
 		"fontPref": {
780
 			"prefix": "icon-",
814
 			"prefix": "icon-",
791
 		},
825
 		},
792
 		"imagePref": {
826
 		"imagePref": {
793
 			"prefix": "icon-",
827
 			"prefix": "icon-",
794
-			"png": true
828
+			"png": true,
829
+			"useClassSelector": true
795
 		},
830
 		},
796
 		"historySize": 100,
831
 		"historySize": 100,
797
 		"showCodes": true,
832
 		"showCodes": true,

+ 33
- 16
index.html View File

28
     <script src="libs/rayo.js?v=1"></script>
28
     <script src="libs/rayo.js?v=1"></script>
29
     <script src="libs/tooltip.js?v=1"></script><!-- bootstrap tooltip lib -->
29
     <script src="libs/tooltip.js?v=1"></script><!-- bootstrap tooltip lib -->
30
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
30
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
31
-    <script src="interface_config.js?v=3"></script>
32
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
31
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
33
-    <script src="muc.js?v=16"></script><!-- simple MUC library -->
32
+    <script src="interface_config.js?v=4"></script>
33
+    <script src="muc.js?v=17"></script><!-- simple MUC library -->
34
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
34
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
35
     <script src="desktopsharing.js?v=3"></script><!-- desktop sharing -->
35
     <script src="desktopsharing.js?v=3"></script><!-- desktop sharing -->
36
     <script src="data_channels.js?v=3"></script><!-- data channels -->
36
     <script src="data_channels.js?v=3"></script><!-- data channels -->
37
-    <script src="app.js?v=20"></script><!-- application logic -->
37
+    <script src="app.js?v=21"></script><!-- application logic -->
38
     <script src="commands.js?v=1"></script><!-- application logic -->
38
     <script src="commands.js?v=1"></script><!-- application logic -->
39
-    <script src="chat.js?v=14"></script><!-- chat logic -->
40
-    <script src="contact_list.js?v=6"></script><!-- contact list logic -->
41
-    <script src="util.js?v=6"></script><!-- utility functions -->
39
+    <script src="chat.js?v=15"></script><!-- chat logic -->
40
+    <script src="contact_list.js?v=7"></script><!-- contact list logic -->
41
+    <script src="side_panel_toggler.js?v=1"></script>
42
+    <script src="util.js?v=7"></script><!-- utility functions -->
42
     <script src="etherpad.js?v=9"></script><!-- etherpad plugin -->
43
     <script src="etherpad.js?v=9"></script><!-- etherpad plugin -->
43
     <script src="prezi.js?v=6"></script><!-- prezi plugin -->
44
     <script src="prezi.js?v=6"></script><!-- prezi plugin -->
44
     <script src="smileys.js?v=3"></script><!-- smiley images -->
45
     <script src="smileys.js?v=3"></script><!-- smiley images -->
47
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
48
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
48
     <script src="rtp_sts.js?v=5"></script><!-- RTP stats processing -->
49
     <script src="rtp_sts.js?v=5"></script><!-- RTP stats processing -->
49
     <script src="local_sts.js?v=2"></script><!-- Local stats processing -->
50
     <script src="local_sts.js?v=2"></script><!-- Local stats processing -->
50
-    <script src="videolayout.js?v=28"></script><!-- video ui -->
51
+    <script src="videolayout.js?v=29"></script><!-- video ui -->
51
     <script src="connectionquality.js?v=1"></script>
52
     <script src="connectionquality.js?v=1"></script>
52
     <script src="toolbar.js?v=6"></script><!-- toolbar ui -->
53
     <script src="toolbar.js?v=6"></script><!-- toolbar ui -->
53
     <script src="toolbar_toggler.js?v=2"></script>
54
     <script src="toolbar_toggler.js?v=2"></script>
54
     <script src="canvas_util.js?v=1"></script><!-- canvas drawing utils -->
55
     <script src="canvas_util.js?v=1"></script><!-- canvas drawing utils -->
55
     <script src="audio_levels.js?v=2"></script><!-- audio levels plugin -->
56
     <script src="audio_levels.js?v=2"></script><!-- audio levels plugin -->
56
-    <script src="media_stream.js?v=1"></script><!-- media stream -->
57
-    <script src="bottom_toolbar.js?v=5"></script><!-- media stream -->
57
+    <script src="media_stream.js?v=2"></script><!-- media stream -->
58
+    <script src="bottom_toolbar.js?v=6"></script><!-- media stream -->
58
     <script src="roomname_generator.js?v=1"></script><!-- generator for random room names -->
59
     <script src="roomname_generator.js?v=1"></script><!-- generator for random room names -->
59
     <script src="keyboard_shortcut.js?v=3"></script>
60
     <script src="keyboard_shortcut.js?v=3"></script>
60
     <script src="tracking.js?v=1"></script><!-- tracking -->
61
     <script src="tracking.js?v=1"></script><!-- tracking -->
61
     <script src="jitsipopover.js?v=3"></script>
62
     <script src="jitsipopover.js?v=3"></script>
62
     <script src="message_handler.js?v=2"></script>
63
     <script src="message_handler.js?v=2"></script>
63
     <script src="api_connector.js?v=2"></script>
64
     <script src="api_connector.js?v=2"></script>
64
-    <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
65
-    <link rel="stylesheet" href="css/font.css?v=5"/>
65
+    <script src="settings_menu.js?v=1"></script>
66
+    <script src="avatar.js?v=1"></script><!-- avatars -->
67
+    <link rel="stylesheet" href="css/font.css?v=6"/>
66
     <link rel="stylesheet" href="css/toastr.css?v=1">
68
     <link rel="stylesheet" href="css/toastr.css?v=1">
67
-    <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=29"/>
68
-    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=13" id="videolayout_default"/>
69
+    <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=30"/>
70
+    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=14" id="videolayout_default"/>
71
+    <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
69
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
72
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
70
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
73
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
71
     <link rel="stylesheet" href="css/popup_menu.css?v=4">
74
     <link rel="stylesheet" href="css/popup_menu.css?v=4">
72
     <link rel="stylesheet" href="css/popover.css?v=2">
75
     <link rel="stylesheet" href="css/popover.css?v=2">
73
     <link rel="stylesheet" href="css/jitsi_popover.css?v=2">
76
     <link rel="stylesheet" href="css/jitsi_popover.css?v=2">
74
-    <link rel="stylesheet" href="css/contact_list.css?v=3">
77
+    <link rel="stylesheet" href="css/contact_list.css?v=4">
75
     <link rel="stylesheet" href="css/chat.css?v=5">
78
     <link rel="stylesheet" href="css/chat.css?v=5">
76
     <link rel="stylesheet" href="css/welcome_page.css?v=2">
79
     <link rel="stylesheet" href="css/welcome_page.css?v=2">
80
+    <link rel="stylesheet" href="css/settingsmenu.css?v=1">
77
     <!--
81
     <!--
78
         Link used for inline installation of chrome desktop streaming extension,
82
         Link used for inline installation of chrome desktop streaming extension,
79
         is updated automatically from the code with the value defined in config.js -->
83
         is updated automatically from the code with the value defined in config.js -->
227
                             <i class="icon-telephone"></i></a>
231
                             <i class="icon-telephone"></i></a>
228
                     </span>
232
                     </span>
229
                     <div class="header_button_separator"></div>
233
                     <div class="header_button_separator"></div>
234
+                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Settings" onclick='PanelToggler.toggleSettingsMenu();'>
235
+                        <i id="settingsButton" class="icon-settings"></i>
236
+                    </a>
237
+                    <div class="header_button_separator"></div>
230
                     <span id="hangup">
238
                     <span id="hangup">
231
                         <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up" onclick='hangup();'>
239
                         <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up" onclick='hangup();'>
232
                             <i class="icon-hangup" style="color:#ff0000;font-size: 1.4em;"></i>
240
                             <i class="icon-hangup" style="color:#ff0000;font-size: 1.4em;"></i>
253
                 <a target="_new"><div class="watermark leftwatermark"></div></a>
261
                 <a target="_new"><div class="watermark leftwatermark"></div></a>
254
                 <a target="_new"><div class="watermark rightwatermark"></div></a>
262
                 <a target="_new"><div class="watermark rightwatermark"></div></a>
255
                 <a class="poweredby" href="http://jitsi.org" target="_new" >powered by jitsi.org</a>
263
                 <a class="poweredby" href="http://jitsi.org" target="_new" >powered by jitsi.org</a>
264
+                <img id="activeSpeakerAvatar" src=""/>
256
                 <video id="largeVideo" autoplay oncontextmenu="return false;"></video>
265
                 <video id="largeVideo" autoplay oncontextmenu="return false;"></video>
257
             </div>
266
             </div>
258
             <div id="remoteVideos">
267
             <div id="remoteVideos">
296
                 </span>
305
                 </span>
297
             </span>
306
             </span>
298
         </div>
307
         </div>
299
-        <div id="chatspace">
308
+        <div id="chatspace" class="right-panel">
300
             <div id="nickname">
309
             <div id="nickname">
301
                 Enter a nickname in the box below
310
                 Enter a nickname in the box below
302
                 <form>
311
                 <form>
314
                 </div>
323
                 </div>
315
             </div>
324
             </div>
316
         </div>
325
         </div>
317
-        <div id="contactlist">
326
+        <div id="contactlist" class="right-panel">
318
             <ul>
327
             <ul>
319
                 <li class="title"><i class="icon-contact-list"></i> CONTACT LIST</li>
328
                 <li class="title"><i class="icon-contact-list"></i> CONTACT LIST</li>
320
             </ul>
329
             </ul>
321
         </div>
330
         </div>
331
+        <div id="settingsmenu" class="right-panel">
332
+            <div class="icon-settings"> SETTINGS</div>
333
+            <img id="avatar" src="https://www.gravatar.com/avatar/87291c37c25be69a072a4514931b1749?d=retro&size=30"/>
334
+            <div class="arrow-up"></div>
335
+            <input type="text" id="setDisplayName" placeholder="Name">
336
+            <input type="text" id="setEmail" placeholder="E-Mail">
337
+            <button onclick="SettingsMenu.update()" id="updateSettings">Update</button>
338
+        </div>
322
         <a id="downloadlog" onclick='dump(event.target);' data-container="body" data-toggle="popover" data-placement="right" data-content="Download logs" ><i class="fa fa-cloud-download"></i></a>
339
         <a id="downloadlog" onclick='dump(event.target);' data-container="body" data-toggle="popover" data-placement="right" data-content="Download logs" ><i class="fa fa-cloud-download"></i></a>
323
     </div>
340
     </div>
324
   </body>
341
   </body>

+ 3
- 1
interface_config.js View File

6
     TOOLBAR_TIMEOUT: 4000,
6
     TOOLBAR_TIMEOUT: 4000,
7
     DEFAULT_REMOTE_DISPLAY_NAME: "Fellow Jitster",
7
     DEFAULT_REMOTE_DISPLAY_NAME: "Fellow Jitster",
8
     DEFAULT_DOMINANT_SPEAKER_DISPLAY_NAME: "Speaker",
8
     DEFAULT_DOMINANT_SPEAKER_DISPLAY_NAME: "Speaker",
9
+    DEFAULT_LOCAL_DISPLAY_NAME: "me",
9
     SHOW_JITSI_WATERMARK: true,
10
     SHOW_JITSI_WATERMARK: true,
10
     JITSI_WATERMARK_LINK: "http://jitsi.org",
11
     JITSI_WATERMARK_LINK: "http://jitsi.org",
11
     SHOW_BRAND_WATERMARK: false,
12
     SHOW_BRAND_WATERMARK: false,
12
     BRAND_WATERMARK_LINK: "",
13
     BRAND_WATERMARK_LINK: "",
13
     SHOW_POWERED_BY: false,
14
     SHOW_POWERED_BY: false,
14
     GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
15
     GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
15
-    APP_NAME: "Jitsi Meet"
16
+    APP_NAME: "Jitsi Meet",
17
+    ACTIVE_SPEAKER_AVATAR_SIZE: 100
16
 };
18
 };

+ 6
- 4
media_stream.js View File

16
      * @constructor
16
      * @constructor
17
      */
17
      */
18
     function MediaStreamProto(data, sid, ssrc) {
18
     function MediaStreamProto(data, sid, ssrc) {
19
-        this.VIDEO_TYPE = "Video";
20
-        this.AUDIO_TYPE = "Audio";
21
         this.stream = data.stream;
19
         this.stream = data.stream;
22
         this.peerjid = data.peerjid;
20
         this.peerjid = data.peerjid;
23
         this.ssrc = ssrc;
21
         this.ssrc = ssrc;
24
         this.session = connection.jingle.sessions[sid];
22
         this.session = connection.jingle.sessions[sid];
25
         this.type = (this.stream.getVideoTracks().length > 0)
23
         this.type = (this.stream.getVideoTracks().length > 0)
26
-                    ? this.VIDEO_TYPE : this.AUDIO_TYPE;
24
+                    ? MediaStream.VIDEO_TYPE : MediaStream.AUDIO_TYPE;
25
+        this.muted = false;
27
     }
26
     }
28
 
27
 
29
     return MediaStreamProto;
28
     return MediaStreamProto;
30
-})();
29
+})();
30
+
31
+MediaStream.VIDEO_TYPE = 'Video';
32
+MediaStream.AUDIO_TYPE = 'Audio';

+ 14
- 0
muc.js View File

335
             pres.c('bridgeIsDown').up();
335
             pres.c('bridgeIsDown').up();
336
         }
336
         }
337
 
337
 
338
+        if(this.presMap['email']) {
339
+            pres.c('email').t(this.presMap['email']).up();
340
+        }
341
+
342
+        if(this.presMap['userId']) {
343
+            pres.c('userId').t(this.presMap['userId']).up();
344
+        }
345
+
338
         if (this.presMap['displayName']) {
346
         if (this.presMap['displayName']) {
339
             // XEP-0172
347
             // XEP-0172
340
             pres.c('nick', {xmlns: 'http://jabber.org/protocol/nick'})
348
             pres.c('nick', {xmlns: 'http://jabber.org/protocol/nick'})
456
     },
464
     },
457
     addBridgeIsDownToPresence: function() {
465
     addBridgeIsDownToPresence: function() {
458
         this.presMap['bridgeIsDown'] = true;
466
         this.presMap['bridgeIsDown'] = true;
467
+    },
468
+    addEmailToPresence: function(email) {
469
+        this.presMap['email'] = email;
470
+    },
471
+    addUserIdToPresence: function(userId) {
472
+        this.presMap['userId'] = userId;
459
     }
473
     }
460
 });
474
 });

+ 83
- 0
settings_menu.js View File

1
+var SettingsMenu = (function(my) {
2
+
3
+    var email = '';
4
+    var displayName = '';
5
+    var userId;
6
+
7
+    if(supportsLocalStorage()) {
8
+        if(!window.localStorage.jitsiMeetId) {
9
+            window.localStorage.jitsiMeetId = generateUniqueId();
10
+            console.log("generated id", window.localStorage.jitsiMeetId);
11
+        }
12
+        userId = window.localStorage.jitsiMeetId || '';
13
+        email = window.localStorage.email || '';
14
+        displayName = window.localStorage.displayname || '';
15
+    } else {
16
+        console.log("local storage is not supported");
17
+        userId = generateUniqueId();
18
+    }
19
+
20
+    my.update = function() {
21
+        var newDisplayName = Util.escapeHtml($('#setDisplayName').get(0).value);
22
+        if(newDisplayName) {
23
+            displayName = newDisplayName;
24
+            connection.emuc.addDisplayNameToPresence(displayName);
25
+            window.localStorage.displayname = displayName;
26
+        }
27
+
28
+        var newEmail = Util.escapeHtml($('#setEmail').get(0).value);
29
+        connection.emuc.addEmailToPresence(newEmail);
30
+        email = newEmail;
31
+        window.localStorage.email = newEmail;
32
+
33
+        connection.emuc.sendPresence();
34
+        Avatar.setUserAvatar(connection.emuc.myroomjid, email);
35
+    };
36
+
37
+    my.isVisible = function() {
38
+        return $('#settingsmenu').is(':visible');
39
+    };
40
+
41
+    my.getUID = function() {
42
+        return userId;
43
+    };
44
+
45
+    my.getEmail = function() {
46
+        return email;
47
+    };
48
+
49
+    my.getDisplayName = function() {
50
+        return displayName;
51
+    };
52
+
53
+    my.setDisplayName = function(newDisplayName) {
54
+        displayName = newDisplayName;
55
+        window.localStorage.displayname = displayName;
56
+        $('#setDisplayName').get(0).value = displayName;
57
+    };
58
+
59
+    function supportsLocalStorage() {
60
+        try {
61
+            return 'localStorage' in window && window.localStorage !== null;
62
+        } catch (e) {
63
+            console.log("localstorage is not supported");
64
+            return false;
65
+        }
66
+    }
67
+
68
+    function generateUniqueId() {
69
+        function _p8() {
70
+            return (Math.random().toString(16)+"000000000").substr(2,8);
71
+        }
72
+        return _p8() + _p8() + _p8() + _p8();
73
+    }
74
+
75
+    $(document).bind('displaynamechanged', function(event, peerJid, newDisplayName) {
76
+       if(peerJid === 'localVideoContainer' ||
77
+           peerJid === connection.emuc.myroomjid) {
78
+           SettingsMenu.setDisplayName(newDisplayName);
79
+       }
80
+    });
81
+
82
+    return my;
83
+}(SettingsMenu || {}));

+ 245
- 0
side_panel_toggler.js View File

1
+/**
2
+ * Toggler for the chat, contact list, settings menu, etc..
3
+ */
4
+var PanelToggler = (function(my) {
5
+
6
+    var currentlyOpen = null;
7
+    var buttons = {
8
+        '#chatspace': '#chatBottomButton',
9
+        '#contactlist': '#contactListButton',
10
+        '#settingsmenu': '#settingsButton'
11
+    };
12
+
13
+    /**
14
+     * Resizes the video area
15
+     * @param isClosing whether the side panel is going to be closed or is going to open / remain opened
16
+     * @param completeFunction a function to be called when the video space is resized
17
+     */
18
+    var resizeVideoArea = function(isClosing, completeFunction) {
19
+        var videospace = $('#videospace');
20
+
21
+        var panelSize = isClosing ? [0, 0] : PanelToggler.getPanelSize();
22
+        var videospaceWidth = window.innerWidth - panelSize[0];
23
+        var videospaceHeight = window.innerHeight;
24
+        var videoSize
25
+            = getVideoSize(null, null, videospaceWidth, videospaceHeight);
26
+        var videoWidth = videoSize[0];
27
+        var videoHeight = videoSize[1];
28
+        var videoPosition = getVideoPosition(videoWidth,
29
+            videoHeight,
30
+            videospaceWidth,
31
+            videospaceHeight);
32
+        var horizontalIndent = videoPosition[0];
33
+        var verticalIndent = videoPosition[1];
34
+
35
+        var thumbnailSize = VideoLayout.calculateThumbnailSize(videospaceWidth);
36
+        var thumbnailsWidth = thumbnailSize[0];
37
+        var thumbnailsHeight = thumbnailSize[1];
38
+        //for chat
39
+
40
+        videospace.animate({
41
+                right: panelSize[0],
42
+                width: videospaceWidth,
43
+                height: videospaceHeight
44
+            },
45
+            {
46
+                queue: false,
47
+                duration: 500,
48
+                complete: completeFunction
49
+            });
50
+
51
+        $('#remoteVideos').animate({
52
+                height: thumbnailsHeight
53
+            },
54
+            {
55
+                queue: false,
56
+                duration: 500
57
+            });
58
+
59
+        $('#remoteVideos>span').animate({
60
+                height: thumbnailsHeight,
61
+                width: thumbnailsWidth
62
+            },
63
+            {
64
+                queue: false,
65
+                duration: 500,
66
+                complete: function () {
67
+                    $(document).trigger(
68
+                        "remotevideo.resized",
69
+                        [thumbnailsWidth,
70
+                            thumbnailsHeight]);
71
+                }
72
+            });
73
+
74
+        $('#largeVideoContainer').animate({
75
+                width: videospaceWidth,
76
+                height: videospaceHeight
77
+            },
78
+            {
79
+                queue: false,
80
+                duration: 500
81
+            });
82
+
83
+        $('#largeVideo').animate({
84
+                width: videoWidth,
85
+                height: videoHeight,
86
+                top: verticalIndent,
87
+                bottom: verticalIndent,
88
+                left: horizontalIndent,
89
+                right: horizontalIndent
90
+            },
91
+            {
92
+                queue: false,
93
+                duration: 500
94
+            });
95
+    };
96
+
97
+    /**
98
+     * Toggles the windows in the side panel
99
+     * @param object the window that should be shown
100
+     * @param selector the selector for the element containing the panel
101
+     * @param onOpenComplete function to be called when the panel is opened
102
+     * @param onOpen function to be called if the window is going to be opened
103
+     * @param onClose function to be called if the window is going to be closed
104
+     */
105
+    var toggle = function(object, selector, onOpenComplete, onOpen, onClose) {
106
+        buttonClick(buttons[selector], "active");
107
+
108
+        if (object.isVisible()) {
109
+            $("#toast-container").animate({
110
+                    right: '5px'
111
+                },
112
+                {
113
+                    queue: false,
114
+                    duration: 500
115
+                });
116
+            $(selector).hide("slide", {
117
+                direction: "right",
118
+                queue: false,
119
+                duration: 500
120
+            });
121
+            if(typeof onClose === "function") {
122
+                onClose();
123
+            }
124
+
125
+            currentlyOpen = null;
126
+        }
127
+        else {
128
+            // Undock the toolbar when the chat is shown and if we're in a
129
+            // video mode.
130
+            if (VideoLayout.isLargeVideoVisible()) {
131
+                ToolbarToggler.dockToolbar(false);
132
+            }
133
+
134
+            if(currentlyOpen) {
135
+                var current = $(currentlyOpen);
136
+                buttonClick(buttons[currentlyOpen], "active");
137
+                current.css('z-index', 4);
138
+                setTimeout(function () {
139
+                    current.css('display', 'none');
140
+                    current.css('z-index', 5);
141
+                }, 500);
142
+            }
143
+
144
+            $("#toast-container").animate({
145
+                    right: (PanelToggler.getPanelSize()[0] + 5) + 'px'
146
+                },
147
+                {
148
+                    queue: false,
149
+                    duration: 500
150
+                });
151
+            $(selector).show("slide", {
152
+                direction: "right",
153
+                queue: false,
154
+                duration: 500,
155
+                complete: onOpenComplete
156
+            });
157
+            if(typeof onOpen === "function") {
158
+                onOpen();
159
+            }
160
+
161
+            currentlyOpen = selector;
162
+        }
163
+    };
164
+
165
+    /**
166
+     * Opens / closes the chat area.
167
+     */
168
+    my.toggleChat = function() {
169
+        var chatCompleteFunction = Chat.isVisible() ?
170
+            function() {} : function () {
171
+            Chat.scrollChatToBottom();
172
+            $('#chatspace').trigger('shown');
173
+        };
174
+
175
+        resizeVideoArea(Chat.isVisible(), chatCompleteFunction);
176
+
177
+        toggle(Chat,
178
+            '#chatspace',
179
+            function () {
180
+                // Request the focus in the nickname field or the chat input field.
181
+                if ($('#nickname').css('visibility') === 'visible') {
182
+                    $('#nickinput').focus();
183
+                } else {
184
+                    $('#usermsg').focus();
185
+                }
186
+            },
187
+            null,
188
+            Chat.resizeChat,
189
+            null);
190
+    };
191
+
192
+    /**
193
+     * Opens / closes the contact list area.
194
+     */
195
+    my.toggleContactList = function () {
196
+        var completeFunction = ContactList.isVisible() ?
197
+            function() {} : function () { $('#contactlist').trigger('shown');};
198
+        resizeVideoArea(ContactList.isVisible(), completeFunction);
199
+
200
+        toggle(ContactList,
201
+            '#contactlist',
202
+            null,
203
+            function() {
204
+                ContactList.setVisualNotification(false);
205
+            },
206
+            null);
207
+    };
208
+
209
+    /**
210
+     * Opens / closes the settings menu
211
+     */
212
+    my.toggleSettingsMenu = function() {
213
+        resizeVideoArea(SettingsMenu.isVisible(), function (){});
214
+        toggle(SettingsMenu,
215
+            '#settingsmenu',
216
+            null,
217
+            function() {
218
+                $('#setDisplayName').get(0).value = SettingsMenu.getDisplayName();
219
+                $('#setEmail').get(0).value = SettingsMenu.getEmail();
220
+            },
221
+            null);
222
+    };
223
+
224
+    /**
225
+     * Returns the size of the side panel.
226
+     */
227
+    my.getPanelSize = function () {
228
+        var availableHeight = window.innerHeight;
229
+        var availableWidth = window.innerWidth;
230
+
231
+        var panelWidth = 200;
232
+        if (availableWidth * 0.2 < 200) {
233
+            panelWidth = availableWidth * 0.2;
234
+        }
235
+
236
+        return [panelWidth, availableHeight];
237
+    };
238
+
239
+    my.isVisible = function() {
240
+        return (Chat.isVisible() || ContactList.isVisible() || SettingsMenu.isVisible());
241
+    };
242
+
243
+    return my;
244
+
245
+}(PanelToggler || {}));

+ 3
- 5
util.js View File

51
      * Returns the available video width.
51
      * Returns the available video width.
52
      */
52
      */
53
     my.getAvailableVideoWidth = function () {
53
     my.getAvailableVideoWidth = function () {
54
-        var chatspaceWidth
55
-            = (Chat.isVisible() || ContactList.isVisible())
56
-                ? $('#chatspace').width()
57
-                : 0;
54
+        var rightPanelWidth
55
+            = PanelToggler.isVisible() ? PanelToggler.getPanelSize()[0] : 0;
58
 
56
 
59
-        return window.innerWidth - chatspaceWidth;
57
+        return window.innerWidth - rightPanelWidth;
60
     };
58
     };
61
 
59
 
62
     my.imageToGrayScale = function (canvas) {
60
     my.imageToGrayScale = function (canvas) {

+ 49
- 40
videolayout.js View File

123
 
123
 
124
         if ($('#largeVideo').attr('src') != newSrc) {
124
         if ($('#largeVideo').attr('src') != newSrc) {
125
 
125
 
126
+            $('#activeSpeakerAvatar').css('visibility', 'hidden');
126
             // Due to the simulcast the localVideoSrc may have changed when the
127
             // Due to the simulcast the localVideoSrc may have changed when the
127
             // fadeOut event triggers. In that case the getJidFromVideoSrc and
128
             // fadeOut event triggers. In that case the getJidFromVideoSrc and
128
             // isVideoSrcDesktop methods will not function correctly.
129
             // isVideoSrcDesktop methods will not function correctly.
155
 
156
 
156
                 var doUpdate = function () {
157
                 var doUpdate = function () {
157
 
158
 
159
+                    Avatar.updateActiveSpeakerAvatarSrc(largeVideoState.userJid);
160
+
158
                     if (!userChanged && largeVideoState.preload
161
                     if (!userChanged && largeVideoState.preload
159
                         && largeVideoState.preload != null
162
                         && largeVideoState.preload != null
160
                         && $(largeVideoState.preload).attr('src') == newSrc) {
163
                         && $(largeVideoState.preload).attr('src') == newSrc) {
227
                         $(this).fadeIn(300);
230
                         $(this).fadeIn(300);
228
                     }
231
                     }
229
 
232
 
233
+                    if(userChanged) {
234
+                        Avatar.showUserAvatar(largeVideoState.oldJid);
235
+                    }
236
+
230
                     largeVideoState.updateInProgress = false;
237
                     largeVideoState.updateInProgress = false;
231
                 };
238
                 };
232
 
239
 
368
      * in the document and creates it eventually.
375
      * in the document and creates it eventually.
369
      * 
376
      * 
370
      * @param peerJid peer Jid to check.
377
      * @param peerJid peer Jid to check.
378
+     * @param userId user email or id for setting the avatar
371
      * 
379
      * 
372
      * @return Returns <tt>true</tt> if the peer container exists,
380
      * @return Returns <tt>true</tt> if the peer container exists,
373
      * <tt>false</tt> - otherwise
381
      * <tt>false</tt> - otherwise
374
      */
382
      */
375
-    my.ensurePeerContainerExists = function(peerJid) {
376
-        ContactList.ensureAddContact(peerJid);
383
+    my.ensurePeerContainerExists = function(peerJid, userId) {
384
+        ContactList.ensureAddContact(peerJid, userId);
377
 
385
 
378
         var resourceJid = Strophe.getResourceFromJid(peerJid);
386
         var resourceJid = Strophe.getResourceFromJid(peerJid);
379
 
387
 
382
         if ($('#' + videoSpanId).length > 0) {
390
         if ($('#' + videoSpanId).length > 0) {
383
             // If there's been a focus change, make sure we add focus related
391
             // If there's been a focus change, make sure we add focus related
384
             // interface!!
392
             // interface!!
385
-            if (focus && $('#remote_popupmenu_' + resourceJid).length <= 0)
386
-                addRemoteVideoMenu( peerJid,
387
-                                    document.getElementById(videoSpanId));
393
+            if (focus && $('#remote_popupmenu_' + resourceJid).length <= 0) {
394
+                addRemoteVideoMenu(peerJid,
395
+                    document.getElementById(videoSpanId));
396
+            }
388
         }
397
         }
389
         else {
398
         else {
390
-            var container
391
-                = VideoLayout.addRemoteVideoContainer(peerJid, videoSpanId);
392
-
399
+            var container =
400
+                VideoLayout.addRemoteVideoContainer(peerJid, videoSpanId, userId);
401
+            Avatar.setUserAvatar(peerJid, userId);
393
             // Set default display name.
402
             // Set default display name.
394
             setDisplayName(videoSpanId);
403
             setDisplayName(videoSpanId);
395
 
404
 
468
                 var videoStream = simulcast.getReceivingVideoStream(stream);
477
                 var videoStream = simulcast.getReceivingVideoStream(stream);
469
                 RTC.attachMediaStream(sel, videoStream);
478
                 RTC.attachMediaStream(sel, videoStream);
470
 
479
 
471
-                if (isVideo)
480
+                if (isVideo) {
472
                     waitForRemoteVideo(sel, thessrc, stream);
481
                     waitForRemoteVideo(sel, thessrc, stream);
482
+                }
483
+
473
             }
484
             }
474
 
485
 
475
             stream.onended = function () {
486
             stream.onended = function () {
619
      */
630
      */
620
     function setDisplayName(videoSpanId, displayName) {
631
     function setDisplayName(videoSpanId, displayName) {
621
         var nameSpan = $('#' + videoSpanId + '>span.displayname');
632
         var nameSpan = $('#' + videoSpanId + '>span.displayname');
622
-        var defaultLocalDisplayName = "Me";
633
+        var defaultLocalDisplayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME;
623
 
634
 
624
         // If we already have a display name for this video.
635
         // If we already have a display name for this video.
625
         if (nameSpan.length > 0) {
636
         if (nameSpan.length > 0) {
680
                     .bind("click", function (e) {
691
                     .bind("click", function (e) {
681
 
692
 
682
                     e.preventDefault();
693
                     e.preventDefault();
694
+                    e.stopPropagation();
683
                     $('#localDisplayName').hide();
695
                     $('#localDisplayName').hide();
684
                     $('#editDisplayName').show();
696
                     $('#editDisplayName').show();
685
                     $('#editDisplayName').focus();
697
                     $('#editDisplayName').focus();
698
                 });
710
                 });
699
             }
711
             }
700
         }
712
         }
701
-    };
713
+    }
702
 
714
 
703
     my.inputDisplayNameHandler = function (name) {
715
     my.inputDisplayNameHandler = function (name) {
704
         if (nickname !== name) {
716
         if (nickname !== name) {
715
                 $('#localDisplayName').text(nickname + " (me)");
727
                 $('#localDisplayName').text(nickname + " (me)");
716
             else
728
             else
717
                 $('#localDisplayName')
729
                 $('#localDisplayName')
718
-                    .text(defaultLocalDisplayName);
730
+                    .text(interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME);
719
             $('#localDisplayName').show();
731
             $('#localDisplayName').show();
720
         }
732
         }
721
 
733
 
911
         $('#largeVideoContainer').width(availableWidth);
923
         $('#largeVideoContainer').width(availableWidth);
912
         $('#largeVideoContainer').height(availableHeight);
924
         $('#largeVideoContainer').height(availableHeight);
913
 
925
 
926
+
927
+        $('#activeSpeakerAvatar').css('top',
928
+            (availableHeight - interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE) / 2);
929
+
914
         VideoLayout.resizeThumbnails();
930
         VideoLayout.resizeThumbnails();
915
     };
931
     };
916
 
932
 
930
         $('#remoteVideos>span').width(width);
946
         $('#remoteVideos>span').width(width);
931
         $('#remoteVideos>span').height(height);
947
         $('#remoteVideos>span').height(height);
932
 
948
 
949
+        $('.userAvatar').css('left', (width - height) / 2);
950
+
933
         $(document).trigger("remotevideo.resized", [width, height]);
951
         $(document).trigger("remotevideo.resized", [width, height]);
934
     };
952
     };
935
 
953
 
1527
                 if (!isVisible) {
1545
                 if (!isVisible) {
1528
                     console.log("Add to last N", resourceJid);
1546
                     console.log("Add to last N", resourceJid);
1529
 
1547
 
1530
-                    mediaStreams.some(function (mediaStream) {
1531
-                        if (mediaStream.peerjid
1532
-                            && Strophe.getResourceFromJid(mediaStream.peerjid)
1533
-                                === resourceJid
1534
-                            && mediaStream.type === mediaStream.VIDEO_TYPE) {
1535
-                            var sel = $('#participant_' + resourceJid + '>video');
1536
-
1537
-                            var videoStream = simulcast.getReceivingVideoStream(mediaStream.stream);
1538
-                            RTC.attachMediaStream(sel, videoStream);
1539
-                            videoSrcToSsrc[sel.attr('src')] = mediaStream.ssrc;
1540
-                            if (lastNPickupJid == mediaStream.peerjid) {
1541
-                                // Clean up the lastN pickup jid.
1542
-                                lastNPickupJid = null;
1543
-
1544
-                                // Don't fire the events again, they've already
1545
-                                // been fired in the contact list click handler.
1546
-                                VideoLayout.handleVideoThumbClicked($(sel).attr('src'), false);
1547
-
1548
-                                updateLargeVideo = false;
1549
-                            }
1548
+                    var jid = connection.emuc.findJidFromResource(resourceJid);
1549
+                    var mediaStream = mediaStreams[jid][MediaStream.VIDEO_TYPE];
1550
+                    var sel = $('#participant_' + resourceJid + '>video');
1550
 
1551
 
1551
-                            waitForRemoteVideo(
1552
-                                    sel,
1553
-                                    mediaStream.ssrc,
1554
-                                    mediaStream.stream);
1555
-                            return true;
1556
-                        }
1557
-                    });
1552
+                    var videoStream = simulcast.getReceivingVideoStream(
1553
+                        mediaStream.stream);
1554
+                    RTC.attachMediaStream(sel, videoStream);
1555
+                    videoSrcToSsrc[sel.attr('src')] = mediaStream.ssrc;
1556
+                    if (lastNPickupJid == mediaStream.peerjid) {
1557
+                        // Clean up the lastN pickup jid.
1558
+                        lastNPickupJid = null;
1559
+
1560
+                        // Don't fire the events again, they've already
1561
+                        // been fired in the contact list click handler.
1562
+                        VideoLayout.handleVideoThumbClicked($(sel).attr('src'), false);
1563
+
1564
+                        updateLargeVideo = false;
1565
+                    }
1566
+                    waitForRemoteVideo(sel, mediaStream.ssrc, mediaStream.stream);
1558
                 }
1567
                 }
1559
-            });
1568
+            })
1560
         }
1569
         }
1561
 
1570
 
1562
         // The endpoint that was being shown in the large video has dropped out
1571
         // The endpoint that was being shown in the large video has dropped out

Loading…
Cancel
Save