2017-02-16 23:02:40 +00:00
|
|
|
/* @flow */
|
|
|
|
|
|
|
|
import React, { Component } from 'react';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
|
|
|
|
import { FeedbackButton } from '../../feedback';
|
|
|
|
import UIEvents from '../../../../service/UI/UIEvents';
|
|
|
|
|
|
|
|
import {
|
|
|
|
changeLocalRaiseHand,
|
|
|
|
setProfileButtonUnclickable,
|
|
|
|
showRecordingButton,
|
|
|
|
toggleSideToolbarContainer
|
|
|
|
} from '../actions';
|
|
|
|
import { getToolbarClassNames } from '../functions';
|
2017-04-06 22:40:10 +00:00
|
|
|
import Toolbar from './Toolbar';
|
2017-02-16 23:02:40 +00:00
|
|
|
|
|
|
|
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 = {
|
2017-04-21 10:00:50 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines whether the local participant is a
|
|
|
|
* guest in the conference.
|
|
|
|
*/
|
|
|
|
_isGuest: React.PropTypes.bool,
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
|
|
|
* Handler dispatching local "Raise hand".
|
|
|
|
*/
|
|
|
|
_onLocalRaiseHandChanged: React.PropTypes.func,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler setting profile button unclickable.
|
|
|
|
*/
|
|
|
|
_onSetProfileButtonUnclickable: React.PropTypes.func,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for showing recording button.
|
|
|
|
*/
|
|
|
|
_onShowRecordingButton: React.PropTypes.func,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler dispatching toggle toolbar container.
|
|
|
|
*/
|
|
|
|
_onSideToolbarContainerToggled: React.PropTypes.func,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Contains map of secondary toolbar buttons.
|
|
|
|
*/
|
|
|
|
_secondaryToolbarButtons: React.PropTypes.instanceOf(Map),
|
|
|
|
|
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Shows whether toolbox is visible.
|
2017-02-16 23:02:40 +00:00
|
|
|
*/
|
|
|
|
_visible: React.PropTypes.bool
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs instance of SecondaryToolbar component.
|
|
|
|
*
|
|
|
|
* @param {Object} props - React component properties.
|
|
|
|
*/
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
const buttonHandlers = {
|
|
|
|
/**
|
|
|
|
* Mount handler for profile button.
|
|
|
|
*
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
profile: {
|
2017-04-21 10:00:50 +00:00
|
|
|
onMount: () => {
|
|
|
|
const {
|
|
|
|
_isGuest,
|
|
|
|
_onSetProfileButtonUnclickable
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
_isGuest || _onSetProfileButtonUnclickable(true);
|
|
|
|
}
|
2017-02-16 23:02:40 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mount/Unmount handlers for raisehand button.
|
|
|
|
*
|
|
|
|
* @type {button}
|
|
|
|
*/
|
|
|
|
raisehand: {
|
2017-04-06 22:40:10 +00:00
|
|
|
onMount: () =>
|
|
|
|
APP.UI.addListener(
|
|
|
|
UIEvents.LOCAL_RAISE_HAND_CHANGED,
|
|
|
|
this.props._onLocalRaiseHandChanged),
|
|
|
|
onUnmount: () =>
|
|
|
|
APP.UI.removeListener(
|
|
|
|
UIEvents.LOCAL_RAISE_HAND_CHANGED,
|
|
|
|
this.props._onLocalRaiseHandChanged)
|
2017-02-16 23:02:40 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mount handler for recording button.
|
|
|
|
*
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
recording: {
|
2017-04-06 22:40:10 +00:00
|
|
|
onMount: () =>
|
|
|
|
config.enableRecording
|
|
|
|
&& this.props._onShowRecordingButton()
|
2017-02-16 23:02:40 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
/**
|
|
|
|
* Object containing on mount/unmount handlers for toolbar buttons.
|
|
|
|
*
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
buttonHandlers
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register legacy UI listener.
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentDidMount(): void {
|
2017-04-06 22:40:10 +00:00
|
|
|
APP.UI.addListener(
|
|
|
|
UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
|
2017-02-16 23:02:40 +00:00
|
|
|
this.props._onSideToolbarContainerToggled);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregisters legacy UI listener.
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentWillUnmount(): void {
|
2017-04-06 22:40:10 +00:00
|
|
|
APP.UI.removeListener(
|
|
|
|
UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
|
2017-02-16 23:02:40 +00:00
|
|
|
this.props._onSideToolbarContainerToggled);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders secondary toolbar component.
|
|
|
|
*
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
2017-04-06 18:43:36 +00:00
|
|
|
render(): ReactElement<*> | null {
|
2017-02-16 23:02:40 +00:00
|
|
|
const { _secondaryToolbarButtons } = this.props;
|
2017-04-06 18:43:36 +00:00
|
|
|
|
|
|
|
// The number of buttons to show in the toolbar isn't fixed, it depends
|
2017-04-06 22:40:10 +00:00
|
|
|
// on the availability of features and configuration parameters. So
|
|
|
|
// there may be nothing to render.
|
2017-04-06 18:43:36 +00:00
|
|
|
if (_secondaryToolbarButtons.size === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { buttonHandlers } = this.state;
|
2017-02-16 23:02:40 +00:00
|
|
|
const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
|
|
|
|
|
|
|
|
return (
|
2017-04-01 05:52:40 +00:00
|
|
|
<Toolbar
|
2017-02-16 23:02:40 +00:00
|
|
|
buttonHandlers = { buttonHandlers }
|
|
|
|
className = { secondaryToolbarClassName }
|
2017-04-06 22:40:10 +00:00
|
|
|
toolbarButtons = { _secondaryToolbarButtons }
|
|
|
|
tooltipPosition = { 'right' }>
|
2017-02-16 23:02:40 +00:00
|
|
|
<FeedbackButton />
|
2017-04-01 05:52:40 +00:00
|
|
|
</Toolbar>
|
2017-02-16 23:02:40 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps some of Redux actions to component's props.
|
|
|
|
*
|
|
|
|
* @param {Function} dispatch - Redux action dispatcher.
|
|
|
|
* @returns {{
|
2017-04-06 22:40:10 +00:00
|
|
|
* _onLocalRaiseHandChanged: Function,
|
|
|
|
* _onSetProfileButtonUnclickable: Function,
|
|
|
|
* _onShowRecordingButton: Function,
|
|
|
|
* _onSideToolbarContainerToggled
|
2017-02-16 23:02:40 +00:00
|
|
|
* }}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function _mapDispatchToProps(dispatch: Function): Object {
|
|
|
|
return {
|
|
|
|
/**
|
|
|
|
* Dispatches an action that 'hand' is raised.
|
|
|
|
*
|
|
|
|
* @param {boolean} isRaisedHand - Show whether hand is raised.
|
|
|
|
* @returns {Object} Dispatched action.
|
|
|
|
*/
|
|
|
|
_onLocalRaiseHandChanged(isRaisedHand: boolean) {
|
|
|
|
return dispatch(changeLocalRaiseHand(isRaisedHand));
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dispatches an action signalling to set profile button unclickable.
|
|
|
|
*
|
|
|
|
* @param {boolean} unclickable - Flag showing whether unclickable
|
|
|
|
* property is true.
|
|
|
|
* @returns {Object} Dispatched action.
|
|
|
|
*/
|
|
|
|
_onSetProfileButtonUnclickable(unclickable: boolean) {
|
|
|
|
return dispatch(setProfileButtonUnclickable(unclickable));
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dispatches an action signalling that recording button should be
|
|
|
|
* shown.
|
|
|
|
*
|
|
|
|
* @returns {Object} Dispatched action.
|
|
|
|
*/
|
|
|
|
_onShowRecordingButton() {
|
|
|
|
return dispatch(showRecordingButton());
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
return dispatch(toggleSideToolbarContainer(containerId));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps part of Redux state to component's props.
|
|
|
|
*
|
|
|
|
* @param {Object} state - Snapshot of Redux store.
|
|
|
|
* @returns {{
|
2017-04-21 10:00:50 +00:00
|
|
|
* _isGuest: boolean,
|
2017-04-06 22:40:10 +00:00
|
|
|
* _secondaryToolbarButtons: Map,
|
|
|
|
* _visible: boolean
|
2017-02-16 23:02:40 +00:00
|
|
|
* }}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function _mapStateToProps(state: Object): Object {
|
2017-04-21 10:00:50 +00:00
|
|
|
const { isGuest } = state['features/jwt'];
|
|
|
|
const { secondaryToolbarButtons, visible } = state['features/toolbox'];
|
2017-02-16 23:02:40 +00:00
|
|
|
|
|
|
|
return {
|
2017-04-21 10:00:50 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines whether the local participant is a
|
|
|
|
* guest in the conference.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_isGuest: isGuest,
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
|
|
|
* Default toolbar buttons for secondary toolbar.
|
|
|
|
*
|
2017-04-06 22:40:10 +00:00
|
|
|
* @private
|
2017-02-16 23:02:40 +00:00
|
|
|
* @type {Map}
|
|
|
|
*/
|
|
|
|
_secondaryToolbarButtons: secondaryToolbarButtons,
|
|
|
|
|
|
|
|
/**
|
2017-04-21 10:00:50 +00:00
|
|
|
* The indicator which determines whether the {@code SecondaryToolbar}
|
|
|
|
* is visible.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
2017-04-06 22:40:10 +00:00
|
|
|
* @private
|
2017-02-16 23:02:40 +00:00
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_visible: visible
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export default connect(_mapStateToProps, _mapDispatchToProps)(SecondaryToolbar);
|