Procházet zdrojové kódy

Creates UI module.

master
hristoterezov před 10 roky
rodič
revize
69b0e2ad32
52 změnil soubory, kde provedl 9836 přidání a 3038 odebrání
  1. 4
    0
      Makefile
  2. 4
    4
      api_connector.js
  3. 24
    610
      app.js
  4. 0
    343
      chat.js
  5. 0
    98
      commands.js
  6. 4
    4
      connectionquality.js
  7. 6
    6
      desktopsharing.js
  8. 0
    206
      etherpad.js
  9. 28
    49
      index.html
  10. 3
    3
      keyboard_shortcut.js
  11. 8
    3
      libs/colibri/colibri.focus.js
  12. 5
    4
      libs/modules/RTC.bundle.js
  13. 6397
    0
      libs/modules/UI.bundle.js
  14. 3
    3
      libs/modules/statistics.bundle.js
  15. 20
    1
      libs/strophe/strophe.jingle.js
  16. 1
    5
      moderatemuc.js
  17. 21
    42
      moderator.js
  18. 1
    1
      modules/RTC/DataChannels.js
  19. 2
    2
      modules/RTC/RTCUtils.js
  20. 545
    0
      modules/UI/UI.js
  21. 7
    3
      modules/UI/audio_levels/AudioLevels.js
  22. 2
    0
      modules/UI/audio_levels/CanvasUtils.js
  23. 60
    54
      modules/UI/avatar/Avatar.js
  24. 195
    0
      modules/UI/etherpad/Etherpad.js
  25. 354
    0
      modules/UI/prezi/Prezi.js
  26. 0
    0
      modules/UI/prezi/PreziPlayer.js
  27. 12
    2
      modules/UI/side_pannels/SidePanelToggler.js
  28. 361
    0
      modules/UI/side_pannels/chat/Chat.js
  29. 95
    0
      modules/UI/side_pannels/chat/Commands.js
  30. 7
    0
      modules/UI/side_pannels/chat/Replacement.js
  31. 48
    0
      modules/UI/side_pannels/chat/smileys.json
  32. 100
    98
      modules/UI/side_pannels/contactlist/ContactList.js
  33. 58
    0
      modules/UI/side_pannels/settings/Settings.js
  34. 42
    0
      modules/UI/side_pannels/settings/SettingsMenu.js
  35. 21
    0
      modules/UI/toolbars/BottomToolbar.js
  36. 203
    44
      modules/UI/toolbars/Toolbar.js
  37. 45
    44
      modules/UI/toolbars/ToolbarToggler.js
  38. 3
    1
      modules/UI/util/JitsiPopover.js
  39. 2
    0
      modules/UI/util/MessageHandler.js
  40. 16
    0
      modules/UI/util/UIUtil.js
  41. 410
    0
      modules/UI/videolayout/ConnectionIndicator.js
  42. 370
    678
      modules/UI/videolayout/VideoLayout.js
  43. 179
    0
      modules/UI/welcome_page/RoomnameGenerator.js
  44. 103
    0
      modules/UI/welcome_page/WelcomePage.js
  45. 2
    2
      modules/statistics/statistics.js
  46. 62
    50
      muc.js
  47. 0
    346
      prezi.js
  48. 3
    3
      recording.js
  49. 0
    188
      roomname_generator.js
  50. 0
    83
      settings_menu.js
  51. 0
    48
      smileys.js
  52. 0
    10
      util.js

+ 4
- 0
Makefile Zobrazit soubor

@@ -20,3 +20,7 @@ clean:
20 20
 
21 21
 deploy:
22 22
 	@mkdir -p $(DEPLOY_DIR) && cp $(OUTPUT_DIR)/*.bundle.js $(DEPLOY_DIR)
23
+	scp $(DEPLOY_DIR)/*.bundle.js hristo.jitsi.net:/srv/web/hristo.jitsi.net/$(DEPLOY_DIR)
24
+
25
+dd: debug deploy
26
+	

+ 4
- 4
api_connector.js Zobrazit soubor

@@ -18,12 +18,12 @@ var APIConnector = (function () {
18 18
      */
19 19
     var commands =
20 20
     {
21
-        displayName: VideoLayout.inputDisplayNameHandler,
21
+        displayName: UI.inputDisplayNameHandler,
22 22
         muteAudio: toggleAudio,
23 23
         muteVideo: toggleVideo,
24
-        toggleFilmStrip: BottomToolbar.toggleFilmStrip,
25
-        toggleChat: BottomToolbar.toggleChat,
26
-        toggleContactList: BottomToolbar.toggleContactList
24
+        toggleFilmStrip: UI.toggleFilmStrip,
25
+        toggleChat: UI.toggleChat,
26
+        toggleContactList: UI.toggleContactList
27 27
     };
28 28
 
29 29
 

+ 24
- 610
app.js Zobrazit soubor

@@ -2,12 +2,9 @@
2 2
 /* application specific logic */
3 3
 var connection = null;
4 4
 var authenticatedUser = false;
5
-var authenticationWindow = null;
6 5
 var activecall = null;
7 6
 var nickname = null;
8
-var sharedKey = '';
9 7
 var focusMucJid = null;
10
-var roomUrl = null;
11 8
 var roomName = null;
12 9
 var ssrc2jid = {};
13 10
 var bridgeIsDown = false;
@@ -59,10 +56,8 @@ var getVideoPosition;
59 56
 var sessionTerminated = false;
60 57
 
61 58
 function init() {
62
-    Toolbar.setupButtonsFromConfig();
63 59
 
64 60
     RTC.addStreamListener(maybeDoJoin, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
65
-    RTC.addStreamListener(VideoLayout.onLocalStreamCreated, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED)
66 61
     RTC.start();
67 62
 
68 63
     var jid = document.getElementById('jid').value || config.hosts.anonymousdomain || config.hosts.domain || window.location.hostname;
@@ -76,13 +71,14 @@ function connect(jid, password) {
76 71
         localVideo = connection.jingle.localVideo;
77 72
     }
78 73
     connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
79
-    
80
-    var email = SettingsMenu.getEmail();
81
-    var displayName = SettingsMenu.getDisplayName();
74
+
75
+    var settings = UI.getSettings();
76
+    var email = settings.email;
77
+    var displayName = settings.displayName;
82 78
     if(email) {
83 79
         connection.emuc.addEmailToPresence(email);
84 80
     } else {
85
-        connection.emuc.addUserIdToPresence(SettingsMenu.getUID());
81
+        connection.emuc.addUserIdToPresence(settings.uid);
86 82
     }
87 83
     if(displayName) {
88 84
         connection.emuc.addDisplayNameToPresence(displayName);
@@ -143,41 +139,9 @@ function maybeDoJoin() {
143 139
     }
144 140
 }
145 141
 
146
-function generateRoomName() {
147
-    var roomnode = null;
148
-    var path = window.location.pathname;
149
-
150
-    // determinde the room node from the url
151
-    // TODO: just the roomnode or the whole bare jid?
152
-    if (config.getroomnode && typeof config.getroomnode === 'function') {
153
-        // custom function might be responsible for doing the pushstate
154
-        roomnode = config.getroomnode(path);
155
-    } else {
156
-        /* fall back to default strategy
157
-         * this is making assumptions about how the URL->room mapping happens.
158
-         * It currently assumes deployment at root, with a rewrite like the
159
-         * following one (for nginx):
160
-        location ~ ^/([a-zA-Z0-9]+)$ {
161
-            rewrite ^/(.*)$ / break;
162
-        }
163
-         */
164
-        if (path.length > 1) {
165
-            roomnode = path.substr(1).toLowerCase();
166
-        } else {
167
-            var word = RoomNameGenerator.generateRoomWithoutSeparator();
168
-            roomnode = word.toLowerCase();
169
-
170
-            window.history.pushState('VideoChat',
171
-                    'Room: ' + word, window.location.pathname + word);
172
-        }
173
-    }
174
-
175
-    roomName = roomnode + '@' + config.hosts.muc;
176
-}
177
-
178 142
 function doJoin() {
179 143
     if (!roomName) {
180
-        generateRoomName();
144
+        UI.generateRoomName();
181 145
     }
182 146
 
183 147
     Moderator.allocateConferenceFocus(
@@ -244,7 +208,6 @@ function waitForRemoteVideo(selector, ssrc, stream, jid) {
244 208
             jid2Ssrc[Strophe.getResourceFromJid(jid)] = ssrc;
245 209
         } else {
246 210
             console.warn("No ssrc given for jid", jid);
247
-//            messageHandler.showError('Warning', 'No ssrc was given for the video.');
248 211
         }
249 212
 
250 213
         $(document).trigger('videoactive.jingle', [selector]);
@@ -328,43 +291,7 @@ function waitForPresence(data, sid) {
328 291
 
329 292
     RTC.createRemoteStream(data, sid, thessrc);
330 293
 
331
-    var container;
332
-    var remotes = document.getElementById('remoteVideos');
333
-
334
-    if (data.peerjid) {
335
-        VideoLayout.ensurePeerContainerExists(data.peerjid);
336
-
337
-        container  = document.getElementById(
338
-                'participant_' + Strophe.getResourceFromJid(data.peerjid));
339
-    } else {
340
-        if (data.stream.id !== 'mixedmslabel'
341
-            // FIXME: default stream is added always with new focus
342
-            // (to be investigated)
343
-            && data.stream.id !== 'default') {
344
-            console.error('can not associate stream',
345
-                data.stream.id,
346
-                'with a participant');
347
-            // We don't want to add it here since it will cause troubles
348
-            return;
349
-        }
350
-        // FIXME: for the mixed ms we dont need a video -- currently
351
-        container = document.createElement('span');
352
-        container.id = 'mixedstream';
353
-        container.className = 'videocontainer';
354
-        remotes.appendChild(container);
355
-        Util.playSoundNotification('userJoined');
356
-    }
357
-
358 294
     var isVideo = data.stream.getVideoTracks().length > 0;
359
-
360
-    if (container) {
361
-        VideoLayout.addRemoteStreamElement( container,
362
-                                            sid,
363
-                                            data.stream,
364
-                                            data.peerjid,
365
-                                            thessrc);
366
-    }
367
-
368 295
     // an attempt to work around https://github.com/jitsi/jitmeet/issues/32
369 296
     if (isVideo &&
370 297
         data.peerjid && sess.peerjid === data.peerjid &&
@@ -393,19 +320,19 @@ function sendKeyframe(pc) {
393 320
                         },
394 321
                         function (error) {
395 322
                             console.log('triggerKeyframe setLocalDescription failed', error);
396
-                            messageHandler.showError();
323
+                            UI.messageHandler.showError();
397 324
                         }
398 325
                     );
399 326
                 },
400 327
                 function (error) {
401 328
                     console.log('triggerKeyframe createAnswer failed', error);
402
-                    messageHandler.showError();
329
+                    UI.messageHandler.showError();
403 330
                 }
404 331
             );
405 332
         },
406 333
         function (error) {
407 334
             console.log('triggerKeyframe setRemoteDescription failed', error);
408
-            messageHandler.showError();
335
+            UI.messageHandler.showError();
409 336
         }
410 337
     );
411 338
 }
@@ -433,7 +360,7 @@ function muteVideo(pc, unmute) {
433 360
                         },
434 361
                         function (error) {
435 362
                             console.log('mute SLD error');
436
-                            messageHandler.showError('Error',
363
+                            UI.messageHandler.showError('Error',
437 364
                                 'Oops! Something went wrong and we failed to ' +
438 365
                                     'mute! (SLD Failure)');
439 366
                         }
@@ -441,13 +368,13 @@ function muteVideo(pc, unmute) {
441 368
                 },
442 369
                 function (error) {
443 370
                     console.log(error);
444
-                    messageHandler.showError();
371
+                    UI.messageHandler.showError();
445 372
                 }
446 373
             );
447 374
         },
