diff --git a/app.js b/app.js
index 49b4b1059..2b6e21982 100644
--- a/app.js
+++ b/app.js
@@ -24,6 +24,7 @@ import RoomnameGenerator from './modules/util/RoomnameGenerator';
import UI from "./modules/UI/UI";
import settings from "./modules/settings/Settings";
import conference from './conference';
+import ConferenceUrl from './modules/URL/ConferenceUrl';
import API from './modules/API/API';
import UIEvents from './service/UI/UIEvents';
@@ -47,6 +48,18 @@ function pushHistoryState(roomName, URL) {
return null;
}
+/**
+ * Replaces current history state(replaces the URL displayed by the browser).
+ * @param {string} newUrl the URL string which is to be displayed by the browser
+ * to the user.
+ */
+function replaceHistoryState (newUrl) {
+ if (window.history
+ && typeof window.history.replaceState === 'function') {
+ window.history.replaceState({}, document.title, newUrl);
+ }
+}
+
/**
* Builds and returns the room name.
*/
@@ -82,6 +95,12 @@ const APP = {
UI,
settings,
conference,
+ /**
+ * After the APP has been initialized provides utility methods for dealing
+ * with the conference room URL(address).
+ * @type ConferenceUrl
+ */
+ ConferenceUrl : null,
connection: null,
API,
init () {
@@ -107,6 +126,10 @@ function setTokenData() {
function init() {
setTokenData();
+ // Initialize the conference URL handler
+ APP.ConferenceUrl = new ConferenceUrl(window.location);
+ // Clean up the URL displayed by the browser
+ replaceHistoryState(APP.ConferenceUrl.getInviteUrl());
var isUIReady = APP.UI.start();
if (isUIReady) {
APP.conference.init({roomName: buildRoomName()}).then(function () {
diff --git a/conference.js b/conference.js
index 3ee6524d8..3d5c94f2b 100644
--- a/conference.js
+++ b/conference.js
@@ -325,10 +325,6 @@ class ConferenceConnector {
}
break;
- case ConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
- APP.UI.notifyBridgeDown();
- break;
-
// not enough rights to create conference
case ConferenceErrors.AUTHENTICATION_REQUIRED:
// schedule reconnect to check if someone else created the room
@@ -363,6 +359,10 @@ class ConferenceConnector {
}
break;
+ // FIXME FOCUS_DISCONNECTED is confusing event name.
+ // What really happens there is that the library is not ready yet,
+ // because Jicofo is not available, but it is going to give
+ // it another try.
case ConferenceErrors.FOCUS_DISCONNECTED:
{
let [focus, retrySec] = params;
@@ -371,8 +371,17 @@ class ConferenceConnector {
break;
case ConferenceErrors.FOCUS_LEFT:
+ case ConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE:
+ // Log the page reload event
+ // FIXME (CallStats - issue) this event will not make it to
+ // the CallStats, because the log queue is not flushed, before
+ // "fabric terminated" is sent to the backed
+ APP.conference.logEvent('page.reload');
+ // FIXME the conference should be stopped by the library and not by
+ // the app. Both the errors above are unrecoverable from the library
+ // perspective.
room.leave().then(() => connection.disconnect());
- APP.UI.notifyFocusLeft();
+ APP.UI.showPageReloadOverlay();
break;
case ConferenceErrors.CONFERENCE_MAX_USERS:
diff --git a/css/_recording.scss b/css/_recording.scss
index 0f58bb789..aa56227a7 100644
--- a/css/_recording.scss
+++ b/css/_recording.scss
@@ -1,4 +1,4 @@
.recordingSpinner {
display: none;
- vertical-align: text-bottom;
+ vertical-align: top;
}
\ No newline at end of file
diff --git a/css/_toolbars.scss b/css/_toolbars.scss
index f8d000e2f..22ac3f049 100644
--- a/css/_toolbars.scss
+++ b/css/_toolbars.scss
@@ -1,5 +1,5 @@
.toolbar {
- background-color: rgba(0,0,0,0.5);
+ background-color: $toolbarBackground;
position: relative;
z-index: $toolbarZ;
height: 100%;
diff --git a/css/_variables.scss b/css/_variables.scss
index 0c8a54d33..7e0ec2c19 100644
--- a/css/_variables.scss
+++ b/css/_variables.scss
@@ -27,6 +27,7 @@ $defaultBackground: #474747;
$tooltipBg: rgba(0,0,0, 0.7);
// Toolbar
+$toolbarBackground: rgba(0, 0, 0, 0.5);
$toolbarSelectBackground: rgba(0, 0, 0, .6);
$toolbarBadgeBackground: #165ECC;
$toolbarBadgeColor: #FFFFFF;
@@ -46,6 +47,8 @@ $dominantSpeakerBg: #165ecc;
$raiseHandBg: #D6D61E;
$audioLevelBg: #44A5FF;
$audioLevelShadow: rgba(9, 36, 77, 0.9);
+$videoStateIndicatorColor: $defaultColor;
+$videoStateIndicatorBackground: $toolbarBackground;
/**
* Feedback Modal
@@ -84,8 +87,9 @@ $sidebarWidth: 200px;
*/
$tooltipsZ: 901;
$toolbarZ: 900;
-$overlayZ: 800;
+$overlayZ: 902;
$notificationZ: 1012;
+$ringingZ: 800;
/**
* Font Colors TODO: Change colors when general dialogs are implemented.
@@ -106,6 +110,6 @@ $linkHoverFontColor: #287ade;
/**
* Forms
*/
-$inputBg: #505F79;
-$inputBgHover: #505F79;
-$inputFontColor: #ECEEF1;
\ No newline at end of file
+$inputBg: $inputSemiBackground;
+$inputBgHover: $inputSemiBackground;
+$inputFontColor: $defaultDarkFontColor;
\ No newline at end of file
diff --git a/css/_videolayout_default.scss b/css/_videolayout_default.scss
index 71879a7a8..9333db78c 100644
--- a/css/_videolayout_default.scss
+++ b/css/_videolayout_default.scss
@@ -511,7 +511,7 @@
display: none;
position: absolute;
width: auto;
- z-index: 1011;
+ z-index: 2;
font-weight: 600;
font-size: 14px;
text-align: center;
@@ -534,7 +534,7 @@
position: absolute;
width: 100%;
top:50%;
- z-index: 1011;
+ z-index: 2;
font-weight: 600;
font-size: 14px;
text-align: center;
@@ -546,47 +546,43 @@
0px 0px 1px rgba(0,0,0,0.3);
}
-#videoResolutionLabel {
- display: none;
- position: absolute;
- top: 5px;
- right: 5px;
- background: rgba(0,0,0,.5);
- padding: 10px;
- color: rgba(255,255,255,.5);
- z-index: 1011;
+.video-state-indicator {
+ background: $videoStateIndicatorBackground;
+ color: $videoStateIndicatorColor;
+ font-size: 13px;
+ line-height: 20px;
+ text-align: center;
+ min-width: 40px;
+ height: 40px;
+ padding: 10px 5px;
border-radius: 50%;
+ position: absolute;
+ box-sizing: border-box;
+}
+
+#videoResolutionLabel,
+.centeredVideoLabel {
+ display: none;
+ z-index: 1011;
}
.centeredVideoLabel {
- display: none;
- position: absolute;
bottom: 45%;
- top: auto;
- right: auto;
- left: auto;
- line-height: 28px;
- height: 28px;
- width: auto;
- padding: 5px;
- margin-right: auto;
- margin-left: auto;
- background: rgba(0,0,0,.5);
- color: #FFF;
- z-index: 1011;
border-radius: 2px;
-webkit-transition: all 2s 2s linear;
transition: all 2s 2s linear;
+
+ &.moveToCorner {
+ bottom: auto;
+ }
}
.moveToCorner {
- top: 5px;
- right: 50px; /*leave free space for the HD label*/
- margin-right: 0px;
- margin-left: auto;
- background: rgba(0,0,0,.3);
- color: rgba(255,255,255,.5);
+ position: absolute;
+ top: 30px;
+ right: 30px;
}
-.hidden {
-}
+.moveToCorner + .moveToCorner {
+ right: 80px;
+}
\ No newline at end of file
diff --git a/css/aui-components/dropdown.scss b/css/aui-components/dropdown.scss
index 930cfebe0..1ef7a531c 100644
--- a/css/aui-components/dropdown.scss
+++ b/css/aui-components/dropdown.scss
@@ -3,6 +3,10 @@ form.aui {
background-color: transparent;
> a {
+ background-color: $inputBg !important;
+ color: $inputFontColor !important;
+ border-color: $inputBg !important;
+ text-shadow: none !important;
margin: 0 auto !important;
width: 100% !important;
}
@@ -32,17 +36,7 @@ form.aui {
z-index: 900;
}
-//Dark theme
-form.aui{
- //Placeholder
- .aui-select2-container.input-container-dark {
- a.select2-choice {
- text-shadow: none;
- }
- }
-}
-
.aui-dropdown2.aui-style-default.dropdown-dark {
background-color: $defaultBackground;
border-color: transparent;
-}
+}
\ No newline at end of file
diff --git a/css/main.scss b/css/main.scss
index c65ff91d9..7fb71d2df 100644
--- a/css/main.scss
+++ b/css/main.scss
@@ -38,6 +38,7 @@
@import 'toastr';
@import 'base';
@import 'overlay/overlay';
+@import 'reload_overlay/reload_overlay';
@import 'modals/dialog';
@import 'modals/feedback/feedback';
@import 'videolayout_default';
diff --git a/css/overlay/_overlay.scss b/css/overlay/_overlay.scss
index f440b5ab2..3152c460f 100644
--- a/css/overlay/_overlay.scss
+++ b/css/overlay/_overlay.scss
@@ -1,48 +1,30 @@
-.overlay {
- position: fixed;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- z-index: $overlayZ;
- background: #21B9FC; /* Old browsers */
- opacity: 0.75;
- display: block;
-}
-
-.overlay_transparent {
- background: rgba(22, 185, 252, .9);
-}
-
.overlay_container {
+ top: 0;
+ left: 0;
width: 100%;
height: 100%;
position: fixed;
z-index: $overlayZ;
+ background: rgba(22, 185, 252, .9);
}
.overlay_content {
color: #fff;
- font-weight: normal;
- font-size: 20px;
text-align: center;
width: 400px;
height: 250px;
top: 50%;
left: 50%;
- position:absolute;
+ position: absolute;
margin-top: -125px;
margin-left: -200px;
}
-
.overlay_text_small {
+ display: block;
font-size: 18px;
}
.overlay_icon {
- position: relative;
- z-index: 1013;
- float: none;
font-size: 100px;
}
diff --git a/css/reload_overlay/_reload_overlay.scss b/css/reload_overlay/_reload_overlay.scss
new file mode 100644
index 000000000..15c8fdbd4
--- /dev/null
+++ b/css/reload_overlay/_reload_overlay.scss
@@ -0,0 +1,17 @@
+.reload_overlay_title {
+ display: block;
+ font-size: 16px;
+ line-height: 20px;
+}
+
+.reload_overlay_msg {
+ display: block;
+ font-size: 12px;
+ line-height: 30px;
+}
+
+#reloadProgressBar {
+ width: 180px;
+ margin: 5px auto;
+}
+
diff --git a/css/ringing/_ringing.scss b/css/ringing/_ringing.scss
index b973bd41a..b04093a78 100644
--- a/css/ringing/_ringing.scss
+++ b/css/ringing/_ringing.scss
@@ -5,7 +5,7 @@
width: 100%;
height: 100%;
position: fixed;
- z-index: $overlayZ;
+ z-index: $ringingZ;
background: linear-gradient(transparent, #000);
opacity: 0.8;
diff --git a/index.html b/index.html
index 2e1be2b35..3426833d3 100644
--- a/index.html
+++ b/index.html
@@ -240,8 +240,8 @@
- HD
-
+ HD
+
diff --git a/lang/main.json b/lang/main.json
index 860483b3d..95f1b6e1b 100644
--- a/lang/main.json
+++ b/lang/main.json
@@ -204,8 +204,9 @@
"detectext": "Error when trying to detect desktopsharing extension.",
"failtoinstall": "Failed to install desktop sharing extension",
"failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.",
- "bridgeUnavailable": "Jitsi Videobridge is currently unavailable. Please try again later!",
- "jicofoUnavailable": "Jicofo is currently unavailable. Please try again later!",
+ "conferenceReloadTitle": "Unfortunately, something went wrong",
+ "conferenceReloadMsg": "We're trying to fix this",
+ "conferenceReloadTimeLeft": "__seconds__ sec.",
"maxUsersLimitReached": "The limit for maximum number of participants in the conference has been reached. The conference is full. Please try again later!",
"lockTitle": "Lock failed",
"lockMessage": "Failed to lock the conference.",
diff --git a/modules/UI/UI.js b/modules/UI/UI.js
index b461c1590..74917a5ef 100644
--- a/modules/UI/UI.js
+++ b/modules/UI/UI.js
@@ -14,12 +14,12 @@ import Recording from "./recording/Recording";
import GumPermissionsOverlay
from './gum_overlay/UserMediaPermissionsGuidanceOverlay';
+import PageReloadOverlay from './reload_overlay/PageReloadOverlay';
import VideoLayout from "./videolayout/VideoLayout";
import FilmStrip from "./videolayout/FilmStrip";
import SettingsMenu from "./side_pannels/settings/SettingsMenu";
import Profile from "./side_pannels/profile/Profile";
import Settings from "./../settings/Settings";
-import { reload } from '../util/helpers';
import RingOverlay from "./ring_overlay/RingOverlay";
import UIErrors from './UIErrors';
@@ -189,13 +189,6 @@ UI.notifyConferenceDestroyed = function (reason) {
"dialog.sessTerminated", reason, true, {}, () => false);
};
-/**
- * Notify user that Jitsi Videobridge is not accessible.
- */
- UI.notifyBridgeDown = function () {
- messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
-};
-
/**
* Show chat error.
* @param err the Error
@@ -259,19 +252,6 @@ UI.setLocalRaisedHandStatus = (raisedHandStatus) => {
*/
UI.initConference = function () {
let id = APP.conference.getMyUserId();
-
- // Do not include query parameters in the invite URL
- // "https:" + "//" + "example.com:8888" + "/SomeConference1245"
- var inviteURL = window.location.protocol + "//" +
- window.location.host + window.location.pathname;
-
- this.emitEvent(UIEvents.INVITE_URL_INITIALISED, inviteURL);
-
- // Clean up the URL displayed by the browser
- if (window.history && typeof window.history.replaceState === 'function') {
- window.history.replaceState({}, document.title, inviteURL);
- }
-
// Add myself to the contact list.
UI.ContactList.addContact(id, true);
@@ -1104,22 +1084,11 @@ UI.notifyFocusDisconnected = function (focus, retrySec) {
};
/**
- * Notify user that focus left the conference so page should be reloaded.
+ * Notify the user that the video conferencing service is badly broken and
+ * the page should be reloaded.
*/
-UI.notifyFocusLeft = function () {
- let msg = APP.translation.generateTranslationHTML(
- 'dialog.jicofoUnavailable'
- );
- messageHandler.openDialog(
- 'dialog.serviceUnavailable',
- msg,
- true, // persistent
- [{title: 'retry'}],
- function () {
- reload();
- return false;
- }
- );
+UI.showPageReloadOverlay = function () {
+ PageReloadOverlay.show(15 /* will reload in 15 seconds */);
};
/**
@@ -1447,6 +1416,18 @@ UI.hideRingOverLay = function () {
FilmStrip.toggleFilmStrip(true);
};
+/**
+ * Indicates if any the "top" overlays are currently visible. The check includes
+ * the call overlay, GUM permissions overlay and a page reload overlay.
+ *
+ * @returns {*|boolean} {true} if the overlay is visible, {false} otherwise
+ */
+UI.isOverlayVisible = function () {
+ return RingOverlay.isVisible()
+ || PageReloadOverlay.isVisible()
+ || GumPermissionsOverlay.isVisible();
+};
+
/**
* Indicates if the ring overlay is currently visible.
*
diff --git a/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js b/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js
index db0d977e4..11c9fd2d3 100644
--- a/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js
+++ b/modules/UI/gum_overlay/UserMediaPermissionsGuidanceOverlay.js
@@ -1,29 +1,50 @@
-/* global $, APP */
+/* global */
-let $overlay;
+import Overlay from '../overlay/Overlay';
/**
- * Internal function that constructs overlay with guidance how to proceed with
- * gUM prompt.
- * @param {string} browser - name of browser for which to construct the
- * guidance overlay.
+ * An overlay with guidance how to proceed with gUM prompt.
*/
-function buildOverlayHtml(browser) {
- $overlay = $(`
- `);
+class GUMOverlayImpl extends Overlay {
- APP.translation.translateElement($overlay);
+ /**
+ * Constructs overlay with guidance how to proceed with gUM prompt.
+ * @param {string} browser - name of browser for which to construct the
+ * guidance overlay.
+ * @override
+ */
+ constructor(browser) {
+ super();
+ this.browser = browser;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ _buildOverlayContent() {
+ return `
+
+
+ `;
+ }
}
+/**
+ * Stores GUM overlay instance.
+ * @type {GUMOverlayImpl}
+ */
+let overlay;
+
export default {
+ /**
+ * Checks whether the overlay is currently visible.
+ * @return {boolean} true if the overlay is visible
+ * or false otherwise.
+ */
+ isVisible () {
+ return overlay && overlay.isVisible();
+ },
/**
* Shows browser-specific overlay with guidance how to proceed with
* gUM prompt.
@@ -31,9 +52,10 @@ export default {
* guidance overlay.
*/
show(browser) {
- !$overlay && buildOverlayHtml(browser);
-
- !$overlay.parents('body').length && $overlay.appendTo('body');
+ if (!overlay) {
+ overlay = new GUMOverlayImpl(browser);
+ }
+ overlay.show();
},
/**
@@ -41,6 +63,6 @@ export default {
* gUM prompt.
*/
hide() {
- $overlay && $overlay.detach();
+ overlay && overlay.hide();
}
};
diff --git a/modules/UI/invite/Invite.js b/modules/UI/invite/Invite.js
index e71b1340d..23ebd79ef 100644
--- a/modules/UI/invite/Invite.js
+++ b/modules/UI/invite/Invite.js
@@ -14,6 +14,7 @@ const ConferenceEvents = JitsiMeetJS.events.conference;
class Invite {
constructor(conference) {
this.conference = conference;
+ this.inviteUrl = APP.ConferenceUrl.getInviteUrl();
this.createRoomLocker(conference);
this.registerListeners();
}
@@ -48,11 +49,6 @@ class Invite {
APP.UI.addListener( UIEvents.INVITE_CLICKED,
() => { this.openLinkDialog(); });
- APP.UI.addListener( UIEvents.INVITE_URL_INITIALISED,
- (inviteUrl) => {
- this.updateInviteUrl(inviteUrl);
- });
-
APP.UI.addListener( UIEvents.PASSWORD_REQUIRED,
() => {
this.setLockedFromElsewhere(true);
@@ -172,14 +168,6 @@ class Invite {
}
}
- /**
- * Updates the room invite url.
- */
- updateInviteUrl (newInviteUrl) {
- this.inviteUrl = newInviteUrl;
- this.updateView();
- }
-
/**
* Helper method for encoding
* Invite URL
diff --git a/modules/UI/overlay/Overlay.js b/modules/UI/overlay/Overlay.js
new file mode 100644
index 000000000..babdc587a
--- /dev/null
+++ b/modules/UI/overlay/Overlay.js
@@ -0,0 +1,82 @@
+/* global $, APP */
+
+/**
+ * Base class for overlay components - the components which are displayed on
+ * top of the application with semi-transparent background covering the whole
+ * screen.
+ */
+export default class Overlay{
+ /**
+ * Creates new Overlay instance.
+ */
+ constructor() {
+ /**
+ *
+ * @type {jQuery}
+ */
+ this.$overlay = null;
+ }
+ /**
+ * Template method which should be used by subclasses to provide the overlay
+ * content. The contents provided by this method are later subject to
+ * the translation using {@link APP.translation.translateElement}.
+ * @return {string} HTML representation of the overlay dialog contents.
+ * @private
+ */
+ _buildOverlayContent() {
+ return '';
+ }
+ /**
+ * Constructs the HTML body of the overlay dialog.
+ */
+ buildOverlayHtml() {
+
+ let overlayContent = this._buildOverlayContent();
+
+ this.$overlay = $(`
+
+
+ ${overlayContent}
+
+
`);
+
+ APP.translation.translateElement(this.$overlay);
+ }
+ /**
+ * Checks whether the page reload overlay has been displayed.
+ * @return {boolean} true if the page reload overlay is currently
+ * visible or false otherwise.
+ */
+ isVisible() {
+ return this.$overlay && this.$overlay.parents('body').length > 0;
+ }
+ /**
+ * Template method called just after the overlay is displayed for the first
+ * time.
+ * @private
+ */
+ _onShow() {
+ // To be overridden by subclasses.
+ }
+ /**
+ * Shows the overlay dialog adn attaches the underlying HTML representation
+ * to the DOM.
+ */
+ show() {
+
+ !this.$overlay && this.buildOverlayHtml();
+
+ if (!this.isVisible()) {
+ this.$overlay.appendTo('body');
+ this._onShow();
+ }
+ }
+
+ /**
+ * Hides the overlay dialog and detaches it's HTML representation from
+ * the DOM.
+ */
+ hide() {
+ this.$overlay && this.$overlay.detach();
+ }
+}
diff --git a/modules/UI/reload_overlay/PageReloadOverlay.js b/modules/UI/reload_overlay/PageReloadOverlay.js
new file mode 100644
index 000000000..bcc225491
--- /dev/null
+++ b/modules/UI/reload_overlay/PageReloadOverlay.js
@@ -0,0 +1,121 @@
+/* global $, APP, AJS */
+
+import Overlay from '../overlay/Overlay';
+
+/**
+ * An overlay dialog which is shown before the conference is reloaded. Shows
+ * a warning message and counts down towards the reload.
+ */
+class PageReloadOverlayImpl extends Overlay{
+ /**
+ * Creates new PageReloadOverlayImpl
+ * @param {number} timeoutSeconds how long the overlay dialog will be
+ * displayed, before the conference will be reloaded.
+ */
+ constructor(timeoutSeconds) {
+ super();
+ /**
+ * Conference reload counter in seconds.
+ * @type {number}
+ */
+ this.timeLeft = timeoutSeconds;
+ /**
+ * Conference reload timeout in seconds.
+ * @type {number}
+ */
+ this.timeout = timeoutSeconds;
+ }
+ /**
+ * Constructs overlay body with the warning message and count down towards
+ * the conference reload.
+ * @override
+ */
+ _buildOverlayContent() {
+ return `
+
+
+ `;
+ }
+
+ /**
+ * Updates the progress indicator position and the label with the time left.
+ */
+ updateDisplay() {
+
+ APP.translation.translateElement(
+ $("#reloadSecRemaining"), { seconds: this.timeLeft });
+
+ const ratio = (this.timeout - this.timeLeft) / this.timeout;
+ AJS.progressBars.update("#reloadProgressBar", ratio);
+ }
+
+ /**
+ * Starts the reload countdown with the animation.
+ * @override
+ */
+ _onShow() {
+
+ // Initialize displays
+ this.updateDisplay();
+
+ var intervalId = window.setInterval(function() {
+
+ if (this.timeLeft >= 1) {
+ this.timeLeft -= 1;
+ }
+
+ this.updateDisplay();
+
+ if (this.timeLeft === 0) {
+ window.clearInterval(intervalId);
+ APP.ConferenceUrl.reload();
+ }
+ }.bind(this), 1000);
+
+ console.info(
+ "The conference will be reloaded after "
+ + this.timeLeft + " seconds.");
+ }
+}
+
+/**
+ * Holds the page reload overlay instance.
+ *
+ * {@type PageReloadOverlayImpl}
+ */
+let overlay;
+
+export default {
+ /**
+ * Checks whether the page reload overlay has been displayed.
+ * @return {boolean} true if the page reload overlay is currently
+ * visible or false otherwise.
+ */
+ isVisible() {
+ return overlay && overlay.isVisible();
+ },
+ /**
+ * Shows the page reload overlay which will do the conference reload after
+ * the given amount of time.
+ *
+ * @param {number} timeoutSeconds how many seconds before the conference
+ * reload will happen.
+ */
+ show(timeoutSeconds) {
+
+ if (!overlay) {
+ overlay = new PageReloadOverlayImpl(timeoutSeconds);
+ }
+ overlay.show();
+ }
+};
diff --git a/modules/UI/toolbars/ToolbarToggler.js b/modules/UI/toolbars/ToolbarToggler.js
index c353d898e..05ff316fb 100644
--- a/modules/UI/toolbars/ToolbarToggler.js
+++ b/modules/UI/toolbars/ToolbarToggler.js
@@ -34,9 +34,10 @@ function hideToolbar(force) { // eslint-disable-line no-unused-vars
clearTimeout(toolbarTimeoutObject);
toolbarTimeoutObject = null;
- if (Toolbar.isHovered()
- || APP.UI.isRingOverlayVisible()
- || SideContainerToggler.isVisible()) {
+ if (force !== true &&
+ (Toolbar.isHovered()
+ || APP.UI.isRingOverlayVisible()
+ || SideContainerToggler.isVisible())) {
toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout);
} else {
Toolbar.hide();
diff --git a/modules/UI/util/MessageHandler.js b/modules/UI/util/MessageHandler.js
index 114418a75..fcc3b008e 100644
--- a/modules/UI/util/MessageHandler.js
+++ b/modules/UI/util/MessageHandler.js
@@ -326,7 +326,7 @@ var messageHandler = {
messageArguments, options) {
// If we're in ringing state we skip all toaster notifications.
- if(!notificationsEnabled || APP.UI.isRingOverlayVisible())
+ if(!notificationsEnabled || APP.UI.isOverlayVisible())
return;
var displayNameSpan = '