Selaa lähdekoodia

Merge branch 'master' into translations-update

master
damencho 8 vuotta sitten
vanhempi
commit
547f96c0c1

+ 23
- 0
app.js Näytä tiedosto

@@ -24,6 +24,7 @@ import RoomnameGenerator from './modules/util/RoomnameGenerator';
24 24
 import UI from "./modules/UI/UI";
25 25
 import settings from "./modules/settings/Settings";
26 26
 import conference from './conference';
27
+import ConferenceUrl from './modules/URL/ConferenceUrl';
27 28
 import API from './modules/API/API';
28 29
 
29 30
 import UIEvents from './service/UI/UIEvents';
@@ -47,6 +48,18 @@ function pushHistoryState(roomName, URL) {
47 48
     return null;
48 49
 }
49 50
 
51
+/**
52
+ * Replaces current history state(replaces the URL displayed by the browser).
53
+ * @param {string} newUrl the URL string which is to be displayed by the browser
54
+ * to the user.
55
+ */
56
+function replaceHistoryState (newUrl) {
57
+    if (window.history
58
+        && typeof window.history.replaceState === 'function') {
59
+        window.history.replaceState({}, document.title, newUrl);
60
+    }
61
+}
62
+
50 63
 /**
51 64
  * Builds and returns the room name.
52 65
  */
@@ -82,6 +95,12 @@ const APP = {
82 95
     UI,
83 96
     settings,
84 97
     conference,
98
+    /**
99
+     * After the APP has been initialized provides utility methods for dealing
100
+     * with the conference room URL(address).
101
+     * @type ConferenceUrl
102
+     */
103
+    ConferenceUrl : null,
85 104
     connection: null,
86 105
     API,
87 106
     init () {
@@ -107,6 +126,10 @@ function setTokenData() {
107 126
 
108 127
 function init() {
109 128
     setTokenData();
129
+    // Initialize the conference URL handler
130
+    APP.ConferenceUrl = new ConferenceUrl(window.location);
131
+    // Clean up the URL displayed by the browser
132
+    replaceHistoryState(APP.ConferenceUrl.getInviteUrl());
110 133
     var isUIReady = APP.UI.start();
111 134
     if (isUIReady) {
112 135
         APP.conference.init({roomName: buildRoomName()}).then(function () {

+ 14
- 5
conference.js Näytä tiedosto

@@ -325,10 +325,6 @@ class ConferenceConnector {
325 325
             }
326 326
             break;
327 327
 
328
-        case ConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
329
-            APP.UI.notifyBridgeDown();
330
-            break;
331
-
332 328
             // not enough rights to create conference
333 329
         case ConferenceErrors.AUTHENTICATION_REQUIRED:
334 330
             // schedule reconnect to check if someone else created the room
@@ -363,6 +359,10 @@ class ConferenceConnector {
363 359
             }
364 360
             break;
365 361
 
362
+            // FIXME FOCUS_DISCONNECTED is confusing event name.
363
+            // What really happens there is that the library is not ready yet,
364
+            // because Jicofo is not available, but it is going to give
365
+            // it another try.
366 366
         case ConferenceErrors.FOCUS_DISCONNECTED:
367 367
             {
368 368
                 let [focus, retrySec] = params;
@@ -371,8 +371,17 @@ class ConferenceConnector {
371 371
             break;
372 372
 
373 373
         case ConferenceErrors.FOCUS_LEFT:
374
+        case ConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
375
+            // Log the page reload event
376
+            // FIXME (CallStats - issue) this event will not make it to
377
+            // the CallStats, because the log queue is not flushed, before
378
+            // "fabric terminated" is sent to the backed
379
+            APP.conference.logEvent('page.reload');
380
+            // FIXME the conference should be stopped by the library and not by
381
+            // the app. Both the errors above are unrecoverable from the library
382
+            // perspective.
374 383
             room.leave().then(() => connection.disconnect());
375
-            APP.UI.notifyFocusLeft();
384
+            APP.UI.showPageReloadOverlay();
376 385
             break;
377 386
 
378 387
         case ConferenceErrors.CONFERENCE_MAX_USERS:

+ 1
- 1
css/_recording.scss Näytä tiedosto

@@ -1,4 +1,4 @@
1 1
 .recordingSpinner {
2 2
     display: none;
3
-    vertical-align: text-bottom;
3
+    vertical-align: top;
4 4
 }

+ 1
- 1
css/_toolbars.scss Näytä tiedosto

@@ -1,5 +1,5 @@
1 1
 .toolbar {
2
-    background-color: rgba(0,0,0,0.5);
2
+    background-color: $toolbarBackground;
3 3
     position: relative;
4 4
     z-index: $toolbarZ;
5 5
     height: 100%;

+ 8
- 4
css/_variables.scss Näytä tiedosto

@@ -27,6 +27,7 @@ $defaultBackground: #474747;
27 27
 $tooltipBg: rgba(0,0,0, 0.7);
28 28
 
29 29
 // Toolbar
30
+$toolbarBackground: rgba(0, 0, 0, 0.5);
30 31
 $toolbarSelectBackground: rgba(0, 0, 0, .6);
31 32
 $toolbarBadgeBackground: #165ECC;
32 33
 $toolbarBadgeColor: #FFFFFF;
@@ -46,6 +47,8 @@ $dominantSpeakerBg: #165ecc;
46 47
 $raiseHandBg: #D6D61E;
47 48
 $audioLevelBg: #44A5FF;
48 49
 $audioLevelShadow: rgba(9, 36, 77, 0.9);
50
+$videoStateIndicatorColor: $defaultColor;
51
+$videoStateIndicatorBackground: $toolbarBackground;
49 52
 
50 53
 /**
51 54
  * Feedback Modal
@@ -84,8 +87,9 @@ $sidebarWidth: 200px;
84 87
  */
85 88
 $tooltipsZ: 901;
86 89
 $toolbarZ: 900;
87
-$overlayZ: 800;
90
+$overlayZ: 902;
88 91
 $notificationZ: 1012;
92
+$ringingZ: 800;
89 93
 
90 94
 /**
91 95
  * Font Colors TODO: Change colors when general dialogs are implemented.
@@ -106,6 +110,6 @@ $linkHoverFontColor: #287ade;
106 110
 /**
107 111
  * Forms
108 112
  */
109
-$inputBg: #505F79;
110
-$inputBgHover: #505F79;
111
-$inputFontColor: #ECEEF1;
113
+$inputBg: $inputSemiBackground;
114
+$inputBgHover: $inputSemiBackground;
115
+$inputFontColor: $defaultDarkFontColor;

+ 28
- 32
css/_videolayout_default.scss Näytä tiedosto

@@ -511,7 +511,7 @@
511 511
     display: none;
512 512
     position: absolute;
513 513
     width: auto;
514
-    z-index: 1011;
514
+    z-index: 2;
515 515
     font-weight: 600;
516 516
     font-size: 14px;
517 517
     text-align: center;
@@ -534,7 +534,7 @@
534 534
     position: absolute;
535 535
     width: 100%;
536 536
     top:50%;
537
-    z-index: 1011;
537
+    z-index: 2;
538 538
     font-weight: 600;
539 539
     font-size: 14px;
540 540
     text-align: center;
@@ -546,47 +546,43 @@
546 546
                     0px 0px 1px rgba(0,0,0,0.3);
547 547
 }
548 548
 
549
-#videoResolutionLabel {
550
-    display: none;
551
-    position: absolute;
552
-    top: 5px;
553
-    right: 5px;
554
-    background: rgba(0,0,0,.5);
555
-    padding: 10px;
556
-    color: rgba(255,255,255,.5);
557
-    z-index: 1011;
549
+.video-state-indicator {
550
+    background: $videoStateIndicatorBackground;
551
+    color: $videoStateIndicatorColor;
552
+    font-size: 13px;
553
+    line-height: 20px;
554
+    text-align: center;
555
+    min-width: 40px;
556
+    height: 40px;
557
+    padding: 10px 5px;
558 558
     border-radius: 50%;
559
+    position: absolute;
560
+    box-sizing: border-box;
559 561
 }
560 562
 
563
+#videoResolutionLabel,
561 564
 .centeredVideoLabel {
562 565
     display: none;
563
-    position: absolute;
564
-    bottom: 45%;
565
-    top: auto;
566
-    right: auto;
567
-    left: auto;
568
-    line-height: 28px;
569
-    height: 28px;
570
-    width: auto;
571
-    padding: 5px;
572
-    margin-right: auto;
573
-    margin-left: auto;
574
-    background: rgba(0,0,0,.5);
575
-    color: #FFF;
576 566
     z-index: 1011;
567
+}
568
+
569
+.centeredVideoLabel {
570
+    bottom: 45%;
577 571
     border-radius: 2px;
578 572
     -webkit-transition: all 2s 2s linear;
579 573
     transition: all 2s 2s linear;
574
+
575
+    &.moveToCorner {
576
+        bottom: auto;
577
+    }
580 578
 }
581 579
 
582 580
 .moveToCorner {
583
-    top: 5px;
584
-    right: 50px; /*leave free space for the HD label*/
585
-    margin-right: 0px;
586
-    margin-left: auto;
587
-    background: rgba(0,0,0,.3);
588
-    color: rgba(255,255,255,.5);
581
+    position: absolute;
582
+    top: 30px;
583
+    right: 30px;
589 584
 }
590 585
 
591
-.hidden {
592
-}
586
+.moveToCorner + .moveToCorner {
587
+    right: 80px;
588
+}

+ 5
- 11
css/aui-components/dropdown.scss Näytä tiedosto

@@ -3,6 +3,10 @@ form.aui {
3 3
         background-color: transparent;
4 4
 
5 5
         > a {
6
+            background-color: $inputBg !important;
7
+            color: $inputFontColor !important;
8
+            border-color: $inputBg !important;
9
+            text-shadow: none !important;
6 10
             margin: 0 auto !important;
7 11
             width: 100% !important;
8 12
         }
@@ -32,17 +36,7 @@ form.aui {
32 36
     z-index: 900;
33 37
 }
34 38
 
35
-//Dark theme
36
-form.aui{
37
-    //Placeholder
38
-    .aui-select2-container.input-container-dark {
39
-        a.select2-choice {
40
-            text-shadow: none;
41
-        }
42
-    }
43
-}
44
-
45 39
 .aui-dropdown2.aui-style-default.dropdown-dark {
46 40
     background-color: $defaultBackground;
47 41
     border-color: transparent;
48
-}
42
+}

+ 1
- 0
css/main.scss Näytä tiedosto

@@ -38,6 +38,7 @@
38 38
 @import 'toastr';
39 39
 @import 'base';
40 40
 @import 'overlay/overlay';
41
+@import 'reload_overlay/reload_overlay';
41 42
 @import 'modals/dialog';
42 43
 @import 'modals/feedback/feedback';
43 44
 @import 'videolayout_default';

+ 5
- 23
css/overlay/_overlay.scss Näytä tiedosto

@@ -1,48 +1,30 @@
1
-.overlay {
2
-    position: fixed;
3
-    left: 0;
4
-    top: 0;
5
-    width: 100%;
6
-    height: 100%;
7
-    z-index: $overlayZ;
8
-    background: #21B9FC; /* Old browsers */
9
-    opacity: 0.75;
10
-    display: block;
11
-}
12
-
13
-.overlay_transparent {
14
-    background: rgba(22, 185, 252, .9);
15
-}
16
-
17 1
 .overlay_container {
2
+    top: 0;
3
+    left: 0;
18 4
     width: 100%;
19 5
     height: 100%;
20 6
     position: fixed;
21 7
     z-index: $overlayZ;
8
+    background: rgba(22, 185, 252, .9);
22 9
 }
23 10
 
24 11
 .overlay_content {
25 12
     color: #fff;
26
-    font-weight: normal;
27
-    font-size: 20px;
28 13
     text-align: center;
29 14
     width: 400px;
30 15
     height: 250px;
31 16
     top: 50%;
32 17
     left: 50%;
33
-    position:absolute;
18
+    position: absolute;
34 19
     margin-top: -125px;
35 20
     margin-left: -200px;
36 21
 }
37 22
 
38
-
39 23
 .overlay_text_small {
24
+    display: block;
40 25
     font-size: 18px;
41 26
 }
42 27
 
43 28
 .overlay_icon {
44
-    position: relative;
45
-    z-index: 1013;
46
-    float: none;
47 29
     font-size: 100px;
48 30
 }

+ 17
- 0
css/reload_overlay/_reload_overlay.scss Näytä tiedosto

@@ -0,0 +1,17 @@
1
+.reload_overlay_title {
2
+    display: block;
3
+    font-size: 16px;
4
+    line-height: 20px;
5
+}
6
+
7
+.reload_overlay_msg {
8
+    display: block;
9
+    font-size: 12px;
10
+    line-height: 30px;
11
+}
12
+
13
+#reloadProgressBar {
14
+    width: 180px;
15
+    margin: 5px auto;
16
+}
17
+

+ 1
- 1
css/ringing/_ringing.scss Näytä tiedosto

@@ -5,7 +5,7 @@
5 5
     width: 100%;
6 6
     height: 100%;
7 7
     position: fixed;
8
-    z-index: $overlayZ;
8
+    z-index: $ringingZ;
9 9
     background: linear-gradient(transparent, #000);
10 10
     opacity: 0.8;
11 11
 

+ 2
- 2
index.html Näytä tiedosto

@@ -240,8 +240,8 @@
240 240
                     <video id="largeVideo" muted="true" autoplay></video>
241 241
                 </div>
242 242
                 <span id="localConnectionMessage"></span>
243
-                <span id="videoResolutionLabel">HD</span>
244
-                <span id="recordingLabel" class="centeredVideoLabel">
243
+                <span id="videoResolutionLabel" class="video-state-indicator moveToCorner">HD</span>
244
+                <span id="recordingLabel" class="video-state-indicator centeredVideoLabel">
245 245
                     <span id="recordingLabelText"></span>
246 246
                     <img id="recordingSpinner" class="recordingSpinner" src="images/spin.svg"></img>
247 247
                 </span>

+ 3
- 2
lang/main.json Näytä tiedosto

@@ -204,8 +204,9 @@
204 204
         "detectext": "Error when trying to detect desktopsharing extension.",
205 205
         "failtoinstall": "Failed to install desktop sharing extension",
206 206
         "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
207
-        "bridgeUnavailable": "Jitsi Videobridge is currently unavailable. Please try again later!",
208
-        "jicofoUnavailable": "Jicofo is currently unavailable. Please try again later!",
207
+        "conferenceReloadTitle": "Unfortunately, something went wrong",
208
+        "conferenceReloadMsg": "We're trying to fix this",
209
+        "conferenceReloadTimeLeft": "__seconds__ sec.",
209 210
         "maxUsersLimitReached": "The limit for maximum number of participants in the conference has been reached. The conference is full. Please try again later!",
210 211
         "lockTitle": "Lock failed",
211 212
         "lockMessage": "Failed to lock the conference.",

+ 17
- 36
modules/UI/UI.js Näytä tiedosto

@@ -14,12 +14,12 @@ import Recording from "./recording/Recording";
14 14
 import GumPermissionsOverlay
15 15
     from './gum_overlay/UserMediaPermissionsGuidanceOverlay';
16 16
 
17
+import PageReloadOverlay from './reload_overlay/PageReloadOverlay';
17 18
 import VideoLayout from "./videolayout/VideoLayout";
18 19
 import FilmStrip from "./videolayout/FilmStrip";
19 20
 import SettingsMenu from "./side_pannels/settings/SettingsMenu";
20 21
 import Profile from "./side_pannels/profile/Profile";
21 22
 import Settings from "./../settings/Settings";
22
-import { reload } from '../util/helpers';
23 23
 import RingOverlay from "./ring_overlay/RingOverlay";
24 24
 import UIErrors from './UIErrors';
25 25
 
@@ -189,13 +189,6 @@ UI.notifyConferenceDestroyed = function (reason) {
189 189
         "dialog.sessTerminated", reason, true, {}, () => false);
190 190
 };
191 191
 
192
-/**
193
- * Notify user that Jitsi Videobridge is not accessible.
194
- */
195
- UI.notifyBridgeDown = function () {
196
-    messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
197
-};
198
-
199 192
 /**
200 193
  * Show chat error.
201 194
  * @param err the Error
@@ -259,19 +252,6 @@ UI.setLocalRaisedHandStatus = (raisedHandStatus) => {
259 252
  */
260 253
 UI.initConference = function () {
261 254
     let id = APP.conference.getMyUserId();
262
-
263
-    // Do not include query parameters in the invite URL
264
-    // "https:" + "//" + "example.com:8888" + "/SomeConference1245"
265
-    var inviteURL = window.location.protocol + "//" +
266
-        window.location.host + window.location.pathname;
267
-
268
-    this.emitEvent(UIEvents.INVITE_URL_INITIALISED, inviteURL);
269
-
270
-    // Clean up the URL displayed by the browser
271
-    if (window.history && typeof window.history.replaceState === 'function') {
272
-        window.history.replaceState({}, document.title, inviteURL);
273
-    }
274
-
275 255
     // Add myself to the contact list.
276 256
     UI.ContactList.addContact(id, true);
277 257
 
@@ -1104,22 +1084,11 @@ UI.notifyFocusDisconnected = function (focus, retrySec) {
1104 1084
 };
1105 1085
 
1106 1086
 /**
1107
- * Notify user that focus left the conference so page should be reloaded.
1087
+ * Notify the user that the video conferencing service is badly broken and
1088
+ * the page should be reloaded.
1108 1089
  */
1109
-UI.notifyFocusLeft = function () {
1110
-    let msg = APP.translation.generateTranslationHTML(
1111
-        'dialog.jicofoUnavailable'
1112
-    );
1113
-    messageHandler.openDialog(
1114
-        'dialog.serviceUnavailable',
1115
-        msg,
1116
-        true, // persistent
1117
-        [{title: 'retry'}],
1118
-        function () {
1119
-            reload();
1120
-            return false;
1121
-        }
1122
-    );
1090
+UI.showPageReloadOverlay = function () {
1091
+    PageReloadOverlay.show(15 /* will reload in 15 seconds */);
1123 1092
 };
1124 1093
 
1125 1094
 /**
@@ -1447,6 +1416,18 @@ UI.hideRingOverLay = function () {
1447 1416
     FilmStrip.toggleFilmStrip(true);
1448 1417
 };
1449 1418
 
1419
+/**
1420
+ * Indicates if any the "top" overlays are currently visible. The check includes
1421
+ * the call overlay, GUM permissions overlay and a page reload overlay.
1422
+ *
1423
+ * @returns {*|boolean} {true} if the overlay is visible, {false} otherwise
1424
+ */
1425
+UI.isOverlayVisible = function () {
1426
+    return RingOverlay.isVisible()
1427
+        || PageReloadOverlay.isVisible()
1428
+        || GumPermissionsOverlay.isVisible();
1429
+};
1430
+
1450 1431
 /**
1451 1432
  * Indicates if the ring overlay is currently visible.
1452 1433
  *

+ 44
- 22
modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js Näytä tiedosto

@@ -1,29 +1,50 @@
1
-/* global $, APP */
1
+/* global */
2 2
 
3
-let $overlay;
3
+import Overlay from '../overlay/Overlay';
4 4
 
5 5
 /**
6
- * Internal function that constructs overlay with guidance how to proceed with
7
- * gUM prompt.
8
- * @param {string} browser - name of browser for which to construct the
9
- *      guidance overlay.
6
+ * An overlay with guidance how to proceed with gUM prompt.
10 7
  */
11
-function buildOverlayHtml(browser) {
12
-    $overlay = $(`
13
-        <div class='overlay_container'>
14
-            <div class='overlay overlay_transparent' />
15
-            <div class='overlay_content'>
16
-                <span class="overlay_icon icon-microphone"></span>
17
-                <span class="overlay_icon icon-camera"></span>
18
-                <span data-i18n='[html]userMedia.${browser}GrantPermissions' 
19
-                    class='overlay_text overlay_text_small'></span>
20
-            </div>
21
-        </div>`);
8
+class GUMOverlayImpl extends Overlay {
22 9
 
23
-    APP.translation.translateElement($overlay);
10
+    /**
11
+     * Constructs overlay with guidance how to proceed with gUM prompt.
12
+     * @param {string} browser - name of browser for which to construct the
13
+     *     guidance overlay.
14
+     * @override
15
+     */
16
+    constructor(browser) {
17
+        super();
18
+        this.browser = browser;
19
+    }
20
+
21
+    /**
22
+     * @inheritDoc
23
+     */
24
+    _buildOverlayContent() {
25
+        return `
26
+            <span class="overlay_icon icon-microphone"></span>
27
+            <span class="overlay_icon icon-camera"></span>
28
+            <span data-i18n='[html]userMedia.${this.browser}GrantPermissions' 
29
+                  class='overlay_text_small'></span>`;
30
+    }
24 31
 }
25 32
 
33
+/**
34
+ * Stores GUM overlay instance.
35
+ * @type {GUMOverlayImpl}
36
+ */
37
+let overlay;
38
+
26 39
 export default {
40
+    /**
41
+     * Checks whether the overlay is currently visible.
42
+     * @return {boolean} <tt>true</tt> if the overlay is visible
43
+     * or <tt>false</tt> otherwise.
44
+     */
45
+    isVisible () {
46
+        return overlay && overlay.isVisible();
47
+    },
27 48
     /**
28 49
      * Shows browser-specific overlay with guidance how to proceed with
29 50
      * gUM prompt.
@@ -31,9 +52,10 @@ export default {
31 52
      *      guidance overlay.
32 53
      */
33 54
     show(browser) {
34
-        !$overlay && buildOverlayHtml(browser);
35
-
36
-        !$overlay.parents('body').length && $overlay.appendTo('body');
55
+        if (!overlay) {
56
+            overlay = new GUMOverlayImpl(browser);
57
+        }
58
+        overlay.show();
37 59
     },
38 60
 
39 61
     /**
@@ -41,6 +63,6 @@ export default {
41 63
      * gUM prompt.
42 64
      */
43 65
     hide() {
44
-        $overlay && $overlay.detach();
66
+        overlay && overlay.hide();
45 67
     }
46 68
 };

+ 1
- 13
modules/UI/invite/Invite.js Näytä tiedosto

@@ -14,6 +14,7 @@ const ConferenceEvents = JitsiMeetJS.events.conference;
14 14
 class Invite {
15 15
     constructor(conference) {
16 16
         this.conference = conference;
17
+        this.inviteUrl = APP.ConferenceUrl.getInviteUrl();
17 18
         this.createRoomLocker(conference);
18 19
         this.registerListeners();
19 20
     }
@@ -48,11 +49,6 @@ class Invite {
48 49
         APP.UI.addListener( UIEvents.INVITE_CLICKED,
49 50
                             () => { this.openLinkDialog(); });
50 51
 
51
-        APP.UI.addListener( UIEvents.INVITE_URL_INITIALISED,
52
-                            (inviteUrl) => {
53
-                                this.updateInviteUrl(inviteUrl);
54
-                            });
55
-
56 52
         APP.UI.addListener( UIEvents.PASSWORD_REQUIRED,
57 53
             () => {
58 54
                 this.setLockedFromElsewhere(true);
@@ -172,14 +168,6 @@ class Invite {
172 168
         }
173 169
     }
174 170
 
175
-    /**
176
-     * Updates the room invite url.
177
-     */
178
-    updateInviteUrl (newInviteUrl) {
179
-        this.inviteUrl = newInviteUrl;
180
-        this.updateView();
181
-    }
182
-
183 171
     /**
184 172
      * Helper method for encoding
185 173
      * Invite URL

+ 82
- 0
modules/UI/overlay/Overlay.js Näytä tiedosto

@@ -0,0 +1,82 @@
1
+/* global $, APP */
2
+
3
+/**
4
+ * Base class for overlay components - the components which are displayed on
5
+ * top of the application with semi-transparent background covering the whole
6
+ * screen.
7
+ */
8
+export default class Overlay{
9
+    /**
10
+     * Creates new <tt>Overlay</tt> instance.
11
+     */
12
+    constructor() {
13
+        /**
14
+         *
15
+         * @type {jQuery}
16
+         */
17
+        this.$overlay = null;
18
+    }
19
+    /**
20
+     * Template method which should be used by subclasses to provide the overlay
21
+     * content. The contents provided by this method are later subject to
22
+     * the translation using {@link APP.translation.translateElement}.
23
+     * @return {string} HTML representation of the overlay dialog contents.
24
+     * @private
25
+     */
26
+    _buildOverlayContent() {
27
+        return '';
28
+    }
29
+    /**
30
+     * Constructs the HTML body of the overlay dialog.
31
+     */
32
+    buildOverlayHtml() {
33
+
34
+        let overlayContent = this._buildOverlayContent();
35
+
36
+        this.$overlay = $(`
37
+            <div class='overlay_container'>
38
+                <div class='overlay_content'>
39
+                    ${overlayContent}
40
+                </div>
41
+            </div>`);
42
+
43
+        APP.translation.translateElement(this.$overlay);
44
+    }
45
+    /**
46
+     * Checks whether the page reload overlay has been displayed.
47
+     * @return {boolean} <tt>true</tt> if the page reload overlay is currently
48
+     * visible or <tt>false</tt> otherwise.
49
+     */
50
+    isVisible() {
51
+        return this.$overlay && this.$overlay.parents('body').length > 0;
52
+    }
53
+    /**
54
+     * Template method called just after the overlay is displayed for the first
55
+     * time.
56
+     * @private
57
+     */
58
+    _onShow() {
59
+        // To be overridden by subclasses.
60
+    }
61
+    /**
62
+     * Shows the overlay dialog adn attaches the underlying HTML representation
63
+     * to the DOM.
64
+     */
65
+    show() {
66
+
67
+        !this.$overlay && this.buildOverlayHtml();
68
+
69
+        if (!this.isVisible()) {
70
+            this.$overlay.appendTo('body');
71
+            this._onShow();
72
+        }
73
+    }
74
+
75
+    /**
76
+     * Hides the overlay dialog and detaches it's HTML representation from
77
+     * the DOM.
78
+     */
79
+    hide() {
80
+        this.$overlay && this.$overlay.detach();
81
+    }
82
+}

+ 121
- 0
modules/UI/reload_overlay/PageReloadOverlay.js Näytä tiedosto

@@ -0,0 +1,121 @@
1
+/* global $, APP, AJS */
2
+
3
+import Overlay from '../overlay/Overlay';
4
+
5
+/**
6
+ * An overlay dialog which is shown before the conference is reloaded. Shows
7
+ * a warning message and counts down towards the reload.
8
+ */
9
+class PageReloadOverlayImpl extends Overlay{
10
+    /**
11
+     * Creates new <tt>PageReloadOverlayImpl</tt>
12
+     * @param {number} timeoutSeconds how long the overlay dialog will be
13
+     * displayed, before the conference will be reloaded.
14
+     */
15
+    constructor(timeoutSeconds) {
16
+        super();
17
+        /**
18
+         * Conference reload counter in seconds.
19
+         * @type {number}
20
+         */
21
+        this.timeLeft = timeoutSeconds;
22
+        /**
23
+         * Conference reload timeout in seconds.
24
+         * @type {number}
25
+         */
26
+        this.timeout = timeoutSeconds;
27
+    }
28
+    /**
29
+     * Constructs overlay body with the warning message and count down towards
30
+     * the conference reload.
31
+     * @override
32
+     */
33
+    _buildOverlayContent() {
34
+        return `
35
+            <span data-i18n='dialog.conferenceReloadTitle' 
36
+                  class='reload_overlay_title'></span>
37
+            <span data-i18n='dialog.conferenceReloadMsg' 
38
+                  class='reload_overlay_msg'></span>
39
+            <div>
40
+                <div id='reloadProgressBar' class="aui-progress-indicator">
41
+                    <span class="aui-progress-indicator-value"></span>
42
+                </div>
43
+                <span id='reloadSecRemaining' 
44
+                      data-i18n="dialog.conferenceReloadTimeLeft" 
45
+                      class='reload_overlay_msg'>
46
+                </span>
47
+            </div>`;
48
+    }
49
+
50
+    /**
51
+     * Updates the progress indicator position and the label with the time left.
52
+     */
53
+    updateDisplay() {
54
+
55
+        APP.translation.translateElement(
56
+            $("#reloadSecRemaining"), { seconds: this.timeLeft });
57
+
58
+        const ratio = (this.timeout - this.timeLeft) / this.timeout;
59
+        AJS.progressBars.update("#reloadProgressBar", ratio);
60
+    }
61
+
62
+    /**
63
+     * Starts the reload countdown with the animation.
64
+     * @override
65
+     */
66
+    _onShow() {
67
+
68
+        // Initialize displays
69
+        this.updateDisplay();
70
+
71
+        var intervalId = window.setInterval(function() {
72
+
73
+            if (this.timeLeft >= 1) {
74
+                this.timeLeft -= 1;
75
+            }
76
+
77
+            this.updateDisplay();
78
+
79
+            if (this.timeLeft === 0) {
80
+                window.clearInterval(intervalId);
81
+                APP.ConferenceUrl.reload();
82
+            }
83
+        }.bind(this), 1000);
84
+
85
+        console.info(
86
+            "The conference will be reloaded after "
87
+                + this.timeLeft + " seconds.");
88
+    }
89
+}
90
+
91
+/**
92
+ * Holds the page reload overlay instance.
93
+ *
94
+ * {@type PageReloadOverlayImpl}
95
+ */
96
+let overlay;
97
+
98
+export default {
99
+    /**
100
+     * Checks whether the page reload overlay has been displayed.
101
+     * @return {boolean} <tt>true</tt> if the page reload overlay is currently
102
+     * visible or <tt>false</tt> otherwise.
103
+     */
104
+    isVisible() {
105
+        return overlay && overlay.isVisible();
106
+    },
107
+    /**
108
+     * Shows the page reload overlay which will do the conference reload after
109
+     * the given amount of time.
110
+     *
111
+     * @param {number} timeoutSeconds how many seconds before the conference
112
+     * reload will happen.
113
+     */
114
+    show(timeoutSeconds) {
115
+
116
+        if (!overlay) {
117
+            overlay = new PageReloadOverlayImpl(timeoutSeconds);
118
+        }
119
+        overlay.show();
120
+    }
121
+};

+ 4
- 3
modules/UI/toolbars/ToolbarToggler.js Näytä tiedosto

@@ -34,9 +34,10 @@ function hideToolbar(force) { // eslint-disable-line no-unused-vars
34 34
     clearTimeout(toolbarTimeoutObject);
35 35
     toolbarTimeoutObject = null;
36 36
 
37
-    if (Toolbar.isHovered()
38
-            || APP.UI.isRingOverlayVisible()
39
-            || SideContainerToggler.isVisible()) {
37
+    if (force !== true &&
38
+            (Toolbar.isHovered()
39
+                || APP.UI.isRingOverlayVisible()
40
+                || SideContainerToggler.isVisible())) {
40 41
         toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
41 42
     } else {
42 43
         Toolbar.hide();

+ 1
- 1
modules/UI/util/MessageHandler.js Näytä tiedosto

@@ -326,7 +326,7 @@ var messageHandler = {
326 326
                      messageArguments, options) {
327 327
 
328 328
         // If we're in ringing state we skip all toaster notifications.
329
-        if(!notificationsEnabled || APP.UI.isRingOverlayVisible())
329
+        if(!notificationsEnabled || APP.UI.isOverlayVisible())
330 330
             return;
331 331
 
332 332
         var displayNameSpan = '<span class="nickname" ';

+ 73
- 0
modules/URL/ConferenceUrl.js Näytä tiedosto

@@ -0,0 +1,73 @@
1
+/* global console */
2
+
3
+import { redirect } from '../util/helpers';
4
+
5
+/**
6
+ * The modules stores information about the URL used to start the conference and
7
+ * provides utility methods for dealing with conference URL and reloads.
8
+ */
9
+export default class ConferenceUrl {
10
+    /**
11
+     * Initializes the module.
12
+     *
13
+     * @param location an object which stores provides the info about conference
14
+     * URL(would be 'window.location' for the Web app). The params below are
15
+     * described based on the following example URL:
16
+     *
17
+     * https://example.com:8888/SomeConference1245?opt=1#somehash
18
+     *
19
+     * @param location.href full URL with all parameters, would be the whole URL
20
+     * from the example string above.
21
+     *
22
+     * @param location.host the host part of the URL, 'example.com' from
23
+     * the sample URL above.
24
+     *
25
+     * @param location.pathname the path part of the URL, would be
26
+     * '/SomeConference1245' from the example above.
27
+     *
28
+     * @param location.protocol the protocol part of the URL, would be 'https:'
29
+     * from the sample URL.
30
+     */
31
+    constructor(location) {
32
+        /**
33
+         * Stores the original conference room URL with all parameters.
34
+         * Example:
35
+         * https://example.com:8888/SomeConference1245?jwt=a5sbc2#blablahash
36
+         * @type {string}
37
+         */
38
+        this.originalURL = location.href;
39
+        /**
40
+         * A simplified version of the conference URL stripped out of
41
+         * the parameters which should be used for sending invites.
42
+         * Example:
43
+         * https://example.com:8888/SomeConference1245
44
+         * @type {string}
45
+         */
46
+        this.inviteURL
47
+            = location.protocol + "//" + location.host + location.pathname;
48
+        console.info("Stored original conference URL: " + this.originalURL);
49
+        console.info("Conference URL for invites: " + this.inviteURL);
50
+    }
51
+    /**
52
+     * Obtains the conference invite URL.
53
+     * @return {string} the URL pointing o the conference which is mean to be
54
+     * used to invite new participants.
55
+     */
56
+    getInviteUrl() {
57
+        return this.inviteURL;
58
+    }
59
+    /**
60
+     * Obtains full conference URL with all original parameters.
61
+     * @return {string} the original URL used to open the current conference.
62
+     */
63
+    getOriginalUrl() {
64
+        return this.originalURL;
65
+    }
66
+    /**
67
+     * Reloads the conference using original URL with all of the parameters.
68
+     */
69
+    reload() {
70
+        console.info("Reloading the conference using URL: " + this.originalURL);
71
+        redirect(this.originalURL);
72
+    }
73
+}

+ 9
- 0
modules/util/helpers.js Näytä tiedosto

@@ -20,6 +20,15 @@ export function reload () {
20 20
     window.location.reload();
21 21
 }
22 22
 
23
+/**
24
+ * Redirects to new URL.
25
+ * @param {string} url the URL pointing to the location where the user should
26
+ * be redirected to.
27
+ */
28
+export function redirect (url) {
29
+    window.location.replace(url);
30
+}
31
+
23 32
 /**
24 33
  * Prints the error and reports it to the global error handler.
25 34
  * @param e {Error} the error

+ 0
- 5
service/UI/UIEvents.js Näytä tiedosto

@@ -145,11 +145,6 @@ export default {
145 145
      */
146 146
     DISPLAY_NAME_CHANGED: "UI.display_name_changed",
147 147
 
148
-    /**
149
-     * Indicates that the invite url has been initialised.
150
-     */
151
-    INVITE_URL_INITIALISED: "UI.invite_url_initialised",
152
-
153 148
     /**
154 149
      * Indicates that a password is required for the call.
155 150
      */

Loading…
Peruuta
Tallenna