448 375
         function (error) {
449 376
             console.log('muteVideo SRD error');
450
-            messageHandler.showError('Error',
377
+            UI.messageHandler.showError('Error',
451 378
                 'Oops! Something went wrong and we failed to stop video!' +
452 379
                     '(SRD Failure)');
453 380
 
@@ -455,53 +382,6 @@ function muteVideo(pc, unmute) {
455 382
     );
456 383
 }
457 384
 
458
-/**
459
- * Callback for audio levels changed.
460
- * @param jid JID of the user
461
- * @param audioLevel the audio level value
462
- */
463
-function audioLevelUpdated(jid, audioLevel)
464
-{
465
-    var resourceJid;
466
-    if(jid === statistics.LOCAL_JID)
467
-    {
468
-        resourceJid = AudioLevels.LOCAL_LEVEL;
469
-        if(isAudioMuted())
470
-        {
471
-            audioLevel = 0;
472
-        }
473
-    }
474
-    else
475
-    {
476
-        resourceJid = Strophe.getResourceFromJid(jid);
477
-    }
478
-
479
-    AudioLevels.updateAudioLevel(resourceJid, audioLevel);
480
-}
481
-
482
-$(document).bind('callincoming.jingle', function (event, sid) {
483
-    var sess = connection.jingle.sessions[sid];
484
-
485
-    // TODO: do we check activecall == null?
486
-    activecall = sess;
487
-
488
-    statistics.onConferenceCreated(sess);
489
-    RTC.onConferenceCreated(sess);
490
-
491
-    // TODO: check affiliation and/or role
492
-    console.log('emuc data for', sess.peerjid, connection.emuc.members[sess.peerjid]);
493
-    sess.usedrip = true; // not-so-naive trickle ice
494
-    sess.sendAnswer();
495
-    sess.accept();
496
-
497
-});
498
-
499
-$(document).bind('conferenceCreated.jingle', function (event, focus)
500
-{
501
-    statistics.onConfereceCreated(getConferenceHandler());
502
-    RTC.onConfereceCreated(focus);
503
-});
504
-
505 385
 $(document).bind('setLocalDescription.jingle', function (event, sid) {
506 386
     // put our ssrcs into presence so other clients can identify our stream
507 387
     var sess = connection.jingle.sessions[sid];
@@ -585,115 +465,7 @@ $(document).bind('iceconnectionstatechange.jingle', function (event, sid, sessio
585 465
 });
586 466
 
587 467
 $(document).bind('joined.muc', function (event, jid, info) {
588
-    updateRoomUrl(window.location.href);
589
-    document.getElementById('localNick').appendChild(
590
-        document.createTextNode(Strophe.getResourceFromJid(jid) + ' (me)')
591
-    );
592
-
593
-    // Add myself to the contact list.
594
-    ContactList.addContact(jid, SettingsMenu.getEmail() || SettingsMenu.getUID());
595
-
596
-    // Once we've joined the muc show the toolbar
597
-    ToolbarToggler.showToolbar();
598
-
599
-    // Show authenticate button if needed
600
-    Toolbar.showAuthenticateButton(
601
-        Moderator.isExternalAuthEnabled() && !Moderator.isModerator());
602
-
603
-    var displayName = !config.displayJids
604
-        ? info.displayName : Strophe.getResourceFromJid(jid);
605
-
606
-    if (displayName)
607
-        $(document).trigger('displaynamechanged',
608
-                            ['localVideoContainer', displayName + ' (me)']);
609
-});
610
-
611
-$(document).bind('entered.muc', function (event, jid, info, pres) {
612
-    console.log('entered', jid, info);
613
-    if (info.isFocus)
614
-    {
615
-        focusMucJid = jid;
616
-        console.info("Ignore focus: " + jid +", real JID: " + info.jid);
617
-        return;
618
-    }
619
-
620
-    messageHandler.notify(info.displayName || 'Somebody',
621
-        'connected',
622
-        'connected');
623
-
624
-    // Add Peer's container
625
-    var id = $(pres).find('>userID').text();
626
-    var email = $(pres).find('>email');
627
-    if(email.length > 0) {
628
-        id = email.text();
629
-    }
630
-    VideoLayout.ensurePeerContainerExists(jid,id);
631
-
632
-    if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantJoined"))
633
-    {
634
-        APIConnector.triggerEvent("participantJoined",{jid: jid});
635
-    }
636 468
 
637
-    /*if (focus !== null) {
638
-        // FIXME: this should prepare the video
639
-        if (focus.confid === null) {
640
-            console.log('make new conference with', jid);
641
-            focus.makeConference(Object.keys(connection.emuc.members),
642
-                function(error) {
643
-                    connection.emuc.addBridgeIsDownToPresence();
644
-                    connection.emuc.sendPresence();
645
-                }
646
-            );
647
-            Toolbar.showRecordingButton(true);
648
-        } else {
649
-            console.log('invite', jid, 'into conference');
650
-            focus.addNewParticipant(jid);
651
-        }
652
-    }*/
653
-});
654
-
655
-$(document).bind('left.muc', function (event, jid) {
656
-    console.log('left.muc', jid);
657
-    var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
658
-        '>.displayname').html();
659
-    messageHandler.notify(displayName || 'Somebody',
660
-        'disconnected',
661
-        'disconnected');
662
-    // Need to call this with a slight delay, otherwise the element couldn't be
663
-    // found for some reason.
664
-    // XXX(gp) it works fine without the timeout for me (with Chrome 38).
665
-    window.setTimeout(function () {
666
-        var container = document.getElementById(
667
-                'participant_' + Strophe.getResourceFromJid(jid));
668
-        if (container) {
669
-            ContactList.removeContact(jid);
670
-            VideoLayout.removeConnectionIndicator(jid);
671
-            // hide here, wait for video to close before removing
672
-            $(container).hide();
673
-            VideoLayout.resizeThumbnails();
674
-        }
675
-    }, 10);
676
-
677
-    if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantLeft"))
678
-    {
679
-        APIConnector.triggerEvent("participantLeft",{jid: jid});
680
-    }
681
-
682
-    delete jid2Ssrc[jid];
683
-
684
-    // Unlock large video
685
-    if (focusedVideoInfo && focusedVideoInfo.jid === jid)
686
-    {
687
-        console.info("Focused video owner has left the conference");
688
-        focusedVideoInfo = null;
689
-    }
690
-
691
-    connection.jingle.terminateByJid(jid);
692
-
693
-    if (connection.emuc.getPrezi(jid)) {
694
-        $(document).trigger('presentationremoved.muc',
695
-                            [jid, connection.emuc.getPrezi(jid)]);
696
-    }
697 469
 });
698 470
 
699 471
 $(document).bind('presence.muc', function (event, jid, info, pres) {
@@ -701,7 +473,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
701 473
     //check if the video bridge is available
702 474
     if($(pres).find(">bridgeIsDown").length > 0 && !bridgeIsDown) {
703 475
         bridgeIsDown = true;
704
-        messageHandler.showError("Error",
476
+        UI.messageHandler.showError("Error",
705 477
             "Jitsi Videobridge is currently unavailable. Please try again later!");
706 478
     }
707 479
 
@@ -756,7 +528,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
756 528
     //check if the video bridge is available
757 529
     if($(pres).find(">bridgeIsDown").length > 0 && !bridgeIsDown) {
758 530
         bridgeIsDown = true;
759
-        messageHandler.showError("Error",
531
+        UI.messageHandler.showError("Error",
760 532
             "Jitsi Videobridge is currently unavailable. Please try again later!");
761 533
     }
762 534
 
@@ -765,14 +537,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
765 537
     if(email.length > 0) {
766 538
         id = email.text();
767 539
     }
768
-    Avatar.setUserAvatar(jid, id);
769
-
770
-});
771
-
772
-$(document).bind('presence.status.muc', function (event, jid, info, pres) {
773
-
774
-    VideoLayout.setPresenceStatus(
775
-        'participant_' + Strophe.getResourceFromJid(jid), info.status);
540
+    UI.setUserAvatar(jid, id);
776 541
 
777 542
 });
778 543
 
@@ -782,80 +547,15 @@ $(document).bind('kicked.muc', function (event, jid) {
782 547
         sessionTerminated = true;
783 548
         disposeConference(false);
784 549
         connection.emuc.doLeave();
785
-        messageHandler.openMessageDialog("Session Terminated",
550
+        UI.messageHandler.openMessageDialog("Session Terminated",
786 551
             "Ouch! You have been kicked out of the meet!");
787 552
     }
788 553
 });
789 554
 
790
-$(document).bind('role.changed.muc', function (event, jid, member, pres) {
791
-        console.info("Role changed for " + jid + ", new role: " + member.role);
792
-
793
-        VideoLayout.showModeratorIndicator();
794
-
795
-        if (member.role === 'moderator') {
796
-            var displayName = member.displayName;
797
-            if (!displayName) {
798
-                displayName = 'Somebody';
799
-            }
800
-            messageHandler.notify(
801
-                displayName,
802
-                'connected',
803
-                'Moderator rights granted to ' + displayName + '!');
804
-        }
805
-    }
806
-);
807
-
808
-$(document).bind('local.role.changed.muc', function (event, jid, info, pres) {
809
-
810
-        console.info("My role changed, new role: " + info.role);
811
-        var isModerator = Moderator.isModerator();
812
-
813
-        VideoLayout.showModeratorIndicator();
814
-        Toolbar.showAuthenticateButton(
815
-            Moderator.isExternalAuthEnabled() && !isModerator);
816
-
817
-        if (isModerator) {
818
-            if (authenticationWindow) {
819
-                authenticationWindow.close();
820
-                authenticationWindow = null;
821
-            }
822
-            messageHandler.notify(
823
-                'Me', 'connected', 'Moderator rights granted !');
824
-        }
825
-    }
826
-);
827
-
828
-$(document).bind('passwordrequired.muc', function (event, jid) {
829
-    console.log('on password required', jid);
830
-
831
-    // password is required
832
-    Toolbar.lockLockButton();
833
-
834
-    messageHandler.openTwoButtonDialog(null,
835
-        '<h2>Password required</h2>' +
836
-        '<input id="lockKey" type="text" placeholder="password" autofocus>',
837
-        true,
838
-        "Ok",
839
-        function (e, v, m, f) {},
840
-        function (event) {
841
-            document.getElementById('lockKey').focus();
842
-        },
843
-        function (e, v, m, f) {
844
-            if (v) {
845
-                var lockKey = document.getElementById('lockKey');
846
-                if (lockKey.value !== null) {
847
-                    setSharedKey(lockKey.value);
848
-                    connection.emuc.doJoin(jid, lockKey.value);
849
-                }
850
-            }
851
-        }
852
-    );
853
-});
854
-
855 555
 $(document).bind('passwordrequired.main', function (event) {
856 556
     console.log('password is required');
857 557
 
858
-    messageHandler.openTwoButtonDialog(null,
558
+    UI.messageHandler.openTwoButtonDialog(null,
859 559
         '<h2>Password required</h2>' +
860 560
             '<input id="passwordrequired.username" type="text" placeholder="user@domain.net" autofocus>' +
861 561
             '<input id="passwordrequired.password" type="password" placeholder="user password">',
@@ -877,51 +577,6 @@ $(document).bind('passwordrequired.main', function (event) {
877 577
     );
878 578
 });
879 579
 
880
-$(document).bind('auth_required.moderator', function () {
881
-    // extract room name from 'room@muc.server.net'
882
-    var room = roomName.substr(0, roomName.indexOf('@'));
883
-
884
-    messageHandler.openDialog(
885
-        'Stop',
886
-        'Authentication is required to create room:<br/>' + room,
887
-        true,
888
-        {
889
-            Authenticate: 'authNow',
890
-            Close: 'close'
891
-        },
892
-        function (onSubmitEvent, submitValue) {
893
-            console.info('On submit: ' + submitValue, submitValue);
894
-            if (submitValue === 'authNow') {
895
-                authenticateClicked();
896
-            } else {
897
-                Toolbar.showAuthenticateButton(true);
898
-            }
899
-        }
900
-    );
901
-});
902
-
903
-function authenticateClicked() {
904
-    // Get authentication URL
905
-    Moderator.getAuthUrl(function (url) {
906
-        // Open popup with authentication URL
907
-        authenticationWindow = messageHandler.openCenteredPopup(
908
-            url, 500, 400,
909
-            function () {
910
-                // On popup closed - retry room allocation
911
-                Moderator.allocateConferenceFocus(
912
-                    roomName, doJoinAfterFocus);
913
-                authenticationWindow = null;
914
-            });
915
-        if (!authenticationWindow) {
916
-            Toolbar.showAuthenticateButton(true);
917
-            messageHandler.openMessageDialog(
918
-                null, "Your browser is blocking popup windows from this site." +
919
-                " Please enable popups in your browser security settings" +
920
-                " and try again.");
921
-        }
922
-    });
923
-};
924
-
925 580
 /**
926 581
  * Checks if video identified by given src is desktop stream.
927 582
  * @param videoSrc eg.
@@ -1060,7 +715,7 @@ function setAudioMuted(mute) {
1060 715
     // isMuted is the opposite of audioEnabled
1061 716
     connection.emuc.addAudioInfoToPresence(mute);
1062 717
     connection.emuc.sendPresence();
1063
-    VideoLayout.showLocalAudioIndicator(mute);
718
+    UI.showLocalAudioIndicator(mute);
1064 719
 
1065 720
     buttonClick("#mute", "icon-microphone icon-mic-disabled");
1066 721
 }
@@ -1079,11 +734,6 @@ function isAudioMuted()
1079 734
     return true;
1080 735
 }
1081 736
 
1082
-// Starts or stops the recording for the conference.
1083
-function toggleRecording() {
1084
-    Recording.toggleRecording();
1085
-}
1086
-
1087 737
 /**
1088 738
  * Returns an array of the video horizontal and vertical indents,
1089 739
  * so that if fits its parent.
@@ -1163,151 +813,17 @@ function getCameraVideoSize(videoWidth,
1163 813
 }
1164 814
 
1165 815
 $(document).ready(function () {
1166
-    document.title = interfaceConfig.APP_NAME;
816
+
1167 817
     if(APIConnector.isEnabled())
1168 818
         APIConnector.init();
1169 819
 
1170
-    if(config.enableWelcomePage && window.location.pathname == "/" &&
1171
-        (!window.localStorage.welcomePageDisabled
1172
-                || window.localStorage.welcomePageDisabled == "false"))
1173
-    {
1174
-        $("#videoconference_page").hide();
1175
-        $("#domain_name").text(
1176
-                window.location.protocol + "//" + window.location.host + "/");
1177
-        $("span[name='appName']").text(interfaceConfig.APP_NAME);
1178
-
1179
-        if (interfaceConfig.SHOW_JITSI_WATERMARK) {
1180
-            var leftWatermarkDiv
1181
-                = $("#welcome_page_header div[class='watermark leftwatermark']");
1182
-            if(leftWatermarkDiv && leftWatermarkDiv.length > 0)
1183
-            {
1184
-                leftWatermarkDiv.css({display: 'block'});
1185
-                leftWatermarkDiv.parent().get(0).href
1186
-                    = interfaceConfig.JITSI_WATERMARK_LINK;
1187
-            }
1188
-
1189
-        }
1190
-
1191
-        if (interfaceConfig.SHOW_BRAND_WATERMARK) {
1192
-            var rightWatermarkDiv
1193
-                = $("#welcome_page_header div[class='watermark rightwatermark']");
1194
-            if(rightWatermarkDiv && rightWatermarkDiv.length > 0) {
1195
-                rightWatermarkDiv.css({display: 'block'});
1196
-                rightWatermarkDiv.parent().get(0).href
1197
-                    = interfaceConfig.BRAND_WATERMARK_LINK;
1198
-                rightWatermarkDiv.get(0).style.backgroundImage
1199
-                    = "url(images/rightwatermark.png)";
1200
-            }
1201
-        }
1202
-
1203
-        if (interfaceConfig.SHOW_POWERED_BY) {
1204
-            $("#welcome_page_header>a[class='poweredby']")
1205
-                .css({display: 'block'});
1206
-        }
1207
-
1208
-        function enter_room()
1209
-        {
1210
-            var val = $("#enter_room_field").val();
1211
-            if(!val) {
1212
-                val = $("#enter_room_field").attr("room_name");
1213
-            }
1214
-            if (val) {
1215
-                window.location.pathname = "/" + val;
1216
-            }
1217
-        }
1218
-        $("#enter_room_button").click(function()
1219
-        {
1220
-            enter_room();
1221
-        });
1222
-
1223
-        $("#enter_room_field").keydown(function (event) {
1224
-            if (event.keyCode === 13 /* enter */) {
1225
-                enter_room();
1226
-            }
1227
-        });
1228
-
1229
-        if (!(interfaceConfig.GENERATE_ROOMNAMES_ON_WELCOME_PAGE === false)){
1230
-            var updateTimeout;
1231
-            var animateTimeout;
1232
-            $("#reload_roomname").click(function () {
1233
-                clearTimeout(updateTimeout);
1234
-                clearTimeout(animateTimeout);
1235
-                update_roomname();
1236
-            });
1237
-            $("#reload_roomname").show();
1238
-
1239
-            function animate(word) {
1240
-                var currentVal = $("#enter_room_field").attr("placeholder");
1241
-                $("#enter_room_field").attr("placeholder", currentVal + word.substr(0, 1));
1242
-                animateTimeout = setTimeout(function() {
1243
-                    animate(word.substring(1, word.length))
1244
-                }, 70);
1245
-            }
1246
-
1247
-            function update_roomname()
1248
-            {
1249
-                var word = RoomNameGenerator.generateRoomWithoutSeparator();
1250
-                $("#enter_room_field").attr("room_name", word);
1251
-                $("#enter_room_field").attr("placeholder", "");
1252
-                clearTimeout(animateTimeout);
1253
-                animate(word);
1254
-                updateTimeout = setTimeout(update_roomname, 10000);
1255
-            }
1256
-            update_roomname();
1257
-        }
1258
-
1259
-        $("#disable_welcome").click(function () {
1260
-            window.localStorage.welcomePageDisabled
1261
-                = $("#disable_welcome").is(":checked");
1262
-        });
1263
-
1264
-        return;
1265
-    }
1266
-
1267
-    if (interfaceConfig.SHOW_JITSI_WATERMARK) {
1268
-        var leftWatermarkDiv
1269
-            = $("#largeVideoContainer div[class='watermark leftwatermark']");
1270
-
1271
-        leftWatermarkDiv.css({display: 'block'});
1272
-        leftWatermarkDiv.parent().get(0).href
1273
-            = interfaceConfig.JITSI_WATERMARK_LINK;
1274
-    }
1275
-
1276
-    if (interfaceConfig.SHOW_BRAND_WATERMARK) {
1277
-        var rightWatermarkDiv
1278
-            = $("#largeVideoContainer div[class='watermark rightwatermark']");
1279
-
1280
-        rightWatermarkDiv.css({display: 'block'});
1281
-        rightWatermarkDiv.parent().get(0).href
1282
-            = interfaceConfig.BRAND_WATERMARK_LINK;
1283
-        rightWatermarkDiv.get(0).style.backgroundImage
1284
-            = "url(images/rightwatermark.png)";
1285
-    }
1286
-
1287
-    if (interfaceConfig.SHOW_POWERED_BY) {
1288
-        $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
1289
-    }
1290
-
1291
-    $("#welcome_page").hide();
1292
-    Chat.init();
1293
-
1294
-    $('body').popover({ selector: '[data-toggle=popover]',
1295
-        trigger: 'click hover',
1296
-        content: function() {
1297
-            return this.getAttribute("content") +
1298
-                   KeyboardShortcut.getShortcut(this.getAttribute("shortcut"));
1299
-        }
1300
-    });
1301
-
1302
-    statistics.addAudioLevelListener(audioLevelUpdated);
820
+    UI.start();
1303 821
     statistics.addConnectionStatsListener(ConnectionQuality.updateLocalStats);
1304 822
     statistics.addRemoteStatsStopListener(ConnectionQuality.stopSendingStats);
823
+    statistics.start();
1305 824
     
1306 825
     Moderator.init();
1307 826
 
1308
-    // Set the defaults for prompt dialogs.
1309
-    jQuery.prompt.setDefaults({persistent: false});
1310
-
1311 827
     // Set default desktop sharing method
1312 828
     setDesktopSharing(config.desktopSharing);
1313 829
     // Initialize Chrome extension inline installs
@@ -1318,62 +834,6 @@ $(document).ready(function () {
1318 834
     // By default we use camera
1319 835
     getVideoSize = getCameraVideoSize;
1320 836
     getVideoPosition = getCameraVideoPosition;
1321
-
1322
-    VideoLayout.resizeLargeVideoContainer();
1323
-    $(window).resize(function () {
1324
-        VideoLayout.resizeLargeVideoContainer();
1325
-        VideoLayout.positionLarge();
1326
-    });
1327
-    // Listen for large video size updates
1328
-    document.getElementById('largeVideo')
1329
-        .addEventListener('loadedmetadata', function (e) {
1330
-            currentVideoWidth = this.videoWidth;
1331
-            currentVideoHeight = this.videoHeight;
1332
-            VideoLayout.positionLarge(currentVideoWidth, currentVideoHeight);
1333
-        });
1334
-
1335
-    document.getElementById('largeVideo').volume = 0;
1336
-
1337
-    if (!$('#settings').is(':visible')) {
1338
-        console.log('init');
1339
-        init();
1340
-    } else {
1341
-        loginInfo.onsubmit = function (e) {
1342
-            if (e.preventDefault) e.preventDefault();
1343
-            $('#settings').hide();
1344
-            init();
1345
-        };
1346
-    }
1347
-
1348
-    toastr.options = {
1349
-        "closeButton": true,
1350
-        "debug": false,
1351
-        "positionClass": "notification-bottom-right",
1352
-        "onclick": null,
1353
-        "showDuration": "300",
1354
-        "hideDuration": "1000",
1355
-        "timeOut": "2000",
1356
-        "extendedTimeOut": "1000",
1357
-        "showEasing": "swing",
1358
-        "hideEasing": "linear",
1359
-        "showMethod": "fadeIn",
1360
-        "hideMethod": "fadeOut",
1361
-        "reposition": function() {
1362
-            if(PanelToggler.isVisible()) {
1363
-                $("#toast-container").addClass("notification-bottom-right-center");
1364
-            } else {
1365
-                $("#toast-container").removeClass("notification-bottom-right-center");
1366
-            }
1367
-        },
1368
-        "newestOnTop": false
1369
-    };
1370
-
1371
-    $('#settingsmenu>input').keyup(function(event){
1372
-        if(event.keyCode === 13) {//enter
1373
-            SettingsMenu.update();
1374
-        }
1375
-    })
1376
-
1377 837
 });
1378 838
 
1379 839
 $(window).bind('beforeunload', function () {
@@ -1404,9 +864,7 @@ $(window).bind('beforeunload', function () {
1404 864
 });
1405 865
 
1406 866
 function disposeConference(onUnload) {
1407
-
1408
-    Toolbar.showAuthenticateButton(false);
1409
-
867
+    UI.onDisposeConference(onUnload);
1410 868
     var handler = getConferenceHandler();
1411 869
     if (handler && handler.peerconnection) {
1412 870
         // FIXME: probably removing streams is not required and close() should
@@ -1469,37 +927,6 @@ function buttonClick(id, classname) {
1469 927
     $(id).toggleClass(classname); // add the class to the clicked element
1470 928
 }
1471 929
 
1472
-/**
1473
- * Locks / unlocks the room.
1474
- */
1475
-function lockRoom(lock) {
1476
-    if (lock)
1477
-        connection.emuc.lockRoom(sharedKey);
1478
-    else
1479
-        connection.emuc.lockRoom('');
1480
-}
1481
-
1482
-/**
1483
- * Sets the shared key.
1484
- */
1485
-function setSharedKey(sKey) {
1486
-    sharedKey = sKey;
1487
-}
1488
-
1489
-/**
1490
- * Updates the room invite url.
1491
- */
1492
-function updateRoomUrl(newRoomUrl) {
1493
-    roomUrl = newRoomUrl;
1494
-
1495
-    // If the invite dialog has been already opened we update the information.
1496
-    var inviteLink = document.getElementById('inviteLinkRef');
1497
-    if (inviteLink) {
1498
-        inviteLink.value = roomUrl;
1499
-        inviteLink.select();
1500
-        document.getElementById('jqi_state0_buttonInvite').disabled = false;
1501
-    }
1502
-}
1503 930
 
1504 931
 /**
1505 932
  * Warning to the user that the conference window is about to be closed.
@@ -1514,19 +941,6 @@ function closePageWarning() {
1514 941
     return "You are about to leave this conversation.";
1515 942
 }
1516 943
 
1517
-/**
1518
- * Resizes and repositions videos in full screen mode.
1519
- */
1520
-$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
1521
-    function () {
1522
-        VideoLayout.resizeLargeVideoContainer();
1523
-        VideoLayout.positionLarge();
1524
-        isFullScreen = document.fullScreen ||
1525
-            document.mozFullScreen ||
1526
-            document.webkitIsFullScreen;
1527
-
1528
-    }
1529
-);
1530 944
 
1531 945
 $(document).bind('error.jingle',
1532 946
     function (event, session, error)
@@ -1540,7 +954,7 @@ $(document).bind('fatalError.jingle',
1540 954
     {
1541 955
         sessionTerminated = true;
1542 956
         connection.emuc.doLeave();
1543
-        messageHandler.showError(  "Sorry",
957
+        UI.messageHandler.showError(  "Sorry",
1544 958
             "Internal application error[setRemoteDescription]");
1545 959
     }
1546 960
 );
@@ -1550,7 +964,7 @@ function callSipButtonClicked()
1550 964
     var defaultNumber
1551 965
         = config.defaultSipNumber ? config.defaultSipNumber : '';
1552 966
 
1553
-    messageHandler.openTwoButtonDialog(null,
967
+    UI.messageHandler.openTwoButtonDialog(null,
1554 968
         '<h2>Enter SIP number</h2>' +
1555 969
             '<input id="sipNumber" type="text"' +
1556 970
             ' value="' + defaultNumber + '" autofocus>',

+ 0
- 343
chat.js Zobrazit soubor

@@ -1,343 +0,0 @@
1
-/* global $, Util, connection, nickname:true, getVideoSize, getVideoPosition, showToolbar, processReplacements */
2
-/**
3
- * Chat related user interface.
4
- */
5
-var Chat = (function (my) {
6
-    var notificationInterval = false;
7
-    var unreadMessages = 0;
8
-
9
-    /**
10
-     * Initializes chat related interface.
11
-     */
12
-    my.init = function () {
13
-        var storedDisplayName = window.localStorage.displayname;
14
-        if (storedDisplayName) {
15
-            nickname = storedDisplayName;
16
-
17
-            Chat.setChatConversationMode(true);
18
-        }
19
-
20
-        $('#nickinput').keydown(function (event) {
21
-            if (event.keyCode === 13) {
22
-                event.preventDefault();
23
-                var val = Util.escapeHtml(this.value);
24
-                this.value = '';
25
-                if (!nickname) {
26
-                    nickname = val;
27
-                    window.localStorage.displayname = nickname;
28
-
29
-                    connection.emuc.addDisplayNameToPresence(nickname);
30
-                    connection.emuc.sendPresence();
31
-
32
-                    Chat.setChatConversationMode(true);
33
-
34
-                    return;
35
-                }
36
-            }
37
-        });
38
-
39
-        $('#usermsg').keydown(function (event) {
40
-            if (event.keyCode === 13) {
41
-                event.preventDefault();
42
-                var value = this.value;
43
-                $('#usermsg').val('').trigger('autosize.resize');
44
-                this.focus();
45
-                var command = new CommandsProcessor(value);
46
-                if(command.isCommand())
47
-                {
48
-                    command.processCommand();
49
-                }
50
-                else
51
-                {
52
-                    var message = Util.escapeHtml(value);
53
-                    connection.emuc.sendMessage(message, nickname);
54
-                }
55
-            }
56
-        });
57
-
58
-        var onTextAreaResize = function () {
59
-            resizeChatConversation();
60
-            Chat.scrollChatToBottom();
61
-        };
62
-        $('#usermsg').autosize({callback: onTextAreaResize});
63
-
64
-        $("#chatspace").bind("shown",
65
-            function () {
66
-                unreadMessages = 0;
67
-                setVisualNotification(false);
68
-            });
69
-
70
-        addSmileys();
71
-    };
72
-
73
-    /**
74
-     * Appends the given message to the chat conversation.
75
-     */
76
-    my.updateChatConversation = function (from, displayName, message) {
77
-        var divClassName = '';
78
-
79
-        if (connection.emuc.myroomjid === from) {
80
-            divClassName = "localuser";
81
-        }
82
-        else {
83
-            divClassName = "remoteuser";
84
-
85
-            if (!Chat.isVisible()) {
86
-                unreadMessages++;
87
-                Util.playSoundNotification('chatNotification');
88
-                setVisualNotification(true);
89
-            }
90
-        }
91
-
92
-        //replace links and smileys
93
-        var escMessage = message.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>'); //Strophe already escapes special symbols on sending, so we escape here only tags to avoid double &amp;
94
-        var escDisplayName = Util.escapeHtml(displayName);
95
-        message = processReplacements(escMessage);
96
-
97
-        var messageContainer =
98
-            '<div class="chatmessage">'+
99
-                '<img src="../images/chatArrow.svg" class="chatArrow">' +
100
-                '<div class="username ' + divClassName +'">' + escDisplayName + '</div>' +
101
-                '<div class="timestamp">' + getCurrentTime() + '</div>' +
102
-                '<div class="usermessage">' + message + '</div>' +
103
-            '</div>';
104
-
105
-        $('#chatconversation').append(messageContainer);
106
-        $('#chatconversation').animate(
107
-                { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
108
-    };
109
-
110
-    /**
111
-     * Appends error message to the conversation
112
-     * @param errorMessage the received error message.
113
-     * @param originalText the original message.
114
-     */
115
-    my.chatAddError = function(errorMessage, originalText)
116
-    {
117
-        errorMessage = Util.escapeHtml(errorMessage);
118
-        originalText = Util.escapeHtml(originalText);
119
-
120
-        $('#chatconversation').append('<div class="errorMessage"><b>Error: </b>'
121
-            + 'Your message' + (originalText? (' \"'+ originalText + '\"') : "")
122
-            + ' was not sent.' + (errorMessage? (' Reason: ' + errorMessage) : '')
123
-            +  '</div>');
124
-        $('#chatconversation').animate(
125
-            { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
126
-    };
127
-
128
-    /**
129
-     * Sets the subject to the UI
130
-     * @param subject the subject
131
-     */
132
-    my.chatSetSubject = function(subject)
133
-    {
134
-        if(subject)
135
-            subject = subject.trim();
136
-        $('#subject').html(linkify(Util.escapeHtml(subject)));
137
-        if(subject == "")
138
-        {
139
-            $("#subject").css({display: "none"});
140
-        }
141
-        else
142
-        {
143
-            $("#subject").css({display: "block"});
144
-        }
145
-    };
146
-
147
-
148
-
149
-    /**
150
-     * Sets the chat conversation mode.
151
-     */
152
-    my.setChatConversationMode = function (isConversationMode) {
153
-        if (isConversationMode) {
154
-            $('#nickname').css({visibility: 'hidden'});
155
-            $('#chatconversation').css({visibility: 'visible'});
156
-            $('#usermsg').css({visibility: 'visible'});
157
-            $('#smileysarea').css({visibility: 'visible'});
158
-            $('#usermsg').focus();
159
-        }
160
-    };
161
-
162
-    /**
163
-     * Resizes the chat area.
164
-     */
165
-    my.resizeChat = function () {
166
-        var chatSize = PanelToggler.getPanelSize();
167
-
168
-        $('#chatspace').width(chatSize[0]);
169
-        $('#chatspace').height(chatSize[1]);
170
-
171
-        resizeChatConversation();
172
-    };
173
-
174
-    /**
175
-     * Indicates if the chat is currently visible.
176
-     */
177
-    my.isVisible = function () {
178
-        return $('#chatspace').is(":visible");
179
-    };
180
-    /**
181
-     * Shows and hides the window with the smileys
182
-     */
183
-    my.toggleSmileys = function() {
184
-        var smileys = $('#smileysContainer');
185
-        if(!smileys.is(':visible')) {
186
-            smileys.show("slide", { direction: "down", duration: 300});
187
-        } else {
188
-            smileys.hide("slide", { direction: "down", duration: 300});
189
-        }
190
-        $('#usermsg').focus();
191
-    };
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
-
203
-    /**
204
-     * Adds the smileys container to the chat
205
-     */
206
-    function addSmileys() {
207
-        var smileysContainer = document.createElement('div');
208
-        smileysContainer.id = 'smileysContainer';
209
-        function addClickFunction(smiley, number) {
210
-            smiley.onclick = function addSmileyToMessage() {
211
-                var usermsg = $('#usermsg');
212
-                var message = usermsg.val();
213
-                message += smileys['smiley' + number];
214
-                usermsg.val(message);
215
-                usermsg.get(0).setSelectionRange(message.length, message.length);
216
-                Chat.toggleSmileys();
217
-                usermsg.focus();
218
-            };
219
-        }
220
-        for(var i = 1; i <= 21; i++) {
221
-            var smileyContainer = document.createElement('div');
222
-            smileyContainer.id = 'smiley' + i;
223
-            smileyContainer.className = 'smileyContainer';
224
-            var smiley = document.createElement('img');
225
-            smiley.src = 'images/smileys/smiley' + i + '.svg';
226
-            smiley.className =  'smiley';
227
-            addClickFunction(smiley, i);
228
-            smileyContainer.appendChild(smiley);
229
-            smileysContainer.appendChild(smileyContainer);
230
-        }
231
-
232
-        $("#chatspace").append(smileysContainer);
233
-    }
234
-
235
-    /**
236
-     * Resizes the chat conversation.
237
-     */
238
-    function resizeChatConversation() {
239
-        var msgareaHeight = $('#usermsg').outerHeight();
240
-        var chatspace = $('#chatspace');
241
-        var width = chatspace.width();
242
-        var chat = $('#chatconversation');
243
-        var smileys = $('#smileysarea');
244
-
245
-        smileys.height(msgareaHeight);
246
-        $("#smileys").css('bottom', (msgareaHeight - 26) / 2);
247
-        $('#smileysContainer').css('bottom', msgareaHeight);
248
-        chat.width(width - 10);
249
-        chat.height(window.innerHeight - 15 - msgareaHeight);
250
-    }
251
-
252
-    /**
253
-     * Shows/hides a visual notification, indicating that a message has arrived.
254
-     */
255
-    function setVisualNotification(show) {
256
-        var unreadMsgElement = document.getElementById('unreadMessages');
257
-        var unreadMsgBottomElement = document.getElementById('bottomUnreadMessages');
258
-
259
-        var glower = $('#chatButton');
260
-        var bottomGlower = $('#chatBottomButton');
261
-
262
-        if (unreadMessages) {
263
-            unreadMsgElement.innerHTML = unreadMessages.toString();
264
-            unreadMsgBottomElement.innerHTML = unreadMessages.toString();
265
-
266
-            ToolbarToggler.dockToolbar(true);
267
-
268
-            var chatButtonElement
269
-                = document.getElementById('chatButton').parentNode;
270
-            var leftIndent = (Util.getTextWidth(chatButtonElement) -
271
-                Util.getTextWidth(unreadMsgElement)) / 2;
272
-            var topIndent = (Util.getTextHeight(chatButtonElement) -
273
-                Util.getTextHeight(unreadMsgElement)) / 2 - 3;
274
-
275
-            unreadMsgElement.setAttribute(
276
-                'style',
277
-                    'top:' + topIndent +
278
-                    '; left:' + leftIndent + ';');
279
-
280
-            var chatBottomButtonElement
281
-                = document.getElementById('chatBottomButton').parentNode;
282
-            var bottomLeftIndent = (Util.getTextWidth(chatBottomButtonElement) -
283
-                Util.getTextWidth(unreadMsgBottomElement)) / 2;
284
-            var bottomTopIndent = (Util.getTextHeight(chatBottomButtonElement) -
285
-                Util.getTextHeight(unreadMsgBottomElement)) / 2 - 2;
286
-
287
-            unreadMsgBottomElement.setAttribute(
288
-                'style',
289
-                    'top:' + bottomTopIndent +
290
-                    '; left:' + bottomLeftIndent + ';');
291
-
292
-
293
-            if (!glower.hasClass('icon-chat-simple')) {
294
-                glower.removeClass('icon-chat');
295
-                glower.addClass('icon-chat-simple');
296
-            }
297
-        }
298
-        else {
299
-            unreadMsgElement.innerHTML = '';
300
-            unreadMsgBottomElement.innerHTML = '';
301
-            glower.removeClass('icon-chat-simple');
302
-            glower.addClass('icon-chat');
303
-        }
304
-
305
-        if (show && !notificationInterval) {
306
-            notificationInterval = window.setInterval(function () {
307
-                glower.toggleClass('active');
308
-                bottomGlower.toggleClass('active glowing');
309
-            }, 800);
310
-        }
311
-        else if (!show && notificationInterval) {
312
-            window.clearInterval(notificationInterval);
313
-            notificationInterval = false;
314
-            glower.removeClass('active');
315
-            bottomGlower.removeClass('glowing');
316
-            bottomGlower.addClass('active');
317
-        }
318
-    }
319
-
320
-
321
-    /**
322
-     * Returns the current time in the format it is shown to the user
323
-     * @returns {string}
324
-     */
325
-    function getCurrentTime() {
326
-        var now     = new Date();
327
-        var hour    = now.getHours();
328
-        var minute  = now.getMinutes();
329
-        var second  = now.getSeconds();
330
-        if(hour.toString().length === 1) {
331
-            hour = '0'+hour;
332
-        }
333
-        if(minute.toString().length === 1) {
334
-            minute = '0'+minute;
335
-        }
336
-        if(second.toString().length === 1) {
337
-            second = '0'+second;
338
-        }
339
-        return hour+':'+minute+':'+second;
340
-    }
341
-
342
-    return my;
343
-}(Chat || {}));

+ 0
- 98
commands.js Zobrazit soubor

@@ -1,98 +0,0 @@
1
-/**
2
- * Handles commands received via chat messages.
3
- */
4
-var CommandsProcessor = (function()
5
-{
6
-    /**
7
-     * Constructs new CommandProccessor instance from a message.
8
-     * @param message the message
9
-     * @constructor
10
-     */
11
-    function CommandsPrototype(message)
12
-    {
13
-        /**
14
-         * Extracts the command from the message.
15
-         * @param message the received message
16
-         * @returns {string} the command
17
-         */
18
-        function getCommand(message)
19
-        {
20
-            if(message)
21
-            {
22
-                for(var command in commands)
23
-                {
24
-                    if(message.indexOf("/" + command) == 0)
25
-                        return command;
26
-                }
27
-            }
28
-            return "";
29
-        };
30
-
31
-        var command = getCommand(message);
32
-
33
-        /**
34
-         * Returns the name of the command.
35
-         * @returns {String} the command
36
-         */
37
-        this.getCommand = function()
38
-        {
39
-            return command;
40
-        }
41
-
42
-
43
-        var messageArgument = message.substr(command.length + 2);
44
-
45
-        /**
46
-         * Returns the arguments of the command.
47
-         * @returns {string}
48
-         */
49
-        this.getArgument = function()
50
-        {
51
-            return messageArgument;
52
-        }
53
-    }
54
-
55
-    /**
56
-     * Checks whether this instance is valid command or not.
57
-     * @returns {boolean}
58
-     */
59
-    CommandsPrototype.prototype.isCommand = function()
60
-    {
61
-        if(this.getCommand())
62
-            return true;
63
-        return false;
64
-    }
65
-
66
-    /**
67
-     * Processes the command.
68
-     */
69
-    CommandsPrototype.prototype.processCommand = function()
70
-    {
71
-        if(!this.isCommand())
72
-            return;
73
-
74
-        commands[this.getCommand()](this.getArgument());
75
-
76
-    }
77
-
78
-    /**
79
-     * Processes the data for topic command.
80
-     * @param commandArguments the arguments of the topic command.
81
-     */
82
-    var processTopic = function(commandArguments)
83
-    {
84
-        var topic = Util.escapeHtml(commandArguments);
85
-        connection.emuc.setSubject(topic);
86
-    }
87
-
88
-    /**
89
-     * List with supported commands. The keys are the names of the commands and
90
-     * the value is the function that processes the message.
91
-     * @type {{String: function}}
92
-     */
93
-    var commands = {
94
-        "topic" : processTopic
95
-    };
96
-
97
-    return CommandsPrototype;
98
-})();

+ 4
- 4
connectionquality.js Zobrazit soubor

@@ -32,7 +32,7 @@ var ConnectionQuality = (function () {
32 32
      */
33 33
     ConnectionQuality.updateLocalStats = function (data) {
34 34
         stats = data;
35
-        VideoLayout.updateLocalConnectionStats(100 - stats.packetLoss.total,stats);
35
+        UI.updateLocalConnectionStats(100 - stats.packetLoss.total,stats);
36 36
         if(sendIntervalId == null)
37 37
         {
38 38
             startSendingStats();
@@ -97,12 +97,12 @@ var ConnectionQuality = (function () {
97 97
     ConnectionQuality.updateRemoteStats = function (jid, data) {
98 98
         if(data == null || data.packetLoss_total == null)
99 99
         {
100
-            VideoLayout.updateConnectionStats(jid, null, null);
100
+            UI.updateConnectionStats(jid, null, null);
101 101
             return;
102 102
         }
103 103
         remoteStats[jid] = parseMUCStats(data);
104 104
 
105
-        VideoLayout.updateConnectionStats(jid, 100 - data.packetLoss_total,remoteStats[jid]);
105
+        UI.updateConnectionStats(jid, 100 - data.packetLoss_total,remoteStats[jid]);
106 106
 
107 107
     };
108 108
 
@@ -113,7 +113,7 @@ var ConnectionQuality = (function () {
113 113
         clearInterval(sendIntervalId);
114 114
         sendIntervalId = null;
115 115
         //notify UI about stopping statistics gathering
116
-        VideoLayout.onStatsStop();
116
+        UI.onStatsStop();
117 117
     };
118 118
 
119 119
     /**

+ 6
- 6
desktopsharing.js Zobrazit soubor

@@ -1,4 +1,4 @@
1
-/* global $, alert, changeLocalVideo, chrome, config, connection, getConferenceHandler, getUserMediaWithConstraints, VideoLayout */
1
+/* global $, alert, changeLocalVideo, chrome, config, connection, getConferenceHandler, getUserMediaWithConstraints */
2 2
 /**
3 3
  * Indicates that desktop stream is currently in use(for toggle purpose).
4 4
  * @type {boolean}
@@ -86,7 +86,7 @@ function isUpdateRequired(minVersion, extVersion)
86 86
     catch (e)
87 87
     {
88 88
         console.error("Failed to parse extension version", e);
89
-        messageHandler.showError('Error',
89
+        UI.messageHandler.showError('Error',
90 90
             'Error when trying to detect desktopsharing extension.');
91 91
         return true;
92 92
     }
@@ -168,7 +168,7 @@ function obtainScreenFromExtension(streamCallback, failCallback) {
168 168
                     function (arg) {
169 169
                         console.log("Failed to install the extension", arg);
170 170
                         failCallback(arg);
171
-                        messageHandler.showError('Error',
171
+                        UI.messageHandler.showError('Error',
172 172
                             'Failed to install desktop sharing extension');
173 173
                     }
174 174
                 );
@@ -247,7 +247,7 @@ function streamSwitchDone() {
247 247
     //window.setTimeout(
248 248
     //    function () {
249 249
     switchInProgress = false;
250
-    Toolbar.changeDesktopSharingButtonState(isUsingScreenStream);
250
+    UI.changeDesktopSharingButtonState(isUsingScreenStream);
251 251
     //    }, 100
252 252
     //);
253 253
 }
@@ -258,7 +258,7 @@ function newStreamCreated(stream) {
258 258
 
259 259
     connection.jingle.localVideo = stream;
260 260
 
261
-    VideoLayout.changeLocalVideo(stream, !isUsingScreenStream);
261
+    UI.changeLocalVideo(stream, !isUsingScreenStream);
262 262
 
263 263
     var conferenceHandler = getConferenceHandler();
264 264
     if (conferenceHandler) {
@@ -267,7 +267,7 @@ function newStreamCreated(stream) {
267 267
     } else {
268 268
         // We are done immediately
269 269
         console.error("No conference handler");
270
-        messageHandler.showError('Error',
270
+        UI.messageHandler.showError('Error',
271 271
             'Unable to switch video stream.');
272 272
         streamSwitchDone();
273 273
     }

+ 0
- 206
etherpad.js Zobrazit soubor

@@ -1,206 +0,0 @@
1
-/* global $, config, connection, dockToolbar, Moderator, Prezi,
2
-   setLargeVideoVisible, ToolbarToggler, Util, VideoLayout */
3
-var Etherpad = (function (my) {
4
-    var etherpadName = null;
5
-    var etherpadIFrame = null;
6
-    var domain = null;
7
-    var options = "?showControls=true&showChat=false&showLineNumbers=true&useMonospaceFont=false";
8
-
9
-    /**
10
-     * Initializes the etherpad.
11
-     */
12
-    my.init = function (name) {
13
-
14
-        if (config.etherpad_base && !etherpadName) {
15
-
16
-            domain = config.etherpad_base;
17
-
18
-            if (!name) {
19
-                // In case we're the focus we generate the name.
20
-                etherpadName = Math.random().toString(36).substring(7) +
21
-                                '_' + (new Date().getTime()).toString();
22
-                shareEtherpad();
23
-            }
24
-            else
25
-                etherpadName = name;
26
-
27
-            enableEtherpadButton();
28
-        }
29
-    };
30
-
31
-    /**
32
-     * Opens/hides the Etherpad.
33
-     */
34
-    my.toggleEtherpad = function (isPresentation) {
35
-        if (!etherpadIFrame)
36
-            createIFrame();
37
-
38
-        var largeVideo = null;
39
-        if (Prezi.isPresentationVisible())
40
-            largeVideo = $('#presentation>iframe');
41
-        else
42
-            largeVideo = $('#largeVideo');
43
-
44
-        if ($('#etherpad>iframe').css('visibility') === 'hidden') {
45
-            $('#activeSpeaker').css('visibility', 'hidden');
46
-            largeVideo.fadeOut(300, function () {
47
-                if (Prezi.isPresentationVisible()) {
48
-                    largeVideo.css({opacity: '0'});
49
-                } else {
50
-                    VideoLayout.setLargeVideoVisible(false);
51
-                }
52
-            });
53
-
54
-            $('#etherpad>iframe').fadeIn(300, function () {
55
-                document.body.style.background = '#eeeeee';
56
-                $('#etherpad>iframe').css({visibility: 'visible'});
57
-                $('#etherpad').css({zIndex: 2});
58
-            });
59
-        }
60
-        else if ($('#etherpad>iframe')) {
61
-            $('#etherpad>iframe').fadeOut(300, function () {
62
-                $('#etherpad>iframe').css({visibility: 'hidden'});
63
-                $('#etherpad').css({zIndex: 0});
64
-                document.body.style.background = 'black';
65
-            });
66
-
67
-            if (!isPresentation) {
68
-                $('#largeVideo').fadeIn(300, function () {
69
-                    VideoLayout.setLargeVideoVisible(true);
70
-                });
71
-            }
72
-        }
73
-        resize();
74
-    };
75
-
76
-    my.isVisible = function() {
77
-        var etherpadIframe = $('#etherpad>iframe');
78
-        return etherpadIframe && etherpadIframe.is(':visible');
79
-    };
80
-
81
-    /**
82
-     * Resizes the etherpad.
83
-     */
84
-    function resize() {
85
-        if ($('#etherpad>iframe').length) {
86
-            var remoteVideos = $('#remoteVideos');
87
-            var availableHeight
88
-                = window.innerHeight - remoteVideos.outerHeight();
89
-            var availableWidth = Util.getAvailableVideoWidth();
90
-
91
-            $('#etherpad>iframe').width(availableWidth);
92
-            $('#etherpad>iframe').height(availableHeight);
93
-        }
94
-    }
95
-
96
-    /**
97
-     * Shares the Etherpad name with other participants.
98
-     */
99
-    function shareEtherpad() {
100
-        connection.emuc.addEtherpadToPresence(etherpadName);
101
-        connection.emuc.sendPresence();
102
-    }
103
-
104
-    /**
105
-     * Creates the Etherpad button and adds it to the toolbar.
106
-     */
107
-    function enableEtherpadButton() {
108
-        if (!$('#etherpadButton').is(":visible"))
109
-            $('#etherpadButton').css({display: 'inline-block'});
110
-    }
111
-
112
-    /**
113
-     * Creates the IFrame for the etherpad.
114
-     */
115
-    function createIFrame() {
116
-        etherpadIFrame = document.createElement('iframe');
117
-        etherpadIFrame.src = domain + etherpadName + options;
118
-        etherpadIFrame.frameBorder = 0;
119
-        etherpadIFrame.scrolling = "no";
120
-        etherpadIFrame.width = $('#largeVideoContainer').width() || 640;
121
-        etherpadIFrame.height = $('#largeVideoContainer').height() || 480;
122
-        etherpadIFrame.setAttribute('style', 'visibility: hidden;');
123
-
124
-        document.getElementById('etherpad').appendChild(etherpadIFrame);
125
-
126
-        etherpadIFrame.onload = function() {
127
-
128
-            document.domain = document.domain;
129
-            bubbleIframeMouseMove(etherpadIFrame);
130
-            setTimeout(function() {
131
-            //the iframes inside of the etherpad are not yet loaded when the etherpad iframe is loaded
132
-                var outer = etherpadIFrame.contentDocument.getElementsByName("ace_outer")[0];
133
-                bubbleIframeMouseMove(outer);
134
-                var inner = outer.contentDocument.getElementsByName("ace_inner")[0];
135
-                bubbleIframeMouseMove(inner);
136
-            }, 2000);
137
-        };
138
-    }
139
-
140
-    function bubbleIframeMouseMove(iframe){
141
-        var existingOnMouseMove = iframe.contentWindow.onmousemove;
142
-        iframe.contentWindow.onmousemove = function(e){
143
-            if(existingOnMouseMove) existingOnMouseMove(e);
144
-            var evt = document.createEvent("MouseEvents");
145
-            var boundingClientRect = iframe.getBoundingClientRect();
146
-            evt.initMouseEvent(
147
-                "mousemove",
148
-                true, // bubbles
149
-                false, // not cancelable
150
-                window,
151
-                e.detail,
152
-                e.screenX,
153
-                e.screenY,
154
-                    e.clientX + boundingClientRect.left,
155
-                    e.clientY + boundingClientRect.top,
156
-                e.ctrlKey,
157
-                e.altKey,
158
-                e.shiftKey,
159
-                e.metaKey,
160
-                e.button,
161
-                null // no related element
162
-            );
163
-            iframe.dispatchEvent(evt);
164
-        };
165
-    }
166
-
167
-    /**
168
-     * On Etherpad added to muc.
169
-     */
170
-    $(document).bind('etherpadadded.muc', function (event, jid, etherpadName) {
171
-        console.log("Etherpad added", etherpadName);
172
-        if (config.etherpad_base && !Moderator.isModerator()) {
173
-            Etherpad.init(etherpadName);
174
-        }
175
-    });
176
-
177
-    /**
178
-     * On focus changed event.
179
-     */
180
-    // FIXME: there is no such event as 'focusechanged.muc'
181
-    $(document).bind('focusechanged.muc', function (event, focus) {
182
-        console.log("Focus changed");
183
-        if (config.etherpad_base)
184
-            shareEtherpad();
185
-    });
186
-
187
-    /**
188
-     * On video selected event.
189
-     */
190
-    $(document).bind('video.selected', function (event, isPresentation) {
191
-        if (!config.etherpad_base)
192
-            return;
193
-
194
-        if (etherpadIFrame && etherpadIFrame.style.visibility !== 'hidden')
195
-            Etherpad.toggleEtherpad(isPresentation);
196
-    });
197
-
198
-    /**
199
-     * Resizes the etherpad, when the window is resized.
200
-     */
201
-    $(window).resize(function () {
202
-        resize();
203
-    });
204
-
205
-    return my;
206
-}(Etherpad || {}));

+ 28
- 49
index.html Zobrazit soubor

@@ -31,44 +31,24 @@
31 31
     <script src="libs/pako.bundle.js?v=1"></script><!-- zlib deflate -->
32 32
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
33 33
     <script src="interface_config.js?v=5"></script>
34
+    <script src="service/RTC/RTCBrowserType.js?v=1"></script>
35
+    <script src="service/RTC/StreamEventTypes.js?v=1"></script>
36
+    <script src="service/RTC/MediaStreamTypes.js?v=1"></script>
37
+    <script src="libs/modules/UI.bundle.js?v=1"></script>
38
+    <script src="libs/modules/statistics.bundle.js?v=1"></script>
39
+    <script src="libs/modules/RTC.bundle.js?v=1"></script>
34 40
     <script src="muc.js?v=17"></script><!-- simple MUC library -->
35 41
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
36 42
     <script src="desktopsharing.js?v=3"></script><!-- desktop sharing -->
37 43
     <script src="app.js?v=22"></script><!-- application logic -->
38
-    <script src="commands.js?v=1"></script><!-- application logic -->
39
-    <script src="chat.js?v=15"></script><!-- chat logic -->
40
-    <script src="contact_list.js?v=8"></script><!-- contact list logic -->
41
-    <script src="side_panel_toggler.js?v=1"></script>
42 44
     <script src="util.js?v=7"></script><!-- utility functions -->
43
-    <script src="etherpad.js?v=10"></script><!-- etherpad plugin -->
44
-    <script src="prezi.js?v=7"></script><!-- prezi plugin -->
45
-    <script src="smileys.js?v=3"></script><!-- smiley images -->
46
-    <script src="replacement.js?v=7"></script><!-- link and smiley replacement -->
47 45
     <script src="moderatemuc.js?v=4"></script><!-- moderator plugin -->
48 46
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
49
-    <script src="videolayout.js?v=31"></script><!-- video ui -->
50 47
     <script src="connectionquality.js?v=1"></script>
51
-    <script src="toolbar.js?v=7"></script><!-- toolbar ui -->
52
-    <script src="toolbar_toggler.js?v=2"></script>
53
-    <script src="canvas_util.js?v=1"></script><!-- canvas drawing utils -->
54
-    <script src="audio_levels.js?v=4"></script><!-- audio levels plugin -->
55
-    <script src="media_stream.js?v=2"></script><!-- media stream -->
56
-    <script src="bottom_toolbar.js?v=6"></script><!-- media stream -->
57 48
     <script src="moderator.js?v=2"></script><!-- media stream -->
58
-    <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="recording.js?v=1"></script>
61 49
     <script src="tracking.js?v=1"></script><!-- tracking -->
62
-    <script src="jitsipopover.js?v=3"></script>
63
-    <script src="message_handler.js?v=2"></script>
64 50
     <script src="api_connector.js?v=2"></script>
65
-    <script src="settings_menu.js?v=1"></script>
66
-    <script src="service/RTC/RTCBrowserType.js?v=1"></script>
67
-    <script src="service/RTC/StreamEventTypes.js?v=1"></script>
68
-    <script src="service/RTC/MediaStreamTypes.js?v=1"></script>
69
-    <script src="libs/modules/statistics.bundle.js?v=1"></script>
70
-    <script src="libs/modules/RTC.bundle.js?v=1"></script>
71
-    <script src="avatar.js?v=4"></script><!-- avatars -->
51
+    <script src="keyboard_shortcut.js?v=1"></script>
72 52
     <link rel="stylesheet" href="css/font.css?v=6"/>
73 53
     <link rel="stylesheet" href="css/toastr.css?v=1">
74 54
     <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=30"/>
@@ -89,7 +69,6 @@
89 69
     <link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/diibjkoicjeejcmhdnailmkgecihlobk">
90 70
     <script src="libs/jquery-impromptu.js"></script>
91 71
     <script src="libs/jquery.autosize.js"></script>
92
-    <script src="libs/prezi_player.js?v=2"></script>
93 72
   </head>
94 73
   <body>
95 74
     <div id="welcome_page">
@@ -179,36 +158,36 @@
179 158
         <div style="position: relative;" id="header_container">
180 159
             <div id="header">
181 160
                 <span id="toolbar">
182
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="mutePopover" content="Mute / Unmute" onclick='toggleAudio();'>
161
+                    <a class="button" id="toolbar_button_mute" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="mutePopover" content="Mute / Unmute">
183 162
                         <i id="mute" class="icon-microphone"></i>
184 163
                     </a>
185 164
                     <div class="header_button_separator"></div>
186
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" content="Start / stop camera" onclick='toggleVideo();'>
165
+                    <a class="button" id="toolbar_button_camera" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" content="Start / stop camera" onclick='toggleVideo();'>
187 166
                         <i id="video" class="icon-camera"></i>
188 167
                     </a>
189 168
                     <span id="authentication" style="display: none">
190 169
                         <div class="header_button_separator"></div>
191
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Authenticate" onclick='authenticateClicked();'>
170
+                        <a class="button" id="toolbar_button_authentication" data-container="body" data-toggle="popover" data-placement="bottom" content="Authenticate">
192 171
                             <i id="authButton" class="icon-avatar"></i>
193 172
                         </a>
194 173
                     </span>
195 174
                     <span id="recording" style="display: none">
196 175
                         <div class="header_button_separator"></div>
197
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Record" onclick='toggleRecording();'>
176
+                        <a class="button" id="toolbar_button_record" data-container="body" data-toggle="popover" data-placement="bottom" content="Record">
198 177
                             <i id="recordButton" class="icon-recEnable"></i>
199 178
                         </a>
200 179
                     </span>
201 180
                     <div class="header_button_separator"></div>
202
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Lock / unlock room" onclick="Toolbar.openLockDialog();">
181
+                    <a class="button" id="toolbar_button_security" data-container="body" data-toggle="popover" data-placement="bottom" content="Lock / unlock room">
203 182
                         <i id="lockIcon" class="icon-security"></i>
204 183
                     </a>
205 184
                     <div class="header_button_separator"></div>
206
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Invite others" onclick="Toolbar.openLinkDialog();">
185
+                    <a class="button" id="toolbar_button_link" data-container="body" data-toggle="popover" data-placement="bottom" content="Invite others">
207 186
                         <i class="icon-link"></i>
208 187
                     </a>
209 188
                     <div class="header_button_separator"></div>
210 189
                     <span class="toolbar_span">
211
-                        <a class="button" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="bottom" content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
190
+                        <a class="button" id="toolbar_button_chat" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="bottom" content="Open / close chat">
212 191
                             <i id="chatButton" class="icon-chat">
213 192
                                 <span id="unreadMessages"></span>
214 193
                             </i>
@@ -216,38 +195,38 @@
216 195
                     </span>
217 196
                     <span id="prezi_button">
218 197
                         <div class="header_button_separator"></div>
219
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Share Prezi" onclick='Prezi.openPreziDialog();'>
198
+                        <a class="button" id="toolbar_button_prezi" data-container="body" data-toggle="popover" data-placement="bottom" content="Share Prezi">
220 199
                             <i class="icon-prezi"></i>
221 200
                         </a>
222 201
                     </span>
223 202
                     <span id="etherpadButton">
224 203
                         <div class="header_button_separator"></div>
225
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Shared document" onclick='Etherpad.toggleEtherpad(0);'>
204
+                        <a class="button" id="toolbar_button_etherpad" data-container="body" data-toggle="popover" data-placement="bottom" content="Shared document">
226 205
                             <i class="icon-share-doc"></i>
227 206
                         </a>
228 207
                     </span>
229 208
                     <div class="header_button_separator"></div>
230 209
                     <span id="desktopsharing" style="display: none">
231
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Share screen" onclick="toggleScreenSharing();">
210
+                        <a class="button" id="toolbar_button_desktopsharing" data-container="body" data-toggle="popover" data-placement="bottom" content="Share screen">
232 211
                             <i class="icon-share-desktop"></i>
233 212
                         </a>
234 213
                     </span>
235 214
                     <div class="header_button_separator"></div>
236
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Enter / Exit Full Screen" onclick='buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");Toolbar.toggleFullScreen();'>
215
+                    <a class="button" id="toolbar_button_fullScreen" data-container="body" data-toggle="popover" data-placement="bottom" content="Enter / Exit Full Screen">
237 216
                         <i id="fullScreen" class="icon-full-screen"></i>
238 217
                     </a>
239 218
                     <span id="sipCallButton" style="display: none">
240 219
                         <div class="header_button_separator"></div>
241
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Call SIP number" onclick='callSipButtonClicked();'>
220
+                        <a class="button" id="toolbar_button_sip" data-container="body" data-toggle="popover" data-placement="bottom" content="Call SIP number">
242 221
                             <i class="icon-telephone"></i></a>
243 222
                     </span>
244 223
                     <div class="header_button_separator"></div>
245
-                    <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Settings" onclick='PanelToggler.toggleSettingsMenu();'>
224
+                    <a class="button" id="toolbar_button_settings" data-container="body" data-toggle="popover" data-placement="bottom" content="Settings" >
246 225
                         <i id="settingsButton" class="icon-settings"></i>
247 226
                     </a>
248 227
                     <div class="header_button_separator"></div>
249 228
                     <span id="hangup">
250
-                        <a class="button" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up" onclick='hangup();'>
229
+                        <a class="button" id="toolbar_button_hangup" data-container="body" data-toggle="popover" data-placement="bottom" content="Hang Up">
251 230
                             <i class="icon-hangup" style="color:#ff0000;font-size: 1.4em;"></i>
252 231
                         </a>
253 232
                     </span>
@@ -264,8 +243,8 @@
264 243
             <input id="connect" type="submit" value="Connect" />
265 244
           </form>
266 245
         </div>
267
-        <div id="reloadPresentation"><a onclick='Prezi.reloadPresentation();'><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
268
-        <div id="videospace" onmousemove="ToolbarToggler.showToolbar();">
246
+        <div id="reloadPresentation"><a id="reloadPresentationLink"><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
247
+        <div id="videospace">
269 248
             <div id="largeVideoContainer" class="videocontainer">
270 249
                 <div id="presentation"></div>
271 250
                 <div id="etherpad"></div>
@@ -297,7 +276,7 @@
297 276
             </div>
298 277
             <span id="bottomToolbar">
299 278
                 <span class="bottomToolbar_span">
300
-                    <a class="bottomToolbarButton" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="top" content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
279
+                    <a class="bottomToolbarButton" id="bottom_toolbar_chat" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="top" content="Open / close chat">
301 280
                         <i id="chatBottomButton" class="icon-chat-simple">
302 281
                             <span id="bottomUnreadMessages"></span>
303 282
                         </i>
@@ -305,7 +284,7 @@
305 284
                 </span>
306 285
                 <div class="bottom_button_separator"></div>
307 286
                 <span class="bottomToolbar_span">
308
-                    <a class="bottomToolbarButton" data-container="body" data-toggle="popover" data-placement="top" id="contactlistpopover" content="Open / close contact list" onclick='BottomToolbar.toggleContactList();'>
287
+                    <a class="bottomToolbarButton" id="bottom_toolbar_contact_list" data-container="body" data-toggle="popover" data-placement="top" id="contactlistpopover" content="Open / close contact list">
309 288
                         <i id="contactListButton" class="icon-contactList">
310 289
                             <span id="numberOfParticipants"></span>
311 290
                         </i>
@@ -313,7 +292,7 @@
313 292
                 </span>
314 293
                 <div class="bottom_button_separator"></div>
315 294
                 <span class="bottomToolbar_span">
316
-                    <a class="bottomToolbarButton" data-container="body" data-toggle="popover" shortcut="filmstripPopover" data-placement="top" content="Show / hide film strip" onclick='BottomToolbar.toggleFilmStrip()'>
295
+                    <a class="bottomToolbarButton" id="bottom_toolbar_film_strip" data-container="body" data-toggle="popover" shortcut="filmstripPopover" data-placement="top" content="Show / hide film strip">
317 296
                         <i id="filmStripButton" class="icon-filmstrip"></i>
318 297
                     </a>
319 298
                 </span>
@@ -332,7 +311,7 @@
332 311
             <audio id="chatNotification" src="sounds/incomingMessage.wav" preload="auto"></audio>
333 312
                 <textarea id="usermsg" placeholder='Enter text...' autofocus></textarea>
334 313
             <div id="smileysarea">
335
-                <div id="smileys" onclick="Chat.toggleSmileys()">
314
+                <div id="smileys" id="toggle_smileys">
336 315
                     <img src="images/smile.svg"/>
337 316
                 </div>
338 317
             </div>
@@ -348,7 +327,7 @@
348 327
             <div class="arrow-up"></div>
349 328
             <input type="text" id="setDisplayName" placeholder="Name">
350 329
             <input type="text" id="setEmail" placeholder="E-Mail">
351
-            <button onclick="SettingsMenu.update()" id="updateSettings">Update</button>
330
+            <button id="updateSettings">Update</button>
352 331
         </div>
353 332
         <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>
354 333
     </div>

+ 3
- 3
keyboard_shortcut.js Zobrazit soubor

@@ -4,12 +4,12 @@ var KeyboardShortcut = (function(my) {
4 4
         67: {
5 5
             character: "C",
6 6
             id: "toggleChatPopover",
7
-            function: BottomToolbar.toggleChat
7
+            function: UI.toggleChat
8 8
         },
9 9
         70: {
10 10
             character: "F",
11 11
             id: "filmstripPopover",
12
-            function: BottomToolbar.toggleFilmStrip
12
+            function: UI.toggleFilmStrip
13 13
         },
14 14
         77: {
15 15
             character: "M",
@@ -45,7 +45,7 @@ var KeyboardShortcut = (function(my) {
45 45
             }
46 46
           //esc while the smileys are visible hides them
47 47
         } else if (keycode === 27 && $('#smileysContainer').is(':visible')) {
48
-            Chat.toggleSmileys();
48
+            UI.toggleSmileys();
49 49
         }
50 50
     };
51 51
 

+ 8
- 3
libs/colibri/colibri.focus.js Zobrazit soubor

@@ -92,6 +92,12 @@ function ColibriFocus(connection, bridgejid) {
92 92
     this.endpointsInfo = null;
93 93
 }
94 94
 
95
+function conferenceCreated(focus)
96
+{
97
+    statistics.onConfereceCreated(getConferenceHandler());
98
+    RTC.onConfereceCreated(focus);
99
+}
100
+
95 101
 // creates a conferences with an initial set of peers
96 102
 ColibriFocus.prototype.makeConference = function (peers, errorCallback) {
97 103
     var self = this;
@@ -411,7 +417,7 @@ ColibriFocus.prototype.createdConference = function (result) {
411 417
     console.log('remote channels', this.channels);
412 418
 
413 419
     // Notify that the focus has created the conference on the bridge
414
-    $(document).trigger('conferenceCreated.jingle', [self]);
420
+    conferenceCreated(self);
415 421
 
416 422
     var bridgeSDP = new SDP(
417 423
         'v=0\r\n' +
@@ -561,8 +567,7 @@ ColibriFocus.prototype.createdConference = function (result) {
561 567
                             }
562 568
 
563 569
                             // Notify we've created the conference
564
-                            $(document).trigger(
565
-                                'conferenceCreated.jingle', self);
570
+                            conferenceCreated(self);
566 571
                         },
567 572
                         function (error) {
568 573
                             console.warn('setLocalDescription failed.', error);

+ 5
- 4
libs/modules/RTC.bundle.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 6397
- 0
libs/modules/UI.bundle.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 3
- 3
libs/modules/statistics.bundle.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 20
- 1
libs/strophe/strophe.jingle.js Zobrazit soubor

@@ -1,4 +1,23 @@
1 1
 /* jshint -W117 */
2
+
3
+
4
+function CallIncomingJingle(sid) {
5
+    var sess = connection.jingle.sessions[sid];
6
+
7
+    // TODO: do we check activecall == null?
8
+    activecall = sess;
9
+
10
+    statistics.onConferenceCreated(sess);
11
+    RTC.onConferenceCreated(sess);
12
+
13
+    // TODO: check affiliation and/or role
14
+    console.log('emuc data for', sess.peerjid, connection.emuc.members[sess.peerjid]);
15
+    sess.usedrip = true; // not-so-naive trickle ice
16
+    sess.sendAnswer();
17
+    sess.accept();
18
+
19
+};
20
+
2 21
 Strophe.addConnectionPlugin('jingle', {
3 22
     connection: null,
4 23
     sessions: {},
@@ -110,7 +129,7 @@ Strophe.addConnectionPlugin('jingle', {
110 129
                 // the callback should either
111 130
                 // .sendAnswer and .accept
112 131
                 // or .sendTerminate -- not necessarily synchronus
113
-                $(document).trigger('callincoming.jingle', [sess.sid]);
132
+                CallIncomingJingle(sess.sid);
114 133
                 break;
115 134
             case 'session-accept':
116 135
                 sess.setRemoteDescription($(iq).find('>jingle'), 'answer');

+ 1
- 5
moderatemuc.js Zobrazit soubor

@@ -1,4 +1,4 @@
1
-/* global $, $iq, config, connection, focusMucJid, forceMuted, messageHandler,
1
+/* global $, $iq, config, connection, focusMucJid, forceMuted,
2 2
    setAudioMuted, Strophe, toggleAudio */
3 3
 /**
4 4
  * Moderate connection plugin.
@@ -32,10 +32,6 @@ Strophe.addConnectionPlugin('moderate', {
32 32
             },
33 33
             function (error) {
34 34
                 console.log('set mute error', error);
35
-                // FIXME: this causes an exception
36
-                //messageHandler.openReportDialog(null, 'Failed to mute ' +
37
-                  //  $("#participant_" + jid).find(".displayname").text() ||
38
-                    //"participant" + '.', error);
39 35
             });
40 36
     },
41 37
     onMute: function (iq) {

+ 21
- 42
moderator.js Zobrazit soubor

@@ -1,5 +1,5 @@
1 1
 /* global $, $iq, config, connection, Etherpad, hangUp, messageHandler,
2
- roomName, sessionTerminated, Strophe, Toolbar, Util, VideoLayout */
2
+ roomName, sessionTerminated, Strophe, Util */
3 3
 /**
4 4
  * Contains logic responsible for enabling/disabling functionality available
5 5
  * only to moderator users.
@@ -13,57 +13,36 @@ var Moderator = (function (my) {
13 13
     var externalAuthEnabled = false;
14 14
 
15 15
     my.isModerator = function () {
16
-        return connection.emuc.isModerator();
16
+        return connection && connection.emuc.isModerator();
17 17
     };
18 18
 
19 19
     my.isPeerModerator = function (peerJid) {
20
-        return connection.emuc.getMemberRole(peerJid) === 'moderator';
20
+        return connection && connection.emuc.getMemberRole(peerJid) === 'moderator';
21 21
     };
22 22
 
23 23
     my.isExternalAuthEnabled = function () {
24 24
         return externalAuthEnabled;
25 25
     };
26 26
 
27
-    my.onModeratorStatusChanged = function (isModerator) {
28
-
29
-        Toolbar.showSipCallButton(isModerator);
30
-        Toolbar.showRecordingButton(
31
-                isModerator); //&&
32
-                // FIXME:
33
-                // Recording visible if
34
-                // there are at least 2(+ 1 focus) participants
35
-                //Object.keys(connection.emuc.members).length >= 3);
36
-
37
-        if (isModerator && config.etherpad_base) {
38
-            Etherpad.init();
39
-        }
40
-    };
41
-
42 27
     my.init = function () {
43
-        $(document).bind(
44
-            'local.role.changed.muc',
45
-            function (event, jid, info, pres) {
46
-                Moderator.onModeratorStatusChanged(Moderator.isModerator());
47
-            }
48
-        );
49
-
50
-        $(document).bind(
51
-            'left.muc',
52
-            function (event, jid) {
53
-                console.info("Someone left is it focus ? " + jid);
54
-                var resource = Strophe.getResourceFromJid(jid);
55
-                if (resource === 'focus' && !sessionTerminated) {
56
-                    console.info(
57
-                        "Focus has left the room - leaving conference");
58
-                    //hangUp();
59
-                    // We'd rather reload to have everything re-initialized
60
-                    // FIXME: show some message before reload
61
-                    location.reload();
62
-                }
63
-            }
64
-        );
28
+        Moderator.onLocalRoleChange = function (from, member, pres) {
29
+            UI.onModeratorStatusChanged(Moderator.isModerator());
30
+        };
65 31
     };
66 32
 
33
+    my.onMucLeft = function (jid) {
34
+        console.info("Someone left is it focus ? " + jid);
35
+        var resource = Strophe.getResourceFromJid(jid);
36
+        if (resource === 'focus' && !sessionTerminated) {
37
+            console.info(
38
+                "Focus has left the room - leaving conference");
39
+            //hangUp();
40
+            // We'd rather reload to have everything re-initialized
41
+            // FIXME: show some message before reload
42
+            location.reload();
43
+        }
44
+    }
45
+
67 46
     my.setFocusUserJid = function (focusJid) {
68 47
         if (!focusUserJid) {
69 48
             focusUserJid = focusJid;
@@ -185,13 +164,13 @@ var Moderator = (function (my) {
185 164
                 // Not authorized to create new room
186 165
                 if ($(error).find('>error>not-authorized').length) {
187 166
                     console.warn("Unauthorized to start the conference");
188
-                    $(document).trigger('auth_required.moderator');
167
+                    UI.onAuthenticationRequired();
189 168
                     return;
190 169
                 }
191 170
                 var waitMs = getNextErrorTimeout();
192 171
                 console.error("Focus error, retry after " + waitMs, error);
193 172
                 // Show message
194
-                messageHandler.notify(
173
+                UI.messageHandler.notify(
195 174
                     'Conference focus', 'disconnected',
196 175
                     Moderator.getFocusComponent() +
197 176
                     ' not available - retry in ' + (waitMs / 1000) + ' sec');

+ 1
- 1
modules/RTC/DataChannels.js Zobrazit soubor

@@ -32,7 +32,7 @@ var DataChannels =
32 32
             // selections so that it can do adaptive simulcast,
33 33
             // we want the notification to trigger even if userJid is undefined,
34 34
             // or null.
35
-            var userJid = VideoLayout.getLargeVideoState().userJid;
35
+            var userJid = UI.getLargeVideoState().userJid;
36 36
             // we want the notification to trigger even if userJid is undefined,
37 37
             // or null.
38 38
             onSelectedEndpointChanged(userJid);

+ 2
- 2
modules/RTC/RTCUtils.js Zobrazit soubor

@@ -245,7 +245,7 @@ RTCUtils.prototype.getUserMediaWithConstraints = function(
245 245
                 });
246 246
         } else {
247 247
 
248
-            RTCUtils.getUserMedia(constraints,
248
+            this.getUserMedia(constraints,
249 249
                 function (stream) {
250 250
                     console.log('onUserMediaSuccess');
251 251
                     success_callback(stream);
@@ -296,7 +296,7 @@ RTCUtils.prototype.obtainAudioAndVideoPermissions = function() {
296 296
                         media: error.media || 'video',
297 297
                         name : error.name
298 298
                     });
299
-                    messageHandler.showError("Error",
299
+                    UI.messageHandler.showError("Error",
300 300
                             "Failed to obtain permissions to use the local microphone" +
301 301
                             "and/or camera.");
302 302
                 }

+ 545
- 0
modules/UI/UI.js Zobrazit soubor

@@ -0,0 +1,545 @@
1
+var UI = {};
2
+
3
+var VideoLayout = require("./videolayout/VideoLayout.js");
4
+var AudioLevels = require("./audio_levels/AudioLevels.js");
5
+var Prezi = require("./prezi/Prezi.js");
6
+var Etherpad = require("./etherpad/Etherpad.js");
7
+var Chat = require("./side_pannels/chat/Chat.js");
8
+var Toolbar = require("./toolbars/toolbar");
9
+var ToolbarToggler = require("./toolbars/toolbartoggler");
10
+var BottomToolbar = require("./toolbars/BottomToolbar");
11
+var ContactList = require("./side_pannels/contactlist/ContactList");
12
+var Avatar = require("./avatar/Avatar");
13
+//var EventEmitter = require("events");
14
+var SettingsMenu = require("./side_pannels/settings/SettingsMenu");
15
+var Settings = require("./side_pannels/settings/Settings");
16
+var PanelToggler = require("./side_pannels/SidePanelToggler");
17
+var RoomNameGenerator = require("./welcome_page/RoomnameGenerator");
18
+UI.messageHandler = require("./util/MessageHandler");
19
+var messageHandler = UI.messageHandler;
20
+
21
+//var eventEmitter = new EventEmitter();
22
+
23
+
24
+
25
+function setupPrezi()
26
+{
27
+    $("#reloadPresentationLink").click(function()
28
+    {
29
+        Prezi.reloadPresentation();
30
+    });
31
+}
32
+
33
+function setupChat()
34
+{
35
+    Chat.init();
36
+    $("#toggle_smileys").click(function() {
37
+        Chat.toggleSmileys();
38
+    });
39
+}
40
+
41
+function setupToolbars() {
42
+    Toolbar.init();
43
+    Toolbar.setupButtonsFromConfig();
44
+    BottomToolbar.init();
45
+}
46
+
47
+
48
+function registerListeners() {
49
+    RTC.addStreamListener(function (stream) {
50
+        switch (stream.type)
51
+        {
52
+            case "audio":
53
+                VideoLayout.changeLocalAudio(stream.getOriginalStream());
54
+                break;
55
+            case "video":
56
+                VideoLayout.changeLocalVideo(stream.getOriginalStream(), true);
57
+                break;
58
+            case "stream":
59
+                VideoLayout.changeLocalStream(stream.getOriginalStream());
60
+                break;
61
+            case "desktop":
62
+                VideoLayout.changeLocalVideo(stream, !isUsingScreenStream);
63
+                break;
64
+        }
65
+    }, StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
66
+
67
+    RTC.addStreamListener(function (stream) {
68
+        VideoLayout.onRemoteStreamAdded(stream);
69
+    }, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED);
70
+
71
+    // Listen for large video size updates
72
+    document.getElementById('largeVideo')
73
+        .addEventListener('loadedmetadata', function (e) {
74
+            currentVideoWidth = this.videoWidth;
75
+            currentVideoHeight = this.videoHeight;
76
+            VideoLayout.positionLarge(currentVideoWidth, currentVideoHeight);
77
+        });
78
+
79
+
80
+    statistics.addAudioLevelListener(function(jid, audioLevel)
81
+    {
82
+        var resourceJid;
83
+        if(jid === statistics.LOCAL_JID)
84
+        {
85
+            resourceJid = AudioLevels.LOCAL_LEVEL;
86
+            if(isAudioMuted())
87
+            {
88
+                audioLevel = 0;
89
+            }
90
+        }
91
+        else
92
+        {
93
+            resourceJid = Strophe.getResourceFromJid(jid);
94
+        }
95
+
96
+        AudioLevels.updateAudioLevel(resourceJid, audioLevel,
97
+            UI.getLargeVideoState().userResourceJid);
98
+    });
99
+
100
+}
101
+
102
+function bindEvents()
103
+{
104
+    /**
105
+     * Resizes and repositions videos in full screen mode.
106
+     */
107
+    $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
108
+        function () {
109
+            VideoLayout.resizeLargeVideoContainer();
110
+            VideoLayout.positionLarge();
111
+            isFullScreen = document.fullScreen ||
112
+                document.mozFullScreen ||
113
+                document.webkitIsFullScreen;
114
+
115
+        }
116
+    );
117
+
118
+    $(window).resize(function () {
119
+        VideoLayout.resizeLargeVideoContainer();
120
+        VideoLayout.positionLarge();
121
+    });
122
+}
123
+
124
+UI.start = function () {
125
+    document.title = interfaceConfig.APP_NAME;
126
+    if(config.enableWelcomePage && window.location.pathname == "/" &&
127
+        (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
128
+    {
129
+        $("#videoconference_page").hide();
130
+        var setupWelcomePage = require("./welcome_page/WelcomePage");
131
+        setupWelcomePage();
132
+
133
+        return;
134
+    }
135
+
136
+    if (interfaceConfig.SHOW_JITSI_WATERMARK) {
137
+        var leftWatermarkDiv
138
+            = $("#largeVideoContainer div[class='watermark leftwatermark']");
139
+
140
+        leftWatermarkDiv.css({display: 'block'});
141
+        leftWatermarkDiv.parent().get(0).href
142
+            = interfaceConfig.JITSI_WATERMARK_LINK;
143
+    }
144
+
145
+    if (interfaceConfig.SHOW_BRAND_WATERMARK) {
146
+        var rightWatermarkDiv
147
+            = $("#largeVideoContainer div[class='watermark rightwatermark']");
148
+
149
+        rightWatermarkDiv.css({display: 'block'});
150
+        rightWatermarkDiv.parent().get(0).href
151
+            = interfaceConfig.BRAND_WATERMARK_LINK;
152
+        rightWatermarkDiv.get(0).style.backgroundImage
153
+            = "url(images/rightwatermark.png)";
154
+    }
155
+
156
+    if (interfaceConfig.SHOW_POWERED_BY) {
157
+        $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
158
+    }
159
+
160
+    $("#welcome_page").hide();
161
+
162
+    $('body').popover({ selector: '[data-toggle=popover]',
163
+        trigger: 'click hover',
164
+        content: function() {
165
+            return this.getAttribute("content") +
166
+                KeyboardShortcut.getShortcut(this.getAttribute("shortcut"));
167
+        }
168
+    });
169
+    VideoLayout.resizeLargeVideoContainer();
170
+    $("#videospace").mousemove(function () {
171
+        return ToolbarToggler.showToolbar();
172
+    });
173
+    // Set the defaults for prompt dialogs.
174
+    jQuery.prompt.setDefaults({persistent: false});
175
+
176
+//    KeyboardShortcut.init();
177
+    registerListeners();
178
+    bindEvents();
179
+    setupPrezi();
180
+    setupToolbars();
181
+    setupChat();
182
+
183
+    document.title = interfaceConfig.APP_NAME;
184
+
185
+    $("#downloadlog").click(function (event) {
186
+        dump(event.target);
187
+    });
188
+
189
+    if(config.enableWelcomePage && window.location.pathname == "/" &&
190
+        (!window.localStorage.welcomePageDisabled || window.localStorage.welcomePageDisabled == "false"))
191
+    {
192
+        $("#videoconference_page").hide();
193
+        var setupWelcomePage = require("./welcome_page/WelcomePage");
194
+        setupWelcomePage();
195
+
196
+        return;
197
+    }
198
+
199
+    $("#welcome_page").hide();
200
+
201
+    document.getElementById('largeVideo').volume = 0;
202
+
203
+    if (!$('#settings').is(':visible')) {
204
+        console.log('init');
205
+        init();
206
+    } else {
207
+        loginInfo.onsubmit = function (e) {
208
+            if (e.preventDefault) e.preventDefault();
209
+            $('#settings').hide();
210
+            init();
211
+        };
212
+    }
213
+
214
+    toastr.options = {
215
+        "closeButton": true,
216
+        "debug": false,
217
+        "positionClass": "notification-bottom-right",
218
+        "onclick": null,
219
+        "showDuration": "300",
220
+        "hideDuration": "1000",
221
+        "timeOut": "2000",
222
+        "extendedTimeOut": "1000",
223
+        "showEasing": "swing",
224
+        "hideEasing": "linear",
225
+        "showMethod": "fadeIn",
226
+        "hideMethod": "fadeOut",
227
+        "reposition": function() {
228
+            if(PanelToggler.isVisible()) {
229
+                $("#toast-container").addClass("notification-bottom-right-center");
230
+            } else {
231
+                $("#toast-container").removeClass("notification-bottom-right-center");
232
+            }
233
+        },
234
+        "newestOnTop": false
235
+    };
236
+
237
+    $('#settingsmenu>input').keyup(function(event){
238
+        if(event.keyCode === 13) {//enter
239
+            SettingsMenu.update();
240
+        }
241
+    });
242
+
243
+    $("#updateSettings").click(function () {
244
+        SettingsMenu.update();
245
+    });
246
+
247
+};
248
+
249
+
250
+UI.setUserAvatar = function (jid, id) {
251
+    Avatar.setUserAvatar(jid, id);
252
+};
253
+
254
+UI.toggleSmileys = function () {
255
+    Chat.toggleSmileys();
256
+};
257
+
258
+UI.chatAddError = function(errorMessage, originalText)
259
+{
260
+    return Chat.chatAddError(errorMessage, originalText);
261
+};
262
+
263
+UI.chatSetSubject = function(text)
264
+{
265
+    return Chat.chatSetSubject(text);
266
+};
267
+
268
+UI.updateChatConversation = function (from, displayName, message) {
269
+    return Chat.updateChatConversation(from, displayName, message);
270
+};
271
+
272
+UI.onMucJoined = function (jid, info) {
273
+    Toolbar.updateRoomUrl(window.location.href);
274
+    document.getElementById('localNick').appendChild(
275
+        document.createTextNode(Strophe.getResourceFromJid(jid) + ' (me)')
276
+    );
277
+
278
+    var settings = Settings.getSettings();
279
+    // Add myself to the contact list.
280
+    ContactList.addContact(jid, settings.email || settings.uid);
281
+
282
+    // Once we've joined the muc show the toolbar
283
+    ToolbarToggler.showToolbar();
284
+
285
+    // Show authenticate button if needed
286
+    Toolbar.showAuthenticateButton(
287
+            Moderator.isExternalAuthEnabled() && !Moderator.isModerator());
288
+
289
+    var displayName = !config.displayJids
290
+        ? info.displayName : Strophe.getResourceFromJid(jid);
291
+
292
+    if (displayName)
293
+        $(document).trigger('displaynamechanged',
294
+            ['localVideoContainer', displayName + ' (me)']);
295
+};
296
+
297
+UI.initEtherpad = function (name) {
298
+    Etherpad.init(name);
299
+};
300
+
301
+UI.onMucLeft = function (jid) {
302
+    console.log('left.muc', jid);
303
+    var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
304
+        '>.displayname').html();
305
+    messageHandler.notify(displayName || 'Somebody',
306
+        'disconnected',
307
+        'disconnected');
308
+    // Need to call this with a slight delay, otherwise the element couldn't be
309
+    // found for some reason.
310
+    // XXX(gp) it works fine without the timeout for me (with Chrome 38).
311
+    window.setTimeout(function () {
312
+        var container = document.getElementById(
313
+                'participant_' + Strophe.getResourceFromJid(jid));
314
+        if (container) {
315
+            ContactList.removeContact(jid);
316
+            VideoLayout.removeConnectionIndicator(jid);
317
+            // hide here, wait for video to close before removing
318
+            $(container).hide();
319
+            VideoLayout.resizeThumbnails();
320
+        }
321
+    }, 10);
322
+
323
+    // Unlock large video
324
+    if (focusedVideoInfo && focusedVideoInfo.jid === jid)
325
+    {
326
+        console.info("Focused video owner has left the conference");
327
+        focusedVideoInfo = null;
328
+    }
329
+
330
+};
331
+
332
+UI.getSettings = function () {
333
+    return Settings.getSettings();
334
+};
335
+
336
+UI.toggleFilmStrip = function () {
337
+    return BottomToolbar.toggleFilmStrip();
338
+};
339
+
340
+UI.toggleChat = function () {
341
+    return BottomToolbar.toggleChat();
342
+};
343
+
344
+UI.toggleContactList = function () {
345
+    return BottomToolbar.toggleContactList();
346
+};
347
+
348
+UI.onLocalRoleChange = function (jid, info, pres) {
349
+
350
+    console.info("My role changed, new role: " + info.role);
351
+    var isModerator = Moderator.isModerator();
352
+
353
+    VideoLayout.showModeratorIndicator();
354
+    Toolbar.showAuthenticateButton(
355
+            Moderator.isExternalAuthEnabled() && !isModerator);
356
+
357
+    if (isModerator) {
358
+        Toolbar.closeAuthenticationWindow();
359
+        messageHandler.notify(
360
+            'Me', 'connected', 'Moderator rights granted !');
361
+    }
362
+};
363
+
364
+UI.onDisposeConference = function (unload) {
365
+    Toolbar.showAuthenticateButton(false);
366
+};
367
+
368
+UI.onModeratorStatusChanged = function (isModerator) {
369
+
370
+    Toolbar.showSipCallButton(isModerator);
371
+    Toolbar.showRecordingButton(
372
+        isModerator); //&&
373
+    // FIXME:
374
+    // Recording visible if
375
+    // there are at least 2(+ 1 focus) participants
376
+    //Object.keys(connection.emuc.members).length >= 3);
377
+
378
+    if (isModerator && config.etherpad_base) {
379
+        Etherpad.init();
380
+    }
381
+};
382
+
383
+UI.onPasswordReqiured = function (callback) {
384
+    // password is required
385
+    Toolbar.lockLockButton();
386
+
387
+    messageHandler.openTwoButtonDialog(null,
388
+            '<h2>Password required</h2>' +
389
+            '<input id="lockKey" type="text" placeholder="password" autofocus>',
390
+        true,
391
+        "Ok",
392
+        function (e, v, m, f) {},
393
+        function (event) {
394
+            document.getElementById('lockKey').focus();
395
+        },
396
+        function (e, v, m, f) {
397
+            if (v) {
398
+                var lockKey = document.getElementById('lockKey');
399
+                if (lockKey.value !== null) {
400
+                    Toolbar.setSharedKey(lockKey.value);
401
+                    callback(lockKey.value);
402
+                }
403
+            }
404
+        }
405
+    );
406
+};
407
+
408
+UI.onAuthenticationRequired = function () {
409
+    // extract room name from 'room@muc.server.net'
410
+    var room = roomName.substr(0, roomName.indexOf('@'));
411
+
412
+    messageHandler.openDialog(
413
+        'Stop',
414
+            'Authentication is required to create room:<br/>' + room,
415
+        true,
416
+        {
417
+            Authenticate: 'authNow',
418
+            Close: 'close'
419
+        },
420
+        function (onSubmitEvent, submitValue) {
421
+            console.info('On submit: ' + submitValue, submitValue);
422
+            if (submitValue === 'authNow') {
423
+                Toolbar.authenticateClicked();
424
+            } else {
425
+                Toolbar.showAuthenticateButton(true);
426
+            }
427
+        }
428
+    );
429
+};
430
+
431
+UI.setRecordingButtonState = function (state) {
432
+    Toolbar.setRecordingButtonState(state);
433
+};
434
+
435
+UI.changeDesktopSharingButtonState = function (isUsingScreenStream) {
436
+    Toolbar.changeDesktopSharingButtonState(isUsingScreenStream);
437
+};
438
+
439
+UI.inputDisplayNameHandler = function (value) {
440
+    VideoLayout.inputDisplayNameHandler(value);
441
+};
442
+
443
+UI.onMucEntered = function (jid, id, displayName) {
444
+    messageHandler.notify(displayName || 'Somebody',
445
+        'connected',
446
+        'connected');
447
+
448
+    // Add Peer's container
449
+    VideoLayout.ensurePeerContainerExists(jid,id);
450
+
451
+    if(APIConnector.isEnabled() &&
452
+        APIConnector.isEventEnabled("participantJoined"))
453
+    {
454
+        APIConnector.triggerEvent("participantJoined",{jid: jid});
455
+    }
456
+};
457
+
458
+UI.onMucPresenceStatus = function ( jid, info) {
459
+    VideoLayout.setPresenceStatus(
460
+            'participant_' + Strophe.getResourceFromJid(jid), info.status);
461
+};
462
+
463
+UI.onMucRoleChanged = function (role, displayName) {
464
+    VideoLayout.showModeratorIndicator();
465
+
466
+    if (role === 'moderator') {
467
+        var displayName = displayName;
468
+        if (!displayName) {
469
+            displayName = 'Somebody';
470
+        }
471
+        messageHandler.notify(
472
+            displayName,
473
+            'connected',
474
+                'Moderator rights granted to ' + displayName + '!');
475
+    }
476
+};
477
+
478
+UI.updateLocalConnectionStats = function(percent, stats)
479
+{
480
+    VideoLayout.updateLocalConnectionStats(percent, stats);
481
+};
482
+
483
+UI.updateConnectionStats = function(jid, percent, stats)
484
+{
485
+    VideoLayout.updateConnectionStats(jid, percent, stats);
486
+};
487
+
488
+UI.onStatsStop = function () {
489
+    VideoLayout.onStatsStop();
490
+};
491
+
492
+UI.getLargeVideoState = function()
493
+{
494
+    return VideoLayout.getLargeVideoState();
495
+};
496
+
497
+UI.showLocalAudioIndicator = function (mute) {
498
+    VideoLayout.showLocalAudioIndicator(mute);
499
+};
500
+
501
+UI.changeLocalVideo = function (stream, flipx) {
502
+    VideoLayout.changeLocalVideo(stream, flipx);
503
+};
504
+
505
+UI.generateRoomName = function() {
506
+    var roomnode = null;
507
+    var path = window.location.pathname;
508
+
509
+    // determinde the room node from the url
510
+    // TODO: just the roomnode or the whole bare jid?
511
+    if (config.getroomnode && typeof config.getroomnode === 'function') {
512
+        // custom function might be responsible for doing the pushstate
513
+        roomnode = config.getroomnode(path);
514
+    } else {
515
+        /* fall back to default strategy
516
+         * this is making assumptions about how the URL->room mapping happens.
517
+         * It currently assumes deployment at root, with a rewrite like the
518
+         * following one (for nginx):
519
+         location ~ ^/([a-zA-Z0-9]+)$ {
520
+         rewrite ^/(.*)$ / break;
521
+         }
522
+         */
523
+        if (path.length > 1) {
524
+            roomnode = path.substr(1).toLowerCase();
525
+        } else {
526
+            var word = RoomNameGenerator.generateRoomWithoutSeparator();
527
+            roomnode = word.toLowerCase();
528
+
529
+            window.history.pushState('VideoChat',
530
+                    'Room: ' + word, window.location.pathname + word);
531
+        }
532
+    }
533
+
534
+    roomName = roomnode + '@' + config.hosts.muc;
535
+};
536
+
537
+
538
+UI.connectionIndicatorShowMore = function(id)
539
+{
540
+    return VideoLayout.connectionIndicators[id].showMore();
541
+}
542
+
543
+
544
+module.exports = UI;
545
+

audio_levels.js → modules/UI/audio_levels/AudioLevels.js Zobrazit soubor

@@ -1,3 +1,5 @@
1
+var CanvasUtil = require("./CanvasUtils");
2
+
1 3
 /**
2 4
  * The audio Levels plugin.
3 5
  */
@@ -10,7 +12,7 @@ var AudioLevels = (function(my) {
10 12
      * Updates the audio level canvas for the given peerJid. If the canvas
11 13
      * didn't exist we create it.
12 14
      */
13
-    my.updateAudioLevelCanvas = function (peerJid) {
15
+    my.updateAudioLevelCanvas = function (peerJid, VideoLayout) {
14 16
         var resourceJid = null;
15 17
         var videoSpanId = null;
16 18
         if (!peerJid)
@@ -66,7 +68,7 @@ var AudioLevels = (function(my) {
66 68
      * which we draw the audio level
67 69
      * @param audioLevel the newAudio level to render
68 70
      */
69
-    my.updateAudioLevel = function (resourceJid, audioLevel) {
71
+    my.updateAudioLevel = function (resourceJid, audioLevel, largeVideoResourceJid) {
70 72
         drawAudioLevelCanvas(resourceJid, audioLevel);
71 73
 
72 74
         var videoSpanId = getVideoSpanId(resourceJid);
@@ -91,7 +93,7 @@ var AudioLevels = (function(my) {
91 93
             resourceJid = Strophe.getResourceFromJid(connection.emuc.myroomjid);
92 94
         }
93 95
 
94
-        if(resourceJid  === VideoLayout.getLargeVideoState().userResourceJid) {
96
+        if(resourceJid  === largeVideoResourceJid) {
95 97
             AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
96 98
         }
97 99
     };
@@ -258,3 +260,5 @@ var AudioLevels = (function(my) {
258 260
     return my;
259 261
 
260 262
 })(AudioLevels || {});
263
+
264
+module.exports = AudioLevels;

canvas_util.js → modules/UI/audio_levels/CanvasUtils.js Zobrazit soubor

@@ -107,3 +107,5 @@ var CanvasUtil = (function(my) {
107 107
 
108 108
     return my;
109 109
 })(CanvasUtil || {});
110
+
111
+module.exports = CanvasUtil;

avatar.js → modules/UI/avatar/Avatar.js Zobrazit soubor

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

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

@@ -0,0 +1,195 @@
1
+/* global $, config, connection, dockToolbar, Moderator,
2
+   setLargeVideoVisible, Util */
3
+
4
+var VideoLayout = require("../videolayout/VideoLayout");
5
+var Prezi = require("../prezi/Prezi");
6
+var UIUtil = require("../util/UIUtil");
7
+
8
+var etherpadName = null;
9
+var etherpadIFrame = null;
10
+var domain = null;
11
+var options = "?showControls=true&showChat=false&showLineNumbers=true&useMonospaceFont=false";
12
+
13
+
14
+/**
15
+ * Resizes the etherpad.
16
+ */
17
+function resize() {
18
+    if ($('#etherpad>iframe').length) {
19
+        var remoteVideos = $('#remoteVideos');
20
+        var availableHeight
21
+            = window.innerHeight - remoteVideos.outerHeight();
22
+        var availableWidth = UIUtil.getAvailableVideoWidth();
23
+
24
+        $('#etherpad>iframe').width(availableWidth);
25
+        $('#etherpad>iframe').height(availableHeight);
26
+    }
27
+}
28
+
29
+/**
30
+ * Shares the Etherpad name with other participants.
31
+ */
32
+function shareEtherpad() {
33
+    connection.emuc.addEtherpadToPresence(etherpadName);
34
+    connection.emuc.sendPresence();
35
+}
36
+
37
+/**
38
+ * Creates the Etherpad button and adds it to the toolbar.
39
+ */
40
+function enableEtherpadButton() {
41
+    if (!$('#etherpadButton').is(":visible"))
42
+        $('#etherpadButton').css({display: 'inline-block'});
43
+}
44
+
45
+/**
46
+ * Creates the IFrame for the etherpad.
47
+ */
48
+function createIFrame() {
49
+    etherpadIFrame = document.createElement('iframe');
50
+    etherpadIFrame.src = domain + etherpadName + options;
51
+    etherpadIFrame.frameBorder = 0;
52
+    etherpadIFrame.scrolling = "no";
53
+    etherpadIFrame.width = $('#largeVideoContainer').width() || 640;
54
+    etherpadIFrame.height = $('#largeVideoContainer').height() || 480;
55
+    etherpadIFrame.setAttribute('style', 'visibility: hidden;');
56
+
57
+    document.getElementById('etherpad').appendChild(etherpadIFrame);
58
+
59
+    etherpadIFrame.onload = function() {
60
+
61
+        document.domain = document.domain;
62
+        bubbleIframeMouseMove(etherpadIFrame);
63
+        setTimeout(function() {
64
+            // the iframes inside of the etherpad are
65
+            // not yet loaded when the etherpad iframe is loaded
66
+            var outer = etherpadIFrame.
67
+                contentDocument.getElementsByName("ace_outer")[0];
68
+            bubbleIframeMouseMove(outer);
69
+            var inner = outer.
70
+                contentDocument.getElementsByName("ace_inner")[0];
71
+            bubbleIframeMouseMove(inner);
72
+        }, 2000);
73
+    };
74
+}
75
+
76
+function bubbleIframeMouseMove(iframe){
77
+    var existingOnMouseMove = iframe.contentWindow.onmousemove;
78
+    iframe.contentWindow.onmousemove = function(e){
79
+        if(existingOnMouseMove) existingOnMouseMove(e);
80
+        var evt = document.createEvent("MouseEvents");
81
+        var boundingClientRect = iframe.getBoundingClientRect();
82
+        evt.initMouseEvent(
83
+            "mousemove",
84
+            true, // bubbles
85
+            false, // not cancelable
86
+            window,
87
+            e.detail,
88
+            e.screenX,
89
+            e.screenY,
90
+                e.clientX + boundingClientRect.left,
91
+                e.clientY + boundingClientRect.top,
92
+            e.ctrlKey,
93
+            e.altKey,
94
+            e.shiftKey,
95
+            e.metaKey,
96
+            e.button,
97
+            null // no related element
98
+        );
99
+        iframe.dispatchEvent(evt);
100
+    };
101
+}
102
+
103
+
104
+/**
105
+ * On video selected event.
106
+ */
107
+$(document).bind('video.selected', function (event, isPresentation) {
108
+    if (config.etherpad_base && etherpadIFrame && etherpadIFrame.style.visibility !== 'hidden')
109
+        Etherpad.toggleEtherpad(isPresentation);
110
+});
111
+
112
+
113
+var Etherpad = {
114
+    /**
115
+     * Initializes the etherpad.
116
+     */
117
+    init: function (name) {
118
+
119
+        if (config.etherpad_base && !etherpadName) {
120
+
121
+            domain = config.etherpad_base;
122
+
123
+            if (!name) {
124
+                // In case we're the focus we generate the name.
125
+                etherpadName = Math.random().toString(36).substring(7) +
126
+                                '_' + (new Date().getTime()).toString();
127
+                shareEtherpad();
128
+            }
129
+            else
130
+                etherpadName = name;
131
+
132
+            enableEtherpadButton();
133
+
134
+            /**
135
+             * Resizes the etherpad, when the window is resized.
136
+             */
137
+            $(window).resize(function () {
138
+                resize();
139
+            });
140
+        }
141
+    },
142
+
143
+    /**
144
+     * Opens/hides the Etherpad.
145
+     */
146
+    toggleEtherpad: function (isPresentation) {
147
+        if (!etherpadIFrame)
148
+            createIFrame();
149
+
150
+        var largeVideo = null;
151
+        if (Prezi.isPresentationVisible())
152
+            largeVideo = $('#presentation>iframe');
153
+        else
154
+            largeVideo = $('#largeVideo');
155
+
156
+        if ($('#etherpad>iframe').css('visibility') === 'hidden') {
157
+            $('#activeSpeaker').css('visibility', 'hidden');
158
+            largeVideo.fadeOut(300, function () {
159
+                if (Prezi.isPresentationVisible()) {
160
+                    largeVideo.css({opacity: '0'});
161
+                } else {
162
+                    VideoLayout.setLargeVideoVisible(false);
163
+                }
164
+            });
165
+
166
+            $('#etherpad>iframe').fadeIn(300, function () {
167
+                document.body.style.background = '#eeeeee';
168
+                $('#etherpad>iframe').css({visibility: 'visible'});
169
+                $('#etherpad').css({zIndex: 2});
170
+            });
171
+        }
172
+        else if ($('#etherpad>iframe')) {
173
+            $('#etherpad>iframe').fadeOut(300, function () {
174
+                $('#etherpad>iframe').css({visibility: 'hidden'});
175
+                $('#etherpad').css({zIndex: 0});
176
+                document.body.style.background = 'black';
177
+            });
178
+
179
+            if (!isPresentation) {
180
+                $('#largeVideo').fadeIn(300, function () {
181
+                    VideoLayout.setLargeVideoVisible(true);
182
+                });
183
+            }
184
+        }
185
+        resize();
186
+    },
187
+
188
+    isVisible: function() {
189
+        var etherpadIframe = $('#etherpad>iframe');
190
+        return etherpadIframe && etherpadIframe.is(':visible');
191
+    }
192
+
193
+};
194
+
195
+module.exports = Etherpad;

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

@@ -0,0 +1,354 @@
1
+var ToolbarToggler = require("../toolbars/ToolbarToggler");
2
+var UIUtil = require("../util/UIUtil");
3
+var VideoLayout = require("../videolayout/VideoLayout");
4
+var messageHandler = require("../util/MessageHandler");
5
+
6
+var preziPlayer = null;
7
+
8
+var Prezi = {
9
+
10
+
11
+    /**
12
+     * Reloads the current presentation.
13
+     */
14
+    reloadPresentation: function() {
15
+        var iframe = document.getElementById(preziPlayer.options.preziId);
16
+        iframe.src = iframe.src;
17
+    },
18
+
19
+    /**
20
+     * Returns <tt>true</tt> if the presentation is visible, <tt>false</tt> -
21
+     * otherwise.
22
+     */
23
+    isPresentationVisible: function () {
24
+        return ($('#presentation>iframe') != null
25
+                && $('#presentation>iframe').css('opacity') == 1);
26
+    },
27
+
28
+    /**
29
+     * Opens the Prezi dialog, from which the user could choose a presentation
30
+     * to load.
31
+     */
32
+    openPreziDialog: function() {
33
+        var myprezi = connection.emuc.getPrezi(connection.emuc.myroomjid);
34
+        if (myprezi) {
35
+            messageHandler.openTwoButtonDialog("Remove Prezi",
36
+                "Are you sure you would like to remove your Prezi?",
37
+                false,
38
+                "Remove",
39
+                function(e,v,m,f) {
40
+                    if(v) {
41
+                        connection.emuc.removePreziFromPresence();
42
+                        connection.emuc.sendPresence();
43
+                    }
44
+                }
45
+            );
46
+        }
47
+        else if (preziPlayer != null) {
48
+            messageHandler.openTwoButtonDialog("Share a Prezi",
49
+                "Another participant is already sharing a Prezi." +
50
+                    "This conference allows only one Prezi at a time.",
51
+                false,
52
+                "Ok",
53
+                function(e,v,m,f) {
54
+                    $.prompt.close();
55
+                }
56
+            );
57
+        }
58
+        else {
59
+            var openPreziState = {
60
+                state0: {
61
+                    html:   '<h2>Share a Prezi</h2>' +
62
+                            '<input id="preziUrl" type="text" ' +
63
+                            'placeholder="e.g. ' +
64
+                            'http://prezi.com/wz7vhjycl7e6/my-prezi" autofocus>',
65
+                    persistent: false,
66
+                    buttons: { "Share": true , "Cancel": false},
67
+                    defaultButton: 1,
68
+                    submit: function(e,v,m,f){
69
+                        e.preventDefault();
70
+                        if(v)
71
+                        {
72
+                            var preziUrl = document.getElementById('preziUrl');
73
+
74
+                            if (preziUrl.value)
75
+                            {
76
+                                var urlValue
77
+                                    = encodeURI(Util.escapeHtml(preziUrl.value));
78
+
79
+                                if (urlValue.indexOf('http://prezi.com/') != 0
80
+                                    && urlValue.indexOf('https://prezi.com/') != 0)
81
+                                {
82
+                                    $.prompt.goToState('state1');
83
+                                    return false;
84
+                                }
85
+                                else {
86
+                                    var presIdTmp = urlValue.substring(
87
+                                            urlValue.indexOf("prezi.com/") + 10);
88
+                                    if (!isAlphanumeric(presIdTmp)
89
+                                            || presIdTmp.indexOf('/') < 2) {
90
+                                        $.prompt.goToState('state1');
91
+                                        return false;
92
+                                    }
93
+                                    else {
94
+                                        connection.emuc
95
+                                            .addPreziToPresence(urlValue, 0);
96
+                                        connection.emuc.sendPresence();
97
+                                        $.prompt.close();
98
+                                    }
99
+                                }
100
+                            }
101
+                        }
102
+                        else
103
+                            $.prompt.close();
104
+                    }
105
+                },
106
+                state1: {
107
+                    html:   '<h2>Share a Prezi</h2>' +
108
+                            'Please provide a correct prezi link.',
109
+                    persistent: false,
110
+                    buttons: { "Back": true, "Cancel": false },
111
+                    defaultButton: 1,
112
+                    submit:function(e,v,m,f) {
113
+                        e.preventDefault();
114
+                        if(v==0)
115
+                            $.prompt.close();
116
+                        else
117
+                            $.prompt.goToState('state0');
118
+                    }
119
+                }
120
+            };
121
+            var focusPreziUrl =  function(e) {
122
+                    document.getElementById('preziUrl').focus();
123
+                };
124
+            messageHandler.openDialogWithStates(openPreziState, focusPreziUrl, focusPreziUrl);
125
+        }
126
+    }
127
+
128
+};
129
+
130
+/**
131
+ * A new presentation has been added.
132
+ *
133
+ * @param event the event indicating the add of a presentation
134
+ * @param jid the jid from which the presentation was added
135
+ * @param presUrl url of the presentation
136
+ * @param currentSlide the current slide to which we should move
137
+ */
138
+function presentationAdded(event, jid, presUrl, currentSlide) {
139
+    console.log("presentation added", presUrl);
140
+
141
+    var presId = getPresentationId(presUrl);
142
+
143
+    var elementId = 'participant_'
144
+        + Strophe.getResourceFromJid(jid)
145
+        + '_' + presId;
146
+
147
+    // We explicitly don't specify the peer jid here, because we don't want
148
+    // this video to be dealt with as a peer related one (for example we
149
+    // don't want to show a mute/kick menu for this one, etc.).
150
+    VideoLayout.addRemoteVideoContainer(null, elementId);
151
+    VideoLayout.resizeThumbnails();
152
+
153
+    var controlsEnabled = false;
154
+    if (jid === connection.emuc.myroomjid)
155
+        controlsEnabled = true;
156
+
157
+    setPresentationVisible(true);
158
+    $('#largeVideoContainer').hover(
159
+        function (event) {
160
+            if (Prezi.isPresentationVisible()) {
161
+                var reloadButtonRight = window.innerWidth
162
+                    - $('#presentation>iframe').offset().left
163
+                    - $('#presentation>iframe').width();
164
+
165
+                $('#reloadPresentation').css({  right: reloadButtonRight,
166
+                    display:'inline-block'});
167
+            }
168
+        },
169
+        function (event) {
170
+            if (!Prezi.isPresentationVisible())
171
+                $('#reloadPresentation').css({display:'none'});
172
+            else {
173
+                var e = event.toElement || event.relatedTarget;
174
+
175
+                if (e && e.id != 'reloadPresentation' && e.id != 'header')
176
+                    $('#reloadPresentation').css({display:'none'});
177
+            }
178
+        });
179
+
180
+    preziPlayer = new PreziPlayer(
181
+        'presentation',
182
+        {preziId: presId,
183
+            width: getPresentationWidth(),
184
+            height: getPresentationHeihgt(),
185
+            controls: controlsEnabled,
186
+            debug: true
187
+        });
188
+
189
+    $('#presentation>iframe').attr('id', preziPlayer.options.preziId);
190
+
191
+    preziPlayer.on(PreziPlayer.EVENT_STATUS, function(event) {
192
+        console.log("prezi status", event.value);
193
+        if (event.value == PreziPlayer.STATUS_CONTENT_READY) {
194
+            if (jid != connection.emuc.myroomjid)
195
+                preziPlayer.flyToStep(currentSlide);
196
+        }
197
+    });
198
+
199
+    preziPlayer.on(PreziPlayer.EVENT_CURRENT_STEP, function(event) {
200
+        console.log("event value", event.value);
201
+        connection.emuc.addCurrentSlideToPresence(event.value);
202
+        connection.emuc.sendPresence();
203
+    });
204
+
205
+    $("#" + elementId).css( 'background-image',
206
+        'url(../images/avatarprezi.png)');
207
+    $("#" + elementId).click(
208
+        function () {
209
+            setPresentationVisible(true);
210
+        }
211
+    );
212
+};
213
+
214
+/**
215
+ * A presentation has been removed.
216
+ *
217
+ * @param event the event indicating the remove of a presentation
218
+ * @param jid the jid for which the presentation was removed
219
+ * @param the url of the presentation
220
+ */
221
+function presentationRemoved(event, jid, presUrl) {
222
+    console.log('presentation removed', presUrl);
223
+    var presId = getPresentationId(presUrl);
224
+    setPresentationVisible(false);
225
+    $('#participant_'
226
+        + Strophe.getResourceFromJid(jid)
227
+        + '_' + presId).remove();
228
+    $('#presentation>iframe').remove();
229
+    if (preziPlayer != null) {
230
+        preziPlayer.destroy();
231
+        preziPlayer = null;
232
+    }
233
+};
234
+
235
+/**
236
+ * Indicates if the given string is an alphanumeric string.
237
+ * Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the
238
+ * purpose of checking URIs.
239
+ */
240
+function isAlphanumeric(unsafeText) {
241
+    var regex = /^[a-z0-9-_\/&\?=;]+$/i;
242
+    return regex.test(unsafeText);
243
+}
244
+
245
+/**
246
+ * Returns the presentation id from the given url.
247
+ */
248
+function getPresentationId (presUrl) {
249
+    var presIdTmp = presUrl.substring(presUrl.indexOf("prezi.com/") + 10);
250
+    return presIdTmp.substring(0, presIdTmp.indexOf('/'));
251
+}
252
+
253
+/**
254
+ * Returns the presentation width.
255
+ */
256
+function getPresentationWidth() {
257
+    var availableWidth = UIUtil.getAvailableVideoWidth();
258
+    var availableHeight = getPresentationHeihgt();
259
+
260
+    var aspectRatio = 16.0 / 9.0;
261
+    if (availableHeight < availableWidth / aspectRatio) {
262
+        availableWidth = Math.floor(availableHeight * aspectRatio);
263
+    }
264
+    return availableWidth;
265
+}
266
+
267
+/**
268
+ * Returns the presentation height.
269
+ */
270
+function getPresentationHeihgt() {
271
+    var remoteVideos = $('#remoteVideos');
272
+    return window.innerHeight - remoteVideos.outerHeight();
273
+}
274
+
275
+/**
276
+ * Resizes the presentation iframe.
277
+ */
278
+function resize() {
279
+    if ($('#presentation>iframe')) {
280
+        $('#presentation>iframe').width(getPresentationWidth());
281
+        $('#presentation>iframe').height(getPresentationHeihgt());
282
+    }
283
+}
284
+
285
+/**
286
+ * Shows/hides a presentation.
287
+ */
288
+function setPresentationVisible(visible) {
289
+    var prezi = $('#presentation>iframe');
290
+    if (visible) {
291
+        // Trigger the video.selected event to indicate a change in the
292
+        // large video.
293
+        $(document).trigger("video.selected", [true]);
294
+
295
+        $('#largeVideo').fadeOut(300);
296
+        prezi.fadeIn(300, function() {
297
+            prezi.css({opacity:'1'});
298
+            ToolbarToggler.dockToolbar(true);
299
+            VideoLayout.setLargeVideoVisible(false);
300
+        });
301
+        $('#activeSpeaker').css('visibility', 'hidden');
302
+    }
303
+    else {
304
+        if (prezi.css('opacity') == '1') {
305
+            prezi.fadeOut(300, function () {
306
+                prezi.css({opacity:'0'});
307
+                $('#reloadPresentation').css({display:'none'});
308
+                $('#largeVideo').fadeIn(300, function() {
309
+                    VideoLayout.setLargeVideoVisible(true);
310
+                    ToolbarToggler.dockToolbar(false);
311
+                });
312
+            });
313
+        }
314
+    }
315
+}
316
+
317
+/**
318
+ * Presentation has been removed.
319
+ */
320
+$(document).bind('presentationremoved.muc', presentationRemoved);
321
+
322
+/**
323
+ * Presentation has been added.
324
+ */
325
+$(document).bind('presentationadded.muc', presentationAdded);
326
+
327
+/*
328
+ * Indicates presentation slide change.
329
+ */
330
+$(document).bind('gotoslide.muc', function (event, jid, presUrl, current) {
331
+    if (preziPlayer && preziPlayer.getCurrentStep() != current) {
332
+        preziPlayer.flyToStep(current);
333
+
334
+        var animationStepsArray = preziPlayer.getAnimationCountOnSteps();
335
+        for (var i = 0; i < parseInt(animationStepsArray[current]); i++) {
336
+            preziPlayer.flyToStep(current, i);
337
+        }
338
+    }
339
+});
340
+
341
+/**
342
+ * On video selected event.
343
+ */
344
+$(document).bind('video.selected', function (event, isPresentation) {
345
+    if (!isPresentation && $('#presentation>iframe')) {
346
+        setPresentationVisible(false);
347
+    }
348
+});
349
+
350
+$(window).resize(function () {
351
+    resize();
352
+});
353
+
354
+module.exports = Prezi;

libs/prezi_player.js → modules/UI/prezi/PreziPlayer.js Zobrazit soubor


side_panel_toggler.js → modules/UI/side_pannels/SidePanelToggler.js Zobrazit soubor

@@ -1,3 +1,10 @@
1
+var Chat = require("./chat/Chat");
2
+var ContactList = require("./contactlist/ContactList");
3
+var Settings = require("./settings/Settings");
4
+var SettingsMenu = require("./settings/SettingsMenu");
5
+var VideoLayout = require("../videolayout/VideoLayout");
6
+var ToolbarToggler = require("../toolbars/ToolbarToggler");
7
+
1 8
 /**
2 9
  * Toggler for the chat, contact list, settings menu, etc..
3 10
  */
@@ -215,8 +222,9 @@ var PanelToggler = (function(my) {
215 222
             '#settingsmenu',
216 223
             null,
217 224
             function() {
218
-                $('#setDisplayName').get(0).value = SettingsMenu.getDisplayName();
219
-                $('#setEmail').get(0).value = SettingsMenu.getEmail();
225
+                var settings = Settings.getSettings();
226
+                $('#setDisplayName').get(0).value = settings.displayName;
227
+                $('#setEmail').get(0).value = settings.email;
220 228
             },
221 229
             null);
222 230
     };
@@ -243,3 +251,5 @@ var PanelToggler = (function(my) {
243 251
     return my;
244 252
 
245 253
 }(PanelToggler || {}));
254
+
255
+module.exports = PanelToggler;

+ 361
- 0
modules/UI/side_pannels/chat/Chat.js Zobrazit soubor

@@ -0,0 +1,361 @@
1
+/* global $, Util, connection, nickname:true, getVideoSize,
2
+getVideoPosition, showToolbar */
3
+var Replacement = require("./Replacement");
4
+var CommandsProcessor = require("./Commands");
5
+var ToolbarToggler = require("../../toolbars/ToolbarToggler");
6
+var smileys = require("./smileys.json").smileys;
7
+
8
+var notificationInterval = false;
9
+var unreadMessages = 0;
10
+
11
+
12
+/**
13
+ * Shows/hides a visual notification, indicating that a message has arrived.
14
+ */
15
+function setVisualNotification(show) {
16
+    var unreadMsgElement = document.getElementById('unreadMessages');
17
+    var unreadMsgBottomElement
18
+        = document.getElementById('bottomUnreadMessages');
19
+
20
+    var glower = $('#chatButton');
21
+    var bottomGlower = $('#chatBottomButton');
22
+
23
+    if (unreadMessages) {
24
+        unreadMsgElement.innerHTML = unreadMessages.toString();
25
+        unreadMsgBottomElement.innerHTML = unreadMessages.toString();
26
+
27
+        ToolbarToggler.dockToolbar(true);
28
+
29
+        var chatButtonElement
30
+            = document.getElementById('chatButton').parentNode;
31
+        var leftIndent = (Util.getTextWidth(chatButtonElement) -
32
+            Util.getTextWidth(unreadMsgElement)) / 2;
33
+        var topIndent = (Util.getTextHeight(chatButtonElement) -
34
+            Util.getTextHeight(unreadMsgElement)) / 2 - 3;
35
+
36
+        unreadMsgElement.setAttribute(
37
+            'style',
38
+                'top:' + topIndent +
39
+                '; left:' + leftIndent + ';');
40
+
41
+        var chatBottomButtonElement
42
+            = document.getElementById('chatBottomButton').parentNode;
43
+        var bottomLeftIndent = (Util.getTextWidth(chatBottomButtonElement) -
44
+            Util.getTextWidth(unreadMsgBottomElement)) / 2;
45
+        var bottomTopIndent = (Util.getTextHeight(chatBottomButtonElement) -
46
+            Util.getTextHeight(unreadMsgBottomElement)) / 2 - 2;
47
+
48
+        unreadMsgBottomElement.setAttribute(
49
+            'style',
50
+                'top:' + bottomTopIndent +
51
+                '; left:' + bottomLeftIndent + ';');
52
+
53
+
54
+        if (!glower.hasClass('icon-chat-simple')) {
55
+            glower.removeClass('icon-chat');
56
+            glower.addClass('icon-chat-simple');
57
+        }
58
+    }
59
+    else {
60
+        unreadMsgElement.innerHTML = '';
61
+        unreadMsgBottomElement.innerHTML = '';
62
+        glower.removeClass('icon-chat-simple');
63
+        glower.addClass('icon-chat');
64
+    }
65
+
66
+    if (show && !notificationInterval) {
67
+        notificationInterval = window.setInterval(function () {
68
+            glower.toggleClass('active');
69
+            bottomGlower.toggleClass('active glowing');
70
+        }, 800);
71
+    }
72
+    else if (!show && notificationInterval) {
73
+        window.clearInterval(notificationInterval);
74
+        notificationInterval = false;
75
+        glower.removeClass('active');
76
+        bottomGlower.removeClass('glowing');
77
+        bottomGlower.addClass('active');
78
+    }
79
+}
80
+
81
+
82
+/**
83
+ * Returns the current time in the format it is shown to the user
84
+ * @returns {string}
85
+ */
86
+function getCurrentTime() {
87
+    var now     = new Date();
88
+    var hour    = now.getHours();
89
+    var minute  = now.getMinutes();
90
+    var second  = now.getSeconds();
91
+    if(hour.toString().length === 1) {
92
+        hour = '0'+hour;
93
+    }
94
+    if(minute.toString().length === 1) {
95
+        minute = '0'+minute;
96
+    }
97
+    if(second.toString().length === 1) {
98
+        second = '0'+second;
99
+    }
100
+    return hour+':'+minute+':'+second;
101
+}
102
+
103
+function toggleSmileys()
104
+{
105
+    var smileys = $('#smileysContainer');
106
+    if(!smileys.is(':visible')) {
107
+        smileys.show("slide", { direction: "down", duration: 300});
108
+    } else {
109
+        smileys.hide("slide", { direction: "down", duration: 300});
110
+    }
111
+    $('#usermsg').focus();
112
+}
113
+
114
+function addClickFunction(smiley, number) {
115
+    smiley.onclick = function addSmileyToMessage() {
116
+        var usermsg = $('#usermsg');
117
+        var message = usermsg.val();
118
+        message += smileys['smiley' + number];
119
+        usermsg.val(message);
120
+        usermsg.get(0).setSelectionRange(message.length, message.length);
121
+        toggleSmileys();
122
+        usermsg.focus();
123
+    };
124
+}
125
+
126
+/**
127
+ * Adds the smileys container to the chat
128
+ */
129
+function addSmileys() {
130
+    var smileysContainer = document.createElement('div');
131
+    smileysContainer.id = 'smileysContainer';
132
+    for(var i = 1; i <= 21; i++) {
133
+        var smileyContainer = document.createElement('div');
134
+        smileyContainer.id = 'smiley' + i;
135
+        smileyContainer.className = 'smileyContainer';
136
+        var smiley = document.createElement('img');
137
+        smiley.src = 'images/smileys/smiley' + i + '.svg';
138
+        smiley.className =  'smiley';
139
+        addClickFunction(smiley, i);
140
+        smileyContainer.appendChild(smiley);
141
+        smileysContainer.appendChild(smileyContainer);
142
+    }
143
+
144
+    $("#chatspace").append(smileysContainer);
145
+}
146
+
147
+/**
148
+ * Resizes the chat conversation.
149
+ */
150
+function resizeChatConversation() {
151
+    var msgareaHeight = $('#usermsg').outerHeight();
152
+    var chatspace = $('#chatspace');
153
+    var width = chatspace.width();
154
+    var chat = $('#chatconversation');
155
+    var smileys = $('#smileysarea');
156
+
157
+    smileys.height(msgareaHeight);
158
+    $("#smileys").css('bottom', (msgareaHeight - 26) / 2);
159
+    $('#smileysContainer').css('bottom', msgareaHeight);
160
+    chat.width(width - 10);
161
+    chat.height(window.innerHeight - 15 - msgareaHeight);
162
+}
163
+
164
+/**
165
+ * Chat related user interface.
166
+ */
167
+var Chat = (function (my) {
168
+    /**
169
+     * Initializes chat related interface.
170
+     */
171
+    my.init = function () {
172
+        var storedDisplayName = window.localStorage.displayname;
173
+        if (storedDisplayName) {
174
+            nickname = storedDisplayName;
175
+
176
+            Chat.setChatConversationMode(true);
177
+        }
178
+
179
+        $('#nickinput').keydown(function (event) {
180
+            if (event.keyCode === 13) {
181
+                event.preventDefault();
182
+                var val = Util.escapeHtml(this.value);
183
+                this.value = '';
184
+                if (!nickname) {
185
+                    nickname = val;
186
+                    window.localStorage.displayname = nickname;
187
+
188
+                    connection.emuc.addDisplayNameToPresence(nickname);
189
+                    connection.emuc.sendPresence();
190
+
191
+                    Chat.setChatConversationMode(true);
192
+
193
+                    return;
194
+                }
195
+            }
196
+        });
197
+
198
+        $('#usermsg').keydown(function (event) {
199
+            if (event.keyCode === 13) {
200
+                event.preventDefault();
201
+                var value = this.value;
202
+                $('#usermsg').val('').trigger('autosize.resize');
203
+                this.focus();
204
+                var command = new CommandsProcessor(value);
205
+                if(command.isCommand())
206
+                {
207
+                    command.processCommand();
208
+                }
209
+                else
210
+                {
211
+                    var message = Util.escapeHtml(value);
212
+                    connection.emuc.sendMessage(message, nickname);
213
+                }
214
+            }
215
+        });
216
+
217
+        var onTextAreaResize = function () {
218
+            resizeChatConversation();
219
+            Chat.scrollChatToBottom();
220
+        };
221
+        $('#usermsg').autosize({callback: onTextAreaResize});
222
+
223
+        $("#chatspace").bind("shown",
224
+            function () {
225
+                unreadMessages = 0;
226
+                setVisualNotification(false);
227
+            });
228
+
229
+        addSmileys();
230
+    };
231
+
232
+    /**
233
+     * Appends the given message to the chat conversation.
234
+     */
235
+    my.updateChatConversation = function (from, displayName, message) {
236
+        var divClassName = '';
237
+
238
+        if (connection.emuc.myroomjid === from) {
239
+            divClassName = "localuser";
240
+        }
241
+        else {
242
+            divClassName = "remoteuser";
243
+
244
+            if (!Chat.isVisible()) {
245
+                unreadMessages++;
246
+                Util.playSoundNotification('chatNotification');
247
+                setVisualNotification(true);
248
+            }
249
+        }
250
+
251
+        // replace links and smileys
252
+        // Strophe already escapes special symbols on sending,
253
+        // so we escape here only tags to avoid double &amp;
254
+        var escMessage = message.replace(/</g, '&lt;').
255
+            replace(/>/g, '&gt;').replace(/\n/g, '<br/>');
256
+        var escDisplayName = Util.escapeHtml(displayName);
257
+        message = Replacement.processReplacements(escMessage);
258
+
259
+        var messageContainer =
260
+            '<div class="chatmessage">'+
261
+                '<img src="../images/chatArrow.svg" class="chatArrow">' +
262
+                '<div class="username ' + divClassName +'">' + escDisplayName +
263
+                '</div>' + '<div class="timestamp">' + getCurrentTime() +
264
+                '</div>' + '<div class="usermessage">' + message + '</div>' +
265
+            '</div>';
266
+
267
+        $('#chatconversation').append(messageContainer);
268
+        $('#chatconversation').animate(
269
+                { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
270
+    };
271
+
272
+    /**
273
+     * Appends error message to the conversation
274
+     * @param errorMessage the received error message.
275
+     * @param originalText the original message.
276
+     */
277
+    my.chatAddError = function(errorMessage, originalText)
278
+    {
279
+        errorMessage = Util.escapeHtml(errorMessage);
280
+        originalText = Util.escapeHtml(originalText);
281
+
282
+        $('#chatconversation').append(
283
+            '<div class="errorMessage"><b>Error: </b>' + 'Your message' +
284
+            (originalText? (' \"'+ originalText + '\"') : "") +
285
+            ' was not sent.' +
286
+            (errorMessage? (' Reason: ' + errorMessage) : '') +  '</div>');
287
+        $('#chatconversation').animate(
288
+            { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
289
+    };
290
+
291
+    /**
292
+     * Sets the subject to the UI
293
+     * @param subject the subject
294
+     */
295
+    my.chatSetSubject = function(subject)
296
+    {
297
+        if(subject)
298
+            subject = subject.trim();
299
+        $('#subject').html(Replacement.linkify(Util.escapeHtml(subject)));
300
+        if(subject === "")
301
+        {
302
+            $("#subject").css({display: "none"});
303
+        }
304
+        else
305
+        {
306
+            $("#subject").css({display: "block"});
307
+        }
308
+    };
309
+
310
+
311
+
312
+    /**
313
+     * Sets the chat conversation mode.
314
+     */
315
+    my.setChatConversationMode = function (isConversationMode) {
316
+        if (isConversationMode) {
317
+            $('#nickname').css({visibility: 'hidden'});
318
+            $('#chatconversation').css({visibility: 'visible'});
319
+            $('#usermsg').css({visibility: 'visible'});
320
+            $('#smileysarea').css({visibility: 'visible'});
321
+            $('#usermsg').focus();
322
+        }
323
+    };
324
+
325
+    /**
326
+     * Resizes the chat area.
327
+     */
328
+    my.resizeChat = function () {
329
+        var chatSize = require("../SidePanelToggler").getPanelSize();
330
+
331
+        $('#chatspace').width(chatSize[0]);
332
+        $('#chatspace').height(chatSize[1]);
333
+
334
+        resizeChatConversation();
335
+    };
336
+
337
+    /**
338
+     * Indicates if the chat is currently visible.
339
+     */
340
+    my.isVisible = function () {
341
+        return $('#chatspace').is(":visible");
342
+    };
343
+    /**
344
+     * Shows and hides the window with the smileys
345
+     */
346
+    my.toggleSmileys = toggleSmileys;
347
+
348
+    /**
349
+     * Scrolls chat to the bottom.
350
+     */
351
+    my.scrollChatToBottom = function() {
352
+        setTimeout(function () {
353
+            $('#chatconversation').scrollTop(
354
+                $('#chatconversation')[0].scrollHeight);
355
+        }, 5);
356
+    };
357
+
358
+
359
+    return my;
360
+}(Chat || {}));
361
+module.exports = Chat;

+ 95
- 0
modules/UI/side_pannels/chat/Commands.js Zobrazit soubor

@@ -0,0 +1,95 @@
1
+/**
2
+ * List with supported commands. The keys are the names of the commands and
3
+ * the value is the function that processes the message.
4
+ * @type {{String: function}}
5
+ */
6
+var commands = {
7
+    "topic" : processTopic
8
+};
9
+
10
+/**
11
+ * Extracts the command from the message.
12
+ * @param message the received message
13
+ * @returns {string} the command
14
+ */
15
+function getCommand(message)
16
+{
17
+    if(message)
18
+    {
19
+        for(var command in commands)
20
+        {
21
+            if(message.indexOf("/" + command) == 0)
22
+                return command;
23
+        }
24
+    }
25
+    return "";
26
+};
27
+
28
+/**
29
+ * Processes the data for topic command.
30
+ * @param commandArguments the arguments of the topic command.
31
+ */
32
+function processTopic(commandArguments)
33
+{
34
+    var topic = Util.escapeHtml(commandArguments);
35
+    connection.emuc.setSubject(topic);
36
+}
37
+
38
+/**
39
+ * Constructs new CommandProccessor instance from a message that
40
+ * handles commands received via chat messages.
41
+ * @param message the message
42
+ * @constructor
43
+ */
44
+function CommandsProcessor(message)
45
+{
46
+
47
+
48
+    var command = getCommand(message);
49
+
50
+    /**
51
+     * Returns the name of the command.
52
+     * @returns {String} the command
53
+     */
54
+    this.getCommand = function()
55
+    {
56
+        return command;
57
+    };
58
+
59
+
60
+    var messageArgument = message.substr(command.length + 2);
61
+
62
+    /**
63
+     * Returns the arguments of the command.
64
+     * @returns {string}
65
+     */
66
+    this.getArgument = function()
67
+    {
68
+        return messageArgument;
69
+    };
70
+}
71
+
72
+/**
73
+ * Checks whether this instance is valid command or not.
74
+ * @returns {boolean}
75
+ */
76
+CommandsProcessor.prototype.isCommand = function()
77
+{
78
+    if(this.getCommand())
79
+        return true;
80
+    return false;
81
+};
82
+
83
+/**
84
+ * Processes the command.
85
+ */
86
+CommandsProcessor.prototype.processCommand = function()
87
+{
88
+    if(!this.isCommand())
89
+        return;
90
+
91
+    commands[this.getCommand()](this.getArgument());
92
+
93
+};
94
+
95
+module.exports = CommandsProcessor;

replacement.js → modules/UI/side_pannels/chat/Replacement.js Zobrazit soubor

@@ -1,3 +1,4 @@
1
+var Smileys = require("./smileys.json");
1 2
 /**
2 3
  * Processes links and smileys in "body"
3 4
  */
@@ -44,6 +45,7 @@ function smilify(body)
44 45
         return body;
45 46
     }
46 47
 
48
+    var regexs = Smileys["regexs"];
47 49
     for(var smiley in regexs) {
48 50
         if(regexs.hasOwnProperty(smiley)) {
49 51
             body = body.replace(regexs[smiley],
@@ -53,3 +55,8 @@ function smilify(body)
53 55
 
54 56
     return body;
55 57
 }
58
+
59
+module.exports = {
60
+    processReplacements: processReplacements,
61
+    linkify: linkify
62
+};

+ 48
- 0
modules/UI/side_pannels/chat/smileys.json Zobrazit soubor

@@ -0,0 +1,48 @@
1
+{
2
+    "smileys": {
3
+        "smiley1": ":)",
4
+        "smiley2": ":(",
5
+        "smiley3": ":D",
6
+        "smiley4": "(y)",
7
+        "smiley5": " :P",
8
+        "smiley6": "(wave)",
9
+        "smiley7": "(blush)",
10
+        "smiley8": "(chuckle)",
11
+        "smiley9": "(shocked)",
12
+        "smiley10": ":*",
13
+        "smiley11": "(n)",
14
+        "smiley12": "(search)",
15
+        "smiley13": " <3",
16
+        "smiley14": "(oops)",
17
+        "smiley15": "(angry)",
18
+        "smiley16": "(angel)",
19
+        "smiley17": "(sick)",
20
+        "smiley18": ";(",
21
+        "smiley19": "(bomb)",
22
+        "smiley20": "(clap)",
23
+        "smiley21": " ;)"
24
+    },
25
+    "regexs": {
26
+        "smiley2": /(:-\(\(|:-\(|:\(\(|:\(|\(sad\))/gi,
27
+        "smiley3": /(:-\)\)|:\)\)|\(lol\)|:-D|:D)/gi,
28
+        "smiley1": /(:-\)|:\))/gi,
29
+        "smiley4": /(\(y\)|\(Y\)|\(ok\))/gi,
30
+        "smiley5": /(:-P|:P|:-p|:p)/gi,
31
+        "smiley6": /(\(wave\))/gi,
32
+        "smiley7": /(\(blush\))/gi,
33
+        "smiley8": /(\(chuckle\))/gi,
34
+        "smiley9": /(:-0|\(shocked\))/gi,
35
+        "smiley10": /(:-\*|:\*|\(kiss\))/gi,
36
+        "smiley11": /(\(n\))/gi,
37
+        "smiley12": /(\(search\))/g,
38
+        "smiley13": /(<3|&lt;3|&amp;lt;3|\(L\)|\(l\)|\(H\)|\(h\))/gi,
39
+        "smiley14": /(\(oops\))/gi,
40
+        "smiley15": /(\(angry\))/gi,
41
+        "smiley16": /(\(angel\))/gi,
42
+        "smiley17": /(\(sick\))/gi,
43
+        "smiley18": /(;-\(\(|;\(\(|;-\(|;\(|:"\(|:"-\(|:~-\(|:~\(|\(upset\))/gi,
44
+        "smiley19": /(\(bomb\))/gi,
45
+        "smiley20": /(\(clap\))/gi,
46
+        "smiley21": /(;-\)|;\)|;-\)\)|;\)\)|;-D|;D|\(wink\))/gi
47
+    }
48
+}

contact_list.js → modules/UI/side_pannels/contactlist/ContactList.js Zobrazit soubor

@@ -1,20 +1,91 @@
1
+
2
+var numberOfContacts = 0;
3
+var notificationInterval;
4
+
1 5
 /**
2
- * Contact list.
6
+ * Updates the number of participants in the contact list button and sets
7
+ * the glow
8
+ * @param delta indicates whether a new user has joined (1) or someone has
9
+ * left(-1)
3 10
  */
4
-var ContactList = (function (my) {
11
+function updateNumberOfParticipants(delta) {
12
+    //when the user is alone we don't show the number of participants
13
+    if(numberOfContacts === 0) {
14
+        $("#numberOfParticipants").text('');
15
+        numberOfContacts += delta;
16
+    } else if(numberOfContacts !== 0 && !ContactList.isVisible()) {
17
+        ContactList.setVisualNotification(true);
18
+        numberOfContacts += delta;
19
+        $("#numberOfParticipants").text(numberOfContacts);
20
+    }
21
+}
5 22
 
6
-    var numberOfContacts = 0;
7
-    var notificationInterval;
23
+/**
24
+ * Creates the avatar element.
25
+ *
26
+ * @return the newly created avatar element
27
+ */
28
+function createAvatar(id) {
29
+    var avatar = document.createElement('img');
30
+    avatar.className = "icon-avatar avatar";
31
+    avatar.src = "https://www.gravatar.com/avatar/" + id + "?d=wavatar&size=30";
32
+
33
+    return avatar;
34
+}
35
+
36
+/**
37
+ * Creates the display name paragraph.
38
+ *
39
+ * @param displayName the display name to set
40
+ */
41
+function createDisplayNameParagraph(displayName) {
42
+    var p = document.createElement('p');
43
+    p.innerText = displayName;
44
+
45
+    return p;
46
+}
47
+
48
+
49
+/**
50
+ * Indicates that the display name has changed.
51
+ */
52
+$(document).bind(   'displaynamechanged',
53
+    function (event, peerJid, displayName) {
54
+        if (peerJid === 'localVideoContainer')
55
+            peerJid = connection.emuc.myroomjid;
8 56
 
57
+        var resourceJid = Strophe.getResourceFromJid(peerJid);
58
+
59
+        var contactName = $('#contactlist #' + resourceJid + '>p');
60
+
61
+        if (contactName && displayName && displayName.length > 0)
62
+            contactName.html(displayName);
63
+    });
64
+
65
+
66
+function stopGlowing(glower) {
67
+    window.clearInterval(notificationInterval);
68
+    notificationInterval = false;
69
+    glower.removeClass('glowing');
70
+    if (!ContactList.isVisible()) {
71
+        glower.removeClass('active');
72
+    }
73
+}
74
+
75
+
76
+/**
77
+ * Contact list.
78
+ */
79
+var ContactList = {
9 80
     /**
10 81
      * Indicates if the chat is currently visible.
11 82
      *
12 83
      * @return <tt>true</tt> if the chat is currently visible, <tt>false</tt> -
13 84
      * otherwise
14 85
      */
15
-    my.isVisible = function () {
86
+    isVisible: function () {
16 87
         return $('#contactlist').is(":visible");
17
-    };
88
+    },
18 89
 
19 90
     /**
20 91
      * Adds a contact for the given peerJid if such doesn't yet exist.
@@ -22,14 +93,14 @@ var ContactList = (function (my) {
22 93
      * @param peerJid the peerJid corresponding to the contact
23 94
      * @param id the user's email or userId used to get the user's avatar
24 95
      */
25
-    my.ensureAddContact = function(peerJid, id) {
96
+    ensureAddContact: function (peerJid, id) {
26 97
         var resourceJid = Strophe.getResourceFromJid(peerJid);
27 98
 
28 99
         var contact = $('#contactlist>ul>li[id="' + resourceJid + '"]');
29 100
 
30 101
         if (!contact || contact.length <= 0)
31
-            ContactList.addContact(peerJid,id);
32
-    };
102
+            ContactList.addContact(peerJid, id);
103
+    },
33 104
 
34 105
     /**
35 106
      * Adds a contact for the given peer jid.
@@ -37,18 +108,16 @@ var ContactList = (function (my) {
37 108
      * @param peerJid the jid of the contact to add
38 109
      * @param id the email or userId of the user
39 110
      */
40
-    my.addContact = function(peerJid, id) {
111
+    addContact: function (peerJid, id) {
41 112
         var resourceJid = Strophe.getResourceFromJid(peerJid);
42 113
 
43 114
         var contactlist = $('#contactlist>ul');
44 115
 
45 116
         var newContact = document.createElement('li');
46
-        // XXX(gp) contact click event handling is now in videolayout.js. Is the
47
-        // following statement (newContact.id = resourceJid) still relevant?
48 117
         newContact.id = resourceJid;
49 118
         newContact.className = "clickable";
50
-        newContact.onclick = function(event) {
51
-            if(event.currentTarget.className === "clickable") {
119
+        newContact.onclick = function (event) {
120
+            if (event.currentTarget.className === "clickable") {
52 121
                 $(ContactList).trigger('contactclicked', [peerJid]);
53 122
             }
54 123
         };
@@ -59,23 +128,22 @@ var ContactList = (function (my) {
59 128
         var clElement = contactlist.get(0);
60 129
 
61 130
         if (resourceJid === Strophe.getResourceFromJid(connection.emuc.myroomjid)
62
-            && $('#contactlist>ul .title')[0].nextSibling.nextSibling)
63
-        {
131
+            && $('#contactlist>ul .title')[0].nextSibling.nextSibling) {
64 132
             clElement.insertBefore(newContact,
65
-                    $('#contactlist>ul .title')[0].nextSibling.nextSibling);
133
+                $('#contactlist>ul .title')[0].nextSibling.nextSibling);
66 134
         }
67 135
         else {
68 136
             clElement.appendChild(newContact);
69 137
         }
70 138
         updateNumberOfParticipants(1);
71
-    };
139
+    },
72 140
 
73 141
     /**
74 142
      * Removes a contact for the given peer jid.
75 143
      *
76 144
      * @param peerJid the peerJid corresponding to the contact to remove
77 145
      */
78
-    my.removeContact = function(peerJid) {
146
+    removeContact: function (peerJid) {
79 147
         var resourceJid = Strophe.getResourceFromJid(peerJid);
80 148
 
81 149
         var contact = $('#contactlist>ul>li[id="' + resourceJid + '"]');
@@ -87,18 +155,10 @@ var ContactList = (function (my) {
87 155
 
88 156
             updateNumberOfParticipants(-1);
89 157
         }
90
-    };
158
+    },
91 159
 
92
-    my.setVisualNotification = function(show, stopGlowingIn) {
160
+    setVisualNotification: function (show, stopGlowingIn) {
93 161
         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
-        }
102 162
 
103 163
         if (show && !notificationInterval) {
104 164
             notificationInterval = window.setInterval(function () {
@@ -106,81 +166,23 @@ var ContactList = (function (my) {
106 166
             }, 800);
107 167
         }
108 168
         else if (!show && notificationInterval) {
109
-            stopGlowing();
110
-        }
111
-        if(stopGlowingIn) {
112
-            setTimeout(stopGlowing, stopGlowingIn);
169
+            stopGlowing(glower);
113 170
         }
114
-    };
115
-
116
-    /**
117
-     * Updates the number of participants in the contact list button and sets
118
-     * the glow
119
-     * @param delta indicates whether a new user has joined (1) or someone has
120
-     * left(-1)
121
-     */
122
-    function updateNumberOfParticipants(delta) {
123
-        //when the user is alone we don't show the number of participants
124
-        if(numberOfContacts === 0) {
125
-            $("#numberOfParticipants").text('');
126
-            numberOfContacts += delta;
127
-        } else if(numberOfContacts !== 0 && !ContactList.isVisible()) {
128
-            ContactList.setVisualNotification(true);
129
-            numberOfContacts += delta;
130
-            $("#numberOfParticipants").text(numberOfContacts);
171
+        if (stopGlowingIn) {
172
+            setTimeout(function () {
173
+                stopGlowing(glower);
174
+            }, stopGlowingIn);
131 175
         }
132
-    }
133
-
134
-    /**
135
-     * Creates the avatar element.
136
-     * 
137
-     * @return the newly created avatar element
138
-     */
139
-    function createAvatar(id) {
140
-        var avatar = document.createElement('img');
141
-        avatar.className = "icon-avatar avatar";
142
-        avatar.src = "https://www.gravatar.com/avatar/" + id + "?d=wavatar&size=30";
143
-
144
-        return avatar;
145
-    }
146
-
147
-    /**
148
-     * Creates the display name paragraph.
149
-     *
150
-     * @param displayName the display name to set
151
-     */
152
-    function createDisplayNameParagraph(displayName) {
153
-        var p = document.createElement('p');
154
-        p.innerText = displayName;
155
-
156
-        return p;
157
-    }
158
-
159
-
160
-    /**
161
-     * Indicates that the display name has changed.
162
-     */
163
-    $(document).bind(   'displaynamechanged',
164
-                        function (event, peerJid, displayName) {
165
-        if (peerJid === 'localVideoContainer')
166
-            peerJid = connection.emuc.myroomjid;
167
-
168
-        var resourceJid = Strophe.getResourceFromJid(peerJid);
169
-
170
-        var contactName = $('#contactlist #' + resourceJid + '>p');
171
-
172
-        if (contactName && displayName && displayName.length > 0)
173
-            contactName.html(displayName);
174
-    });
176
+    },
175 177
 
176
-    my.setClickable = function(resourceJid, isClickable) {
178
+    setClickable: function (resourceJid, isClickable) {
177 179
         var contact = $('#contactlist>ul>li[id="' + resourceJid + '"]');
178
-        if(isClickable) {
180
+        if (isClickable) {
179 181
             contact.addClass('clickable');
180 182
         } else {
181 183
             contact.removeClass('clickable');
182 184
         }
183
-    };
185
+    }
186
+};
184 187
 
185
-    return my;
186
-}(ContactList || {}));
188
+module.exports = ContactList;

+ 58
- 0
modules/UI/side_pannels/settings/Settings.js Zobrazit soubor

@@ -0,0 +1,58 @@
1
+var email = '';
2
+var displayName = '';
3
+var userId;
4
+
5
+
6
+function supportsLocalStorage() {
7
+    try {
8
+        return 'localStorage' in window && window.localStorage !== null;
9
+    } catch (e) {
10
+        console.log("localstorage is not supported");
11
+        return false;
12
+    }
13
+}
14
+
15
+
16
+function generateUniqueId() {
17
+    function _p8() {
18
+        return (Math.random().toString(16)+"000000000").substr(2,8);
19
+    }
20
+    return _p8() + _p8() + _p8() + _p8();
21
+}
22
+
23
+if(supportsLocalStorage()) {
24
+    if(!window.localStorage.jitsiMeetId) {
25
+        window.localStorage.jitsiMeetId = generateUniqueId();
26
+        console.log("generated id", window.localStorage.jitsiMeetId);
27
+    }
28
+    userId = window.localStorage.jitsiMeetId || '';
29
+    email = window.localStorage.email || '';
30
+    displayName = window.localStorage.displayname || '';
31
+} else {
32
+    console.log("local storage is not supported");
33
+    userId = generateUniqueId();
34
+}
35
+
36
+var Settings =
37
+{
38
+    setDisplayName: function (newDisplayName) {
39
+        displayName = newDisplayName;
40
+        window.localStorage.displayname = displayName;
41
+        return displayName;
42
+    },
43
+    setEmail: function(newEmail)
44
+    {
45
+        email = newEmail;
46
+        window.localStorage.email = newEmail;
47
+        return email;
48
+    },
49
+    getSettings: function () {
50
+        return {
51
+            email: email,
52
+            displayName: displayName,
53
+            uid: userId
54
+        };
55
+    }
56
+};
57
+
58
+module.exports = Settings;

+ 42
- 0
modules/UI/side_pannels/settings/SettingsMenu.js Zobrazit soubor

@@ -0,0 +1,42 @@
1
+var Avatar = require("../../avatar/Avatar");
2
+var Settings = require("./Settings");
3
+
4
+
5
+var SettingsMenu = {
6
+
7
+    update: function() {
8
+        var newDisplayName = Util.escapeHtml($('#setDisplayName').get(0).value);
9
+        var newEmail = Util.escapeHtml($('#setEmail').get(0).value);
10
+
11
+        if(newDisplayName) {
12
+            var displayName = Settings.setDisplayName(newDisplayName);
13
+            connection.emuc.addDisplayNameToPresence(displayName);
14
+        }
15
+
16
+
17
+        connection.emuc.addEmailToPresence(newEmail);
18
+        var email = Settings.setEmail(newEmail);
19
+
20
+
21
+        connection.emuc.sendPresence();
22
+        Avatar.setUserAvatar(connection.emuc.myroomjid, email);
23
+    },
24
+
25
+    isVisible: function() {
26
+        return $('#settingsmenu').is(':visible');
27
+    },
28
+
29
+    setDisplayName: function(newDisplayName) {
30
+        var displayName = Settings.setDisplayName(newDisplayName);
31
+        $('#setDisplayName').get(0).value = displayName;
32
+    }
33
+};
34
+
35
+$(document).bind('displaynamechanged', function(event, peerJid, newDisplayName) {
36
+    if(peerJid === 'localVideoContainer' ||
37
+        peerJid === connection.emuc.myroomjid) {
38
+        SettingsMenu.setDisplayName(newDisplayName);
39
+    }
40
+});
41
+
42
+module.exports = SettingsMenu;

bottom_toolbar.js → modules/UI/toolbars/BottomToolbar.js Zobrazit soubor

@@ -1,4 +1,23 @@
1
+var PanelToggler = require("../side_pannels/SidePanelToggler");
2
+
3
+var buttonHandlers = {
4
+    "bottom_toolbar_contact_list": function () {
5
+        BottomToolbar.toggleContactList();
6
+    },
7
+    "bottom_toolbar_film_strip": function () {
8
+        BottomToolbar.toggleFilmStrip();
9
+    },
10
+    "bottom_toolbar_chat": function () {
11
+        BottomToolbar.toggleChat();
12
+    }
13
+};
14
+
1 15
 var BottomToolbar = (function (my) {
16
+    my.init = function () {
17
+        for(var k in buttonHandlers)
18
+            $("#" + k).click(buttonHandlers[k]);
19
+    };
20
+
2 21
     my.toggleChat = function() {
3 22
         PanelToggler.toggleChat();
4 23
     };
@@ -20,3 +39,5 @@ var BottomToolbar = (function (my) {
20 39
 
21 40
     return my;
22 41
 }(BottomToolbar || {}));
42
+
43
+module.exports = BottomToolbar;

toolbar.js → modules/UI/toolbars/Toolbar.js Zobrazit soubor

@@ -1,7 +1,205 @@
1
-/* global $, buttonClick, config, lockRoom, messageHandler, Moderator, roomUrl,
1
+/* global $, buttonClick, config, lockRoom,  Moderator,
2 2
    setSharedKey, sharedKey, Util */
3
+var messageHandler = require("../util/MessageHandler");
4
+var BottomToolbar = require("./BottomToolbar");
5
+var Prezi = require("../prezi/Prezi");
6
+var Etherpad = require("../etherpad/Etherpad");
7
+var PanelToggler = require("../side_pannels/SidePanelToggler");
8
+
9
+var roomUrl = null;
10
+var sharedKey = '';
11
+var authenticationWindow = null;
12
+
13
+var buttonHandlers =
14
+{
15
+    "toolbar_button_mute": function () {
16
+        return toggleAudio();
17
+    },
18
+    "toolbar_button_camera": function () {
19
+        return toggleVideo();
20
+    },
21
+    "toolbar_button_authentication": function () {
22
+        return Toolbar.authenticateClicked();
23
+    },
24
+    "toolbar_button_record": function () {
25
+        return toggleRecording();
26
+    },
27
+    "toolbar_button_security": function () {
28
+        return Toolbar.openLockDialog();
29
+    },
30
+    "toolbar_button_link": function () {
31
+        return Toolbar.openLinkDialog();
32
+    },
33
+    "toolbar_button_chat": function () {
34
+        return BottomToolbar.toggleChat();
35
+    },
36
+    "toolbar_button_prezi": function () {
37
+        return Prezi.openPreziDialog();
38
+    },
39
+    "toolbar_button_etherpad": function () {
40
+        return Etherpad.toggleEtherpad(0);
41
+    },
42
+    "toolbar_button_desktopsharing": function () {
43
+        return toggleScreenSharing();
44
+    },
45
+    "toolbar_button_fullScreen": function()
46
+    {
47
+        buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");
48
+        return Toolbar.toggleFullScreen();
49
+    },
50
+    "toolbar_button_sip": function () {
51
+        return callSipButtonClicked();
52
+    },
53
+    "toolbar_button_settings": function () {
54
+        PanelToggler.toggleSettingsMenu();
55
+    },
56
+    "toolbar_button_hangup": function () {
57
+        return hangup();
58
+    }
59
+};
60
+
61
+/**
62
+ * Starts or stops the recording for the conference.
63
+ */
64
+
65
+function toggleRecording() {
66
+    Recording.toggleRecording();
67
+}
68
+
69
+/**
70
+ * Locks / unlocks the room.
71
+ */
72
+function lockRoom(lock) {
73
+    var currentSharedKey = '';
74
+    if (lock)
75
+        currentSharedKey = sharedKey;
76
+
77
+    connection.emuc.lockRoom(currentSharedKey, function (res) {
78
+        // password is required
79
+        if (sharedKey)
80
+        {
81
+            console.log('set room password');
82
+            Toolbar.lockLockButton();
83
+        }
84
+        else
85
+        {
86
+            console.log('removed room password');
87
+            Toolbar.unlockLockButton();
88
+        }
89
+    }, function (err) {
90
+        console.warn('setting password failed', err);
91
+        messageHandler.showError('Lock failed',
92
+            'Failed to lock conference.',
93
+            err);
94
+        Toolbar.setSharedKey('');
95
+    }, function () {
96
+        console.warn('room passwords not supported');
97
+        messageHandler.showError('Warning',
98
+            'Room passwords are currently not supported.');
99
+        Toolbar.setSharedKey('');
100
+    });
101
+};
102
+
103
+/**
104
+ * Invite participants to conference.
105
+ */
106
+function inviteParticipants() {
107
+    if (roomUrl === null)
108
+        return;
109
+
110
+    var sharedKeyText = "";
111
+    if (sharedKey && sharedKey.length > 0) {
112
+        sharedKeyText =
113
+            "This conference is password protected. Please use the " +
114
+            "following pin when joining:%0D%0A%0D%0A" +
115
+            sharedKey + "%0D%0A%0D%0A";
116
+    }
117
+
118
+    var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1);
119
+    var subject = "Invitation to a " + interfaceConfig.APP_NAME + " (" + conferenceName + ")";
120
+    var body = "Hey there, I%27d like to invite you to a " + interfaceConfig.APP_NAME +
121
+        " conference I%27ve just set up.%0D%0A%0D%0A" +
122
+        "Please click on the following link in order" +
123
+        " to join the conference.%0D%0A%0D%0A" +
124
+        roomUrl +
125
+        "%0D%0A%0D%0A" +
126
+        sharedKeyText +
127
+        "Note that " + interfaceConfig.APP_NAME + " is currently" +
128
+        " only supported by Chromium," +
129
+        " Google Chrome and Opera, so you need" +
130
+        " to be using one of these browsers.%0D%0A%0D%0A" +
131
+        "Talk to you in a sec!";
132
+
133
+    if (window.localStorage.displayname) {
134
+        body += "%0D%0A%0D%0A" + window.localStorage.displayname;
135
+    }
136
+
137
+    if (interfaceConfig.INVITATION_POWERED_BY) {
138
+        body += "%0D%0A%0D%0A--%0D%0Apowered by jitsi.org";
139
+    }
140
+
141
+    window.open("mailto:?subject=" + subject + "&body=" + body, '_blank');
142
+}
143
+
3 144
 var Toolbar = (function (my) {
4 145
 
146
+    my.init = function () {
147
+        for(var k in buttonHandlers)
148
+            $("#" + k).click(buttonHandlers[k]);
149
+    }
150
+
151
+    /**
152
+     * Sets shared key
153
+     * @param sKey the shared key
154
+     */
155
+    my.setSharedKey = function (sKey) {
156
+        sharedKey = sKey;
157
+    };
158
+
159
+    my.closeAuthenticationWindow = function () {
160
+        if (authenticationWindow) {
161
+            authenticationWindow.close();
162
+            authenticationWindow = null;
163
+        }
164
+    }
165
+
166
+    my.authenticateClicked = function () {
167
+        // Get authentication URL
168
+        Moderator.getAuthUrl(function (url) {
169
+            // Open popup with authentication URL
170
+            authenticationWindow = messageHandler.openCenteredPopup(
171
+                url, 500, 400,
172
+                function () {
173
+                    // On popup closed - retry room allocation
174
+                    Moderator.allocateConferenceFocus(
175
+                        roomName, doJoinAfterFocus);
176
+                    authenticationWindow = null;
177
+                });
178
+            if (!authenticationWindow) {
179
+                Toolbar.showAuthenticateButton(true);
180
+                messageHandler.openMessageDialog(
181
+                    null, "Your browser is blocking popup windows from this site." +
182
+                        " Please enable popups in your browser security settings" +
183
+                        " and try again.");
184
+            }
185
+        });
186
+    };
187
+
188
+    /**
189
+     * Updates the room invite url.
190
+     */
191
+    my.updateRoomUrl = function (newRoomUrl) {
192
+        roomUrl = newRoomUrl;
193
+
194
+        // If the invite dialog has been already opened we update the information.
195
+        var inviteLink = document.getElementById('inviteLinkRef');
196
+        if (inviteLink) {
197
+            inviteLink.value = roomUrl;
198
+            inviteLink.select();
199
+            document.getElementById('jqi_state0_buttonInvite').disabled = false;
200
+        }
201
+    }
202
+
5 203
     /**
6 204
      * Disables and enables some of the buttons.
7 205
      */
@@ -41,7 +239,7 @@ var Toolbar = (function (my) {
41 239
                     "Remove",
42 240
                     function (e, v) {
43 241
                         if (v) {
44
-                            setSharedKey('');
242
+                            Toolbar.setSharedKey('');
45 243
                             lockRoom(false);
46 244
                         }
47 245
                     });
@@ -57,7 +255,7 @@ var Toolbar = (function (my) {
57 255
                             var lockKey = document.getElementById('lockKey');
58 256
 
59 257
                             if (lockKey.value) {
60
-                                setSharedKey(Util.escapeHtml(lockKey.value));
258
+                                Toolbar.setSharedKey(Util.escapeHtml(lockKey.value));
61 259
                                 lockRoom(true);
62 260
                             }
63 261
                         }
@@ -104,47 +302,6 @@ var Toolbar = (function (my) {
104 302
         );
105 303
     };
106 304
 
107
-    /**
108
-     * Invite participants to conference.
109
-     */
110
-    function inviteParticipants() {
111
-        if (roomUrl === null)
112
-            return;
113
-
114
-        var sharedKeyText = "";
115
-        if (sharedKey && sharedKey.length > 0) {
116
-            sharedKeyText =
117
-                "This conference is password protected. Please use the " +
118
-                "following pin when joining:%0D%0A%0D%0A" +
119
-                sharedKey + "%0D%0A%0D%0A";
120
-        }
121
-
122
-        var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1);
123
-        var subject = "Invitation to a " + interfaceConfig.APP_NAME + " (" + conferenceName + ")";
124
-        var body = "Hey there, I%27d like to invite you to a " + interfaceConfig.APP_NAME +
125
-                    " conference I%27ve just set up.%0D%0A%0D%0A" +
126
-                    "Please click on the following link in order" +
127
-                    " to join the conference.%0D%0A%0D%0A" +
128
-                    roomUrl +
129
-                    "%0D%0A%0D%0A" +
130
-                    sharedKeyText +
131
-                    "Note that " + interfaceConfig.APP_NAME + " is currently" +
132
-                    " only supported by Chromium," +
133
-                    " Google Chrome and Opera, so you need" +
134
-                    " to be using one of these browsers.%0D%0A%0D%0A" +
135
-                    "Talk to you in a sec!";
136
-
137
-        if (window.localStorage.displayname) {
138
-            body += "%0D%0A%0D%0A" + window.localStorage.displayname;
139
-        }
140
-
141
-        if (interfaceConfig.INVITATION_POWERED_BY) {
142
-            body += "%0D%0A%0D%0A--%0D%0Apowered by jitsi.org";
143
-        }
144
-
145
-        window.open("mailto:?subject=" + subject + "&body=" + body, '_blank');
146
-    }
147
-
148 305
     /**
149 306
      * Opens the settings dialog.
150 307
      */
@@ -291,3 +448,5 @@ var Toolbar = (function (my) {
291 448
 
292 449
     return my;
293 450
 }(Toolbar || {}));
451
+
452
+module.exports = Toolbar;

toolbar_toggler.js → modules/UI/toolbars/ToolbarToggler.js Zobrazit soubor

@@ -1,12 +1,46 @@
1 1
 /* global $, interfaceConfig, Moderator, showDesktopSharingButton */
2
-var ToolbarToggler = (function (my) {
3
-    var toolbarTimeoutObject,
4
-        toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT;
5 2
 
3
+var toolbarTimeoutObject,
4
+    toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT;
5
+
6
+/**
7
+ * Hides the toolbar.
8
+ */
9
+function hideToolbar() {
10
+    var header = $("#header"),
11
+        bottomToolbar = $("#bottomToolbar");
12
+    var isToolbarHover = false;
13
+    header.find('*').each(function () {
14
+        var id = $(this).attr('id');
15
+        if ($("#" + id + ":hover").length > 0) {
16
+            isToolbarHover = true;
17
+        }
18
+    });
19
+    if ($("#bottomToolbar:hover").length > 0) {
20
+        isToolbarHover = true;
21
+    }
22
+
23
+    clearTimeout(toolbarTimeoutObject);
24
+    toolbarTimeoutObject = null;
25
+
26
+    if (!isToolbarHover) {
27
+        header.hide("slide", { direction: "up", duration: 300});
28
+        $('#subject').animate({top: "-=40"}, 300);
29
+        if ($("#remoteVideos").hasClass("hidden")) {
30
+            bottomToolbar.hide(
31
+                "slide", {direction: "right", duration: 300});
32
+        }
33
+    }
34
+    else {
35
+        toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
36
+    }
37
+}
38
+
39
+var ToolbarToggler = {
6 40
     /**
7 41
      * Shows the main toolbar.
8 42
      */
9
-    my.showToolbar = function () {
43
+    showToolbar: function () {
10 44
         var header = $("#header"),
11 45
             bottomToolbar = $("#bottomToolbar");
12 46
         if (!header.is(':visible') || !bottomToolbar.is(":visible")) {
@@ -34,40 +68,7 @@ var ToolbarToggler = (function (my) {
34 68
 
35 69
         // Show/hide desktop sharing button
36 70
         showDesktopSharingButton();
37
-    };
38
-
39
-    /**
40
-     * Hides the toolbar.
41
-     */
42
-    var hideToolbar = function () {
43
-        var header = $("#header"),
44
-            bottomToolbar = $("#bottomToolbar");
45
-        var isToolbarHover = false;
46
-        header.find('*').each(function () {
47
-            var id = $(this).attr('id');
48
-            if ($("#" + id + ":hover").length > 0) {
49
-                isToolbarHover = true;
50
-            }
51
-        });
52
-        if ($("#bottomToolbar:hover").length > 0) {
53
-            isToolbarHover = true;
54
-        }
55
-
56
-        clearTimeout(toolbarTimeoutObject);
57
-        toolbarTimeoutObject = null;
58
-
59
-        if (!isToolbarHover) {
60
-            header.hide("slide", { direction: "up", duration: 300});
61
-            $('#subject').animate({top: "-=40"}, 300);
62
-            if ($("#remoteVideos").hasClass("hidden")) {
63
-                bottomToolbar.hide(
64
-                    "slide", {direction: "right", duration: 300});
65
-            }
66
-        }
67
-        else {
68
-            toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
69
-        }
70
-    };
71
+    },
71 72
 
72 73
 
73 74
     /**
@@ -75,11 +76,11 @@ var ToolbarToggler = (function (my) {
75 76
      *
76 77
      * @param isDock indicates what operation to perform
77 78
      */
78
-    my.dockToolbar = function (isDock) {
79
+    dockToolbar: function (isDock) {
79 80
         if (isDock) {
80 81
             // First make sure the toolbar is shown.
81 82
             if (!$('#header').is(':visible')) {
82
-                ToolbarToggler.showToolbar();
83
+                this.showToolbar();
83 84
             }
84 85
 
85 86
             // Then clear the time out, to dock the toolbar.
@@ -90,14 +91,14 @@ var ToolbarToggler = (function (my) {
90 91
         }
91 92
         else {
92 93
             if (!$('#header').is(':visible')) {
93
-                ToolbarToggler.showToolbar();
94
+                this.showToolbar();
94 95
             }
95 96
             else {
96 97
                 toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
97 98
             }
98 99
         }
99
-    };
100
+    }
100 101
 
102
+};
101 103
 
102
-    return my;
103
-}(ToolbarToggler || {}));
104
+module.exports = ToolbarToggler;

jitsipopover.js → modules/UI/util/JitsiPopover.js Zobrazit soubor

@@ -118,4 +118,6 @@ var JitsiPopover = (function () {
118 118
     return JitsiPopover;
119 119
 
120 120
 
121
-})();
121
+})();
122
+
123
+module.exports = JitsiPopover;

message_handler.js → modules/UI/util/MessageHandler.js Zobrazit soubor

@@ -149,4 +149,6 @@ var messageHandler = (function(my) {
149 149
     return my;
150 150
 }(messageHandler || {}));
151 151
 
152
+module.exports = messageHandler;
153
+
152 154
 

+ 16
- 0
modules/UI/util/UIUtil.js Zobrazit soubor

@@ -0,0 +1,16 @@
1
+/**
2
+ * Created by hristo on 12/22/14.
3
+ */
4
+module.exports = {
5
+    /**
6
+     * Returns the available video width.
7
+     */
8
+    getAvailableVideoWidth: function () {
9
+        var PanelToggler = require("../side_pannels/SidePanelToggler");
10
+        var rightPanelWidth
11
+            = PanelToggler.isVisible() ? PanelToggler.getPanelSize()[0] : 0;
12
+
13
+        return window.innerWidth - rightPanelWidth;
14
+    }
15
+
16
+};

+ 410
- 0
modules/UI/videolayout/ConnectionIndicator.js Zobrazit soubor

@@ -0,0 +1,410 @@
1
+var JitsiPopover = require("../util/JitsiPopover");
2
+
3
+/**
4
+ * Constructs new connection indicator.
5
+ * @param videoContainer the video container associated with the indicator.
6
+ * @constructor
7
+ */
8
+function ConnectionIndicator(videoContainer, jid, VideoLayout)
9
+{
10
+    this.videoContainer = videoContainer;
11
+    this.bandwidth = null;
12
+    this.packetLoss = null;
13
+    this.bitrate = null;
14
+    this.showMoreValue = false;
15
+    this.resolution = null;
16
+    this.transport = [];
17
+    this.popover = null;
18
+    this.jid = jid;
19
+    this.create();
20
+    this.videoLayout = VideoLayout;
21
+}
22
+
23
+/**
24
+ * Values for the connection quality
25
+ * @type {{98: string,
26
+ *         81: string,
27
+ *         64: string,
28
+ *         47: string,
29
+ *         30: string,
30
+ *         0: string}}
31
+ */
32
+ConnectionIndicator.connectionQualityValues = {
33
+    98: "18px", //full
34
+    81: "15px",//4 bars
35
+    64: "11px",//3 bars
36
+    47: "7px",//2 bars
37
+    30: "3px",//1 bar
38
+    0: "0px"//empty
39
+};
40
+
41
+ConnectionIndicator.getIP = function(value)
42
+{
43
+    return value.substring(0, value.lastIndexOf(":"));
44
+};
45
+
46
+ConnectionIndicator.getPort = function(value)
47
+{
48
+    return value.substring(value.lastIndexOf(":") + 1, value.length);
49
+};
50
+
51
+ConnectionIndicator.getStringFromArray = function (array) {
52
+    var res = "";
53
+    for(var i = 0; i < array.length; i++)
54
+    {
55
+        res += (i === 0? "" : ", ") + array[i];
56
+    }
57
+    return res;
58
+};
59
+
60
+/**
61
+ * Generates the html content.
62
+ * @returns {string} the html content.
63
+ */
64
+ConnectionIndicator.prototype.generateText = function () {
65
+    var downloadBitrate, uploadBitrate, packetLoss, resolution, i;
66
+
67
+    if(this.bitrate === null)
68
+    {
69
+        downloadBitrate = "N/A";
70
+        uploadBitrate = "N/A";
71
+    }
72
+    else
73
+    {
74
+        downloadBitrate =
75
+            this.bitrate.download? this.bitrate.download + " Kbps" : "N/A";
76
+        uploadBitrate =
77
+            this.bitrate.upload? this.bitrate.upload + " Kbps" : "N/A";
78
+    }
79
+
80
+    if(this.packetLoss === null)
81
+    {
82
+        packetLoss = "N/A";
83
+    }
84
+    else
85
+    {
86
+
87
+        packetLoss = "<span class='jitsipopover_green'>&darr;</span>" +
88
+            (this.packetLoss.download !== null? this.packetLoss.download : "N/A") +
89
+            "% <span class='jitsipopover_orange'>&uarr;</span>" +
90
+            (this.packetLoss.upload !== null? this.packetLoss.upload : "N/A") + "%";
91
+    }
92
+
93
+    var resolutionValue = null;
94
+    if(this.resolution)
95
+    {
96
+        var keys = Object.keys(this.resolution);
97
+        if(keys.length == 1)
98
+        {
99
+            for(var ssrc in this.resolution)
100
+            {
101
+                resolutionValue = this.resolution[ssrc];
102
+            }
103
+        }
104
+        else if(keys.length > 1)
105
+        {
106
+            var displayedSsrc = simulcast.getReceivingSSRC(this.jid);
107
+            resolutionValue = this.resolution[displayedSsrc];
108
+        }
109
+    }
110
+
111
+    if(this.jid === null)
112
+    {
113
+        resolution = "";
114
+        if(this.resolution === null || !Object.keys(this.resolution) ||
115
+            Object.keys(this.resolution).length === 0)
116
+        {
117
+            resolution = "N/A";
118
+        }
119
+        else
120
+            for(i in this.resolution)
121
+            {
122
+                resolutionValue = this.resolution[i];
123
+                if(resolutionValue)
124
+                {
125
+                    if(resolutionValue.height &&
126
+                        resolutionValue.width)
127
+                    {
128
+                        resolution += (resolution === ""? "" : ", ") +
129
+                            resolutionValue.width + "x" +
130
+                            resolutionValue.height;
131
+                    }
132
+                }
133
+            }
134
+    }
135
+    else if(!resolutionValue ||
136
+        !resolutionValue.height ||
137
+        !resolutionValue.width)
138
+    {
139
+        resolution = "N/A";
140
+    }
141
+    else
142
+    {
143
+        resolution = resolutionValue.width + "x" + resolutionValue.height;
144
+    }
145
+
146
+    var result = "<table style='width:100%'>" +
147
+        "<tr>" +
148
+        "<td><span class='jitsipopover_blue'>Bitrate:</span></td>" +
149
+        "<td><span class='jitsipopover_green'>&darr;</span>" +
150
+        downloadBitrate + " <span class='jitsipopover_orange'>&uarr;</span>" +
151
+        uploadBitrate + "</td>" +
152
+        "</tr><tr>" +
153
+        "<td><span class='jitsipopover_blue'>Packet loss: </span></td>" +
154
+        "<td>" + packetLoss  + "</td>" +
155
+        "</tr><tr>" +
156
+        "<td><span class='jitsipopover_blue'>Resolution:</span></td>" +
157
+        "<td>" + resolution + "</td></tr></table>";
158
+
159
+    if(this.videoContainer.id == "localVideoContainer")
160
+        result += "<div class=\"jitsipopover_showmore\" " +
161
+            "onclick = \"UI.connectionIndicatorShowMore('" +
162
+            this.videoContainer.id + "')\">" +
163
+            (this.showMoreValue? "Show less" : "Show More") + "</div><br />";
164
+
165
+    if(this.showMoreValue)
166
+    {
167
+        var downloadBandwidth, uploadBandwidth, transport;
168
+        if(this.bandwidth === null)
169
+        {
170
+            downloadBandwidth = "N/A";
171
+            uploadBandwidth = "N/A";
172
+        }
173
+        else
174
+        {
175
+            downloadBandwidth = this.bandwidth.download?
176
+                this.bandwidth.download + " Kbps" :
177
+                "N/A";
178
+            uploadBandwidth = this.bandwidth.upload?
179
+                this.bandwidth.upload + " Kbps" :
180
+                "N/A";
181
+        }
182
+
183
+        if(!this.transport || this.transport.length === 0)
184
+        {
185
+            transport = "<tr>" +
186
+                "<td><span class='jitsipopover_blue'>Address:</span></td>" +
187
+                "<td> N/A</td></tr>";
188
+        }
189
+        else
190
+        {
191
+            var data = {remoteIP: [], localIP:[], remotePort:[], localPort:[]};
192
+            for(i = 0; i < this.transport.length; i++)
193
+            {
194
+                var ip =  ConnectionIndicator.getIP(this.transport[i].ip);
195
+                var port = ConnectionIndicator.getPort(this.transport[i].ip);
196
+                var localIP =
197
+                    ConnectionIndicator.getIP(this.transport[i].localip);
198
+                var localPort =
199
+                    ConnectionIndicator.getPort(this.transport[i].localip);
200
+                if(data.remoteIP.indexOf(ip) == -1)
201
+                {
202
+                    data.remoteIP.push(ip);
203
+                }
204
+
205
+                if(data.remotePort.indexOf(port) == -1)
206
+                {
207
+                    data.remotePort.push(port);
208
+                }
209
+
210
+                if(data.localIP.indexOf(localIP) == -1)
211
+                {
212
+                    data.localIP.push(localIP);
213
+                }
214
+
215
+                if(data.localPort.indexOf(localPort) == -1)
216
+                {
217
+                    data.localPort.push(localPort);
218
+                }
219
+
220
+            }
221
+            var localTransport =
222
+                "<tr><td><span class='jitsipopover_blue'>Local address" +
223
+                (data.localIP.length > 1? "es" : "") + ": </span></td><td> " +
224
+                ConnectionIndicator.getStringFromArray(data.localIP) +
225
+                "</td></tr>";
226
+            transport =
227
+                "<tr><td><span class='jitsipopover_blue'>Remote address"+
228
+                (data.remoteIP.length > 1? "es" : "") + ":</span></td><td> " +
229
+                ConnectionIndicator.getStringFromArray(data.remoteIP) +
230
+                "</td></tr>";
231
+            if(this.transport.length > 1)
232
+            {
233
+                transport += "<tr>" +
234
+                    "<td>" +
235
+                    "<span class='jitsipopover_blue'>Remote ports:</span>" +
236
+                    "</td><td>";
237
+                localTransport += "<tr>" +
238
+                    "<td>" +
239
+                    "<span class='jitsipopover_blue'>Local ports:</span>" +
240
+                    "</td><td>";
241
+            }
242
+            else
243
+            {
244
+                transport +=
245
+                    "<tr>" +
246
+                    "<td>" +
247
+                    "<span class='jitsipopover_blue'>Remote port:</span>" +
248
+                    "</td><td>";
249
+                localTransport +=
250
+                    "<tr>" +
251
+                    "<td>" +
252
+                    "<span class='jitsipopover_blue'>Local port:</span>" +
253
+                    "</td><td>";
254
+            }
255
+
256
+            transport +=
257
+                ConnectionIndicator.getStringFromArray(data.remotePort);
258
+            localTransport +=
259
+                ConnectionIndicator.getStringFromArray(data.localPort);
260
+            transport += "</td></tr>";
261
+            transport += localTransport + "</td></tr>";
262
+            transport +="<tr>" +
263
+                "<td><span class='jitsipopover_blue'>Transport:</span></td>" +
264
+                "<td>" + this.transport[0].type + "</td></tr>";
265
+
266
+        }
267
+
268
+        result += "<table  style='width:100%'>" +
269
+            "<tr>" +
270
+            "<td>" +
271
+            "<span class='jitsipopover_blue'>Estimated bandwidth:</span>" +
272
+            "</td><td>" +
273
+            "<span class='jitsipopover_green'>&darr;</span>" +
274
+            downloadBandwidth +
275
+            " <span class='jitsipopover_orange'>&uarr;</span>" +
276
+            uploadBandwidth + "</td></tr>";
277
+
278
+        result += transport + "</table>";
279
+
280
+    }
281
+
282
+    return result;
283
+};
284
+
285
+/**
286
+ * Shows or hide the additional information.
287
+ */
288
+ConnectionIndicator.prototype.showMore = function () {
289
+    this.showMoreValue = !this.showMoreValue;
290
+    this.updatePopoverData();
291
+};
292
+
293
+
294
+function createIcon(classes)
295
+{
296
+    var icon = document.createElement("span");
297
+    for(var i in classes)
298
+    {
299
+        icon.classList.add(classes[i]);
300
+    }
301
+    icon.appendChild(
302
+        document.createElement("i")).classList.add("icon-connection");
303
+    return icon;
304
+}
305
+
306
+/**
307
+ * Creates the indicator
308
+ */
309
+ConnectionIndicator.prototype.create = function () {
310
+    this.connectionIndicatorContainer = document.createElement("div");
311
+    this.connectionIndicatorContainer.className = "connectionindicator";
312
+    this.connectionIndicatorContainer.style.display = "none";
313
+    this.videoContainer.appendChild(this.connectionIndicatorContainer);
314
+    this.popover = new JitsiPopover(
315
+        $("#" + this.videoContainer.id + " > .connectionindicator"),
316
+        {content: "<div class=\"connection_info\">Come back here for " +
317
+            "connection information once the conference starts</div>",
318
+            skin: "black"});
319
+
320
+    this.emptyIcon = this.connectionIndicatorContainer.appendChild(
321
+        createIcon(["connection", "connection_empty"]));
322
+    this.fullIcon = this.connectionIndicatorContainer.appendChild(
323
+        createIcon(["connection", "connection_full"]));
324
+
325
+};
326
+
327
+/**
328
+ * Removes the indicator
329
+ */
330
+ConnectionIndicator.prototype.remove = function()
331
+{
332
+    this.connectionIndicatorContainer.remove();
333
+    this.popover.forceHide();
334
+
335
+};
336
+
337
+/**
338
+ * Updates the data of the indicator
339
+ * @param percent the percent of connection quality
340
+ * @param object the statistics data.
341
+ */
342
+ConnectionIndicator.prototype.updateConnectionQuality =
343
+function (percent, object) {
344
+
345
+    if(percent === null)
346
+    {
347
+        this.connectionIndicatorContainer.style.display = "none";
348
+        this.popover.forceHide();
349
+        return;
350
+    }
351
+    else
352
+    {
353
+        if(this.connectionIndicatorContainer.style.display == "none") {
354
+            this.connectionIndicatorContainer.style.display = "block";
355
+            this.videoLayout.updateMutePosition(this.videoContainer.id);
356
+        }
357
+    }
358
+    this.bandwidth = object.bandwidth;
359
+    this.bitrate = object.bitrate;
360
+    this.packetLoss = object.packetLoss;
361
+    this.transport = object.transport;
362
+    if(object.resolution)
363
+    {
364
+        this.resolution = object.resolution;
365
+    }
366
+    for(var quality in ConnectionIndicator.connectionQualityValues)
367
+    {
368
+        if(percent >= quality)
369
+        {
370
+            this.fullIcon.style.width =
371
+                ConnectionIndicator.connectionQualityValues[quality];
372
+        }
373
+    }
374
+    this.updatePopoverData();
375
+};
376
+
377
+/**
378
+ * Updates the resolution
379
+ * @param resolution the new resolution
380
+ */
381
+ConnectionIndicator.prototype.updateResolution = function (resolution) {
382
+    this.resolution = resolution;
383
+    this.updatePopoverData();
384
+};
385
+
386
+/**
387
+ * Updates the content of the popover
388
+ */
389
+ConnectionIndicator.prototype.updatePopoverData = function () {
390
+    this.popover.updateContent(
391
+            "<div class=\"connection_info\">" + this.generateText() + "</div>");
392
+};
393
+
394
+/**
395
+ * Hides the popover
396
+ */
397
+ConnectionIndicator.prototype.hide = function () {
398
+    this.popover.forceHide();
399
+};
400
+
401
+/**
402
+ * Hides the indicator
403
+ */
404
+ConnectionIndicator.prototype.hideIndicator = function () {
405
+    this.connectionIndicatorContainer.style.display = "none";
406
+    if(this.popover)
407
+        this.popover.forceHide();
408
+};
409
+
410
+module.exports = ConnectionIndicator;

modules/UI/videolayout/VideoLayout.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 179
- 0
modules/UI/welcome_page/RoomnameGenerator.js Zobrazit soubor

@@ -0,0 +1,179 @@
1
+//var nouns = [
2
+//];
3
+var pluralNouns = [
4
+    "Aliens", "Animals", "Antelopes", "Ants", "Apes", "Apples", "Baboons", "Bacteria", "Badgers", "Bananas", "Bats",
5
+    "Bears", "Birds", "Bonobos", "Brides", "Bugs", "Bulls", "Butterflies", "Cheetahs",
6
+    "Cherries", "Chicken", "Children", "Chimps", "Clowns", "Cows", "Creatures", "Dinosaurs", "Dogs", "Dolphins",
7
+    "Donkeys", "Dragons", "Ducks", "Dwarfs", "Eagles", "Elephants", "Elves", "FAIL", "Fathers",
8
+    "Fish", "Flowers", "Frogs", "Fruit", "Fungi", "Galaxies", "Geese", "Goats",
9
+    "Gorillas", "Hedgehogs", "Hippos", "Horses", "Hunters", "Insects", "Kids", "Knights",
10
+    "Lemons", "Lemurs", "Leopards", "LifeForms", "Lions", "Lizards", "Mice", "Monkeys", "Monsters",
11
+    "Mushrooms", "Octopodes", "Oranges", "Orangutans", "Organisms", "Pants", "Parrots", "Penguins",
12
+    "People", "Pigeons", "Pigs", "Pineapples", "Plants", "Potatoes", "Priests", "Rats", "Reptiles", "Reptilians",
13
+    "Rhinos", "Seagulls", "Sheep", "Siblings", "Snakes", "Spaghetti", "Spiders", "Squid", "Squirrels",
14
+    "Stars", "Students", "Teachers", "Tigers", "Tomatoes", "Trees", "Vampires", "Vegetables", "Viruses", "Vulcans",
15
+    "Warewolves", "Weasels", "Whales", "Witches", "Wizards", "Wolves", "Workers", "Worms", "Zebras"
16
+];
17
+//var places = [
18
+//"Pub", "University", "Airport", "Library", "Mall", "Theater", "Stadium", "Office", "Show", "Gallows", "Beach",
19
+// "Cemetery", "Hospital", "Reception", "Restaurant", "Bar", "Church", "House", "School", "Square", "Village",
20
+// "Cinema", "Movies", "Party", "Restroom", "End", "Jail", "PostOffice", "Station", "Circus", "Gates", "Entrance",
21
+// "Bridge"
22
+//];
23
+var verbs = [
24
+    "Abandon", "Adapt", "Advertise", "Answer", "Anticipate", "Appreciate",
25
+    "Approach", "Argue", "Ask", "Bite", "Blossom", "Blush", "Breathe", "Breed", "Bribe", "Burn", "Calculate",
26
+    "Clean", "Code", "Communicate", "Compute", "Confess", "Confiscate", "Conjugate", "Conjure", "Consume",
27
+    "Contemplate", "Crawl", "Dance", "Delegate", "Devour", "Develop", "Differ", "Discuss",
28
+    "Dissolve", "Drink", "Eat", "Elaborate", "Emancipate", "Estimate", "Expire", "Extinguish",
29
+    "Extract", "FAIL", "Facilitate", "Fall", "Feed", "Finish", "Floss", "Fly", "Follow", "Fragment", "Freeze",
30
+    "Gather", "Glow", "Grow", "Hex", "Hide", "Hug", "Hurry", "Improve", "Intersect", "Investigate", "Jinx",
31
+    "Joke", "Jubilate", "Kiss", "Laugh", "Manage", "Meet", "Merge", "Move", "Object", "Observe", "Offer",
32
+    "Paint", "Participate", "Party", "Perform", "Plan", "Pursue", "Pierce", "Play", "Postpone", "Pray", "Proclaim",
33
+    "Question", "Read", "Reckon", "Rejoice", "Represent", "Resize", "Rhyme", "Scream", "Search", "Select", "Share", "Shoot",
34
+    "Shout", "Signal", "Sing", "Skate", "Sleep", "Smile", "Smoke", "Solve", "Spell", "Steer", "Stink",
35
+    "Substitute", "Swim", "Taste", "Teach", "Terminate", "Think", "Type", "Unite", "Vanish", "Worship"
36
+];
37
+var adverbs = [
38
+    "Absently", "Accurately", "Accusingly", "Adorably", "AllTheTime", "Alone", "Always", "Amazingly", "Angrily",
39
+    "Anxiously", "Anywhere", "Appallingly", "Apparently", "Articulately", "Astonishingly", "Badly", "Barely",
40
+    "Beautifully", "Blindly", "Bravely", "Brightly", "Briskly", "Brutally", "Calmly", "Carefully", "Casually",
41
+    "Cautiously", "Cleverly", "Constantly", "Correctly", "Crazily", "Curiously", "Cynically", "Daily",
42
+    "Dangerously", "Deliberately", "Delicately", "Desperately", "Discreetly", "Eagerly", "Easily", "Euphoricly",
43
+    "Evenly", "Everywhere", "Exactly", "Expectantly", "Extensively", "FAIL", "Ferociously", "Fiercely", "Finely",
44
+    "Flatly", "Frequently", "Frighteningly", "Gently", "Gloriously", "Grimly", "Guiltily", "Happily",
45
+    "Hard", "Hastily", "Heroically", "High", "Highly", "Hourly", "Humbly", "Hysterically", "Immensely",
46
+    "Impartially", "Impolitely", "Indifferently", "Intensely", "Jealously", "Jovially", "Kindly", "Lazily",
47
+    "Lightly", "Loudly", "Lovingly", "Loyally", "Magnificently", "Malevolently", "Merrily", "Mightily", "Miserably",
48
+    "Mysteriously", "NOT", "Nervously", "Nicely", "Nowhere", "Objectively", "Obnoxiously", "Obsessively",
49
+    "Obviously", "Often", "Painfully", "Patiently", "Playfully", "Politely", "Poorly", "Precisely", "Promptly",
50
+    "Quickly", "Quietly", "Randomly", "Rapidly", "Rarely", "Recklessly", "Regularly", "Remorsefully", "Responsibly",
51
+    "Rudely", "Ruthlessly", "Sadly", "Scornfully", "Seamlessly", "Seldom", "Selfishly", "Seriously", "Shakily",
52
+    "Sharply", "Sideways", "Silently", "Sleepily", "Slightly", "Slowly", "Slyly", "Smoothly", "Softly", "Solemnly", "Steadily", "Sternly", "Strangely", "Strongly", "Stunningly", "Surely", "Tenderly", "Thoughtfully",
53
+    "Tightly", "Uneasily", "Vanishingly", "Violently", "Warmly", "Weakly", "Wearily", "Weekly", "Weirdly", "Well",
54
+    "Well", "Wickedly", "Wildly", "Wisely", "Wonderfully", "Yearly"
55
+];
56
+var adjectives = [
57
+    "Abominable", "Accurate", "Adorable", "All", "Alleged", "Ancient", "Angry", "Angry", "Anxious", "Appalling",
58
+    "Apparent", "Astonishing", "Attractive", "Awesome", "Baby", "Bad", "Beautiful", "Benign", "Big", "Bitter",
59
+    "Blind", "Blue", "Bold", "Brave", "Bright", "Brisk", "Calm", "Camouflaged", "Casual", "Cautious",
60
+    "Choppy", "Chosen", "Clever", "Cold", "Cool", "Crawly", "Crazy", "Creepy", "Cruel", "Curious", "Cynical",
61
+    "Dangerous", "Dark", "Delicate", "Desperate", "Difficult", "Discreet", "Disguised", "Dizzy",
62
+    "Dumb", "Eager", "Easy", "Edgy", "Electric", "Elegant", "Emancipated", "Enormous", "Euphoric", "Evil",
63
+    "FAIL", "Fast", "Ferocious", "Fierce", "Fine", "Flawed", "Flying", "Foolish", "Foxy",
64
+    "Freezing", "Funny", "Furious", "Gentle", "Glorious", "Golden", "Good", "Green", "Green", "Guilty",
65
+    "Hairy", "Happy", "Hard", "Hasty", "Hazy", "Heroic", "Hostile", "Hot", "Humble", "Humongous",
66
+    "Humorous", "Hysterical", "Idealistic", "Ignorant", "Immense", "Impartial", "Impolite", "Indifferent",
67
+    "Infuriated", "Insightful", "Intense", "Interesting", "Intimidated", "Intriguing", "Jealous", "Jolly", "Jovial",
68
+    "Jumpy", "Kind", "Laughing", "Lazy", "Liquid", "Lonely", "Longing", "Loud", "Loving", "Loyal", "Macabre", "Mad",
69
+    "Magical", "Magnificent", "Malevolent", "Medieval", "Memorable", "Mere", "Merry", "Mighty",
70
+    "Mischievous", "Miserable", "Modified", "Moody", "Most", "Mysterious", "Mystical", "Needy",
71
+    "Nervous", "Nice", "Objective", "Obnoxious", "Obsessive", "Obvious", "Opinionated", "Orange",
72
+    "Painful", "Passionate", "Perfect", "Pink", "Playful", "Poisonous", "Polite", "Poor", "Popular", "Powerful",
73
+    "Precise", "Preserved", "Pretty", "Purple", "Quick", "Quiet", "Random", "Rapid", "Rare", "Real",
74
+    "Reassuring", "Reckless", "Red", "Regular", "Remorseful", "Responsible", "Rich", "Rude", "Ruthless",
75
+    "Sad", "Scared", "Scary", "Scornful", "Screaming", "Selfish", "Serious", "Shady", "Shaky", "Sharp",
76
+    "Shiny", "Shy", "Simple", "Sleepy", "Slow", "Sly", "Small", "Smart", "Smelly", "Smiling", "Smooth",
77
+    "Smug", "Sober", "Soft", "Solemn", "Square", "Square", "Steady", "Strange", "Strong",
78
+    "Stunning", "Subjective", "Successful", "Surly", "Sweet", "Tactful", "Tense",
79
+    "Thoughtful", "Tight", "Tiny", "Tolerant", "Uneasy", "Unique", "Unseen", "Warm", "Weak",
80
+    "Weird", "WellCooked", "Wild", "Wise", "Witty", "Wonderful", "Worried", "Yellow", "Young",
81
+    "Zealous"
82
+    ];
83
+//var pronouns = [
84
+//];
85
+//var conjunctions = [
86
+//"And", "Or", "For", "Above", "Before", "Against", "Between"
87
+//];
88
+
89
+/*
90
+ * Maps a string (category name) to the array of words from that category.
91
+ */
92
+var CATEGORIES =
93
+{
94
+    //"_NOUN_": nouns,
95
+    "_PLURALNOUN_": pluralNouns,
96
+    //"_PLACE_": places,
97
+    "_VERB_": verbs,
98
+    "_ADVERB_": adverbs,
99
+    "_ADJECTIVE_": adjectives
100
+    //"_PRONOUN_": pronouns,
101
+    //"_CONJUNCTION_": conjunctions,
102
+};
103
+
104
+var PATTERNS = [
105
+    "_ADJECTIVE__PLURALNOUN__VERB__ADVERB_"
106
+
107
+    // BeautifulFungiOrSpaghetti
108
+    //"_ADJECTIVE__PLURALNOUN__CONJUNCTION__PLURALNOUN_",
109
+
110
+    // AmazinglyScaryToy
111
+    //"_ADVERB__ADJECTIVE__NOUN_",
112
+
113
+    // NeitherTrashNorRifle
114
+    //"Neither_NOUN_Nor_NOUN_",
115
+    //"Either_NOUN_Or_NOUN_",
116
+
117
+    // EitherCopulateOrInvestigate
118
+    //"Either_VERB_Or_VERB_",
119
+    //"Neither_VERB_Nor_VERB_",
120
+
121
+    //"The_ADJECTIVE__ADJECTIVE__NOUN_",
122
+    //"The_ADVERB__ADJECTIVE__NOUN_",
123
+    //"The_ADVERB__ADJECTIVE__NOUN_s",
124
+    //"The_ADVERB__ADJECTIVE__PLURALNOUN__VERB_",
125
+
126
+    // WolvesComputeBadly
127
+    //"_PLURALNOUN__VERB__ADVERB_",
128
+
129
+    // UniteFacilitateAndMerge
130
+    //"_VERB__VERB_And_VERB_",
131
+
132
+    //NastyWitchesAtThePub
133
+    //"_ADJECTIVE__PLURALNOUN_AtThe_PLACE_",
134
+];
135
+
136
+
137
+/*
138
+ * Returns a random element from the array 'arr'
139
+ */
140
+function randomElement(arr)
141
+{
142
+    return arr[Math.floor(Math.random() * arr.length)];
143
+}
144
+
145
+/*
146
+ * Returns true if the string 's' contains one of the
147
+ * template strings.
148
+ */
149
+function hasTemplate(s)
150
+{
151
+    for (var template in CATEGORIES){
152
+        if (s.indexOf(template) >= 0){
153
+            return true;
154
+        }
155
+    }
156
+}
157
+
158
+/**
159
+ * Generates new room name.
160
+ */
161
+var RoomNameGenerator = {
162
+    generateRoomWithoutSeparator: function()
163
+    {
164
+        // Note that if more than one pattern is available, the choice of 'name' won't be random (names from patterns
165
+        // with fewer options will have higher probability of being chosen that names from patterns with more options).
166
+        var name = randomElement(PATTERNS);
167
+        var word;
168
+        while (hasTemplate(name)){
169
+            for (var template in CATEGORIES){
170
+                word = randomElement(CATEGORIES[template]);
171
+                name = name.replace(template, word);
172
+            }
173
+        }
174
+
175
+        return name;
176
+    }
177
+}
178
+
179
+module.exports = RoomNameGenerator;

+ 103
- 0
modules/UI/welcome_page/WelcomePage.js Zobrazit soubor

@@ -0,0 +1,103 @@
1
+var animateTimeout, updateTimeout;
2
+
3
+var RoomNameGenerator = require("./RoomnameGenerator");
4
+
5
+function enter_room()
6
+{
7
+    var val = $("#enter_room_field").val();
8
+    if(!val) {
9
+        val = $("#enter_room_field").attr("room_name");
10
+    }
11
+    if (val) {
12
+        window.location.pathname = "/" + val;
13
+    }
14
+}
15
+
16
+function animate(word) {
17
+    var currentVal = $("#enter_room_field").attr("placeholder");
18
+    $("#enter_room_field").attr("placeholder", currentVal + word.substr(0, 1));
19
+    animateTimeout = setTimeout(function() {
20
+        animate(word.substring(1, word.length))
21
+    }, 70);
22
+}
23
+
24
+function update_roomname()
25
+{
26
+    var word = RoomNameGenerator.generateRoomWithoutSeparator();
27
+    $("#enter_room_field").attr("room_name", word);
28
+    $("#enter_room_field").attr("placeholder", "");
29
+    clearTimeout(animateTimeout);
30
+    animate(word);
31
+    updateTimeout = setTimeout(update_roomname, 10000);
32
+}
33
+
34
+
35
+function setupWelcomePage()
36
+{
37
+    $("#videoconference_page").hide();
38
+    $("#domain_name").text(
39
+            window.location.protocol + "//" + window.location.host + "/");
40
+    $("span[name='appName']").text(interfaceConfig.APP_NAME);
41
+
42
+    if (interfaceConfig.SHOW_JITSI_WATERMARK) {
43
+        var leftWatermarkDiv
44
+            = $("#welcome_page_header div[class='watermark leftwatermark']");
45
+        if(leftWatermarkDiv && leftWatermarkDiv.length > 0)
46
+        {
47
+            leftWatermarkDiv.css({display: 'block'});
48
+            leftWatermarkDiv.parent().get(0).href
49
+                = interfaceConfig.JITSI_WATERMARK_LINK;
50
+        }
51
+
52
+    }
53
+
54
+    if (interfaceConfig.SHOW_BRAND_WATERMARK) {
55
+        var rightWatermarkDiv
56
+            = $("#welcome_page_header div[class='watermark rightwatermark']");
57
+        if(rightWatermarkDiv && rightWatermarkDiv.length > 0) {
58
+            rightWatermarkDiv.css({display: 'block'});
59
+            rightWatermarkDiv.parent().get(0).href
60
+                = interfaceConfig.BRAND_WATERMARK_LINK;
61
+            rightWatermarkDiv.get(0).style.backgroundImage
62
+                = "url(images/rightwatermark.png)";
63
+        }
64
+    }
65
+
66
+    if (interfaceConfig.SHOW_POWERED_BY) {
67
+        $("#welcome_page_header>a[class='poweredby']")
68
+            .css({display: 'block'});
69
+    }
70
+
71
+    $("#enter_room_button").click(function()
72
+    {
73
+        enter_room();
74
+    });
75
+
76
+    $("#enter_room_field").keydown(function (event) {
77
+        if (event.keyCode === 13 /* enter */) {
78
+            enter_room();
79
+        }
80
+    });
81
+
82
+    if (!(interfaceConfig.GENERATE_ROOMNAMES_ON_WELCOME_PAGE === false)){
83
+        var updateTimeout;
84
+        var animateTimeout;
85
+        $("#reload_roomname").click(function () {
86
+            clearTimeout(updateTimeout);
87
+            clearTimeout(animateTimeout);
88
+            update_roomname();
89
+        });
90
+        $("#reload_roomname").show();
91
+
92
+
93
+        update_roomname();
94
+    }
95
+
96
+    $("#disable_welcome").click(function () {
97
+        window.localStorage.welcomePageDisabled
98
+            = $("#disable_welcome").is(":checked");
99
+    });
100
+
101
+}
102
+
103
+module.exports = setupWelcomePage;

+ 2
- 2
modules/statistics/statistics.js Zobrazit soubor

@@ -51,10 +51,10 @@ function startRemoteStats (peerconnection) {
51 51
 
52 52
 function onStreamCreated(stream)
53 53
 {
54
-    if(stream.getAudioTracks().length === 0)
54
+    if(stream.getOriginalStream().getAudioTracks().length === 0)
55 55
         return;
56 56
 
57
-    localStats = new LocalStats(stream, 100, this,
57
+    localStats = new LocalStats(stream.getOriginalStream(), 100, statistics,
58 58
         eventEmitter);
59 59
     localStats.start();
60 60
 }

+ 62
- 50
muc.js Zobrazit soubor

@@ -49,6 +49,7 @@ Strophe.addConnectionPlugin('emuc', {
49 49
     onPresence: function (pres) {
50 50
         var from = pres.getAttribute('from');
51 51
         var type = pres.getAttribute('type');
52
+        console.debug("Presence " + from + " - " + type);
52 53
         if (type != null) {
53 54
             return true;
54 55
         }
@@ -56,7 +57,9 @@ Strophe.addConnectionPlugin('emuc', {
56 57
         // Parse etherpad tag.
57 58
         var etherpad = $(pres).find('>etherpad');
58 59
         if (etherpad.length) {
59
-            $(document).trigger('etherpadadded.muc', [from, etherpad.text()]);
60
+            if (config.etherpad_base && !Moderator.isModerator()) {
61
+                UI.initEtherpad(etherpad.text());
62
+            }
60 63
         }
61 64
 
62 65
         // Parse prezi tag.
@@ -138,24 +141,40 @@ Strophe.addConnectionPlugin('emuc', {
138 141
             if (member.affiliation == 'owner') this.isOwner = true;
139 142
             if (this.role !== member.role) {
140 143
                 this.role = member.role;
141
-                $(document).trigger('local.role.changed.muc', [from, member, pres]);
144
+                if(Moderator.onLocalRoleChange)
145
+                    Moderator.onLocalRoleChange(from, member, pres);
146
+                UI.onLocalRoleChange(from, member, pres);
142 147
             }
143 148
             if (!this.joined) {
144 149
                 this.joined = true;
145 150
                 $(document).trigger('joined.muc', [from, member]);
151
+                UI.onMucJoined(from, member);
146 152
                 this.list_members.push(from);
147 153
             }
148 154
         } else if (this.members[from] === undefined) {
149 155
             // new participant
150 156
             this.members[from] = member;
151 157
             this.list_members.push(from);
152
-            $(document).trigger('entered.muc', [from, member, pres]);
158
+            console.log('entered', from, member);
159
+            if (member.isFocus)
160
+            {
161
+                focusMucJid = from;
162
+                console.info("Ignore focus: " + from +", real JID: " + member.jid);
163
+            }
164
+            else {
165
+                var id = $(pres).find('>userID').text();
166
+                var email = $(pres).find('>email');
167
+                if (email.length > 0) {
168
+                    id = email.text();
169
+                }
170
+                UI.onMucEntered(from, id, member.displayName);
171
+            }
153 172
         } else {
154 173
             // Presence update for existing participant
155 174
             // Watch role change:
156 175
             if (this.members[from].role != member.role) {
157
-                this.members[from].role = member.role
158
-                $(document).trigger('role.changed.muc', [from, member, pres]);
176
+                this.members[from].role = member.role;
177
+                UI.onMucRoleChanged(member.role, member.displayName);
159 178
             }
160 179
         }
161 180
         // Always trigger presence to update bindings
@@ -164,7 +183,7 @@ Strophe.addConnectionPlugin('emuc', {
164 183
 
165 184
         // Trigger status message update
166 185
         if (member.status) {
167
-            $(document).trigger('presence.status.muc', [from, member, pres]);
186
+            UI.onMucPresenceStatus(from, member);
168 187
         }
169 188
 
170 189
         return true;
@@ -175,7 +194,7 @@ Strophe.addConnectionPlugin('emuc', {
175 194
         if (!$(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="110"]').length) {
176 195
             delete this.members[from];
177 196
             this.list_members.splice(this.list_members.indexOf(from), 1);
178
-            $(document).trigger('left.muc', [from]);
197
+            this.onParticipantLeft(from);
179 198
         }
180 199
         // If the status code is 110 this means we're leaving and we would like
181 200
         // to remove everyone else from our view, so we trigger the event.
@@ -184,7 +203,7 @@ Strophe.addConnectionPlugin('emuc', {
184 203
                 var member = this.list_members[i];
185 204
                 delete this.members[i];
186 205
                 this.list_members.splice(i, 1);
187
-                $(document).trigger('left.muc', member);
206
+                this.onParticipantLeft(member);
188 207
             }
189 208
         }
190 209
         if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="307"]').length) {
@@ -195,7 +214,11 @@ Strophe.addConnectionPlugin('emuc', {
195 214
     onPresenceError: function (pres) {
196 215
         var from = pres.getAttribute('from');
197 216
         if ($(pres).find('>error[type="auth"]>not-authorized[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) {
198
-            $(document).trigger('passwordrequired.muc', [from]);
217
+            console.log('on password required', from);
218
+
219
+            UI.onPasswordReqiured(function (value) {
220
+                connection.emuc.doJoin(from, value);
221
+            })
199 222
         } else if ($(pres).find(
200 223
                 '>error[type="cancel"]>not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) {
201 224
             var toDomain = Strophe.getDomainFromJid(pres.getAttribute('to'));
@@ -205,13 +228,13 @@ Strophe.addConnectionPlugin('emuc', {
205 228
                 $(document).trigger('passwordrequired.main');
206 229
             } else {
207 230
                 console.warn('onPresError ', pres);
208
-                messageHandler.openReportDialog(null,
231
+                UI.messageHandler.openReportDialog(null,
209 232
                     'Oops! Something went wrong and we couldn`t connect to the conference.',
210 233
                 pres);
211 234
             }
212 235
         } else {
213 236
             console.warn('onPresError ', pres);
214
-            messageHandler.openReportDialog(null,
237
+            UI.messageHandler.openReportDialog(null,
215 238
                 'Oops! Something went wrong and we couldn`t connect to the conference.',
216 239
                 pres);
217 240
         }
@@ -244,7 +267,7 @@ Strophe.addConnectionPlugin('emuc', {
244 267
         var type = msg.getAttribute("type");
245 268
         if(type == "error")
246 269
         {
247
-            Chat.chatAddError($(msg).find('>text').text(), txt);
270
+            UI.chatAddError($(msg).find('>text').text(), txt);
248 271
             return true;
249 272
         }
250 273
 
@@ -253,7 +276,7 @@ Strophe.addConnectionPlugin('emuc', {
253 276
         {
254 277
             var subjectText = subject.text();
255 278
             if(subjectText || subjectText == "") {
256
-                Chat.chatSetSubject(subjectText);
279
+                UI.chatSetSubject(subjectText);
257 280
                 console.log("Subject is changed to " + subjectText);
258 281
             }
259 282
         }
@@ -261,7 +284,7 @@ Strophe.addConnectionPlugin('emuc', {
261 284
 
262 285
         if (txt) {
263 286
             console.log('chat', nick, txt);
264
-            Chat.updateChatConversation(from, nick, txt);
287
+            UI.updateChatConversation(from, nick, txt);
265 288
             if(APIConnector.isEnabled() && APIConnector.isEventEnabled("incomingMessage"))
266 289
             {
267 290
                 if(from != this.myroomjid)
@@ -271,7 +294,7 @@ Strophe.addConnectionPlugin('emuc', {
271 294
         }
272 295
         return true;
273 296
     },
274
-    lockRoom: function (key) {
297
+    lockRoom: function (key, onSuccess, onError, onNotSupported) {
275 298
         //http://xmpp.org/extensions/xep-0045.html#roomconfig
276 299
         var ob = this;
277 300
         this.connection.sendIQ($iq({to: this.roomjid, type: 'get'}).c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'}),
@@ -285,43 +308,12 @@ Strophe.addConnectionPlugin('emuc', {
285 308
                     formsubmit.c('field', {'var': 'muc#roomconfig_whois'}).c('value').t('anyone').up().up();
286 309
                     // FIXME: is muc#roomconfig_passwordprotectedroom required?
287 310
                     this.connection.sendIQ(formsubmit,
288
-                        function (res) {
289
-                            // password is required
290
-                            if (sharedKey)
291
-                            {
292
-                                console.log('set room password');
293
-                                Toolbar.lockLockButton();
294
-                            }
295
-                            else
296
-                            {
297
-                                console.log('removed room password');
298
-                                Toolbar.unlockLockButton();
299
-                            }
300
-                        },
301
-                        function (err) {
302
-                            console.warn('setting password failed', err);
303
-                            messageHandler.showError('Lock failed',
304
-                                'Failed to lock conference.',
305
-                                err);
306
-                            setSharedKey('');
307
-                        }
308
-                    );
311
+                        onSuccess,
312
+                        onError);
309 313
                 } else {
310
-                    console.warn('room passwords not supported');
311
-                    messageHandler.showError('Warning',
312
-                        'Room passwords are currently not supported.');
313
-                    setSharedKey('');
314
-
314
+                    onNotSupported();
315 315
                 }
316
-            },
317
-            function (err) {
318
-                console.warn('setting password failed', err);
319
-                messageHandler.showError('Lock failed',
320
-                    'Failed to lock conference.',
321
-                    err);
322
-                setSharedKey('');
323
-            }
324
-        );
316
+            }, onError);
325 317
     },
326 318
     kick: function (jid) {
327 319
         var kickIQ = $iq({to: this.roomjid, type: 'set'})
@@ -427,6 +419,7 @@ Strophe.addConnectionPlugin('emuc', {
427 419
         }
428 420
 
429 421
         pres.up();
422
+//        console.debug(pres.toString());
430 423
         connection.send(pres);
431 424
     },
432 425
     addDisplayNameToPresence: function (displayName) {
@@ -509,5 +502,24 @@ Strophe.addConnectionPlugin('emuc', {
509 502
             return this.members[peerJid].role;
510 503
         }
511 504
         return null;
505
+    },
506
+    onParticipantLeft: function (jid) {
507
+        UI.onMucLeft(jid);
508
+
509
+        if(APIConnector.isEnabled() && APIConnector.isEventEnabled("participantLeft"))
510
+        {
511
+            APIConnector.triggerEvent("participantLeft",{jid: jid});
512
+        }
513
+
514
+        delete jid2Ssrc[jid];
515
+
516
+        connection.jingle.terminateByJid(jid);
517
+
518
+        if (connection.emuc.getPrezi(jid)) {
519
+            $(document).trigger('presentationremoved.muc',
520
+                [jid, connection.emuc.getPrezi(jid)]);
521
+        }
522
+
523
+        Moderator.onMucLeft(jid);
512 524
     }
513 525
 });

+ 0
- 346
prezi.js Zobrazit soubor

@@ -1,346 +0,0 @@
1
-var Prezi = (function (my) {
2
-    var preziPlayer = null;
3
-
4
-    /**
5
-     * Reloads the current presentation.
6
-     */
7
-    my.reloadPresentation = function() {
8
-        var iframe = document.getElementById(preziPlayer.options.preziId);
9
-        iframe.src = iframe.src;
10
-    };
11
-
12
-    /**
13
-     * Shows/hides a presentation.
14
-     */
15
-    my.setPresentationVisible = function (visible) {
16
-        var prezi = $('#presentation>iframe');
17
-        if (visible) {
18
-            // Trigger the video.selected event to indicate a change in the
19
-            // large video.
20
-            $(document).trigger("video.selected", [true]);
21
-
22
-            $('#largeVideo').fadeOut(300);
23
-            prezi.fadeIn(300, function() {
24
-                prezi.css({opacity:'1'});
25
-                ToolbarToggler.dockToolbar(true);
26
-                VideoLayout.setLargeVideoVisible(false);
27
-            });
28
-            $('#activeSpeaker').css('visibility', 'hidden');
29
-        }
30
-        else {
31
-            if (prezi.css('opacity') == '1') {
32
-                prezi.fadeOut(300, function () {
33
-                    prezi.css({opacity:'0'});
34
-                    $('#reloadPresentation').css({display:'none'});
35
-                    $('#largeVideo').fadeIn(300, function() {
36
-                        VideoLayout.setLargeVideoVisible(true);
37
-                        ToolbarToggler.dockToolbar(false);
38
-                    });
39
-                });
40
-            }
41
-        }
42
-    };
43
-
44
-    /**
45
-     * Returns <tt>true</tt> if the presentation is visible, <tt>false</tt> -
46
-     * otherwise.
47
-     */
48
-    my.isPresentationVisible = function () {
49
-        return ($('#presentation>iframe') != null
50
-                && $('#presentation>iframe').css('opacity') == 1);
51
-    };
52
-
53
-    /**
54
-     * Opens the Prezi dialog, from which the user could choose a presentation
55
-     * to load.
56
-     */
57
-    my.openPreziDialog = function() {
58
-        var myprezi = connection.emuc.getPrezi(connection.emuc.myroomjid);
59
-        if (myprezi) {
60
-            messageHandler.openTwoButtonDialog("Remove Prezi",
61
-                "Are you sure you would like to remove your Prezi?",
62
-                false,
63
-                "Remove",
64
-                function(e,v,m,f) {
65
-                    if(v) {
66
-                        connection.emuc.removePreziFromPresence();
67
-                        connection.emuc.sendPresence();
68
-                    }
69
-                }
70
-            );
71
-        }
72
-        else if (preziPlayer != null) {
73
-            messageHandler.openTwoButtonDialog("Share a Prezi",
74
-                "Another participant is already sharing a Prezi." +
75
-                    "This conference allows only one Prezi at a time.",
76
-                false,
77
-                "Ok",
78
-                function(e,v,m,f) {
79
-                    $.prompt.close();
80
-                }
81
-            );
82
-        }
83
-        else {
84
-            var openPreziState = {
85
-                state0: {
86
-                    html:   '<h2>Share a Prezi</h2>' +
87
-                            '<input id="preziUrl" type="text" ' +
88
-                            'placeholder="e.g. ' +
89
-                            'http://prezi.com/wz7vhjycl7e6/my-prezi" autofocus>',
90
-                    persistent: false,
91
-                    buttons: { "Share": true , "Cancel": false},
92
-                    defaultButton: 1,
93
-                    submit: function(e,v,m,f){
94
-                        e.preventDefault();
95
-                        if(v)
96
-                        {
97
-                            var preziUrl = document.getElementById('preziUrl');
98
-
99
-                            if (preziUrl.value)
100
-                            {
101
-                                var urlValue
102
-                                    = encodeURI(Util.escapeHtml(preziUrl.value));
103
-
104
-                                if (urlValue.indexOf('http://prezi.com/') != 0
105
-                                    && urlValue.indexOf('https://prezi.com/') != 0)
106
-                                {
107
-                                    $.prompt.goToState('state1');
108
-                                    return false;
109
-                                }
110
-                                else {
111
-                                    var presIdTmp = urlValue.substring(
112
-                                            urlValue.indexOf("prezi.com/") + 10);
113
-                                    if (!isAlphanumeric(presIdTmp)
114
-                                            || presIdTmp.indexOf('/') < 2) {
115
-                                        $.prompt.goToState('state1');
116
-                                        return false;
117
-                                    }
118
-                                    else {
119
-                                        connection.emuc
120
-                                            .addPreziToPresence(urlValue, 0);
121
-                                        connection.emuc.sendPresence();
122
-                                        $.prompt.close();
123
-                                    }
124
-                                }
125
-                            }
126
-                        }
127
-                        else
128
-                            $.prompt.close();
129
-                    }
130
-                },
131
-                state1: {
132
-                    html:   '<h2>Share a Prezi</h2>' +
133
-                            'Please provide a correct prezi link.',
134
-                    persistent: false,
135
-                    buttons: { "Back": true, "Cancel": false },
136
-                    defaultButton: 1,
137
-                    submit:function(e,v,m,f) {
138
-                        e.preventDefault();
139
-                        if(v==0)
140
-                            $.prompt.close();
141
-                        else
142
-                            $.prompt.goToState('state0');
143
-                    }
144
-                }
145
-            };
146
-            var focusPreziUrl =  function(e) {
147
-                    document.getElementById('preziUrl').focus();
148
-                };
149
-            messageHandler.openDialogWithStates(openPreziState, focusPreziUrl, focusPreziUrl);
150
-        }
151
-    };
152
-
153
-    /**
154
-     * A new presentation has been added.
155
-     * 
156
-     * @param event the event indicating the add of a presentation
157
-     * @param jid the jid from which the presentation was added
158
-     * @param presUrl url of the presentation
159
-     * @param currentSlide the current slide to which we should move
160
-     */
161
-    var presentationAdded = function(event, jid, presUrl, currentSlide) {
162
-        console.log("presentation added", presUrl);
163
-
164
-        var presId = getPresentationId(presUrl);
165
-
166
-        var elementId = 'participant_'
167
-                        + Strophe.getResourceFromJid(jid)
168
-                        + '_' + presId;
169
-
170
-        // We explicitly don't specify the peer jid here, because we don't want
171
-        // this video to be dealt with as a peer related one (for example we
172
-        // don't want to show a mute/kick menu for this one, etc.).
173
-        VideoLayout.addRemoteVideoContainer(null, elementId);
174
-        VideoLayout.resizeThumbnails();
175
-
176
-        var controlsEnabled = false;
177
-        if (jid === connection.emuc.myroomjid)
178
-            controlsEnabled = true;
179
-
180
-        Prezi.setPresentationVisible(true);
181
-        $('#largeVideoContainer').hover(
182
-            function (event) {
183
-                if (Prezi.isPresentationVisible()) {
184
-                    var reloadButtonRight = window.innerWidth
185
-                        - $('#presentation>iframe').offset().left
186
-                        - $('#presentation>iframe').width();
187
-
188
-                    $('#reloadPresentation').css({  right: reloadButtonRight,
189
-                                                    display:'inline-block'});
190
-                }
191
-            },
192
-            function (event) {
193
-                if (!Prezi.isPresentationVisible())
194
-                    $('#reloadPresentation').css({display:'none'});
195
-                else {
196
-                    var e = event.toElement || event.relatedTarget;
197
-
198
-                    if (e && e.id != 'reloadPresentation' && e.id != 'header')
199
-                        $('#reloadPresentation').css({display:'none'});
200
-                }
201
-            });
202
-
203
-        preziPlayer = new PreziPlayer(
204
-                    'presentation',
205
-                    {preziId: presId,
206
-                    width: getPresentationWidth(),
207
-                    height: getPresentationHeihgt(),
208
-                    controls: controlsEnabled,
209
-                    debug: true
210
-                    });
211
-
212
-        $('#presentation>iframe').attr('id', preziPlayer.options.preziId);
213
-
214
-        preziPlayer.on(PreziPlayer.EVENT_STATUS, function(event) {
215
-            console.log("prezi status", event.value);
216
-            if (event.value == PreziPlayer.STATUS_CONTENT_READY) {
217
-                if (jid != connection.emuc.myroomjid)
218
-                    preziPlayer.flyToStep(currentSlide);
219
-            }
220
-        });
221
-
222
-        preziPlayer.on(PreziPlayer.EVENT_CURRENT_STEP, function(event) {
223
-            console.log("event value", event.value);
224
-            connection.emuc.addCurrentSlideToPresence(event.value);
225
-            connection.emuc.sendPresence();
226
-        });
227
-
228
-        $("#" + elementId).css( 'background-image',
229
-                                'url(../images/avatarprezi.png)');
230
-        $("#" + elementId).click(
231
-            function () {
232
-                Prezi.setPresentationVisible(true);
233
-            }
234
-        );
235
-    };
236
-
237
-    /**
238
-     * A presentation has been removed.
239
-     * 
240
-     * @param event the event indicating the remove of a presentation
241
-     * @param jid the jid for which the presentation was removed
242
-     * @param the url of the presentation
243
-     */
244
-    var presentationRemoved = function (event, jid, presUrl) {
245
-        console.log('presentation removed', presUrl);
246
-        var presId = getPresentationId(presUrl);
247
-        Prezi.setPresentationVisible(false);
248
-        $('#participant_'
249
-                + Strophe.getResourceFromJid(jid)
250
-                + '_' + presId).remove();
251
-        $('#presentation>iframe').remove();
252
-        if (preziPlayer != null) {
253
-            preziPlayer.destroy();
254
-            preziPlayer = null;
255
-        }
256
-    };
257
-
258
-    /**
259
-     * Indicates if the given string is an alphanumeric string.
260
-     * Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the
261
-     * purpose of checking URIs.
262
-     */
263
-    function isAlphanumeric(unsafeText) {
264
-        var regex = /^[a-z0-9-_\/&\?=;]+$/i;
265
-        return regex.test(unsafeText);
266
-    }
267
-
268
-    /**
269
-     * Returns the presentation id from the given url.
270
-     */
271
-    function getPresentationId (presUrl) {
272
-        var presIdTmp = presUrl.substring(presUrl.indexOf("prezi.com/") + 10);
273
-        return presIdTmp.substring(0, presIdTmp.indexOf('/'));
274
-    }
275
-
276
-    /**
277
-     * Returns the presentation width.
278
-     */
279
-    function getPresentationWidth() {
280
-        var availableWidth = Util.getAvailableVideoWidth();
281
-        var availableHeight = getPresentationHeihgt();
282
-
283
-        var aspectRatio = 16.0 / 9.0;
284
-        if (availableHeight < availableWidth / aspectRatio) {
285
-            availableWidth = Math.floor(availableHeight * aspectRatio);
286
-        }
287
-        return availableWidth;
288
-    }
289
-
290
-    /**
291
-     * Returns the presentation height.
292
-     */
293
-    function getPresentationHeihgt() {
294
-        var remoteVideos = $('#remoteVideos');
295
-        return window.innerHeight - remoteVideos.outerHeight();
296
-    }
297
-
298
-    /**
299
-     * Resizes the presentation iframe.
300
-     */
301
-    function resize() {
302
-        if ($('#presentation>iframe')) {
303
-            $('#presentation>iframe').width(getPresentationWidth());
304
-            $('#presentation>iframe').height(getPresentationHeihgt());
305
-        }
306
-    }
307
-
308
-    /**
309
-     * Presentation has been removed.
310
-     */
311
-    $(document).bind('presentationremoved.muc', presentationRemoved);
312
-
313
-    /**
314
-     * Presentation has been added.
315
-     */
316
-    $(document).bind('presentationadded.muc', presentationAdded);
317
-
318
-    /*
319
-     * Indicates presentation slide change.
320
-     */
321
-    $(document).bind('gotoslide.muc', function (event, jid, presUrl, current) {
322
-        if (preziPlayer && preziPlayer.getCurrentStep() != current) {
323
-            preziPlayer.flyToStep(current);
324
-
325
-            var animationStepsArray = preziPlayer.getAnimationCountOnSteps();
326
-            for (var i = 0; i < parseInt(animationStepsArray[current]); i++) {
327
-                preziPlayer.flyToStep(current, i);
328
-            }
329
-        }
330
-    });
331
-
332
-    /**
333
-     * On video selected event.
334
-     */
335
-    $(document).bind('video.selected', function (event, isPresentation) {
336
-        if (!isPresentation && $('#presentation>iframe')) {
337
-            Prezi.setPresentationVisible(false);
338
-        }
339
-    });
340
-
341
-    $(window).resize(function () {
342
-        resize();
343
-    });
344
-
345
-    return my;
346
-}(Prezi || {}));

+ 3
- 3
recording.js Zobrazit soubor

@@ -45,7 +45,7 @@ var Recording = (function (my) {
45 45
 
46 46
         if (!recordingToken)
47 47
         {
48
-            messageHandler.openTwoButtonDialog(null,
48
+            UI.messageHandler.openTwoButtonDialog(null,
49 49
                     '<h2>Enter recording token</h2>' +
50 50
                     '<input id="recordingToken" type="text" placeholder="token" autofocus>',
51 51
                 false,
@@ -70,7 +70,7 @@ var Recording = (function (my) {
70 70
         }
71 71
 
72 72
         var oldState = recordingEnabled;
73
-        Toolbar.setRecordingButtonState(!oldState);
73
+        UI.setRecordingButtonState(!oldState);
74 74
         my.setRecording(!oldState,
75 75
             recordingToken,
76 76
             function (state) {
@@ -99,7 +99,7 @@ var Recording = (function (my) {
99 99
                     my.setRecordingToken(null);
100 100
                 }
101 101
                 // Update with returned status
102
-                Toolbar.setRecordingButtonState(state);
102
+                UI.setRecordingButtonState(state);
103 103
             }
104 104
         );
105 105
     };

+ 0
- 188
roomname_generator.js Zobrazit soubor

@@ -1,188 +0,0 @@
1
-var RoomNameGenerator = function(my) {
2
-    /**
3
-     * Constructs new RoomNameGenerator object.
4
-     * @constructor constructs new RoomNameGenerator object.
5
-     */
6
-    function RoomNameGeneratorProto()
7
-    {
8
-    }
9
-
10
-    //var nouns = [
11
-    //];
12
-    var pluralNouns = [
13
-        "Aliens", "Animals", "Antelopes", "Ants", "Apes", "Apples", "Baboons", "Bacteria", "Badgers", "Bananas", "Bats",
14
-        "Bears", "Birds", "Bonobos", "Brides", "Bugs", "Bulls", "Butterflies", "Cheetahs",
15
-        "Cherries", "Chicken", "Children", "Chimps", "Clowns", "Cows", "Creatures", "Dinosaurs", "Dogs", "Dolphins",
16
-        "Donkeys", "Dragons", "Ducks", "Dwarfs", "Eagles", "Elephants", "Elves", "FAIL", "Fathers",
17
-        "Fish", "Flowers", "Frogs", "Fruit", "Fungi", "Galaxies", "Geese", "Goats",
18
-        "Gorillas", "Hedgehogs", "Hippos", "Horses", "Hunters", "Insects", "Kids", "Knights",
19
-        "Lemons", "Lemurs", "Leopards", "LifeForms", "Lions", "Lizards", "Mice", "Monkeys", "Monsters",
20
-        "Mushrooms", "Octopodes", "Oranges", "Orangutans", "Organisms", "Pants", "Parrots", "Penguins",
21
-        "People", "Pigeons", "Pigs", "Pineapples", "Plants", "Potatoes", "Priests", "Rats", "Reptiles", "Reptilians",
22
-        "Rhinos", "Seagulls", "Sheep", "Siblings", "Snakes", "Spaghetti", "Spiders", "Squid", "Squirrels",
23
-        "Stars", "Students", "Teachers", "Tigers", "Tomatoes", "Trees", "Vampires", "Vegetables", "Viruses", "Vulcans",
24
-        "Warewolves", "Weasels", "Whales", "Witches", "Wizards", "Wolves", "Workers", "Worms", "Zebras"
25
-    ];
26
-    //var places = [
27
-    //"Pub", "University", "Airport", "Library", "Mall", "Theater", "Stadium", "Office", "Show", "Gallows", "Beach",
28
-    // "Cemetery", "Hospital", "Reception", "Restaurant", "Bar", "Church", "House", "School", "Square", "Village",
29
-    // "Cinema", "Movies", "Party", "Restroom", "End", "Jail", "PostOffice", "Station", "Circus", "Gates", "Entrance",
30
-    // "Bridge"
31
-    //];
32
-    var verbs = [
33
-        "Abandon", "Adapt", "Advertise", "Answer", "Anticipate", "Appreciate",
34
-        "Approach", "Argue", "Ask", "Bite", "Blossom", "Blush", "Breathe", "Breed", "Bribe", "Burn", "Calculate",
35
-        "Clean", "Code", "Communicate", "Compute", "Confess", "Confiscate", "Conjugate", "Conjure", "Consume",
36
-        "Contemplate", "Crawl", "Dance", "Delegate", "Devour", "Develop", "Differ", "Discuss",
37
-        "Dissolve", "Drink", "Eat", "Elaborate", "Emancipate", "Estimate", "Expire", "Extinguish",
38
-        "Extract", "FAIL", "Facilitate", "Fall", "Feed", "Finish", "Floss", "Fly", "Follow", "Fragment", "Freeze",
39
-        "Gather", "Glow", "Grow", "Hex", "Hide", "Hug", "Hurry", "Improve", "Intersect", "Investigate", "Jinx",
40
-        "Joke", "Jubilate", "Kiss", "Laugh", "Manage", "Meet", "Merge", "Move", "Object", "Observe", "Offer",
41
-        "Paint", "Participate", "Party", "Perform", "Plan", "Pursue", "Pierce", "Play", "Postpone", "Pray", "Proclaim",
42
-        "Question", "Read", "Reckon", "Rejoice", "Represent", "Resize", "Rhyme", "Scream", "Search", "Select", "Share", "Shoot",
43
-        "Shout", "Signal", "Sing", "Skate", "Sleep", "Smile", "Smoke", "Solve", "Spell", "Steer", "Stink",
44
-        "Substitute", "Swim", "Taste", "Teach", "Terminate", "Think", "Type", "Unite", "Vanish", "Worship"
45
-    ];
46
-    var adverbs = [
47
-        "Absently", "Accurately", "Accusingly", "Adorably", "AllTheTime", "Alone", "Always", "Amazingly", "Angrily",
48
-        "Anxiously", "Anywhere", "Appallingly", "Apparently", "Articulately", "Astonishingly", "Badly", "Barely",
49
-        "Beautifully", "Blindly", "Bravely", "Brightly", "Briskly", "Brutally", "Calmly", "Carefully", "Casually",
50
-        "Cautiously", "Cleverly", "Constantly", "Correctly", "Crazily", "Curiously", "Cynically", "Daily",
51
-        "Dangerously", "Deliberately", "Delicately", "Desperately", "Discreetly", "Eagerly", "Easily", "Euphoricly",
52
-        "Evenly", "Everywhere", "Exactly", "Expectantly", "Extensively", "FAIL", "Ferociously", "Fiercely", "Finely",
53
-        "Flatly", "Frequently", "Frighteningly", "Gently", "Gloriously", "Grimly", "Guiltily", "Happily",
54
-        "Hard", "Hastily", "Heroically", "High", "Highly", "Hourly", "Humbly", "Hysterically", "Immensely",
55
-        "Impartially", "Impolitely", "Indifferently", "Intensely", "Jealously", "Jovially", "Kindly", "Lazily",
56
-        "Lightly", "Loudly", "Lovingly", "Loyally", "Magnificently", "Malevolently", "Merrily", "Mightily", "Miserably",
57
-        "Mysteriously", "NOT", "Nervously", "Nicely", "Nowhere", "Objectively", "Obnoxiously", "Obsessively",
58
-        "Obviously", "Often", "Painfully", "Patiently", "Playfully", "Politely", "Poorly", "Precisely", "Promptly",
59
-        "Quickly", "Quietly", "Randomly", "Rapidly", "Rarely", "Recklessly", "Regularly", "Remorsefully", "Responsibly",
60
-        "Rudely", "Ruthlessly", "Sadly", "Scornfully", "Seamlessly", "Seldom", "Selfishly", "Seriously", "Shakily",
61
-        "Sharply", "Sideways", "Silently", "Sleepily", "Slightly", "Slowly", "Slyly", "Smoothly", "Softly", "Solemnly", "Steadily", "Sternly", "Strangely", "Strongly", "Stunningly", "Surely", "Tenderly", "Thoughtfully",
62
-        "Tightly", "Uneasily", "Vanishingly", "Violently", "Warmly", "Weakly", "Wearily", "Weekly", "Weirdly", "Well",
63
-        "Well", "Wickedly", "Wildly", "Wisely", "Wonderfully", "Yearly"
64
-    ];
65
-    var adjectives = [
66
-        "Abominable", "Accurate", "Adorable", "All", "Alleged", "Ancient", "Angry", "Angry", "Anxious", "Appalling",
67
-        "Apparent", "Astonishing", "Attractive", "Awesome", "Baby", "Bad", "Beautiful", "Benign", "Big", "Bitter",
68
-        "Blind", "Blue", "Bold", "Brave", "Bright", "Brisk", "Calm", "Camouflaged", "Casual", "Cautious",
69
-        "Choppy", "Chosen", "Clever", "Cold", "Cool", "Crawly", "Crazy", "Creepy", "Cruel", "Curious", "Cynical",
70
-        "Dangerous", "Dark", "Delicate", "Desperate", "Difficult", "Discreet", "Disguised", "Dizzy",
71
-        "Dumb", "Eager", "Easy", "Edgy", "Electric", "Elegant", "Emancipated", "Enormous", "Euphoric", "Evil",
72
-        "FAIL", "Fast", "Ferocious", "Fierce", "Fine", "Flawed", "Flying", "Foolish", "Foxy",
73
-        "Freezing", "Funny", "Furious", "Gentle", "Glorious", "Golden", "Good", "Green", "Green", "Guilty",
74
-        "Hairy", "Happy", "Hard", "Hasty", "Hazy", "Heroic", "Hostile", "Hot", "Humble", "Humongous",
75
-        "Humorous", "Hysterical", "Idealistic", "Ignorant", "Immense", "Impartial", "Impolite", "Indifferent",
76
-        "Infuriated", "Insightful", "Intense", "Interesting", "Intimidated", "Intriguing", "Jealous", "Jolly", "Jovial",
77
-        "Jumpy", "Kind", "Laughing", "Lazy", "Liquid", "Lonely", "Longing", "Loud", "Loving", "Loyal", "Macabre", "Mad",
78
-        "Magical", "Magnificent", "Malevolent", "Medieval", "Memorable", "Mere", "Merry", "Mighty",
79
-        "Mischievous", "Miserable", "Modified", "Moody", "Most", "Mysterious", "Mystical", "Needy",
80
-        "Nervous", "Nice", "Objective", "Obnoxious", "Obsessive", "Obvious", "Opinionated", "Orange",
81
-        "Painful", "Passionate", "Perfect", "Pink", "Playful", "Poisonous", "Polite", "Poor", "Popular", "Powerful", 
82
-        "Precise", "Preserved", "Pretty", "Purple", "Quick", "Quiet", "Random", "Rapid", "Rare", "Real",
83
-        "Reassuring", "Reckless", "Red", "Regular", "Remorseful", "Responsible", "Rich", "Rude", "Ruthless",
84
-        "Sad", "Scared", "Scary", "Scornful", "Screaming", "Selfish", "Serious", "Shady", "Shaky", "Sharp",
85
-        "Shiny", "Shy", "Simple", "Sleepy", "Slow", "Sly", "Small", "Smart", "Smelly", "Smiling", "Smooth",
86
-        "Smug", "Sober", "Soft", "Solemn", "Square", "Square", "Steady", "Strange", "Strong",
87
-        "Stunning", "Subjective", "Successful", "Surly", "Sweet", "Tactful", "Tense",
88
-        "Thoughtful", "Tight", "Tiny", "Tolerant", "Uneasy", "Unique", "Unseen", "Warm", "Weak",
89
-        "Weird", "WellCooked", "Wild", "Wise", "Witty", "Wonderful", "Worried", "Yellow", "Young",
90
-        "Zealous"
91
-        ];
92
-    //var pronouns = [
93
-    //];
94
-    //var conjunctions = [
95
-    //"And", "Or", "For", "Above", "Before", "Against", "Between"
96
-    //];
97
-
98
-    /*
99
-     * Maps a string (category name) to the array of words from that category.
100
-     */
101
-    var CATEGORIES =
102
-    {
103
-        //"_NOUN_": nouns,
104
-        "_PLURALNOUN_": pluralNouns,
105
-        //"_PLACE_": places,
106
-        "_VERB_": verbs,
107
-        "_ADVERB_": adverbs,
108
-        "_ADJECTIVE_": adjectives
109
-        //"_PRONOUN_": pronouns,
110
-        //"_CONJUNCTION_": conjunctions,
111
-    };
112
-
113
-    var PATTERNS = [
114
-        "_ADJECTIVE__PLURALNOUN__VERB__ADVERB_"
115
-
116
-        // BeautifulFungiOrSpaghetti
117
-        //"_ADJECTIVE__PLURALNOUN__CONJUNCTION__PLURALNOUN_",
118
-
119
-        // AmazinglyScaryToy
120
-        //"_ADVERB__ADJECTIVE__NOUN_",
121
-
122
-        // NeitherTrashNorRifle
123
-        //"Neither_NOUN_Nor_NOUN_",
124
-        //"Either_NOUN_Or_NOUN_",
125
-
126
-        // EitherCopulateOrInvestigate
127
-        //"Either_VERB_Or_VERB_",
128
-        //"Neither_VERB_Nor_VERB_",
129
-
130
-        //"The_ADJECTIVE__ADJECTIVE__NOUN_",
131
-        //"The_ADVERB__ADJECTIVE__NOUN_",
132
-        //"The_ADVERB__ADJECTIVE__NOUN_s",
133
-        //"The_ADVERB__ADJECTIVE__PLURALNOUN__VERB_",
134
-
135
-        // WolvesComputeBadly
136
-        //"_PLURALNOUN__VERB__ADVERB_",
137
-
138
-        // UniteFacilitateAndMerge
139
-        //"_VERB__VERB_And_VERB_",
140
-
141
-        //NastyWitchesAtThePub
142
-        //"_ADJECTIVE__PLURALNOUN_AtThe_PLACE_",
143
-    ];
144
-
145
-
146
-    /*
147
-     * Returns a random element from the array 'arr' 
148
-     */
149
-    function randomElement(arr)
150
-    {
151
-        return arr[Math.floor(Math.random() * arr.length)];
152
-    }
153
-
154
-    /*
155
-     * Returns true if the string 's' contains one of the
156
-     * template strings.
157
-     */
158
-    function hasTemplate(s)
159
-    {
160
-        for (var template in CATEGORIES){
161
-            if (s.indexOf(template) >= 0){
162
-                return true;
163
-            }
164
-        }
165
-    }
166
-
167
-    /**
168
-     * Generates new room name.
169
-     */
170
-    RoomNameGeneratorProto.generateRoomWithoutSeparator = function()
171
-    {
172
-        // Note that if more than one pattern is available, the choice of 'name' won't be random (names from patterns
173
-        // with fewer options will have higher probability of being chosen that names from patterns with more options).
174
-        var name = randomElement(PATTERNS);
175
-        var word;
176
-        while (hasTemplate(name)){
177
-            for (var template in CATEGORIES){
178
-                word = randomElement(CATEGORIES[template]);
179
-                name = name.replace(template, word);
180
-            }
181
-        }
182
-
183
-        return name;
184
-    };
185
-
186
-    return RoomNameGeneratorProto;
187
-}();
188
-

+ 0
- 83
settings_menu.js Zobrazit soubor

@@ -1,83 +0,0 @@
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 || {}));

+ 0
- 48
smileys.js Zobrazit soubor

@@ -1,48 +0,0 @@
1
-var smileys = {
2
-    "smiley1": ':)',
3
-    "smiley2": ':(',
4
-    "smiley3": ':D',
5
-    "smiley4": '(y)',
6
-    "smiley5": ' :P',
7
-    "smiley6": '(wave)',
8
-    "smiley7": '(blush)',
9
-    "smiley8": '(chuckle)',
10
-    "smiley9": '(shocked)',
11
-    "smiley10": ':*',
12
-    "smiley11": '(n)',
13
-    "smiley12": '(search)',
14
-    "smiley13": ' <3',
15
-    "smiley14": '(oops)',
16
-    "smiley15": '(angry)',
17
-    "smiley16": '(angel)',
18
-    "smiley17": '(sick)',
19
-    "smiley18": ';(',
20
-    "smiley19": '(bomb)',
21
-    "smiley20": '(clap)',
22
-    "smiley21": ' ;)'
23
-};
24
-
25
-var regexs = {
26
-    'smiley2': /(:-\(\(|:-\(|:\(\(|:\(|\(sad\))/gi,
27
-    'smiley3': /(:-\)\)|:\)\)|\(lol\)|:-D|:D)/gi,
28
-    'smiley1': /(:-\)|:\))/gi,
29
-    'smiley4': /(\(y\)|\(Y\)|\(ok\))/gi,
30
-    'smiley5': /(:-P|:P|:-p|:p)/gi,
31
-    'smiley6': /(\(wave\))/gi,
32
-    'smiley7': /(\(blush\))/gi,
33
-    'smiley8': /(\(chuckle\))/gi,
34
-    'smiley9': /(:-0|\(shocked\))/gi,
35
-    'smiley10': /(:-\*|:\*|\(kiss\))/gi,
36
-    'smiley11': /(\(n\))/gi,
37
-    'smiley12': /(\(search\))/g,
38
-    'smiley13': /(<3|&lt;3|&amp;lt;3|\(L\)|\(l\)|\(H\)|\(h\))/gi,
39
-    'smiley14': /(\(oops\))/gi,
40
-    'smiley15': /(\(angry\))/gi,
41
-    'smiley16': /(\(angel\))/gi,
42
-    'smiley17': /(\(sick\))/gi,
43
-    'smiley18': /(;-\(\(|;\(\(|;-\(|;\(|:'\(|:'-\(|:~-\(|:~\(|\(upset\))/gi,
44
-    'smiley19': /(\(bomb\))/gi,
45
-    'smiley20': /(\(clap\))/gi,
46
-    'smiley21': /(;-\)|;\)|;-\)\)|;\)\)|;-D|;D|\(wink\))/gi
47
-};
48
-

+ 0
- 10
util.js Zobrazit soubor

@@ -47,16 +47,6 @@ var Util = (function (my) {
47 47
         return $('<div/>').text(unsafeText).html();
48 48
     };
49 49
 
50
-    /**
51
-     * Returns the available video width.
52
-     */
53
-    my.getAvailableVideoWidth = function () {
54
-        var rightPanelWidth
55
-            = PanelToggler.isVisible() ? PanelToggler.getPanelSize()[0] : 0;
56
-
57
-        return window.innerWidth - rightPanelWidth;
58
-    };
59
-
60 50
     my.imageToGrayScale = function (canvas) {
61 51
         var context = canvas.getContext('2d');
62 52
         var imgData = context.getImageData(0, 0, canvas.width, canvas.height);

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