It got broken while rewriting the Web toolbar in React Toolbox. There is a problem with the toolbars and how we construct the intialState of the buttons. The _getInitialState() in the toolbox reducer gets the list of buttons from interfaceConfig, but in fact interfaceConfig is meant to be overriden in several very important cases. One of the cases being the external API, which we use in several projects in production.
260 lines
6.7 KiB
JavaScript
260 lines
6.7 KiB
JavaScript
/* @flow */
|
|
|
|
import React, { Component } from 'react';
|
|
import { connect } from 'react-redux';
|
|
|
|
import UIEvents from '../../../../service/UI/UIEvents';
|
|
|
|
import {
|
|
setDefaultToolboxButtons,
|
|
setToolboxAlwaysVisible
|
|
} from '../actions';
|
|
import {
|
|
abstractMapStateToProps,
|
|
showCustomToolbarPopup
|
|
} from '../functions';
|
|
import Notice from './Notice';
|
|
import PrimaryToolbar from './PrimaryToolbar';
|
|
import SecondaryToolbar from './SecondaryToolbar';
|
|
|
|
declare var APP: Object;
|
|
declare var config: Object;
|
|
declare var interfaceConfig: Object;
|
|
|
|
/**
|
|
* Implements the conference toolbox on React/Web.
|
|
*/
|
|
class Toolbox extends Component {
|
|
/**
|
|
* App component's property types.
|
|
*
|
|
* @static
|
|
*/
|
|
static propTypes = {
|
|
/**
|
|
* Handler dispatching setting default buttons action.
|
|
*/
|
|
_setDefaultToolboxButtons: React.PropTypes.func,
|
|
|
|
/**
|
|
* Handler dispatching reset always visible toolbox action.
|
|
*/
|
|
_setToolboxAlwaysVisible: React.PropTypes.func,
|
|
|
|
/**
|
|
* Represents conference subject.
|
|
*/
|
|
_subject: React.PropTypes.string,
|
|
|
|
/**
|
|
* Flag showing whether to set subject slide in animation.
|
|
*/
|
|
_subjectSlideIn: React.PropTypes.bool,
|
|
|
|
/**
|
|
* Property containing toolbox timeout id.
|
|
*/
|
|
_timeoutID: React.PropTypes.number
|
|
};
|
|
|
|
/**
|
|
* Invokes reset always visible toolbox after mounting the component and
|
|
* registers legacy UI listeners.
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
componentDidMount(): void {
|
|
this.props._setToolboxAlwaysVisible();
|
|
|
|
APP.UI.addListener(
|
|
UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
|
|
showCustomToolbarPopup);
|
|
|
|
// FIXME The redux action SET_DEFAULT_TOOLBOX_BUTTONS and related source
|
|
// code such as the redux action creator setDefaultToolboxButtons and
|
|
// _setDefaultToolboxButtons were introduced to solve the following bug
|
|
// in the implementation of features/toolbar at the time of this
|
|
// writing: getDefaultToolboxButtons uses interfaceConfig which is not
|
|
// in the redux store at the time of this writing yet interfaceConfig is
|
|
// modified after getDefaultToolboxButtons is called.
|
|
// SET_DEFAULT_TOOLBOX_BUTTONS represents/implements an explicit delay
|
|
// of the invocation of getDefaultToolboxButtons until, heuristically,
|
|
// all existing changes to interfaceConfig have been applied already in
|
|
// our known execution paths.
|
|
this.props._setDefaultToolboxButtons();
|
|
}
|
|
|
|
/**
|
|
* Unregisters legacy UI listeners.
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
componentWillUnmount(): void {
|
|
APP.UI.removeListener(
|
|
UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
|
|
showCustomToolbarPopup);
|
|
}
|
|
|
|
/**
|
|
* Implements React's {@link Component#render()}.
|
|
*
|
|
* @inheritdoc
|
|
* @returns {ReactElement}
|
|
*/
|
|
render(): ReactElement<*> {
|
|
return (
|
|
<div>
|
|
{
|
|
this._renderSubject()
|
|
}
|
|
{
|
|
this._renderToolbars()
|
|
}
|
|
<div id = 'sideToolbarContainer' />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns React element representing toolbox subject.
|
|
*
|
|
* @returns {ReactElement}
|
|
* @private
|
|
*/
|
|
_renderSubject(): ReactElement<*> | null {
|
|
const { _subjectSlideIn, _subject } = this.props;
|
|
const classNames = [ 'subject' ];
|
|
|
|
if (!_subject) {
|
|
return null;
|
|
}
|
|
|
|
if (_subjectSlideIn) {
|
|
classNames.push('subject_slide-in');
|
|
} else {
|
|
classNames.push('subject_slide-out');
|
|
}
|
|
|
|
// XXX: Since chat is now not reactified we have to dangerously set
|
|
// inner HTML into the component. This has to be refactored while
|
|
// reactification of the Chat.js
|
|
const innerHtml = {
|
|
__html: _subject
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className = { classNames.join(' ') }
|
|
|
|
// eslint-disable-next-line react/no-danger
|
|
dangerouslySetInnerHTML = { innerHtml }
|
|
id = 'subject' />
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders primary and secondary toolbars.
|
|
*
|
|
* @returns {ReactElement}
|
|
* @private
|
|
*/
|
|
_renderToolbars(): ReactElement<*> | null {
|
|
// The toolbars should not be shown until timeoutID is initialized.
|
|
if (this.props._timeoutID === null) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<Notice />
|
|
<PrimaryToolbar />
|
|
<SecondaryToolbar />
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maps parts of Redux actions to component props.
|
|
*
|
|
* @param {Function} dispatch - Redux action dispatcher.
|
|
* @returns {{
|
|
* _setDefaultToolboxButtons: Function,
|
|
* _setToolboxAlwaysVisible: Function
|
|
* }}
|
|
* @private
|
|
*/
|
|
function _mapDispatchToProps(dispatch: Function): Object {
|
|
return {
|
|
/**
|
|
* Dispatches a (redux) action to set the default toolbar buttons.
|
|
*
|
|
* @returns {Object} Dispatched action.
|
|
*/
|
|
_setDefaultToolboxButtons() {
|
|
dispatch(setDefaultToolboxButtons());
|
|
},
|
|
|
|
/**
|
|
* Dispatches a (redux) action to reset the permanent visibility of
|
|
* the Toolbox.
|
|
*
|
|
* @returns {Object} Dispatched action.
|
|
*/
|
|
_setToolboxAlwaysVisible() {
|
|
dispatch(
|
|
setToolboxAlwaysVisible(config.alwaysVisibleToolbar === true));
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Maps parts of toolbox state to component props.
|
|
*
|
|
* @param {Object} state - Redux state.
|
|
* @private
|
|
* @returns {{
|
|
* _audioMuted: boolean,
|
|
* _locked: boolean,
|
|
* _subjectSlideIn: boolean,
|
|
* _videoMuted: boolean
|
|
* }}
|
|
*/
|
|
function _mapStateToProps(state: Object): Object {
|
|
const {
|
|
subject,
|
|
subjectSlideIn,
|
|
timeoutID
|
|
} = state['features/toolbox'];
|
|
|
|
return {
|
|
...abstractMapStateToProps(state),
|
|
|
|
/**
|
|
* Property containing conference subject.
|
|
*
|
|
* @protected
|
|
* @type {string}
|
|
*/
|
|
_subject: subject,
|
|
|
|
/**
|
|
* Flag showing whether to set subject slide in animation.
|
|
*
|
|
* @protected
|
|
* @type {boolean}
|
|
*/
|
|
_subjectSlideIn: subjectSlideIn,
|
|
|
|
/**
|
|
* Property containing toolbox timeout id.
|
|
*
|
|
* @protected
|
|
* @type {number}
|
|
*/
|
|
_timeoutID: timeoutID
|
|
};
|
|
}
|
|
|
|
export default connect(_mapStateToProps, _mapDispatchToProps)(Toolbox);
|