2017-02-16 23:02:40 +00:00
|
|
|
/* @flow */
|
|
|
|
|
|
|
|
import React, { Component } from 'react';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
|
|
|
|
import UIEvents from '../../../../service/UI/UIEvents';
|
|
|
|
|
2017-04-04 11:53:10 +00:00
|
|
|
import {
|
|
|
|
setDefaultToolboxButtons,
|
|
|
|
setToolboxAlwaysVisible
|
|
|
|
} from '../actions';
|
2017-02-16 23:02:40 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Implements the conference toolbox on React/Web.
|
2017-02-16 23:02:40 +00:00
|
|
|
*/
|
2017-04-01 05:52:40 +00:00
|
|
|
class Toolbox extends Component {
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
|
|
|
* App component's property types.
|
|
|
|
*
|
|
|
|
* @static
|
|
|
|
*/
|
|
|
|
static propTypes = {
|
2017-04-06 18:43:36 +00:00
|
|
|
/**
|
|
|
|
* Indicates if the toolbox should always be visible.
|
|
|
|
*/
|
|
|
|
_alwaysVisible: React.PropTypes.bool,
|
|
|
|
|
2017-04-04 11:53:10 +00:00
|
|
|
/**
|
|
|
|
* Handler dispatching setting default buttons action.
|
|
|
|
*/
|
|
|
|
_setDefaultToolboxButtons: React.PropTypes.func,
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Handler dispatching reset always visible toolbox action.
|
2017-02-16 23:02:40 +00:00
|
|
|
*/
|
2017-04-01 05:52:40 +00:00
|
|
|
_setToolboxAlwaysVisible: React.PropTypes.func,
|
2017-02-16 23:02:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents conference subject.
|
|
|
|
*/
|
|
|
|
_subject: React.PropTypes.string,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag showing whether to set subject slide in animation.
|
|
|
|
*/
|
|
|
|
_subjectSlideIn: React.PropTypes.bool,
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Property containing toolbox timeout id.
|
2017-02-16 23:02:40 +00:00
|
|
|
*/
|
2017-04-01 05:52:40 +00:00
|
|
|
_timeoutID: React.PropTypes.number
|
2017-02-16 23:02:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Invokes reset always visible toolbox after mounting the component and
|
2017-02-16 23:02:40 +00:00
|
|
|
* registers legacy UI listeners.
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentDidMount(): void {
|
2017-04-01 05:52:40 +00:00
|
|
|
this.props._setToolboxAlwaysVisible();
|
2017-02-16 23:02:40 +00:00
|
|
|
|
2017-04-01 05:52:40 +00:00
|
|
|
APP.UI.addListener(
|
|
|
|
UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
|
2017-02-16 23:02:40 +00:00
|
|
|
showCustomToolbarPopup);
|
2017-04-04 11:53:10 +00:00
|
|
|
|
|
|
|
// 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();
|
2017-02-16 23:02:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregisters legacy UI listeners.
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentWillUnmount(): void {
|
2017-04-01 05:52:40 +00:00
|
|
|
APP.UI.removeListener(
|
|
|
|
UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
|
2017-02-16 23:02:40 +00:00
|
|
|
showCustomToolbarPopup);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render(): ReactElement<*> {
|
|
|
|
return (
|
2017-07-06 02:07:00 +00:00
|
|
|
<div className = 'toolbox'>
|
2017-02-16 23:02:40 +00:00
|
|
|
{
|
|
|
|
this._renderSubject()
|
|
|
|
}
|
|
|
|
{
|
|
|
|
this._renderToolbars()
|
|
|
|
}
|
|
|
|
<div id = 'sideToolbarContainer' />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Returns React element representing toolbox subject.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
|
|
|
* @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 {
|
2017-04-06 18:43:36 +00:00
|
|
|
// In case we're not in alwaysVisible mode the toolbox should not be
|
|
|
|
// shown until timeoutID is initialized.
|
|
|
|
if (!this.props._alwaysVisible && this.props._timeoutID === null) {
|
2017-02-16 23:02:40 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2017-07-06 02:07:00 +00:00
|
|
|
<div className = 'toolbox-toolbars'>
|
2017-02-16 23:02:40 +00:00
|
|
|
<Notice />
|
|
|
|
<PrimaryToolbar />
|
|
|
|
<SecondaryToolbar />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps parts of Redux actions to component props.
|
|
|
|
*
|
|
|
|
* @param {Function} dispatch - Redux action dispatcher.
|
|
|
|
* @returns {{
|
2017-04-04 11:53:10 +00:00
|
|
|
* _setDefaultToolboxButtons: Function,
|
2017-04-01 05:52:40 +00:00
|
|
|
* _setToolboxAlwaysVisible: Function
|
2017-02-16 23:02:40 +00:00
|
|
|
* }}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function _mapDispatchToProps(dispatch: Function): Object {
|
|
|
|
return {
|
2017-04-04 11:53:10 +00:00
|
|
|
/**
|
|
|
|
* Dispatches a (redux) action to set the default toolbar buttons.
|
|
|
|
*
|
|
|
|
* @returns {Object} Dispatched action.
|
|
|
|
*/
|
|
|
|
_setDefaultToolboxButtons() {
|
|
|
|
dispatch(setDefaultToolboxButtons());
|
|
|
|
},
|
2017-02-16 23:02:40 +00:00
|
|
|
|
|
|
|
/**
|
2017-04-04 11:53:10 +00:00
|
|
|
* Dispatches a (redux) action to reset the permanent visibility of
|
|
|
|
* the Toolbox.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
|
|
|
* @returns {Object} Dispatched action.
|
|
|
|
*/
|
2017-04-01 05:52:40 +00:00
|
|
|
_setToolboxAlwaysVisible() {
|
2017-04-06 18:43:36 +00:00
|
|
|
dispatch(setToolboxAlwaysVisible(
|
|
|
|
config.alwaysVisibleToolbar === true
|
|
|
|
|| interfaceConfig.filmStripOnly));
|
2017-02-16 23:02:40 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Maps parts of toolbox state to component props.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
|
|
|
* @param {Object} state - Redux state.
|
|
|
|
* @private
|
|
|
|
* @returns {{
|
2017-04-06 18:43:36 +00:00
|
|
|
* _alwaysVisible: boolean,
|
2017-02-16 23:02:40 +00:00
|
|
|
* _audioMuted: boolean,
|
|
|
|
* _subjectSlideIn: boolean,
|
|
|
|
* _videoMuted: boolean
|
|
|
|
* }}
|
|
|
|
*/
|
|
|
|
function _mapStateToProps(state: Object): Object {
|
|
|
|
const {
|
2017-04-06 18:43:36 +00:00
|
|
|
alwaysVisible,
|
2017-02-16 23:02:40 +00:00
|
|
|
subject,
|
|
|
|
subjectSlideIn,
|
2017-04-01 05:52:40 +00:00
|
|
|
timeoutID
|
|
|
|
} = state['features/toolbox'];
|
2017-02-16 23:02:40 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
...abstractMapStateToProps(state),
|
|
|
|
|
2017-04-06 18:43:36 +00:00
|
|
|
/**
|
|
|
|
* Indicates if the toolbox should always be visible.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_alwaysVisible: alwaysVisible,
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
|
|
|
* Property containing conference subject.
|
|
|
|
*
|
2017-04-06 18:43:36 +00:00
|
|
|
* @private
|
2017-02-16 23:02:40 +00:00
|
|
|
* @type {string}
|
|
|
|
*/
|
|
|
|
_subject: subject,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag showing whether to set subject slide in animation.
|
|
|
|
*
|
2017-04-06 18:43:36 +00:00
|
|
|
* @private
|
2017-02-16 23:02:40 +00:00
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_subjectSlideIn: subjectSlideIn,
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Property containing toolbox timeout id.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
2017-04-06 18:43:36 +00:00
|
|
|
* @private
|
2017-02-16 23:02:40 +00:00
|
|
|
* @type {number}
|
|
|
|
*/
|
2017-04-01 05:52:40 +00:00
|
|
|
_timeoutID: timeoutID
|
2017-02-16 23:02:40 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-01 05:52:40 +00:00
|
|
|
export default connect(_mapStateToProps, _mapDispatchToProps)(Toolbox);
|