jiti-meet/modules/UI/UI.js

723 lines
19 KiB
JavaScript
Raw Normal View History

/* global APP, $, config, interfaceConfig */
const logger = require('jitsi-meet-logger').getLogger(__filename);
2016-11-11 15:00:54 +00:00
const UI = {};
2015-01-07 14:54:03 +00:00
import messageHandler from './util/MessageHandler';
import UIUtil from './util/UIUtil';
import UIEvents from '../../service/UI/UIEvents';
2015-12-25 16:55:45 +00:00
import EtherpadManager from './etherpad/Etherpad';
import SharedVideoManager from './shared_video/SharedVideo';
2015-12-14 12:26:50 +00:00
import VideoLayout from './videolayout/VideoLayout';
2015-12-14 12:26:50 +00:00
import { getLocalParticipant } from '../../react/features/base/participants';
import { toggleChat } from '../../react/features/chat';
import { setDocumentUrl } from '../../react/features/etherpad';
import { setFilmstripVisible } from '../../react/features/filmstrip';
import { joinLeaveNotificationsDisabled, setNotificationsEnabled } from '../../react/features/notifications';
2017-02-16 23:02:40 +00:00
import {
2017-04-01 05:52:40 +00:00
dockToolbox,
feat(recording): frontend logic can support live streaming and recording (#2952) * feat(recording): frontend logic can support live streaming and recording Instead of either live streaming or recording, now both can live together. The changes to facilitate such include the following: - Killing the state storing in Recording.js. Instead state is stored in the lib and updated in redux for labels to display the necessary state updates. - Creating a new container, Labels, for recording labels. Previously labels were manually created and positioned. The container can create a reasonable number of labels and only the container itself needs to be positioned with CSS. The VideoQualityLabel has been shoved into the container as well because it moves along with the recording labels. - The action for updating recording state has been modified to enable updating an array of recording sessions to support having multiple sessions. - Confirmation dialogs for stopping and starting a file recording session have been created, as they previously were jquery modals opened by Recording.js. - Toolbox.web displays live streaming and recording buttons based on configuration instead of recording availability. - VideoQualityLabel and RecordingLabel have been simplified to remove any positioning logic, as the Labels container handles such. - Previous recording state update logic has been moved into the RecordingLabel component. Each RecordingLabel is in charge of displaying state for a recording session. The display UX has been left alone. - Sipgw availability is no longer broadcast so remove logic depending on its state. Some moving around of code was necessary to get around linting errors about the existing code being too deeply nested (even though I didn't touch it). * work around lib-jitsi-meet circular dependency issues * refactor labels to use html base * pass in translation keys to video quality label * add video quality classnames for torture tests * break up, rearrange recorder session update listener * add comment about disabling startup resize animation * rename session to sessionData * chore(deps): update to latest lib for recording changes
2018-05-16 14:00:16 +00:00
setToolboxEnabled,
2017-04-01 05:52:40 +00:00
showToolbox
} from '../../react/features/toolbox';
2017-02-16 23:02:40 +00:00
const EventEmitter = require('events');
UI.messageHandler = messageHandler;
const eventEmitter = new EventEmitter();
2015-12-03 13:11:01 +00:00
UI.eventEmitter = eventEmitter;
2015-01-07 14:54:03 +00:00
2015-12-25 16:55:45 +00:00
let etherpadManager;
let sharedVideoManager;
2015-12-25 16:55:45 +00:00
const UIListeners = new Map([
[
UIEvents.ETHERPAD_CLICKED,
() => etherpadManager && etherpadManager.toggleEtherpad()
], [
UIEvents.SHARED_VIDEO_CLICKED,
() => sharedVideoManager && sharedVideoManager.toggleSharedVideo()
], [
UIEvents.TOGGLE_FILMSTRIP,
() => UI.toggleFilmstrip()
]
]);
2016-05-26 08:53:02 +00:00
Restructures the analytics events (#2333) * ref: Restructures the pinned/unpinned events. * ref: Refactors the "audio only disabled" event. * ref: Refactors the "stream switch delay" event. * ref: Refactors the "select participant failed" event. * ref: Refactors the "initially muted" events. * ref: Refactors the screen sharing started/stopped events. * ref: Restructures the "device list changed" events. * ref: Restructures the "shared video" events. * ref: Restructures the "start muted" events. * ref: Restructures the "start audio only" event. * ref: Restructures the "sync track state" event. * ref: Restructures the "callkit" events. * ref: Restructures the "replace track". * ref: Restructures keyboard shortcuts events. * ref: Restructures most of the toolbar events. * ref: Refactors the API events. * ref: Restructures the video quality, profile button and invite dialog events. * ref: Refactors the "device changed" events. * ref: Refactors the page reload event. * ref: Removes an unused function. * ref: Removes a method which is needlessly exposed under a different name. * ref: Refactors the events from the remote video menu. * ref: Refactors the events from the profile pane. * ref: Restructures the recording-related events. Removes events fired when recording with something other than jibri (which isn't currently supported anyway). * ref: Cleans up AnalyticsEvents.js. * ref: Removes an unused function and adds documentation. * feat: Adds events for all API calls. * fix: Addresses feedback. * fix: Brings back mistakenly removed code. * fix: Simplifies code and fixes a bug in toggleFilmstrip when the 'visible' parameter is defined. * feat: Removes the resolution change application log. * ref: Uses consistent naming for events' attributes. Uses "_" as a separator instead of camel case or ".". * ref: Don't add the user agent and conference name as permanent properties. The library does this on its own now. * ref: Adapts the GA handler to changes in lib-jitsi-meet. * ref: Removes unused fields from the analytics handler initializaiton. * ref: Renames the google analytics file and add docs. * fix: Fixes the push-to-talk events and logs. * npm: Updates lib-jitsi-meet to 515374c8d383cb17df8ed76427e6f0fb5ea6ff1e. * fix: Fixes a recently introduced bug in the google analytics handler. * ref: Uses "value" instead of "delay" since this is friendlier to GA.
2018-01-03 21:24:07 +00:00
/**
* Indicates if we're currently in full screen mode.
*
* @return {boolean} {true} to indicate that we're currently in full screen
* mode, {false} otherwise
*/
UI.isFullScreen = function() {
return UIUtil.isFullScreen();
};
/**
* Returns true if the etherpad window is currently visible.
* @returns {Boolean} - true if the etherpad window is currently visible.
*/
UI.isEtherpadVisible = function() {
return Boolean(etherpadManager && etherpadManager.isVisible());
};
/**
* Returns true if there is a shared video which is being shown (?).
* @returns {boolean} - true if there is a shared video which is being shown.
*/
UI.isSharedVideoShown = function() {
return Boolean(sharedVideoManager && sharedVideoManager.isSharedVideoShown);
};
2016-01-15 14:59:35 +00:00
/**
* Notify user that server has shut down.
*/
UI.notifyGracefulShutdown = function() {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
descriptionKey: 'dialog.gracefulShutdown',
titleKey: 'dialog.serviceUnavailable'
});
2015-11-30 15:24:42 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Notify user that reservation error happened.
*/
UI.notifyReservationError = function(code, msg) {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
descriptionArguments: {
code,
msg
},
descriptionKey: 'dialog.reservationErrorMsg',
titleKey: 'dialog.reservationError'
});
2015-11-30 15:24:42 +00:00
};
2016-01-25 22:39:05 +00:00
/**
* Notify user that conference was destroyed.
* @param reason {string} the reason text
*/
UI.notifyConferenceDestroyed = function(reason) {
// FIXME: use Session Terminated from translation, but
2016-01-25 22:39:05 +00:00
// 'reason' text comes from XMPP packet and is not translated
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
description: reason,
titleKey: 'dialog.sessTerminated'
});
2016-01-25 22:39:05 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Change nickname for the user.
* @param {string} id user id
* @param {string} displayName new nickname
*/
UI.changeDisplayName = function(id, displayName) {
2015-12-01 13:41:58 +00:00
VideoLayout.onDisplayNameChanged(id, displayName);
2015-11-30 15:24:42 +00:00
};
2016-06-20 21:13:17 +00:00
/**
* Initialize conference UI.
2016-01-15 14:59:35 +00:00
*/
UI.initConference = function() {
const { getState } = APP.store;
const { id, name } = getLocalParticipant(getState);
UI.showToolbar();
const displayName = config.displayJids ? id : name;
2015-11-30 15:24:42 +00:00
if (displayName) {
UI.changeDisplayName('localVideoContainer', displayName);
}
};
/**
* Returns the shared document manager object.
* @return {EtherpadManager} the shared document manager object
*/
UI.getSharedVideoManager = function() {
return sharedVideoManager;
};
/**
* Starts the UI module and initializes all related components.
*
* @returns {boolean} true if the UI is ready and the conference should be
2017-05-26 16:28:14 +00:00
* established, false - otherwise (for example in the case of welcome page)
*/
UI.start = function() {
2015-01-07 14:54:03 +00:00
// Set the defaults for prompt dialogs.
$.prompt.setDefaults({ persistent: false });
2015-01-07 14:54:03 +00:00
VideoLayout.init(eventEmitter);
2015-12-25 16:55:45 +00:00
if (!interfaceConfig.filmStripOnly) {
VideoLayout.initLargeVideo();
2015-12-25 16:55:45 +00:00
}
feat(recording): frontend logic can support live streaming and recording (#2952) * feat(recording): frontend logic can support live streaming and recording Instead of either live streaming or recording, now both can live together. The changes to facilitate such include the following: - Killing the state storing in Recording.js. Instead state is stored in the lib and updated in redux for labels to display the necessary state updates. - Creating a new container, Labels, for recording labels. Previously labels were manually created and positioned. The container can create a reasonable number of labels and only the container itself needs to be positioned with CSS. The VideoQualityLabel has been shoved into the container as well because it moves along with the recording labels. - The action for updating recording state has been modified to enable updating an array of recording sessions to support having multiple sessions. - Confirmation dialogs for stopping and starting a file recording session have been created, as they previously were jquery modals opened by Recording.js. - Toolbox.web displays live streaming and recording buttons based on configuration instead of recording availability. - VideoQualityLabel and RecordingLabel have been simplified to remove any positioning logic, as the Labels container handles such. - Previous recording state update logic has been moved into the RecordingLabel component. Each RecordingLabel is in charge of displaying state for a recording session. The display UX has been left alone. - Sipgw availability is no longer broadcast so remove logic depending on its state. Some moving around of code was necessary to get around linting errors about the existing code being too deeply nested (even though I didn't touch it). * work around lib-jitsi-meet circular dependency issues * refactor labels to use html base * pass in translation keys to video quality label * add video quality classnames for torture tests * break up, rearrange recorder session update listener * add comment about disabling startup resize animation * rename session to sessionData * chore(deps): update to latest lib for recording changes
2018-05-16 14:00:16 +00:00
// Do not animate the video area on UI start (second argument passed into
// resizeVideoArea) because the animation is not visible anyway. Plus with
// the current dom layout, the quality label is part of the video layout and
// will be seen animating in.
VideoLayout.resizeVideoArea();
2015-12-25 16:55:45 +00:00
sharedVideoManager = new SharedVideoManager(eventEmitter);
if (interfaceConfig.filmStripOnly) {
$('body').addClass('filmstrip-only');
APP.store.dispatch(setNotificationsEnabled(false));
} else if (config.iAmRecorder) {
// in case of iAmSipGateway keep local video visible
if (!config.iAmSipGateway) {
VideoLayout.setLocalVideoVisible(false);
APP.store.dispatch(setNotificationsEnabled(false));
feat(recording): frontend logic can support live streaming and recording (#2952) * feat(recording): frontend logic can support live streaming and recording Instead of either live streaming or recording, now both can live together. The changes to facilitate such include the following: - Killing the state storing in Recording.js. Instead state is stored in the lib and updated in redux for labels to display the necessary state updates. - Creating a new container, Labels, for recording labels. Previously labels were manually created and positioned. The container can create a reasonable number of labels and only the container itself needs to be positioned with CSS. The VideoQualityLabel has been shoved into the container as well because it moves along with the recording labels. - The action for updating recording state has been modified to enable updating an array of recording sessions to support having multiple sessions. - Confirmation dialogs for stopping and starting a file recording session have been created, as they previously were jquery modals opened by Recording.js. - Toolbox.web displays live streaming and recording buttons based on configuration instead of recording availability. - VideoQualityLabel and RecordingLabel have been simplified to remove any positioning logic, as the Labels container handles such. - Previous recording state update logic has been moved into the RecordingLabel component. Each RecordingLabel is in charge of displaying state for a recording session. The display UX has been left alone. - Sipgw availability is no longer broadcast so remove logic depending on its state. Some moving around of code was necessary to get around linting errors about the existing code being too deeply nested (even though I didn't touch it). * work around lib-jitsi-meet circular dependency issues * refactor labels to use html base * pass in translation keys to video quality label * add video quality classnames for torture tests * break up, rearrange recorder session update listener * add comment about disabling startup resize animation * rename session to sessionData * chore(deps): update to latest lib for recording changes
2018-05-16 14:00:16 +00:00
}
2015-01-22 16:02:37 +00:00
APP.store.dispatch(setToolboxEnabled(false));
UI.messageHandler.enablePopups(false);
}
};
2016-06-13 21:11:44 +00:00
/**
* Setup some UI event listeners.
*/
UI.registerListeners
= () => UIListeners.forEach((value, key) => UI.addListener(key, value));
/**
* Setup some DOM event listeners.
*/
UI.bindEvents = () => {
/**
*
*/
function onResize() {
VideoLayout.onResize();
}
// Resize and reposition videos in full screen mode.
$(document).on(
'webkitfullscreenchange mozfullscreenchange fullscreenchange',
onResize);
$(window).resize(onResize);
};
/**
* Unbind some DOM event listeners.
*/
UI.unbindEvents = () => {
$(document).off(
'webkitfullscreenchange mozfullscreenchange fullscreenchange');
$(window).off('resize');
2015-01-07 14:54:03 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Show local video stream on UI.
2016-01-15 14:59:35 +00:00
* @param {JitsiTrack} track stream to show
*/
UI.addLocalVideoStream = track => {
VideoLayout.changeLocalVideo(track);
2015-11-30 11:54:54 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Setup and show Etherpad.
* @param {string} name etherpad id
*/
UI.initEtherpad = name => {
2015-12-30 20:57:28 +00:00
if (etherpadManager || !config.etherpad_base || !name) {
2015-12-25 16:55:45 +00:00
return;
}
2016-11-11 15:00:54 +00:00
logger.log('Etherpad is enabled');
2017-02-16 23:02:40 +00:00
etherpadManager = new EtherpadManager(eventEmitter);
const url = new URL(name, config.etherpad_base);
APP.store.dispatch(setDocumentUrl(url.toString()));
2015-12-25 16:55:45 +00:00
};
2015-01-07 14:54:03 +00:00
/**
* Returns the shared document manager object.
* @return {EtherpadManager} the shared document manager object
*/
UI.getSharedDocumentManager = () => etherpadManager;
2016-01-15 14:59:35 +00:00
/**
* Show user on UI.
* @param {JitsiParticipant} user
2016-01-15 14:59:35 +00:00
*/
UI.addUser = function(user) {
const id = user.getId();
const displayName = user.getDisplayName();
const status = user.getStatus();
if (status) {
// FIXME: move updateUserStatus in participantPresenceChanged action
UI.updateUserStatus(user, status);
}
2015-01-07 14:54:03 +00:00
// set initial display name
if (displayName) {
UI.changeDisplayName(id, displayName);
}
2015-11-30 15:24:42 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Update videotype for specified user.
* @param {string} id user id
* @param {string} newVideoType new videotype
*/
UI.onPeerVideoTypeChanged
= (id, newVideoType) => VideoLayout.onVideoTypeChanged(id, newVideoType);
2017-05-19 15:12:24 +00:00
/**
* Updates the user status.
*
* @param {JitsiParticipant} user - The user which status we need to update.
* @param {string} status - The new status.
*/
UI.updateUserStatus = (user, status) => {
2018-06-26 22:56:22 +00:00
const reduxState = APP.store.getState() || {};
const { calleeInfoVisible } = reduxState['features/invite'] || {};
// We hide status updates when join/leave notifications are disabled,
// as jigasi is the component with statuses and they are seen as join/leave notifications.
if (!status || calleeInfoVisible || joinLeaveNotificationsDisabled()) {
return;
}
const displayName = user.getDisplayName();
messageHandler.participantNotification(
displayName,
'',
'connected',
'dialOut.statusMessage',
{ status: UIUtil.escapeHtml(status) });
2017-05-19 15:12:24 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Toggles filmstrip.
2016-01-15 14:59:35 +00:00
*/
UI.toggleFilmstrip = function() {
const { visible } = APP.store.getState()['features/filmstrip'];
APP.store.dispatch(setFilmstripVisible(!visible));
2015-01-27 09:56:22 +00:00
};
/**
* Toggles the visibility of the chat panel.
2016-09-11 21:54:32 +00:00
*/
UI.toggleChat = () => APP.store.dispatch(toggleChat());
2016-09-11 21:54:32 +00:00
/**
* Handle new user display name.
*/
UI.inputDisplayNameHandler = function(newDisplayName) {
eventEmitter.emit(UIEvents.NICKNAME_CHANGED, newDisplayName);
2015-01-07 14:54:03 +00:00
};
/**
* Return the type of the remote video.
* @param jid the jid for the remote video
* @returns the video type video or screen.
*/
UI.getRemoteVideoType = function(jid) {
return VideoLayout.getRemoteVideoType(jid);
};
2016-01-15 14:59:35 +00:00
// FIXME check if someone user this
UI.showLoginPopup = function(callback) {
2016-11-11 15:00:54 +00:00
logger.log('password is required');
const message
= `<input name="username" type="text"
2016-11-09 16:46:58 +00:00
placeholder="user@domain.net"
class="input-control" autofocus>
<input name="password" type="password"
data-i18n="[placeholder]dialog.userPassword"
2016-11-09 16:46:58 +00:00
class="input-control"
placeholder="user password">`
;
// eslint-disable-next-line max-params
const submitFunction = (e, v, m, f) => {
if (v && f.username && f.password) {
callback(f.username, f.password);
}
};
messageHandler.openTwoButtonDialog({
titleKey: 'dialog.passwordRequired',
msgString: message,
leftButtonKey: 'dialog.Ok',
submitFunction,
focus: ':input:first'
});
};
UI.askForNickname = function() {
// eslint-disable-next-line no-alert
2015-11-30 15:24:42 +00:00
return window.prompt('Your nickname (optional)');
};
2015-01-07 14:54:03 +00:00
/**
2016-01-06 22:39:13 +00:00
* Sets muted audio state for participant
*/
UI.setAudioMuted = function(id, muted) {
2016-01-06 22:39:13 +00:00
VideoLayout.onAudioMute(id, muted);
if (APP.conference.isLocalId(id)) {
APP.conference.updateAudioIconEnabled();
}
2015-11-30 11:54:54 +00:00
};
2016-01-06 22:39:13 +00:00
/**
* Sets muted video state for participant
*/
UI.setVideoMuted = function(id, muted) {
2016-01-06 22:39:13 +00:00
VideoLayout.onVideoMute(id, muted);
if (APP.conference.isLocalId(id)) {
APP.conference.updateVideoIconEnabled();
}
};
/**
* Triggers an update of remote video and large video displays so they may pick
* up any state changes that have occurred elsewhere.
*
* @returns {void}
*/
UI.updateAllVideos = () => VideoLayout.updateAllVideos();
/**
* Adds a listener that would be notified on the given type of event.
*
* @param type the type of the event we're listening for
* @param listener a function that would be called when notified
*/
UI.addListener = function(type, listener) {
2015-01-22 16:02:37 +00:00
eventEmitter.on(type, listener);
};
2015-01-22 16:02:37 +00:00
/**
* Removes the all listeners for all events.
*
* @returns {void}
*/
UI.removeAllListeners = function() {
eventEmitter.removeAllListeners();
};
/**
* Removes the given listener for the given type of event.
*
* @param type the type of the event we're listening for
* @param listener the listener we want to remove
*/
UI.removeListener = function(type, listener) {
eventEmitter.removeListener(type, listener);
};
2016-09-11 21:54:32 +00:00
/**
* Emits the event of given type by specifying the parameters in options.
*
* @param type the type of the event we're emitting
* @param options the parameters for the event
*/
2017-02-16 23:02:40 +00:00
UI.emitEvent = (type, ...options) => eventEmitter.emit(type, ...options);
2016-09-11 21:54:32 +00:00
2018-11-30 22:13:39 +00:00
UI.clickOnVideo = videoNumber => VideoLayout.togglePin(videoNumber);
2015-01-22 16:26:05 +00:00
2017-04-01 05:52:40 +00:00
// Used by torture.
UI.showToolbar = timeout => APP.store.dispatch(showToolbox(timeout));
2015-02-09 08:12:55 +00:00
2017-04-01 05:52:40 +00:00
// Used by torture.
UI.dockToolbar = dock => APP.store.dispatch(dockToolbox(dock));
2015-02-09 08:12:55 +00:00
/**
* Updates the displayed avatar for participant.
*
* @param {string} id - User id whose avatar should be updated.
* @param {string} avatarURL - The URL to avatar image to display.
* @returns {void}
2016-06-13 21:11:44 +00:00
*/
2019-06-26 14:08:23 +00:00
UI.refreshAvatarDisplay = function(id) {
VideoLayout.changeUserAvatar(id);
2015-11-30 11:54:54 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Notify user that connection failed.
* @param {string} stropheErrorMsg raw Strophe error message
*/
UI.notifyConnectionFailed = function(stropheErrorMsg) {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
let descriptionKey;
let descriptionArguments;
2015-11-30 11:54:54 +00:00
if (stropheErrorMsg) {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
descriptionKey = 'dialog.connectErrorWithMsg';
descriptionArguments = { msg: stropheErrorMsg };
} else {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
descriptionKey = 'dialog.connectError';
}
2015-11-30 11:54:54 +00:00
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
descriptionArguments,
descriptionKey,
titleKey: 'connection.CONNFAIL'
});
};
2016-03-15 19:08:01 +00:00
/**
* Notify user that maximum users limit has been reached.
2016-03-15 19:08:01 +00:00
*/
UI.notifyMaxUsersLimitReached = function() {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
hideErrorSupportLink: true,
descriptionKey: 'dialog.maxUsersLimitReached',
titleKey: 'dialog.maxUsersLimitReachedTitle'
});
};
2016-01-15 14:59:35 +00:00
/**
* Notify user that he was automatically muted when joned the conference.
*/
UI.notifyInitiallyMuted = function() {
messageHandler.participantNotification(
null,
'notify.mutedTitle',
'connected',
'notify.muted',
null);
2015-11-30 11:54:54 +00:00
};
UI.handleLastNEndpoints = function(leavingIds, enteringIds) {
VideoLayout.onLastNEndpointsChanged(leavingIds, enteringIds);
2015-11-30 11:54:54 +00:00
};
2016-01-15 14:59:35 +00:00
/**
* Update audio level visualization for specified user.
* @param {string} id user id
* @param {number} lvl audio level
*/
UI.setAudioLevel = (id, lvl) => VideoLayout.setAudioLevel(id, lvl);
2015-11-30 11:54:54 +00:00
2016-01-15 14:59:35 +00:00
/**
* Hide connection quality statistics from UI.
*/
UI.hideStats = function() {
2015-11-30 11:54:54 +00:00
VideoLayout.hideStats();
};
2015-12-04 14:12:57 +00:00
UI.notifyTokenAuthFailed = function() {
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
messageHandler.showError({
descriptionKey: 'dialog.tokenAuthFailed',
titleKey: 'dialog.tokenAuthFailedTitle'
});
2015-12-17 15:31:11 +00:00
};
ref(notifications): convert some dialogs to error or warning notifica… (#1991) * ref(notifications): convert some dialogs to error or warning notifications - Expand the configurability of the Notification component so warnings and errors can be displayed. - Allow Notification to take in arbitrary text for the body. - Rename defaultTitleKey to titleKey for consistency with descriptionKey. * ref(notifications): remove openReportDialog method openReportDialog is a wrapper around showError that adds a logger statement. It is being called in one place only so remove the method and have that one place call logger. * ref(notifications): UI.showTrackNotWorkingDialog takes a boolean Change UI.showTrackNotWorkingDialog so it takes a boolean arguments instead of the entire track. A small refactor so the method needs to know less. * [squash] Fixes eslint errors * WiP: Fixes desktop sharing error strings and adds support button * [squash] Fix icons appearances * [squash] Fix translate titles and messages * [squash] fix(translation): Fixes incorrect password string * [squash] fix(recording): Fixes recording message * [squash] fix(warning): Turns some warnings to errors and makes support link optional. * [squash] fix(translation): Addressing language comments * [squash] Fixes jsdoc and formatting * [squash] fix(noopener): Fixes window.open noopener * [squash] fix(constants): Extract constants and refactor NotificationWithToggle * [squash] fix(lang): Fixes camera and mic error titles * [squash] fix(supportLink): Renames addSupportLink to hideErrorSupportLink
2017-11-03 19:05:03 +00:00
UI.notifyInternalError = function(error) {
messageHandler.showError({
descriptionArguments: { error },
descriptionKey: 'dialog.internalError',
titleKey: 'dialog.internalErrorTitle'
});
2016-01-25 22:39:05 +00:00
};
UI.notifyFocusDisconnected = function(focus, retrySec) {
messageHandler.participantNotification(
null, 'notify.focus',
'disconnected', 'notify.focusFail',
{ component: focus,
ms: retrySec }
2016-01-25 22:39:05 +00:00
);
};
2016-09-16 05:17:27 +00:00
/**
* Notifies interested listeners that the raise hand property has changed.
*
* @param {boolean} isRaisedHand indicates the current state of the
* "raised hand"
*/
UI.onLocalRaiseHandChanged = function(isRaisedHand) {
eventEmitter.emit(UIEvents.LOCAL_RAISE_HAND_CHANGED, isRaisedHand);
2016-09-16 05:09:26 +00:00
};
/**
* Update list of available physical devices.
*/
UI.onAvailableDevicesChanged = function() {
APP.conference.updateAudioIconEnabled();
APP.conference.updateVideoIconEnabled();
2016-05-26 08:53:02 +00:00
};
/**
* Returns the id of the current video shown on large.
2016-01-15 14:59:35 +00:00
* Currently used by tests (torture).
*/
UI.getLargeVideoID = function() {
return VideoLayout.getLargeVideoID();
};
/**
* Returns the current video shown on large.
* Currently used by tests (torture).
*/
UI.getLargeVideo = function() {
return VideoLayout.getLargeVideo();
};
/**
* Shows "Please go to chrome webstore to install the desktop sharing extension"
* 2 button dialog with buttons - cancel and go to web store.
* @param url {string} the url of the extension.
*/
UI.showExtensionExternalInstallationDialog = function(url) {
let openedWindow = null;
const submitFunction = function(e, v) {
if (v) {
e.preventDefault();
if (openedWindow === null || openedWindow.closed) {
openedWindow
= window.open(
url,
'extension_store_window',
'resizable,scrollbars=yes,status=1');
} else {
openedWindow.focus();
}
}
};
const closeFunction = function(e, v) {
if (openedWindow) {
// Ideally we would close the popup, but this does not seem to work
// on Chrome. Leaving it uncommented in case it could work
// in some version.
openedWindow.close();
openedWindow = null;
}
if (!v) {
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
}
};
messageHandler.openTwoButtonDialog({
titleKey: 'dialog.externalInstallationTitle',
msgKey: 'dialog.externalInstallationMsg',
leftButtonKey: 'dialog.goToStore',
submitFunction,
loadedFunction: $.noop,
closeFunction
});
};
/**
* Shows a dialog which asks user to install the extension. This one is
* displayed after installation is triggered from the script, but fails because
* it must be initiated by user gesture.
* @param callback {function} function to be executed after user clicks
* the install button - it should make another attempt to install the extension.
*/
UI.showExtensionInlineInstallationDialog = function(callback) {
const submitFunction = function(e, v) {
if (v) {
callback();
}
};
const closeFunction = function(e, v) {
if (!v) {
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
}
};
messageHandler.openTwoButtonDialog({
titleKey: 'dialog.externalInstallationTitle',
msgKey: 'dialog.inlineInstallationMsg',
leftButtonKey: 'dialog.inlineInstallExtension',
submitFunction,
loadedFunction: $.noop,
closeFunction
});
};
/**
* Show shared video.
* @param {string} id the id of the sender of the command
* @param {string} url video url
* @param {string} attributes
*/
UI.onSharedVideoStart = function(id, url, attributes) {
if (sharedVideoManager) {
2016-04-28 16:54:10 +00:00
sharedVideoManager.onSharedVideoStart(id, url, attributes);
}
};
/**
* Update shared video.
* @param {string} id the id of the sender of the command
* @param {string} url video url
* @param {string} attributes
*/
UI.onSharedVideoUpdate = function(id, url, attributes) {
if (sharedVideoManager) {
2016-04-28 16:54:10 +00:00
sharedVideoManager.onSharedVideoUpdate(id, url, attributes);
}
};
/**
* Stop showing shared video.
* @param {string} id the id of the sender of the command
* @param {string} attributes
*/
UI.onSharedVideoStop = function(id, attributes) {
if (sharedVideoManager) {
2016-04-28 16:54:10 +00:00
sharedVideoManager.onSharedVideoStop(id, attributes);
}
};
/**
* Handles user's features changes.
*/
UI.onUserFeaturesChanged = user => VideoLayout.onUserFeaturesChanged(user);
/**
* Returns the number of known remote videos.
*
* @returns {number} The number of remote videos.
*/
UI.getRemoteVideosCount = () => VideoLayout.getRemoteVideosCount();
/**
* Sets the remote control active status for a remote participant.
*
* @param {string} participantID - The id of the remote participant.
* @param {boolean} isActive - The new remote control active status.
* @returns {void}
*/
UI.setRemoteControlActiveStatus = function(participantID, isActive) {
VideoLayout.setRemoteControlActiveStatus(participantID, isActive);
};
/**
* Sets the remote control active status for the local participant.
*
* @returns {void}
*/
UI.setLocalRemoteControlActiveChanged = function() {
VideoLayout.setLocalRemoteControlActiveChanged();
};
// TODO: Export every function separately. For now there is no point of doing
// this because we are importing everything.
export default UI;