feat(toolbox): axe the old toolbox (#2731)
This PR takes The Bulldozer Approach (R): removes the old toolbox and lots of associated code, though not all of it. Subsequent cleanups will follow.
This commit is contained in:
parent
0cd32c8155
commit
b73b51f1f4
|
@ -106,10 +106,7 @@ import {
|
||||||
suspendDetected
|
suspendDetected
|
||||||
} from './react/features/overlay';
|
} from './react/features/overlay';
|
||||||
import { setSharedVideoStatus } from './react/features/shared-video';
|
import { setSharedVideoStatus } from './react/features/shared-video';
|
||||||
import {
|
import { isButtonEnabled } from './react/features/toolbox';
|
||||||
isButtonEnabled,
|
|
||||||
showDesktopSharingButton
|
|
||||||
} from './react/features/toolbox';
|
|
||||||
|
|
||||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
||||||
|
@ -768,7 +765,6 @@ export default {
|
||||||
|
|
||||||
APP.store.dispatch(
|
APP.store.dispatch(
|
||||||
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
|
setDesktopSharingEnabled(this.isDesktopSharingEnabled));
|
||||||
APP.store.dispatch(showDesktopSharingButton());
|
|
||||||
|
|
||||||
this._createRoom(tracks);
|
this._createRoom(tracks);
|
||||||
APP.remoteControl.init();
|
APP.remoteControl.init();
|
||||||
|
@ -1359,7 +1355,6 @@ export default {
|
||||||
this.isSharingScreen = newStream && newStream.videoType === 'desktop';
|
this.isSharingScreen = newStream && newStream.videoType === 'desktop';
|
||||||
|
|
||||||
if (wasSharingScreen !== this.isSharingScreen) {
|
if (wasSharingScreen !== this.isSharingScreen) {
|
||||||
APP.UI.updateDesktopSharingButtons();
|
|
||||||
APP.API.notifyScreenSharingStatusChanged(this.isSharingScreen);
|
APP.API.notifyScreenSharingStatusChanged(this.isSharingScreen);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -153,19 +153,7 @@ var interfaceConfig = {
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
VIDEO_QUALITY_LABEL_DISABLED: false,
|
VIDEO_QUALITY_LABEL_DISABLED: false
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a temporary feature flag used to gate access to the toolbox so it
|
|
||||||
* can be developed through smaller changesets and set to false if bad bugs
|
|
||||||
* are found. This feature flag will be removed at some point, as well as
|
|
||||||
* the old toolbox. This new toolbox will be horizontal and the previous
|
|
||||||
* feature of supporting menu button ordering through interfaceConfig will
|
|
||||||
* be removed. Support for configuring which buttons display will remain.
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
_USE_NEW_TOOLBOX: true
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify custom URL for downloading android mobile app.
|
* Specify custom URL for downloading android mobile app.
|
||||||
|
|
|
@ -36,14 +36,7 @@ import {
|
||||||
showWarningNotification
|
showWarningNotification
|
||||||
} from '../../react/features/notifications';
|
} from '../../react/features/notifications';
|
||||||
import {
|
import {
|
||||||
checkAutoEnableDesktopSharing,
|
|
||||||
clearButtonPopup,
|
|
||||||
dockToolbox,
|
dockToolbox,
|
||||||
setButtonPopupTimeout,
|
|
||||||
setToolbarButton,
|
|
||||||
showDialPadButton,
|
|
||||||
showEtherpadButton,
|
|
||||||
showSharedVideoButton,
|
|
||||||
showToolbox
|
showToolbox
|
||||||
} from '../../react/features/toolbox';
|
} from '../../react/features/toolbox';
|
||||||
|
|
||||||
|
@ -278,7 +271,7 @@ UI.setLocalRaisedHandStatus
|
||||||
* Initialize conference UI.
|
* Initialize conference UI.
|
||||||
*/
|
*/
|
||||||
UI.initConference = function() {
|
UI.initConference = function() {
|
||||||
const { dispatch, getState } = APP.store;
|
const { getState } = APP.store;
|
||||||
const { email, id, name } = getLocalParticipant(getState);
|
const { email, id, name } = getLocalParticipant(getState);
|
||||||
|
|
||||||
// Update default button states before showing the toolbar
|
// Update default button states before showing the toolbar
|
||||||
|
@ -298,8 +291,6 @@ UI.initConference = function() {
|
||||||
UI.setUserEmail(id, email);
|
UI.setUserEmail(id, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(checkAutoEnableDesktopSharing());
|
|
||||||
|
|
||||||
// FollowMe attempts to copy certain aspects of the moderator's UI into the
|
// FollowMe attempts to copy certain aspects of the moderator's UI into the
|
||||||
// other participants' UI. Consequently, it needs (1) read and write access
|
// other participants' UI. Consequently, it needs (1) read and write access
|
||||||
// to the UI (depending on the moderator role of the local participant) and
|
// to the UI (depending on the moderator role of the local participant) and
|
||||||
|
@ -372,11 +363,10 @@ UI.start = function() {
|
||||||
$('body').addClass('vertical-filmstrip');
|
$('body').addClass('vertical-filmstrip');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: remove this class once the old toolbar has been removed. This class
|
// TODO: remove this class once the old toolbar has been removed. This class
|
||||||
// is set so that any CSS changes needed to adjust elements outside of the
|
// is set so that any CSS changes needed to adjust elements outside of the
|
||||||
// new toolbar can be scoped to just the app with the new toolbar enabled.
|
// new toolbar can be scoped to just the app with the new toolbar enabled.
|
||||||
if (interfaceConfig._USE_NEW_TOOLBOX && !interfaceConfig.filmStripOnly) {
|
if (!interfaceConfig.filmStripOnly) {
|
||||||
$('body').addClass('use-new-toolbox');
|
$('body').addClass('use-new-toolbox');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +466,6 @@ UI.initEtherpad = name => {
|
||||||
= new EtherpadManager(config.etherpad_base, name, eventEmitter);
|
= new EtherpadManager(config.etherpad_base, name, eventEmitter);
|
||||||
|
|
||||||
APP.store.dispatch(setEtherpadHasInitialzied());
|
APP.store.dispatch(setEtherpadHasInitialzied());
|
||||||
APP.store.dispatch(showEtherpadButton());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -544,8 +533,6 @@ UI.onPeerVideoTypeChanged
|
||||||
UI.updateLocalRole = isModerator => {
|
UI.updateLocalRole = isModerator => {
|
||||||
VideoLayout.showModeratorIndicator();
|
VideoLayout.showModeratorIndicator();
|
||||||
|
|
||||||
APP.store.dispatch(showSharedVideoButton());
|
|
||||||
|
|
||||||
Recording.showRecordingButton(isModerator);
|
Recording.showRecordingButton(isModerator);
|
||||||
|
|
||||||
if (isModerator) {
|
if (isModerator) {
|
||||||
|
@ -672,14 +659,9 @@ UI.inputDisplayNameHandler = function(newDisplayName) {
|
||||||
* @param {number} timeout - The time to show the popup
|
* @param {number} timeout - The time to show the popup
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line max-params
|
// eslint-disable-next-line max-params, no-unused-vars
|
||||||
UI.showCustomToolbarPopup = function(buttonName, popupID, show, timeout) {
|
UI.showCustomToolbarPopup = function(buttonName, popupID, show, timeout) {
|
||||||
const action
|
// TODO: this is no longer implemented as of Toolbox v2. Remove?
|
||||||
= show
|
|
||||||
? setButtonPopupTimeout(buttonName, popupID, timeout)
|
|
||||||
: clearButtonPopup(buttonName);
|
|
||||||
|
|
||||||
APP.store.dispatch(action);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -904,17 +886,6 @@ UI.promptDisplayName = () => {
|
||||||
*/
|
*/
|
||||||
UI.setAudioLevel = (id, lvl) => VideoLayout.setAudioLevel(id, lvl);
|
UI.setAudioLevel = (id, lvl) => VideoLayout.setAudioLevel(id, lvl);
|
||||||
|
|
||||||
/**
|
|
||||||
* Update state of desktop sharing buttons.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
UI.updateDesktopSharingButtons
|
|
||||||
= () =>
|
|
||||||
APP.store.dispatch(setToolbarButton('desktop', {
|
|
||||||
toggled: APP.conference.isSharingScreen
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide connection quality statistics from UI.
|
* Hide connection quality statistics from UI.
|
||||||
*/
|
*/
|
||||||
|
@ -946,8 +917,9 @@ UI.addMessage = function(from, displayName, message, stamp) {
|
||||||
Chat.updateChatConversation(from, displayName, message, stamp);
|
Chat.updateChatConversation(from, displayName, message, stamp);
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.updateDTMFSupport
|
// TODO: With Toolbox v2 this got scrapped. Remove?
|
||||||
= isDTMFSupported => APP.store.dispatch(showDialPadButton(isDTMFSupported));
|
// eslint-disable-next-line no-empty-function
|
||||||
|
UI.updateDTMFSupport = () => { };
|
||||||
|
|
||||||
UI.updateRecordingState = function(state) {
|
UI.updateRecordingState = function(state) {
|
||||||
Recording.updateRecordingState(state);
|
Recording.updateRecordingState(state);
|
||||||
|
|
|
@ -129,8 +129,7 @@ class Etherpad extends LargeContainer {
|
||||||
let height, width;
|
let height, width;
|
||||||
|
|
||||||
if (interfaceConfig.VERTICAL_FILMSTRIP) {
|
if (interfaceConfig.VERTICAL_FILMSTRIP) {
|
||||||
height = interfaceConfig._USE_NEW_TOOLBOX
|
height = containerHeight - getToolboxHeight();
|
||||||
? containerHeight - getToolboxHeight() : containerHeight;
|
|
||||||
width = containerWidth - Filmstrip.getFilmstripWidth();
|
width = containerWidth - Filmstrip.getFilmstripWidth();
|
||||||
} else {
|
} else {
|
||||||
height = containerHeight - Filmstrip.getFilmstripHeight();
|
height = containerHeight - Filmstrip.getFilmstripHeight();
|
||||||
|
|
|
@ -699,8 +699,7 @@ class SharedVideoContainer extends LargeContainer {
|
||||||
let height, width;
|
let height, width;
|
||||||
|
|
||||||
if (interfaceConfig.VERTICAL_FILMSTRIP) {
|
if (interfaceConfig.VERTICAL_FILMSTRIP) {
|
||||||
height = interfaceConfig._USE_NEW_TOOLBOX
|
height = containerHeight - getToolboxHeight();
|
||||||
? containerHeight - getToolboxHeight() : containerHeight;
|
|
||||||
width = containerWidth - Filmstrip.getFilmstripWidth();
|
width = containerWidth - Filmstrip.getFilmstripWidth();
|
||||||
} else {
|
} else {
|
||||||
height = containerHeight - Filmstrip.getFilmstripHeight();
|
height = containerHeight - Filmstrip.getFilmstripHeight();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global APP, $, interfaceConfig */
|
/* global APP, $ */
|
||||||
|
|
||||||
import { processReplacements, linkify } from './Replacement';
|
import { processReplacements, linkify } from './Replacement';
|
||||||
import CommandsProcessor from './Commands';
|
import CommandsProcessor from './Commands';
|
||||||
|
@ -181,15 +181,11 @@ function resizeChatConversation() {
|
||||||
$('#smileysContainer').css('bottom', msgareaHeight);
|
$('#smileysContainer').css('bottom', msgareaHeight);
|
||||||
chat.width(width - 10);
|
chat.width(width - 10);
|
||||||
|
|
||||||
if (interfaceConfig._USE_NEW_TOOLBOX) {
|
const maybeAMagicNumberForPaddingAndMargin = 100;
|
||||||
const maybeAMagicNumberForPaddingAndMargin = 100;
|
const offset = maybeAMagicNumberForPaddingAndMargin
|
||||||
const offset = maybeAMagicNumberForPaddingAndMargin
|
+ msgareaHeight + getToolboxHeight();
|
||||||
+ msgareaHeight + getToolboxHeight();
|
|
||||||
|
|
||||||
chat.height(window.innerHeight - offset);
|
chat.height(window.innerHeight - offset);
|
||||||
} else {
|
|
||||||
chat.height(window.innerHeight - 15 - msgareaHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,7 +14,6 @@ import { NotificationsContainer } from '../../notifications';
|
||||||
import { SidePanel } from '../../side-panel';
|
import { SidePanel } from '../../side-panel';
|
||||||
import {
|
import {
|
||||||
Toolbox,
|
Toolbox,
|
||||||
ToolboxV2,
|
|
||||||
fullScreenChanged,
|
fullScreenChanged,
|
||||||
setToolboxAlwaysVisible,
|
setToolboxAlwaysVisible,
|
||||||
showToolbox
|
showToolbox
|
||||||
|
@ -139,7 +138,6 @@ class Conference extends Component<Props> {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
_USE_NEW_TOOLBOX,
|
|
||||||
VIDEO_QUALITY_LABEL_DISABLED,
|
VIDEO_QUALITY_LABEL_DISABLED,
|
||||||
filmStripOnly
|
filmStripOnly
|
||||||
} = interfaceConfig;
|
} = interfaceConfig;
|
||||||
|
@ -148,16 +146,6 @@ class Conference extends Component<Props> {
|
||||||
|| VIDEO_QUALITY_LABEL_DISABLED
|
|| VIDEO_QUALITY_LABEL_DISABLED
|
||||||
|| this.props._iAmRecorder;
|
|| this.props._iAmRecorder;
|
||||||
|
|
||||||
let ToolboxToUse;
|
|
||||||
|
|
||||||
if (filmStripOnly) {
|
|
||||||
ToolboxToUse = null;
|
|
||||||
} else if (interfaceConfig._USE_NEW_TOOLBOX) {
|
|
||||||
ToolboxToUse = ToolboxV2;
|
|
||||||
} else {
|
|
||||||
ToolboxToUse = Toolbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id = 'videoconference_page'
|
id = 'videoconference_page'
|
||||||
|
@ -168,10 +156,8 @@ class Conference extends Component<Props> {
|
||||||
<Filmstrip filmstripOnly = { filmStripOnly } />
|
<Filmstrip filmstripOnly = { filmStripOnly } />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ ToolboxToUse && <ToolboxToUse /> }
|
{ !filmStripOnly && <Toolbox /> }
|
||||||
|
{ !filmStripOnly && <SidePanel /> }
|
||||||
{ _USE_NEW_TOOLBOX && !filmStripOnly
|
|
||||||
&& <SidePanel /> }
|
|
||||||
|
|
||||||
<DialogContainer />
|
<DialogContainer />
|
||||||
<NotificationsContainer />
|
<NotificationsContainer />
|
||||||
|
|
|
@ -5,9 +5,7 @@ import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
|
import { ToolboxFilmstrip, dockToolbox } from '../../toolbox';
|
||||||
import { InviteButton } from '../../invite';
|
|
||||||
import { Toolbox, ToolboxFilmstrip, dockToolbox } from '../../toolbox';
|
|
||||||
|
|
||||||
import { setFilmstripHovered } from '../actions';
|
import { setFilmstripHovered } from '../actions';
|
||||||
import { shouldRemoteVideosBeVisible } from '../functions';
|
import { shouldRemoteVideosBeVisible } from '../functions';
|
||||||
|
@ -35,29 +33,11 @@ class Filmstrip extends Component<*> {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
/**
|
|
||||||
* Whether invite button rendering should be skipped,
|
|
||||||
* by default it is. false
|
|
||||||
*/
|
|
||||||
_hideInviteButton: PropTypes.bool,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not remote videos are currently being hovered over.
|
* Whether or not remote videos are currently being hovered over.
|
||||||
*/
|
*/
|
||||||
_hovered: PropTypes.bool,
|
_hovered: PropTypes.bool,
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the feature to directly invite people into the
|
|
||||||
* conference is available.
|
|
||||||
*/
|
|
||||||
_isAddToCallAvailable: PropTypes.bool,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the feature to dial out to number to join the
|
|
||||||
* conference is available.
|
|
||||||
*/
|
|
||||||
_isDialOutAvailable: PropTypes.bool,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the remote videos should be visible. Will toggle
|
* Whether or not the remote videos should be visible. Will toggle
|
||||||
* a class for hiding the videos.
|
* a class for hiding the videos.
|
||||||
|
@ -115,9 +95,6 @@ class Filmstrip extends Component<*> {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
_hideInviteButton,
|
|
||||||
_isAddToCallAvailable,
|
|
||||||
_isDialOutAvailable,
|
|
||||||
_remoteVideosVisible,
|
_remoteVideosVisible,
|
||||||
_toolboxVisible,
|
_toolboxVisible,
|
||||||
filmstripOnly
|
filmstripOnly
|
||||||
|
@ -136,12 +113,9 @@ class Filmstrip extends Component<*> {
|
||||||
const filmstripClassNames = `filmstrip ${_remoteVideosVisible
|
const filmstripClassNames = `filmstrip ${_remoteVideosVisible
|
||||||
? '' : 'hide-videos'} ${reduceHeight ? 'reduce-height' : ''}`;
|
? '' : 'hide-videos'} ${reduceHeight ? 'reduce-height' : ''}`;
|
||||||
|
|
||||||
const ToolboxToUse = interfaceConfig._USE_NEW_TOOLBOX
|
|
||||||
? ToolboxFilmstrip : Toolbox;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className = { filmstripClassNames }>
|
<div className = { filmstripClassNames }>
|
||||||
{ filmstripOnly ? <ToolboxToUse /> : null }
|
{ filmstripOnly && <ToolboxFilmstrip /> }
|
||||||
<div
|
<div
|
||||||
className = 'filmstrip__videos'
|
className = 'filmstrip__videos'
|
||||||
id = 'remoteVideos'>
|
id = 'remoteVideos'>
|
||||||
|
@ -150,11 +124,6 @@ class Filmstrip extends Component<*> {
|
||||||
id = 'filmstripLocalVideo'
|
id = 'filmstripLocalVideo'
|
||||||
onMouseOut = { this._onMouseOut }
|
onMouseOut = { this._onMouseOut }
|
||||||
onMouseOver = { this._onMouseOver }>
|
onMouseOver = { this._onMouseOver }>
|
||||||
{ filmstripOnly || _hideInviteButton
|
|
||||||
? null
|
|
||||||
: <InviteButton
|
|
||||||
enableAddPeople = { _isAddToCallAvailable }
|
|
||||||
enableDialOut = { _isDialOutAvailable } /> }
|
|
||||||
<div id = 'filmstripLocalVideoThumbnail' />
|
<div id = 'filmstripLocalVideoThumbnail' />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -185,9 +154,7 @@ class Filmstrip extends Component<*> {
|
||||||
*/
|
*/
|
||||||
_notifyOfHoveredStateUpdate() {
|
_notifyOfHoveredStateUpdate() {
|
||||||
if (this.props._hovered !== this._isHovered) {
|
if (this.props._hovered !== this._isHovered) {
|
||||||
if (interfaceConfig._USE_NEW_TOOLBOX) {
|
this.props.dispatch(dockToolbox(this._isHovered));
|
||||||
this.props.dispatch(dockToolbox(this._isHovered));
|
|
||||||
}
|
|
||||||
this.props.dispatch(setFilmstripHovered(this._isHovered));
|
this.props.dispatch(setFilmstripHovered(this._isHovered));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,36 +190,16 @@ class Filmstrip extends Component<*> {
|
||||||
* @param {Object} state - The Redux state.
|
* @param {Object} state - The Redux state.
|
||||||
* @private
|
* @private
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* _hideInviteButton: boolean,
|
|
||||||
* _hovered: boolean,
|
* _hovered: boolean,
|
||||||
* _isAddToCallAvailable: boolean,
|
|
||||||
* _isDialOutAvailable: boolean,
|
|
||||||
* _remoteVideosVisible: boolean,
|
* _remoteVideosVisible: boolean,
|
||||||
* _toolboxVisible: boolean
|
* _toolboxVisible: boolean
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
const { conference } = state['features/base/conference'];
|
|
||||||
const {
|
|
||||||
enableUserRolesBasedOnToken,
|
|
||||||
iAmRecorder
|
|
||||||
} = state['features/base/config'];
|
|
||||||
const { isGuest } = state['features/base/jwt'];
|
|
||||||
const { hovered } = state['features/filmstrip'];
|
const { hovered } = state['features/filmstrip'];
|
||||||
|
|
||||||
const isAddToCallAvailable = !isGuest;
|
|
||||||
const isDialOutAvailable
|
|
||||||
= getLocalParticipant(state).role === PARTICIPANT_ROLE.MODERATOR
|
|
||||||
&& conference && conference.isSIPCallingSupported()
|
|
||||||
&& (!enableUserRolesBasedOnToken || !isGuest);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_hideInviteButton: iAmRecorder
|
|
||||||
|| (!isAddToCallAvailable && !isDialOutAvailable)
|
|
||||||
|| interfaceConfig._USE_NEW_TOOLBOX,
|
|
||||||
_hovered: hovered,
|
_hovered: hovered,
|
||||||
_isAddToCallAvailable: isAddToCallAvailable,
|
|
||||||
_isDialOutAvailable: isDialOutAvailable,
|
|
||||||
_remoteVideosVisible: shouldRemoteVideosBeVisible(state),
|
_remoteVideosVisible: shouldRemoteVideosBeVisible(state),
|
||||||
_toolboxVisible: state['features/toolbox'].visible
|
_toolboxVisible: state['features/toolbox'].visible
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* global interfaceConfig */
|
|
||||||
|
|
||||||
import InlineDialog from '@atlaskit/inline-dialog';
|
import InlineDialog from '@atlaskit/inline-dialog';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
@ -8,30 +6,12 @@ import { connect } from 'react-redux';
|
||||||
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { getParticipantCount } from '../../base/participants';
|
import { getParticipantCount } from '../../base/participants';
|
||||||
import {
|
import { ToolbarButtonV2 } from '../../toolbox';
|
||||||
ToolbarButton,
|
|
||||||
ToolbarButtonV2,
|
|
||||||
TOOLTIP_TO_POPUP_POSITION
|
|
||||||
} from '../../toolbox';
|
|
||||||
|
|
||||||
import { updateDialInNumbers } from '../actions';
|
import { updateDialInNumbers } from '../actions';
|
||||||
|
|
||||||
import { InfoDialog } from './info-dialog';
|
import { InfoDialog } from './info-dialog';
|
||||||
|
|
||||||
/**
|
|
||||||
* A configuration object to describe how {@code ToolbarButton} should render
|
|
||||||
* the button.
|
|
||||||
*
|
|
||||||
* @type {object}
|
|
||||||
*/
|
|
||||||
const DEFAULT_BUTTON_CONFIGURATION = {
|
|
||||||
buttonName: 'info',
|
|
||||||
classNames: [ 'button', 'icon-info' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_info',
|
|
||||||
tooltipKey: 'info.tooltip'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of time, in milliseconds, to wait until automatically showing
|
* The amount of time, in milliseconds, to wait until automatically showing
|
||||||
* the {@code InfoDialog}. This is essentially a hack as automatic showing
|
* the {@code InfoDialog}. This is essentially a hack as automatic showing
|
||||||
|
@ -170,9 +150,26 @@ class InfoDialogButton extends Component {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
return interfaceConfig._USE_NEW_TOOLBOX
|
const { t } = this.props;
|
||||||
? this._renderNewToolbarButton()
|
const { showDialog } = this.state;
|
||||||
: this._renderOldToolbarButton();
|
const iconClass = `icon-info ${showDialog ? 'toggled' : ''}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className = 'toolbox-button-wth-dialog'>
|
||||||
|
<InlineDialog
|
||||||
|
content = {
|
||||||
|
<InfoDialog onClose = { this._onDialogClose } /> }
|
||||||
|
isOpen = { showDialog }
|
||||||
|
onClose = { this._onDialogClose }
|
||||||
|
position = { 'top right' }>
|
||||||
|
<ToolbarButtonV2
|
||||||
|
accessibilityLabel = 'Info'
|
||||||
|
iconName = { iconClass }
|
||||||
|
onClick = { this._onDialogToggle }
|
||||||
|
tooltip = { t('info.tooltip') } />
|
||||||
|
</InlineDialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,69 +206,6 @@ class InfoDialogButton extends Component {
|
||||||
|
|
||||||
this.setState({ showDialog: !this.state.showDialog });
|
this.setState({ showDialog: !this.state.showDialog });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a React Element for the {@code InfoDialog} using legacy
|
|
||||||
* {@code ToolbarButton}.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
_renderOldToolbarButton() {
|
|
||||||
const { tooltipPosition } = this.props;
|
|
||||||
const { showDialog } = this.state;
|
|
||||||
|
|
||||||
const buttonConfiguration = {
|
|
||||||
...DEFAULT_BUTTON_CONFIGURATION,
|
|
||||||
classNames: [
|
|
||||||
...DEFAULT_BUTTON_CONFIGURATION.classNames,
|
|
||||||
showDialog ? 'toggled button-active' : ''
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InlineDialog
|
|
||||||
content = { <InfoDialog onClose = { this._onDialogClose } /> }
|
|
||||||
isOpen = { showDialog }
|
|
||||||
onClose = { this._onDialogClose }
|
|
||||||
position = { TOOLTIP_TO_POPUP_POSITION[tooltipPosition] }>
|
|
||||||
<ToolbarButton
|
|
||||||
button = { buttonConfiguration }
|
|
||||||
onClick = { this._onDialogToggle }
|
|
||||||
tooltipPosition = { tooltipPosition } />
|
|
||||||
</InlineDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a React Element for the {@code InfoDialog} using the newer
|
|
||||||
* {@code ToolbarButtonV2}.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
_renderNewToolbarButton() {
|
|
||||||
const { t } = this.props;
|
|
||||||
const { showDialog } = this.state;
|
|
||||||
const iconClass = `icon-info ${showDialog ? 'toggled' : ''}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className = 'toolbox-button-wth-dialog'>
|
|
||||||
<InlineDialog
|
|
||||||
content = {
|
|
||||||
<InfoDialog onClose = { this._onDialogClose } /> }
|
|
||||||
isOpen = { showDialog }
|
|
||||||
onClose = { this._onDialogClose }
|
|
||||||
position = { 'top right' }>
|
|
||||||
<ToolbarButtonV2
|
|
||||||
accessibilityLabel = 'Info'
|
|
||||||
iconName = { iconClass }
|
|
||||||
onClick = { this._onDialogToggle }
|
|
||||||
tooltip = { t('info.tooltip') } />
|
|
||||||
</InlineDialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -61,17 +61,6 @@ export const SET_SUBJECT = Symbol('SET_SUBJECT');
|
||||||
*/
|
*/
|
||||||
export const SET_SUBJECT_SLIDE_IN = Symbol('SET_SUBJECT_SLIDE_IN');
|
export const SET_SUBJECT_SLIDE_IN = Symbol('SET_SUBJECT_SLIDE_IN');
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of the action which sets the descriptor of a toolbar button.
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* type: SET_TOOLBAR_BUTTON,
|
|
||||||
* button: Object,
|
|
||||||
* key: string
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export const SET_TOOLBAR_BUTTON = Symbol('SET_TOOLBAR_BUTTON');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the action which sets the indicator which determiens whether a
|
* The type of the action which sets the indicator which determiens whether a
|
||||||
* fToolbar in the Toolbox is hovered.
|
* fToolbar in the Toolbox is hovered.
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import type { Dispatch } from 'redux-thunk';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CLEAR_TOOLBOX_TIMEOUT,
|
CLEAR_TOOLBOX_TIMEOUT,
|
||||||
SET_SUBJECT,
|
SET_SUBJECT,
|
||||||
SET_SUBJECT_SLIDE_IN,
|
SET_SUBJECT_SLIDE_IN,
|
||||||
SET_TOOLBAR_BUTTON,
|
|
||||||
SET_TOOLBAR_HOVERED,
|
SET_TOOLBAR_HOVERED,
|
||||||
SET_TOOLBOX_ALWAYS_VISIBLE,
|
SET_TOOLBOX_ALWAYS_VISIBLE,
|
||||||
SET_TOOLBOX_ENABLED,
|
SET_TOOLBOX_ENABLED,
|
||||||
|
@ -15,28 +12,6 @@ import {
|
||||||
SET_TOOLBOX_VISIBLE
|
SET_TOOLBOX_VISIBLE
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME: We should make sure all common functions for native and web are
|
|
||||||
* merged in a global functions file.
|
|
||||||
*/
|
|
||||||
import { getButton } from './functions.native';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for local raise hand changed event.
|
|
||||||
*
|
|
||||||
* @param {boolean} handRaised - Flag showing whether hand is raised.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function changeLocalRaiseHand(handRaised: boolean): Function {
|
|
||||||
return (dispatch: Dispatch<*>, getState: Function) => {
|
|
||||||
const buttonName = 'raisehand';
|
|
||||||
const button = getButton(buttonName, getState());
|
|
||||||
|
|
||||||
button.toggled = handRaised;
|
|
||||||
|
|
||||||
dispatch(setToolbarButton(buttonName, button));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that toolbox timeout should be cleared.
|
* Signals that toolbox timeout should be cleared.
|
||||||
|
@ -81,25 +56,6 @@ export function setSubjectSlideIn(subjectSlideIn: boolean): Object {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals that value of the button specified by key should be changed.
|
|
||||||
*
|
|
||||||
* @param {string} buttonName - Button key.
|
|
||||||
* @param {Object} button - Button object.
|
|
||||||
* @returns {{
|
|
||||||
* type: SET_TOOLBAR_BUTTON,
|
|
||||||
* button: Object,
|
|
||||||
* buttonName: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
export function setToolbarButton(buttonName: string, button: Object): Object {
|
|
||||||
return {
|
|
||||||
type: SET_TOOLBAR_BUTTON,
|
|
||||||
button,
|
|
||||||
buttonName
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that toolbar is hovered value should be changed.
|
* Signals that toolbar is hovered value should be changed.
|
||||||
*
|
*
|
||||||
|
@ -203,51 +159,3 @@ export function setToolboxVisible(visible: boolean): Object {
|
||||||
visible
|
visible
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows etherpad button if it's not shown.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function showEtherpadButton(): Function {
|
|
||||||
return (dispatch: Dispatch<*>) => {
|
|
||||||
dispatch(setToolbarButton('etherpad', {
|
|
||||||
hidden: false
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for full screen toggled event.
|
|
||||||
*
|
|
||||||
* @param {boolean} isFullScreen - Flag showing whether app in full
|
|
||||||
* screen mode.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function toggleFullScreen(isFullScreen: boolean): Function {
|
|
||||||
return (dispatch: Dispatch<*>, getState: Function) => {
|
|
||||||
const buttonName = 'fullscreen';
|
|
||||||
const button = getButton(buttonName, getState());
|
|
||||||
|
|
||||||
if (button) {
|
|
||||||
button.toggled = isFullScreen;
|
|
||||||
dispatch(setToolbarButton(buttonName, button));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets negation of button's toggle property.
|
|
||||||
*
|
|
||||||
* @param {string} buttonName - Button key.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function toggleToolbarButton(buttonName: string): Function {
|
|
||||||
return (dispatch: Dispatch, getState: Function) => {
|
|
||||||
const button = getButton(buttonName, getState());
|
|
||||||
|
|
||||||
dispatch(setToolbarButton(buttonName, {
|
|
||||||
toggled: !button.toggled
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,73 +1,24 @@
|
||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import Recording from '../../../modules/UI/recording/Recording';
|
|
||||||
import SideContainerToggler
|
import SideContainerToggler
|
||||||
from '../../../modules/UI/side_pannels/SideContainerToggler';
|
from '../../../modules/UI/side_pannels/SideContainerToggler';
|
||||||
|
|
||||||
import UIEvents from '../../../service/UI/UIEvents';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
changeLocalRaiseHand,
|
|
||||||
clearToolboxTimeout,
|
clearToolboxTimeout,
|
||||||
setSubjectSlideIn,
|
setSubjectSlideIn,
|
||||||
setToolbarButton,
|
|
||||||
setToolboxTimeout,
|
setToolboxTimeout,
|
||||||
setToolboxTimeoutMS,
|
setToolboxTimeoutMS,
|
||||||
setToolboxVisible,
|
setToolboxVisible
|
||||||
toggleToolbarButton
|
|
||||||
} from './actions.native';
|
} from './actions.native';
|
||||||
import {
|
import {
|
||||||
FULL_SCREEN_CHANGED,
|
FULL_SCREEN_CHANGED,
|
||||||
SET_DEFAULT_TOOLBOX_BUTTONS,
|
|
||||||
SET_FULL_SCREEN
|
SET_FULL_SCREEN
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import {
|
|
||||||
getButton,
|
|
||||||
getDefaultToolboxButtons,
|
|
||||||
isButtonEnabled
|
|
||||||
} from './functions';
|
|
||||||
|
|
||||||
declare var $: Function;
|
|
||||||
declare var APP: Object;
|
|
||||||
declare var config: Object;
|
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
export * from './actions.native';
|
export * from './actions.native';
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether desktop sharing is enabled and whether
|
|
||||||
* we have params to start automatically sharing.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function checkAutoEnableDesktopSharing(): Function {
|
|
||||||
return () => {
|
|
||||||
// XXX Should use dispatcher to toggle screensharing but screensharing
|
|
||||||
// hasn't been React-ified yet.
|
|
||||||
if (isButtonEnabled('desktop')
|
|
||||||
&& config.autoEnableDesktopSharing) {
|
|
||||||
APP.UI.eventEmitter.emit(UIEvents.TOGGLE_SCREENSHARING);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action to hide any popups displayed by the associated button.
|
|
||||||
*
|
|
||||||
* @param {string} buttonName - The name of the button as specified in the
|
|
||||||
* button configurations for the toolbar.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function clearButtonPopup(buttonName) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
_clearPopupTimeout(buttonName, getState());
|
|
||||||
|
|
||||||
dispatch(setToolbarButton(buttonName, {
|
|
||||||
popupDisplay: null
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Docks/undocks the Toolbox.
|
* Docks/undocks the Toolbox.
|
||||||
*
|
*
|
||||||
|
@ -115,56 +66,6 @@ export function fullScreenChanged(fullScreen: boolean) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns button on mount/unmount handlers with dispatch function stored in
|
|
||||||
* closure.
|
|
||||||
*
|
|
||||||
* @param {Function} dispatch - Redux action dispatcher.
|
|
||||||
* @returns {Object} Button on mount/unmount handlers.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _getButtonHandlers(dispatch) {
|
|
||||||
const localRaiseHandHandler
|
|
||||||
= (...args) => dispatch(changeLocalRaiseHand(...args));
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Mount handler for desktop button.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
desktop: {
|
|
||||||
onMount: () => dispatch(showDesktopSharingButton())
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mount/Unmount handlers for raisehand button.
|
|
||||||
*
|
|
||||||
* @type {button}
|
|
||||||
*/
|
|
||||||
raisehand: {
|
|
||||||
onMount: () =>
|
|
||||||
APP.UI.addListener(
|
|
||||||
UIEvents.LOCAL_RAISE_HAND_CHANGED,
|
|
||||||
localRaiseHandHandler),
|
|
||||||
onUnmount: () =>
|
|
||||||
APP.UI.removeListener(
|
|
||||||
UIEvents.LOCAL_RAISE_HAND_CHANGED,
|
|
||||||
localRaiseHandHandler)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mount handler for recording button.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
recording: {
|
|
||||||
onMount: () =>
|
|
||||||
config.enableRecording && dispatch(showRecordingButton())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides the toolbox.
|
* Hides the toolbox.
|
||||||
*
|
*
|
||||||
|
@ -202,97 +103,6 @@ export function hideToolbox(force: boolean = false): Function {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action to show the popup associated with a button. Sets a
|
|
||||||
* timeout to be fired which will dismiss the popup.
|
|
||||||
*
|
|
||||||
* @param {string} buttonName - The name of the button as specified in the
|
|
||||||
* button configurations for the toolbar.
|
|
||||||
* @param {string} popupName - The id of the popup to show as specified in
|
|
||||||
* the button configurations for the toolbar.
|
|
||||||
* @param {number} timeout - The time in milliseconds to show the popup.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function setButtonPopupTimeout(buttonName, popupName, timeout) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
_clearPopupTimeout(buttonName, getState());
|
|
||||||
|
|
||||||
const newTimeoutId = setTimeout(() => {
|
|
||||||
dispatch(clearButtonPopup(buttonName));
|
|
||||||
}, timeout);
|
|
||||||
|
|
||||||
dispatch(setToolbarButton(buttonName, {
|
|
||||||
popupDisplay: {
|
|
||||||
popupID: popupName,
|
|
||||||
timeoutID: newTimeoutId
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default toolbar buttons of the Toolbox.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function setDefaultToolboxButtons(): Function {
|
|
||||||
return (dispatch: Dispatch) => {
|
|
||||||
// Save dispatch function in closure.
|
|
||||||
const buttonHandlers = _getButtonHandlers(dispatch);
|
|
||||||
const toolboxButtons = getDefaultToolboxButtons(buttonHandlers);
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: SET_DEFAULT_TOOLBOX_BUTTONS,
|
|
||||||
...toolboxButtons
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows desktop sharing button.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function showDesktopSharingButton(): Function {
|
|
||||||
return (dispatch: Dispatch<*>) => {
|
|
||||||
const buttonName = 'desktop';
|
|
||||||
const disabledTooltipText
|
|
||||||
= APP.conference.desktopSharingDisabledTooltip;
|
|
||||||
const showTooltip
|
|
||||||
= disabledTooltipText
|
|
||||||
&& APP.conference.isDesktopSharingDisabledByConfig;
|
|
||||||
const visible
|
|
||||||
= isButtonEnabled(buttonName)
|
|
||||||
&& (APP.conference.isDesktopSharingEnabled || showTooltip);
|
|
||||||
|
|
||||||
const newState = {
|
|
||||||
enabled: APP.conference.isDesktopSharingEnabled,
|
|
||||||
hidden: !visible,
|
|
||||||
tooltipText: showTooltip ? disabledTooltipText : undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch(setToolbarButton(buttonName, newState));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides the dialpad button.
|
|
||||||
*
|
|
||||||
* @param {boolean} show - Flag showing whether to show button or not.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function showDialPadButton(show: boolean): Function {
|
|
||||||
return (dispatch: Dispatch<*>) => {
|
|
||||||
const buttonName = 'dialpad';
|
|
||||||
|
|
||||||
if (show && isButtonEnabled(buttonName)) {
|
|
||||||
dispatch(setToolbarButton(buttonName, {
|
|
||||||
hidden: false
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals a request to enter or exit full screen mode.
|
* Signals a request to enter or exit full screen mode.
|
||||||
*
|
*
|
||||||
|
@ -309,39 +119,6 @@ export function setFullScreen(fullScreen: boolean) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows recording button.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function showRecordingButton(): Function {
|
|
||||||
return (dispatch: Dispatch<*>) => {
|
|
||||||
dispatch(setToolbarButton('recording', {
|
|
||||||
hidden: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
Recording.initRecordingButton();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides the 'shared video' button.
|
|
||||||
*
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function showSharedVideoButton(): Function {
|
|
||||||
return (dispatch: Dispatch<*>) => {
|
|
||||||
const buttonName = 'sharedvideo';
|
|
||||||
|
|
||||||
if (isButtonEnabled(buttonName)
|
|
||||||
&& !config.disableThirdPartyRequests) {
|
|
||||||
dispatch(setToolbarButton(buttonName, {
|
|
||||||
hidden: false
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the toolbox for specified timeout.
|
* Shows the toolbox for specified timeout.
|
||||||
*
|
*
|
||||||
|
@ -374,43 +151,3 @@ export function showToolbox(timeout: number = 0): Object {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for side toolbar container toggled event.
|
|
||||||
*
|
|
||||||
* @param {string} containerId - ID of the container.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function toggleSideToolbarContainer(containerId: string): Function {
|
|
||||||
return (dispatch: Dispatch, getState: Function) => {
|
|
||||||
const { secondaryToolbarButtons } = getState()['features/toolbox'];
|
|
||||||
|
|
||||||
for (const key of secondaryToolbarButtons.keys()) {
|
|
||||||
const button = secondaryToolbarButtons.get(key);
|
|
||||||
|
|
||||||
if (isButtonEnabled(key)
|
|
||||||
&& button.sideContainerId
|
|
||||||
&& button.sideContainerId === containerId) {
|
|
||||||
dispatch(toggleToolbarButton(key));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the timeout set for hiding a button popup.
|
|
||||||
*
|
|
||||||
* @param {string} buttonName - The name of the button as specified in the
|
|
||||||
* button configurations for the toolbar.
|
|
||||||
* @param {Object} state - The redux state in which the button is expected to
|
|
||||||
* be defined.
|
|
||||||
* @private
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function _clearPopupTimeout(buttonName, state) {
|
|
||||||
const { popupDisplay } = getButton(buttonName, state);
|
|
||||||
const { timeoutID } = popupDisplay || {};
|
|
||||||
|
|
||||||
clearTimeout(timeoutID);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { getToolbarClassNames } from '../functions';
|
|
||||||
import Toolbar from './Toolbar';
|
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of PrimaryToolbar React Component.
|
|
||||||
*
|
|
||||||
* @class PrimaryToolbar
|
|
||||||
* @extends Component
|
|
||||||
*/
|
|
||||||
class PrimaryToolbar extends Component<*, *> {
|
|
||||||
static propTypes = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains toolbar buttons for primary toolbar.
|
|
||||||
*/
|
|
||||||
_primaryToolbarButtons: PropTypes.instanceOf(Map),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows whether toolbox is visible.
|
|
||||||
*/
|
|
||||||
_visible: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
state: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders primary toolbar component.
|
|
||||||
*
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
render(): React$Element<*> | null {
|
|
||||||
const { _primaryToolbarButtons } = this.props;
|
|
||||||
|
|
||||||
// The number of buttons to show in the toolbar isn't fixed, it depends
|
|
||||||
// on the availability of features and configuration parameters. So
|
|
||||||
// there may be nothing to render.
|
|
||||||
if (_primaryToolbarButtons.size === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { primaryToolbarClassName } = getToolbarClassNames(this.props);
|
|
||||||
const tooltipPosition
|
|
||||||
= interfaceConfig.filmStripOnly ? 'left' : 'bottom';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Toolbar
|
|
||||||
className = { primaryToolbarClassName }
|
|
||||||
toolbarButtons = { _primaryToolbarButtons }
|
|
||||||
tooltipPosition = { tooltipPosition } />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps part of Redux store to React component props.
|
|
||||||
*
|
|
||||||
* @param {Object} state - Snapshot of Redux store.
|
|
||||||
* @returns {{
|
|
||||||
* _primaryToolbarButtons: Map,
|
|
||||||
* _visible: boolean
|
|
||||||
* }}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _mapStateToProps(state: Object): Object {
|
|
||||||
const {
|
|
||||||
primaryToolbarButtons,
|
|
||||||
visible
|
|
||||||
} = state['features/toolbox'];
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Default toolbar buttons for primary toolbar.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @type {Map}
|
|
||||||
*/
|
|
||||||
_primaryToolbarButtons: primaryToolbarButtons,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows whether toolbox is visible.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
_visible: visible
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(_mapStateToProps)(PrimaryToolbar);
|
|
|
@ -1,188 +0,0 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { FeedbackButton } from '../../feedback';
|
|
||||||
import UIEvents from '../../../../service/UI/UIEvents';
|
|
||||||
|
|
||||||
import {
|
|
||||||
toggleSideToolbarContainer
|
|
||||||
} from '../actions';
|
|
||||||
import { getToolbarClassNames } from '../functions';
|
|
||||||
import Toolbar from './Toolbar';
|
|
||||||
|
|
||||||
declare var APP: Object;
|
|
||||||
declare var config: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of secondary toolbar React component.
|
|
||||||
*
|
|
||||||
* @class SecondaryToolbar
|
|
||||||
* @extends Component
|
|
||||||
*/
|
|
||||||
class SecondaryToolbar extends Component<*, *> {
|
|
||||||
state: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Secondary toolbar property types.
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
static propTypes = {
|
|
||||||
/**
|
|
||||||
* Application ID for callstats.io API. The {@code FeedbackButton} will
|
|
||||||
* display if defined.
|
|
||||||
*/
|
|
||||||
_callStatsID: PropTypes.string,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The indicator which determines whether the local participant is a
|
|
||||||
* guest in the conference.
|
|
||||||
*/
|
|
||||||
_isGuest: PropTypes.bool,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler dispatching toggle toolbar container.
|
|
||||||
*/
|
|
||||||
_onSideToolbarContainerToggled: PropTypes.func,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains map of secondary toolbar buttons.
|
|
||||||
*/
|
|
||||||
_secondaryToolbarButtons: PropTypes.instanceOf(Map),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows whether toolbox is visible.
|
|
||||||
*/
|
|
||||||
_visible: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register legacy UI listener.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
componentDidMount(): void {
|
|
||||||
APP.UI.addListener(
|
|
||||||
UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
|
|
||||||
this.props._onSideToolbarContainerToggled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters legacy UI listener.
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
componentWillUnmount(): void {
|
|
||||||
APP.UI.removeListener(
|
|
||||||
UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
|
|
||||||
this.props._onSideToolbarContainerToggled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders secondary toolbar component.
|
|
||||||
*
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
render(): React$Element<*> | null {
|
|
||||||
const { _callStatsID, _secondaryToolbarButtons } = this.props;
|
|
||||||
|
|
||||||
// The number of buttons to show in the toolbar isn't fixed, it depends
|
|
||||||
// on the availability of features and configuration parameters. So
|
|
||||||
// there may be nothing to render.
|
|
||||||
if (_secondaryToolbarButtons.size === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Toolbar
|
|
||||||
className = { secondaryToolbarClassName }
|
|
||||||
toolbarButtons = { _secondaryToolbarButtons }
|
|
||||||
tooltipPosition = 'right'>
|
|
||||||
{ _callStatsID
|
|
||||||
? <FeedbackButton tooltipPosition = 'right' /> : null }
|
|
||||||
</Toolbar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps some of Redux actions to component's props.
|
|
||||||
*
|
|
||||||
* @param {Function} dispatch - Redux action dispatcher.
|
|
||||||
* @returns {{
|
|
||||||
* _onSideToolbarContainerToggled
|
|
||||||
* }}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _mapDispatchToProps(dispatch: Function): Object {
|
|
||||||
return {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action signalling that side toolbar container is
|
|
||||||
* toggled.
|
|
||||||
*
|
|
||||||
* @param {string} containerId - Id of side toolbar container.
|
|
||||||
* @returns {Object} Dispatched action.
|
|
||||||
*/
|
|
||||||
_onSideToolbarContainerToggled(containerId: string) {
|
|
||||||
dispatch(toggleSideToolbarContainer(containerId));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps part of Redux state to component's props.
|
|
||||||
*
|
|
||||||
* @param {Object} state - Snapshot of Redux store.
|
|
||||||
* @returns {{
|
|
||||||
* _isGuest: boolean,
|
|
||||||
* _secondaryToolbarButtons: Map,
|
|
||||||
* _visible: boolean
|
|
||||||
* }}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _mapStateToProps(state: Object): Object {
|
|
||||||
const { isGuest } = state['features/base/jwt'];
|
|
||||||
const { secondaryToolbarButtons, visible } = state['features/toolbox'];
|
|
||||||
const { callStatsID } = state['features/base/config'];
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Application ID for callstats.io API.
|
|
||||||
*/
|
|
||||||
_callStatsID: callStatsID,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The indicator which determines whether the local participant is a
|
|
||||||
* guest in the conference.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
_isGuest: isGuest,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default toolbar buttons for secondary toolbar.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @type {Map}
|
|
||||||
*/
|
|
||||||
_secondaryToolbarButtons: secondaryToolbarButtons,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The indicator which determines whether the {@code SecondaryToolbar}
|
|
||||||
* is visible.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
_visible: visible
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(_mapStateToProps, _mapDispatchToProps)(SecondaryToolbar);
|
|
|
@ -1,181 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { setToolbarHovered } from '../actions';
|
|
||||||
|
|
||||||
import StatelessToolbar from './StatelessToolbar';
|
|
||||||
import ToolbarButton from './ToolbarButton';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements a toolbar in React/Web. It is a strip that contains a set of
|
|
||||||
* toolbar items such as buttons. Toolbar is commonly placed inside of a
|
|
||||||
* Toolbox.
|
|
||||||
*
|
|
||||||
* @class Toolbar
|
|
||||||
* @extends Component
|
|
||||||
*/
|
|
||||||
class Toolbar extends Component<*> {
|
|
||||||
/**
|
|
||||||
* Base toolbar component's property types.
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
static propTypes = {
|
|
||||||
/**
|
|
||||||
* Children of current React component.
|
|
||||||
*/
|
|
||||||
children: PropTypes.element,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toolbar's class name.
|
|
||||||
*/
|
|
||||||
className: PropTypes.string,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to dispatch an action when a button is clicked or on mouse
|
|
||||||
* out/in event.
|
|
||||||
*/
|
|
||||||
dispatch: PropTypes.func,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map with toolbar buttons.
|
|
||||||
*/
|
|
||||||
toolbarButtons: PropTypes.instanceOf(Map),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the position of the tooltip.
|
|
||||||
*/
|
|
||||||
tooltipPosition: PropTypes.oneOf([ 'bottom', 'left', 'right', 'top' ])
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor of Primary toolbar class.
|
|
||||||
*
|
|
||||||
* @param {Object} props - Object containing React component properties.
|
|
||||||
*/
|
|
||||||
constructor(props: Object) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
// Bind callbacks to preverse this.
|
|
||||||
this._onMouseOut = this._onMouseOut.bind(this);
|
|
||||||
this._onMouseOver = this._onMouseOver.bind(this);
|
|
||||||
this._renderToolbarButton = this._renderToolbarButton.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements React's {@link Component#render()}.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
render(): React$Element<*> {
|
|
||||||
const props = {
|
|
||||||
className: this.props.className,
|
|
||||||
onMouseOut: this._onMouseOut,
|
|
||||||
onMouseOver: this._onMouseOver
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StatelessToolbar { ...props }>
|
|
||||||
{
|
|
||||||
[ ...this.props.toolbarButtons.entries() ]
|
|
||||||
.map(this._renderToolbarButton)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.props.children
|
|
||||||
}
|
|
||||||
</StatelessToolbar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMouseOut: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action signalling that toolbar is no being hovered.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onMouseOut() {
|
|
||||||
this.props.dispatch(setToolbarHovered(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMouseOver: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action signalling that toolbar is now being hovered.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onMouseOver() {
|
|
||||||
this.props.dispatch(setToolbarHovered(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderToolbarButton: (Array<*>) => React$Element<*>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders toolbar button. Method is passed to map function.
|
|
||||||
*
|
|
||||||
* @param {Array} keyValuePair - Key value pair containing button and its
|
|
||||||
* key.
|
|
||||||
* @private
|
|
||||||
* @returns {ReactElement} A toolbar button.
|
|
||||||
*/
|
|
||||||
_renderToolbarButton([ key, button ]): React$Element<*> {
|
|
||||||
const { tooltipPosition } = this.props;
|
|
||||||
|
|
||||||
if (button.component) {
|
|
||||||
return (
|
|
||||||
<button.component
|
|
||||||
key = { key }
|
|
||||||
toggled = { button.toggled }
|
|
||||||
tooltipPosition = { tooltipPosition } />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
childComponent: ChildComponent,
|
|
||||||
onClick,
|
|
||||||
onMount,
|
|
||||||
onUnmount
|
|
||||||
} = button;
|
|
||||||
const onClickWithDispatch = (...args) =>
|
|
||||||
onClick && onClick(this.props.dispatch, ...args);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToolbarButton
|
|
||||||
button = { button }
|
|
||||||
key = { key }
|
|
||||||
|
|
||||||
// TODO The following disables an eslint error alerting about a
|
|
||||||
// known potential/theoretical performance pernalty:
|
|
||||||
//
|
|
||||||
// A bind call or arrow function in a JSX prop will create a
|
|
||||||
// brand new function on every single render. This is bad for
|
|
||||||
// performance, as it will result in the garbage collector being
|
|
||||||
// invoked way more than is necessary. It may also cause
|
|
||||||
// unnecessary re-renders if a brand new function is passed as a
|
|
||||||
// prop to a component that uses reference equality check on the
|
|
||||||
// prop to determine if it should update.
|
|
||||||
//
|
|
||||||
// I'm not addressing the potential/theoretical performance
|
|
||||||
// penalty at the time of this writing because I don't know for
|
|
||||||
// a fact that it's a practical performance penalty in the case.
|
|
||||||
//
|
|
||||||
// eslint-disable-next-line react/jsx-no-bind
|
|
||||||
onClick = { onClickWithDispatch }
|
|
||||||
onMount = { onMount }
|
|
||||||
onUnmount = { onUnmount }
|
|
||||||
tooltipPosition = { tooltipPosition }>
|
|
||||||
{ button.html || null }
|
|
||||||
{ ChildComponent ? <ChildComponent /> : null }
|
|
||||||
</ToolbarButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect()(Toolbar);
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,5 @@ export { default as ToolbarButton } from './ToolbarButton';
|
||||||
export { default as ToolbarButtonV2 } from './ToolbarButtonV2';
|
export { default as ToolbarButtonV2 } from './ToolbarButtonV2';
|
||||||
export { default as ToolbarButtonWithDialog }
|
export { default as ToolbarButtonWithDialog }
|
||||||
from './ToolbarButtonWithDialog';
|
from './ToolbarButtonWithDialog';
|
||||||
export { default as Toolbox } from './Toolbox';
|
|
||||||
export { default as ToolboxFilmstrip } from './ToolboxFilmstrip';
|
export { default as ToolboxFilmstrip } from './ToolboxFilmstrip';
|
||||||
export { default as ToolboxV2 } from './ToolboxV2';
|
export { default as Toolbox } from './Toolbox';
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export default undefined;
|
|
|
@ -1,532 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { setFullScreen } from '../toolbox';
|
|
||||||
import {
|
|
||||||
ACTION_SHORTCUT_TRIGGERED as TRIGGERED,
|
|
||||||
AUDIO_MUTE,
|
|
||||||
VIDEO_MUTE,
|
|
||||||
createShortcutEvent,
|
|
||||||
createToolbarEvent,
|
|
||||||
sendAnalytics
|
|
||||||
} from '../analytics';
|
|
||||||
import {
|
|
||||||
getLocalParticipant,
|
|
||||||
participantUpdated
|
|
||||||
} from '../base/participants';
|
|
||||||
import { ParticipantCounter } from '../contact-list';
|
|
||||||
import { openDeviceSelectionDialog } from '../device-selection';
|
|
||||||
import { InfoDialogButton } from '../invite';
|
|
||||||
import UIEvents from '../../../service/UI/UIEvents';
|
|
||||||
import { VideoQualityButton } from '../video-quality';
|
|
||||||
|
|
||||||
import ProfileButton from './components/ProfileButton';
|
|
||||||
|
|
||||||
declare var APP: Object;
|
|
||||||
declare var interfaceConfig: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cache of {@link getDefaultButtons()}.
|
|
||||||
*/
|
|
||||||
let defaultButtons: Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a map of all button descriptors and according properties.
|
|
||||||
*
|
|
||||||
* @returns {Object} - The maps of default button descriptors.
|
|
||||||
*/
|
|
||||||
export default function getDefaultButtons() {
|
|
||||||
if (defaultButtons) {
|
|
||||||
return defaultButtons;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultButtons = {
|
|
||||||
/**
|
|
||||||
* The descriptor of the camera toolbar button.
|
|
||||||
*/
|
|
||||||
camera: {
|
|
||||||
classNames: [ 'button', 'icon-camera' ],
|
|
||||||
enabled: true,
|
|
||||||
isDisplayed: () => true,
|
|
||||||
id: 'toolbar_button_camera',
|
|
||||||
onClick() {
|
|
||||||
// TODO: Why is this different from the code which handles
|
|
||||||
// a keyboard shortcut?
|
|
||||||
const newVideoMutedState = !APP.conference.isLocalVideoMuted();
|
|
||||||
|
|
||||||
// The 'enable' attribute in the event is set to true if the
|
|
||||||
// button click triggered a mute action, and set to false if it
|
|
||||||
// triggered an unmute action.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
VIDEO_MUTE,
|
|
||||||
{
|
|
||||||
enable: newVideoMutedState
|
|
||||||
}));
|
|
||||||
APP.UI.emitEvent(UIEvents.VIDEO_MUTED, newVideoMutedState);
|
|
||||||
},
|
|
||||||
popups: [
|
|
||||||
{
|
|
||||||
dataAttr: 'audioOnly.featureToggleDisabled',
|
|
||||||
dataInterpolate: { feature: 'video mute' },
|
|
||||||
id: 'unmuteWhileAudioOnly'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
shortcut: 'V',
|
|
||||||
shortcutAttr: 'toggleVideoPopover',
|
|
||||||
shortcutFunc() {
|
|
||||||
if (APP.conference.isAudioOnly()) {
|
|
||||||
APP.UI.emitEvent(UIEvents.VIDEO_UNMUTING_WHILE_AUDIO_ONLY);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The 'enable' attribute in the event is set to true if the
|
|
||||||
// shortcut triggered a mute action, and set to false if it
|
|
||||||
// triggered an unmute action.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
VIDEO_MUTE,
|
|
||||||
TRIGGERED,
|
|
||||||
{ enable: !APP.conference.isLocalVideoMuted() }));
|
|
||||||
APP.conference.toggleVideoMuted();
|
|
||||||
},
|
|
||||||
shortcutDescription: 'keyboardShortcuts.videoMute',
|
|
||||||
tooltipKey: 'toolbar.videomute'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the chat toolbar button.
|
|
||||||
*/
|
|
||||||
chat: {
|
|
||||||
classNames: [ 'button', 'icon-chat' ],
|
|
||||||
enabled: true,
|
|
||||||
html: <span className = 'badge-round'>
|
|
||||||
<span id = 'unreadMessages' /></span>,
|
|
||||||
id: 'toolbar_button_chat',
|
|
||||||
onClick() {
|
|
||||||
// The 'enable' attribute is set to true if the click resulted
|
|
||||||
// in the chat panel being shown, and to false if it was hidden.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'toggle.chat',
|
|
||||||
{
|
|
||||||
enable: !APP.UI.isChatVisible()
|
|
||||||
}));
|
|
||||||
APP.UI.emitEvent(UIEvents.TOGGLE_CHAT);
|
|
||||||
},
|
|
||||||
shortcut: 'C',
|
|
||||||
shortcutAttr: 'toggleChatPopover',
|
|
||||||
shortcutFunc() {
|
|
||||||
// The 'enable' attribute is set to true if the shortcut
|
|
||||||
// resulted in the chat panel being shown, and to false if it
|
|
||||||
// was hidden.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
'toggle.chat',
|
|
||||||
{
|
|
||||||
enable: !APP.UI.isChatVisible()
|
|
||||||
}));
|
|
||||||
APP.UI.toggleChat();
|
|
||||||
},
|
|
||||||
shortcutDescription: 'keyboardShortcuts.toggleChat',
|
|
||||||
sideContainerId: 'chat_container',
|
|
||||||
tooltipKey: 'toolbar.chat'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the contact list toolbar button.
|
|
||||||
*/
|
|
||||||
contacts: {
|
|
||||||
childComponent: ParticipantCounter,
|
|
||||||
classNames: [ 'button', 'icon-contactList' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_contact_list',
|
|
||||||
onClick() {
|
|
||||||
// TODO: Include an 'enable' attribute which specifies whether
|
|
||||||
// the contacts panel was shown or hidden.
|
|
||||||
sendAnalytics(createToolbarEvent('contacts'));
|
|
||||||
APP.UI.emitEvent(UIEvents.TOGGLE_CONTACT_LIST);
|
|
||||||
},
|
|
||||||
sideContainerId: 'contacts_container',
|
|
||||||
tooltipKey: 'bottomtoolbar.contactlist'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the desktop sharing toolbar button.
|
|
||||||
*/
|
|
||||||
desktop: {
|
|
||||||
classNames: [ 'button', 'icon-share-desktop' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_desktopsharing',
|
|
||||||
onClick() {
|
|
||||||
// TODO: Why is the button clicked handled differently that
|
|
||||||
// a keyboard shortcut press (firing a TOGGLE_SCREENSHARING
|
|
||||||
// event vs. directly calling toggleScreenSharing())?
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'screen.sharing',
|
|
||||||
{
|
|
||||||
enable: !APP.conference.isSharingScreen
|
|
||||||
}));
|
|
||||||
APP.UI.emitEvent(UIEvents.TOGGLE_SCREENSHARING);
|
|
||||||
},
|
|
||||||
popups: [
|
|
||||||
{
|
|
||||||
dataAttr: 'audioOnly.featureToggleDisabled',
|
|
||||||
dataInterpolate: { feature: 'screen sharing' },
|
|
||||||
id: 'screenshareWhileAudioOnly'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
shortcut: 'D',
|
|
||||||
shortcutAttr: 'toggleDesktopSharingPopover',
|
|
||||||
shortcutFunc() {
|
|
||||||
// The 'enable' attribute is set to true if pressing the
|
|
||||||
// shortcut resulted in screen sharing being enabled, and false
|
|
||||||
// if it resulted in screen sharing being disabled.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
'toggle.screen.sharing',
|
|
||||||
TRIGGERED,
|
|
||||||
{ enable: !APP.conference.isSharingScreen }));
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-empty-function
|
|
||||||
APP.conference.toggleScreenSharing().catch(() => {});
|
|
||||||
},
|
|
||||||
shortcutDescription: 'keyboardShortcuts.toggleScreensharing',
|
|
||||||
tooltipKey: 'toolbar.sharescreen'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the device selection toolbar button.
|
|
||||||
*/
|
|
||||||
fodeviceselection: {
|
|
||||||
classNames: [ 'button', 'icon-settings' ],
|
|
||||||
enabled: true,
|
|
||||||
isDisplayed() {
|
|
||||||
return interfaceConfig.filmStripOnly;
|
|
||||||
},
|
|
||||||
id: 'toolbar_button_fodeviceselection',
|
|
||||||
onClick(dispatch: Function) {
|
|
||||||
sendAnalytics(
|
|
||||||
createToolbarEvent('filmstrip.only.device.selection'));
|
|
||||||
|
|
||||||
dispatch(openDeviceSelectionDialog());
|
|
||||||
},
|
|
||||||
sideContainerId: 'settings_container',
|
|
||||||
tooltipKey: 'toolbar.Settings'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the dialpad toolbar button.
|
|
||||||
*/
|
|
||||||
dialpad: {
|
|
||||||
classNames: [ 'button', 'icon-dialpad' ],
|
|
||||||
enabled: true,
|
|
||||||
|
|
||||||
// TODO: remove it after UI.updateDTMFSupport fix
|
|
||||||
hidden: true,
|
|
||||||
id: 'toolbar_button_dialpad',
|
|
||||||
onClick() {
|
|
||||||
sendAnalytics(createToolbarEvent('dialpad'));
|
|
||||||
},
|
|
||||||
tooltipKey: 'toolbar.dialpad'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the etherpad toolbar button.
|
|
||||||
*/
|
|
||||||
etherpad: {
|
|
||||||
classNames: [ 'button', 'icon-share-doc' ],
|
|
||||||
enabled: true,
|
|
||||||
hidden: true,
|
|
||||||
id: 'toolbar_button_etherpad',
|
|
||||||
onClick() {
|
|
||||||
// The 'enable' attribute is set to true if the click resulted
|
|
||||||
// in the etherpad panel being shown, or false it it was hidden.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'toggle.etherpad',
|
|
||||||
{
|
|
||||||
enable: !APP.UI.isEtherpadVisible()
|
|
||||||
}));
|
|
||||||
APP.UI.emitEvent(UIEvents.ETHERPAD_CLICKED);
|
|
||||||
},
|
|
||||||
tooltipKey: 'toolbar.etherpad'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the toolbar button which toggles full-screen mode.
|
|
||||||
*/
|
|
||||||
fullscreen: {
|
|
||||||
classNames: [ 'button', 'icon-full-screen' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_fullScreen',
|
|
||||||
onClick() {
|
|
||||||
const state = APP.store.getState();
|
|
||||||
const isFullScreen = Boolean(
|
|
||||||
state['features/toolbox'].fullScreen);
|
|
||||||
|
|
||||||
// The 'enable' attribute is set to true if the action resulted
|
|
||||||
// in fullscreen mode being enabled.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'toggle.fullscreen',
|
|
||||||
{
|
|
||||||
enable: !isFullScreen
|
|
||||||
}));
|
|
||||||
|
|
||||||
APP.store.dispatch(setFullScreen(!isFullScreen));
|
|
||||||
},
|
|
||||||
shortcut: 'S',
|
|
||||||
shortcutAttr: 'toggleFullscreenPopover',
|
|
||||||
shortcutDescription: 'keyboardShortcuts.fullScreen',
|
|
||||||
shortcutFunc() {
|
|
||||||
const state = APP.store.getState();
|
|
||||||
const isFullScreen = Boolean(
|
|
||||||
state['features/toolbox'].fullScreen);
|
|
||||||
|
|
||||||
// The 'enable' attribute is set to true if the action resulted
|
|
||||||
// in fullscreen mode being enabled.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
'toggle.fullscreen',
|
|
||||||
{
|
|
||||||
enable: !isFullScreen
|
|
||||||
}));
|
|
||||||
|
|
||||||
APP.store.dispatch(setFullScreen(!isFullScreen));
|
|
||||||
},
|
|
||||||
tooltipKey: 'toolbar.fullscreen'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the toolbar button which hangs up the
|
|
||||||
* call/conference.
|
|
||||||
*/
|
|
||||||
hangup: {
|
|
||||||
classNames: [ 'button', 'icon-hangup', 'button_hangup' ],
|
|
||||||
enabled: true,
|
|
||||||
isDisplayed: () => true,
|
|
||||||
id: 'toolbar_button_hangup',
|
|
||||||
onClick() {
|
|
||||||
sendAnalytics(createToolbarEvent('hangup'));
|
|
||||||
APP.UI.emitEvent(UIEvents.HANGUP);
|
|
||||||
},
|
|
||||||
tooltipKey: 'toolbar.hangup'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the toolbar button which opens a dialog for the
|
|
||||||
* conference URL and inviting others.
|
|
||||||
*/
|
|
||||||
info: {
|
|
||||||
component: InfoDialogButton
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the microphone toolbar button.
|
|
||||||
*/
|
|
||||||
microphone: {
|
|
||||||
classNames: [ 'button', 'icon-microphone' ],
|
|
||||||
enabled: true,
|
|
||||||
isDisplayed: () => true,
|
|
||||||
id: 'toolbar_button_mute',
|
|
||||||
onClick() {
|
|
||||||
const sharedVideoManager = APP.UI.getSharedVideoManager();
|
|
||||||
|
|
||||||
// TODO: Clicking the mute button and pressing the mute shortcut
|
|
||||||
// could be handled in a uniform manner. The code below checks
|
|
||||||
// the mute status and fires the appropriate event (MUTED or
|
|
||||||
// UNMUTED), while the code which handles the keyboard shortcut
|
|
||||||
// calls toggleAudioMuted(). Also strangely the the user is
|
|
||||||
// only warned if they click the button (and not if they use
|
|
||||||
// the shortcut).
|
|
||||||
if (APP.conference.isLocalAudioMuted()) {
|
|
||||||
// If there's a shared video with the volume "on" and we
|
|
||||||
// aren't the video owner, we warn the user
|
|
||||||
// that currently it's not possible to unmute.
|
|
||||||
if (sharedVideoManager
|
|
||||||
&& sharedVideoManager.isSharedVideoVolumeOn()
|
|
||||||
&& !sharedVideoManager.isSharedVideoOwner()) {
|
|
||||||
APP.UI.showCustomToolbarPopup(
|
|
||||||
'microphone', 'unableToUnmutePopup', true, 5000);
|
|
||||||
} else {
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
AUDIO_MUTE,
|
|
||||||
{ enable: false }));
|
|
||||||
APP.UI.emitEvent(UIEvents.AUDIO_MUTED, false, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
AUDIO_MUTE,
|
|
||||||
{ enable: true }));
|
|
||||||
APP.UI.emitEvent(UIEvents.AUDIO_MUTED, true, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
popups: [
|
|
||||||
{
|
|
||||||
dataAttr: 'toolbar.micMutedPopup',
|
|
||||||
id: 'micMutedPopup'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataAttr: 'toolbar.unableToUnmutePopup',
|
|
||||||
id: 'unableToUnmutePopup'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataAttr: 'toolbar.talkWhileMutedPopup',
|
|
||||||
id: 'talkWhileMutedPopup'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
shortcut: 'M',
|
|
||||||
shortcutAttr: 'mutePopover',
|
|
||||||
shortcutFunc() {
|
|
||||||
// The 'enable' attribute in the event is set to true if the
|
|
||||||
// shortcut triggered a mute action, and set to false if it
|
|
||||||
// triggered an unmute action.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
AUDIO_MUTE,
|
|
||||||
TRIGGERED,
|
|
||||||
{ enable: !APP.conference.isLocalAudioMuted() }));
|
|
||||||
APP.conference.toggleAudioMuted();
|
|
||||||
},
|
|
||||||
shortcutDescription: 'keyboardShortcuts.mute',
|
|
||||||
tooltipKey: 'toolbar.mute'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the profile toolbar button.
|
|
||||||
*/
|
|
||||||
profile: {
|
|
||||||
component: ProfileButton,
|
|
||||||
sideContainerId: 'profile_container'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the "Raise hand" toolbar button.
|
|
||||||
*/
|
|
||||||
raisehand: {
|
|
||||||
classNames: [ 'button', 'icon-raised-hand' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_raisehand',
|
|
||||||
onClick() {
|
|
||||||
// TODO: reduce duplication with shortcutFunc below.
|
|
||||||
const localParticipant
|
|
||||||
= getLocalParticipant(APP.store.getState());
|
|
||||||
const currentRaisedHand = localParticipant.raisedHand;
|
|
||||||
|
|
||||||
// The 'enable' attribute is set to true if the pressing of the
|
|
||||||
// shortcut resulted in the hand being raised, and to false
|
|
||||||
// if it resulted in the hand being 'lowered'.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'raise.hand',
|
|
||||||
{ enable: !currentRaisedHand }));
|
|
||||||
|
|
||||||
APP.store.dispatch(participantUpdated({
|
|
||||||
id: localParticipant.id,
|
|
||||||
local: true,
|
|
||||||
raisedHand: !currentRaisedHand
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
shortcut: 'R',
|
|
||||||
shortcutAttr: 'raiseHandPopover',
|
|
||||||
shortcutDescription: 'keyboardShortcuts.raiseHand',
|
|
||||||
shortcutFunc() {
|
|
||||||
const localParticipant
|
|
||||||
= getLocalParticipant(APP.store.getState());
|
|
||||||
const currentRaisedHand = localParticipant.raisedHand;
|
|
||||||
|
|
||||||
// The 'enable' attribute is set to true if the pressing of the
|
|
||||||
// shortcut resulted in the hand being raised, and to false
|
|
||||||
// if it resulted in the hand being 'lowered'.
|
|
||||||
sendAnalytics(createShortcutEvent(
|
|
||||||
'toggle.raise.hand',
|
|
||||||
TRIGGERED,
|
|
||||||
{ enable: !currentRaisedHand }));
|
|
||||||
|
|
||||||
APP.store.dispatch(participantUpdated({
|
|
||||||
id: localParticipant.id,
|
|
||||||
local: true,
|
|
||||||
raisedHand: !currentRaisedHand
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
tooltipKey: 'toolbar.raiseHand'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the recording toolbar button. Requires additional
|
|
||||||
* initialization in the recording module.
|
|
||||||
*/
|
|
||||||
recording: {
|
|
||||||
classNames: [ 'button' ],
|
|
||||||
enabled: true,
|
|
||||||
|
|
||||||
// will be displayed once the recording functionality is detected
|
|
||||||
hidden: true,
|
|
||||||
id: 'toolbar_button_record',
|
|
||||||
tooltipKey: 'liveStreaming.buttonTooltip'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the settings toolbar button.
|
|
||||||
*/
|
|
||||||
settings: {
|
|
||||||
classNames: [ 'button', 'icon-settings' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_settings',
|
|
||||||
onClick() {
|
|
||||||
// TODO: Include an 'enable' attribute which specifies whether
|
|
||||||
// the settings panel was shown or hidden.
|
|
||||||
sendAnalytics(createToolbarEvent('settings'));
|
|
||||||
APP.UI.emitEvent(UIEvents.TOGGLE_SETTINGS);
|
|
||||||
},
|
|
||||||
sideContainerId: 'settings_container',
|
|
||||||
tooltipKey: 'toolbar.Settings'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The descriptor of the "Share YouTube video" toolbar button.
|
|
||||||
*/
|
|
||||||
sharedvideo: {
|
|
||||||
classNames: [ 'button', 'icon-shared-video' ],
|
|
||||||
enabled: true,
|
|
||||||
id: 'toolbar_button_sharedvideo',
|
|
||||||
onClick() {
|
|
||||||
// The 'enable' attribute is set to true if the click resulted
|
|
||||||
// in the "start sharing video" dialog being shown, and false
|
|
||||||
// if it resulted in the "stop sharing video" dialog being
|
|
||||||
// shown.
|
|
||||||
sendAnalytics(createToolbarEvent(
|
|
||||||
'shared.video.toggled',
|
|
||||||
{
|
|
||||||
enable: !APP.UI.isSharedVideoShown()
|
|
||||||
}));
|
|
||||||
APP.UI.emitEvent(UIEvents.SHARED_VIDEO_CLICKED);
|
|
||||||
},
|
|
||||||
popups: [
|
|
||||||
{
|
|
||||||
dataAttr: 'toolbar.sharedVideoMutedPopup',
|
|
||||||
id: 'sharedVideoMutedPopup'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
tooltipKey: 'toolbar.sharedvideo'
|
|
||||||
},
|
|
||||||
|
|
||||||
videoquality: {
|
|
||||||
component: VideoQualityButton
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.keys(defaultButtons).forEach(name => {
|
|
||||||
const button = defaultButtons[name];
|
|
||||||
|
|
||||||
if (!button.isDisplayed) {
|
|
||||||
button.isDisplayed = _isDisplayed;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return defaultButtons;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default implementation of the {@code isDisplayed} method of the toolbar
|
|
||||||
* button definition returned by {@link getDefaultButtons()}.
|
|
||||||
*
|
|
||||||
* @returns {boolean} If the user intarface is full i.e. not filmstrip-only,
|
|
||||||
* then {@code true}; otherwise, {@code false}.
|
|
||||||
*/
|
|
||||||
function _isDisplayed() {
|
|
||||||
return !interfaceConfig.filmStripOnly;
|
|
||||||
}
|
|
|
@ -1,10 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import SideContainerToggler
|
|
||||||
from '../../../modules/UI/side_pannels/SideContainerToggler';
|
|
||||||
|
|
||||||
import getDefaultButtons from './defaultToolbarButtons';
|
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -13,92 +8,6 @@ export {
|
||||||
getButton
|
getButton
|
||||||
} from './functions.native';
|
} from './functions.native';
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an object which contains the default buttons for the primary and
|
|
||||||
* secondary toolbars.
|
|
||||||
*
|
|
||||||
* @param {Object} buttonHandlers - Contains additional toolbox button
|
|
||||||
* handlers.
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
export function getDefaultToolboxButtons(buttonHandlers: Object): Object {
|
|
||||||
let toolbarButtons = {
|
|
||||||
primaryToolbarButtons: new Map(),
|
|
||||||
secondaryToolbarButtons: new Map()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof interfaceConfig !== 'undefined'
|
|
||||||
&& interfaceConfig.TOOLBAR_BUTTONS) {
|
|
||||||
|
|
||||||
toolbarButtons
|
|
||||||
= interfaceConfig.TOOLBAR_BUTTONS.reduce(
|
|
||||||
(acc, buttonName) => {
|
|
||||||
const buttons = getDefaultButtons();
|
|
||||||
let button = buttons ? buttons[buttonName] : null;
|
|
||||||
const currentButtonHandlers = buttonHandlers[buttonName];
|
|
||||||
|
|
||||||
if (button) {
|
|
||||||
const place = _getToolbarButtonPlace(buttonName);
|
|
||||||
|
|
||||||
button.buttonName = buttonName;
|
|
||||||
|
|
||||||
if (currentButtonHandlers) {
|
|
||||||
button = {
|
|
||||||
...button,
|
|
||||||
...currentButtonHandlers
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If isDisplayed method is not defined, display the
|
|
||||||
// button only for non-filmstripOnly mode
|
|
||||||
if (button.isDisplayed()) {
|
|
||||||
acc[place].set(buttonName, button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
toolbarButtons);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toolbarButtons;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns toolbar class names to add while rendering.
|
|
||||||
*
|
|
||||||
* @param {Object} props - Props object pass to React component.
|
|
||||||
* @returns {Object}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
export function getToolbarClassNames(props: Object) {
|
|
||||||
const primaryToolbarClassNames = [
|
|
||||||
interfaceConfig.filmStripOnly
|
|
||||||
? 'toolbar_filmstrip-only'
|
|
||||||
: 'toolbar_primary'
|
|
||||||
];
|
|
||||||
const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
|
|
||||||
|
|
||||||
if (props._visible) {
|
|
||||||
const slideInAnimation
|
|
||||||
= SideContainerToggler.isVisible ? 'slideInExtX' : 'slideInX';
|
|
||||||
|
|
||||||
primaryToolbarClassNames.push('fadeIn');
|
|
||||||
secondaryToolbarClassNames.push(slideInAnimation);
|
|
||||||
} else {
|
|
||||||
const slideOutAnimation
|
|
||||||
= SideContainerToggler.isVisible ? 'slideOutExtX' : 'slideOutX';
|
|
||||||
|
|
||||||
primaryToolbarClassNames.push('fadeOut');
|
|
||||||
secondaryToolbarClassNames.push(slideOutAnimation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
primaryToolbarClassName: primaryToolbarClassNames.join(' '),
|
|
||||||
secondaryToolbarClassName: secondaryToolbarClassNames.join(' ')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for getting the height of the toolbox.
|
* Helper for getting the height of the toolbox.
|
||||||
*
|
*
|
||||||
|
@ -122,18 +31,3 @@ export function isButtonEnabled(name: string) {
|
||||||
return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1
|
return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1
|
||||||
|| interfaceConfig.MAIN_TOOLBAR_BUTTONS.indexOf(name) !== -1;
|
|| interfaceConfig.MAIN_TOOLBAR_BUTTONS.indexOf(name) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get place for toolbar button. Now it can be in the primary Toolbar or in the
|
|
||||||
* secondary Toolbar.
|
|
||||||
*
|
|
||||||
* @param {string} btn - Button name.
|
|
||||||
* @private
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function _getToolbarButtonPlace(btn) {
|
|
||||||
return (
|
|
||||||
interfaceConfig.MAIN_TOOLBAR_BUTTONS.includes(btn)
|
|
||||||
? 'primaryToolbarButtons'
|
|
||||||
: 'secondaryToolbarButtons');
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {
|
|
||||||
MEDIA_TYPE,
|
|
||||||
SET_AUDIO_AVAILABLE,
|
|
||||||
SET_VIDEO_AVAILABLE
|
|
||||||
} from '../base/media';
|
|
||||||
import { MiddlewareRegistry } from '../base/redux';
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
import { isLocalTrackMuted, TRACK_UPDATED } from '../base/tracks';
|
|
||||||
|
|
||||||
import { setToolbarButton, toggleFullScreen } from './actions';
|
|
||||||
import {
|
import {
|
||||||
CLEAR_TOOLBOX_TIMEOUT,
|
CLEAR_TOOLBOX_TIMEOUT,
|
||||||
FULL_SCREEN_CHANGED,
|
|
||||||
SET_TOOLBOX_TIMEOUT,
|
SET_TOOLBOX_TIMEOUT,
|
||||||
SET_FULL_SCREEN
|
SET_FULL_SCREEN
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
|
@ -34,12 +26,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FULL_SCREEN_CHANGED:
|
|
||||||
return _fullScreenChanged(store, next, action);
|
|
||||||
|
|
||||||
case SET_AUDIO_AVAILABLE:
|
|
||||||
return _setMediaAvailableOrMuted(store, next, action);
|
|
||||||
|
|
||||||
case SET_FULL_SCREEN:
|
case SET_FULL_SCREEN:
|
||||||
return _setFullScreen(next, action);
|
return _setFullScreen(next, action);
|
||||||
|
|
||||||
|
@ -48,102 +34,15 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
const { handler, timeoutMS } = action;
|
const { handler, timeoutMS } = action;
|
||||||
|
|
||||||
clearTimeout(timeoutID);
|
clearTimeout(timeoutID);
|
||||||
const newTimeoutId = setTimeout(handler, timeoutMS);
|
action.timeoutID = setTimeout(handler, timeoutMS);
|
||||||
|
|
||||||
action.timeoutID = newTimeoutId;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SET_VIDEO_AVAILABLE:
|
|
||||||
return _setMediaAvailableOrMuted(store, next, action);
|
|
||||||
|
|
||||||
case TRACK_UPDATED:
|
|
||||||
if (action.track.jitsiTrack.isLocal()) {
|
|
||||||
return _setMediaAvailableOrMuted(store, next, action);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the the redux state with the current known state of full screen.
|
|
||||||
*
|
|
||||||
* @param {Store} store - The redux store in which the specified action is being
|
|
||||||
* dispatched.
|
|
||||||
* @param {Dispatch} next - The redux dispatch function to dispatch the
|
|
||||||
* specified action to the specified store.
|
|
||||||
* @param {Action} action - The redux action FULL_SCREEN_CHANGED which is being
|
|
||||||
* dispatched in the specified store.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
|
||||||
*/
|
|
||||||
function _fullScreenChanged({ dispatch }, next, action) {
|
|
||||||
if (typeof APP === 'object') {
|
|
||||||
dispatch(toggleFullScreen(action.fullScreen));
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjusts the state of toolbar's microphone or camera button.
|
|
||||||
*
|
|
||||||
* @param {Store} store - The redux store.
|
|
||||||
* @param {Function} next - The redux function to continue dispatching the
|
|
||||||
* specified {@code action} in the specified {@code store}.
|
|
||||||
* @param {Object} action - {@code SET_AUDIO_AVAILABLE},
|
|
||||||
* {@code SET_VIDEO_AVAILABLE}, or {@code TRACK_UPDATED}.
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
function _setMediaAvailableOrMuted({ dispatch, getState }, next, action) {
|
|
||||||
const result = next(action);
|
|
||||||
|
|
||||||
let mediaType;
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case SET_AUDIO_AVAILABLE:
|
|
||||||
mediaType = MEDIA_TYPE.AUDIO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SET_VIDEO_AVAILABLE:
|
|
||||||
mediaType = MEDIA_TYPE.VIDEO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TRACK_UPDATED:
|
|
||||||
mediaType
|
|
||||||
= action.track.jitsiTrack.isAudioTrack()
|
|
||||||
? MEDIA_TYPE.AUDIO
|
|
||||||
: MEDIA_TYPE.VIDEO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error(`Unsupported action ${action}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = getState();
|
|
||||||
const { audio, video } = state['features/base/media'];
|
|
||||||
const { available } = mediaType === MEDIA_TYPE.AUDIO ? audio : video;
|
|
||||||
const i18nKey
|
|
||||||
= mediaType === MEDIA_TYPE.AUDIO
|
|
||||||
? available ? 'mute' : 'micDisabled'
|
|
||||||
: available ? 'videomute' : 'cameraDisabled';
|
|
||||||
const tracks = state['features/base/tracks'];
|
|
||||||
const muted = isLocalTrackMuted(tracks, mediaType);
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
setToolbarButton(
|
|
||||||
mediaType === MEDIA_TYPE.AUDIO ? 'microphone' : 'camera',
|
|
||||||
{
|
|
||||||
enabled: available,
|
|
||||||
i18n: `[content]toolbar.${i18nKey}`,
|
|
||||||
toggled: available ? muted : true
|
|
||||||
}));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes an external request to enter or exit full screen mode.
|
* Makes an external request to enter or exit full screen mode.
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
SET_DEFAULT_TOOLBOX_BUTTONS,
|
SET_DEFAULT_TOOLBOX_BUTTONS,
|
||||||
SET_SUBJECT,
|
SET_SUBJECT,
|
||||||
SET_SUBJECT_SLIDE_IN,
|
SET_SUBJECT_SLIDE_IN,
|
||||||
SET_TOOLBAR_BUTTON,
|
|
||||||
SET_TOOLBAR_HOVERED,
|
SET_TOOLBAR_HOVERED,
|
||||||
SET_TOOLBOX_ALWAYS_VISIBLE,
|
SET_TOOLBOX_ALWAYS_VISIBLE,
|
||||||
SET_TOOLBOX_ENABLED,
|
SET_TOOLBOX_ENABLED,
|
||||||
|
@ -16,7 +15,6 @@ import {
|
||||||
SET_TOOLBOX_TIMEOUT_MS,
|
SET_TOOLBOX_TIMEOUT_MS,
|
||||||
SET_TOOLBOX_VISIBLE
|
SET_TOOLBOX_VISIBLE
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import getDefaultButtons from './defaultToolbarButtons';
|
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
|
@ -161,9 +159,6 @@ ReducerRegistry.register(
|
||||||
subjectSlideIn: action.subjectSlideIn
|
subjectSlideIn: action.subjectSlideIn
|
||||||
};
|
};
|
||||||
|
|
||||||
case SET_TOOLBAR_BUTTON:
|
|
||||||
return _setToolbarButton(state, action);
|
|
||||||
|
|
||||||
case SET_TOOLBAR_HOVERED:
|
case SET_TOOLBAR_HOVERED:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -204,46 +199,3 @@ ReducerRegistry.register(
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduces the redux action {@code SET_TOOLBAR_BUTTON} in the feature toolbox.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The redux state.
|
|
||||||
* @param {Object} action - The redux action of type {@code SET_TOOLBAR_BUTTON}.
|
|
||||||
* @param {Object} action.button - Object describing toolbar button.
|
|
||||||
* @param {Object} action.buttonName - The name of the button.
|
|
||||||
* @private
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
function _setToolbarButton(state, { button, buttonName }): Object {
|
|
||||||
// XXX getDefaultButtons, defaultToolbarButtons, SET_TOOLBAR_BUTTON are
|
|
||||||
// abstractions fully implemented on Web only.
|
|
||||||
const buttons = getDefaultButtons && getDefaultButtons();
|
|
||||||
const buttonDefinition = buttons && buttons[buttonName];
|
|
||||||
|
|
||||||
// We don't need to update if the button shouldn't be displayed
|
|
||||||
if (!buttonDefinition || !buttonDefinition.isDisplayed()) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { primaryToolbarButtons, secondaryToolbarButtons } = state;
|
|
||||||
let selectedButton = primaryToolbarButtons.get(buttonName);
|
|
||||||
let place = 'primaryToolbarButtons';
|
|
||||||
|
|
||||||
if (!selectedButton) {
|
|
||||||
selectedButton = secondaryToolbarButtons.get(buttonName);
|
|
||||||
place = 'secondaryToolbarButtons';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedButton = {
|
|
||||||
...selectedButton,
|
|
||||||
...button
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatedToolbar = state[place].set(buttonName, selectedButton);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
[place]: new Map(updatedToolbar)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue