You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SecondaryToolbar.web.js 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /* @flow */
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { FeedbackButton } from '../../feedback';
  5. import UIEvents from '../../../../service/UI/UIEvents';
  6. import {
  7. changeLocalRaiseHand,
  8. setProfileButtonUnclickable,
  9. showRecordingButton,
  10. toggleSideToolbarContainer
  11. } from '../actions';
  12. import { getToolbarClassNames } from '../functions';
  13. import Toolbar from './Toolbar';
  14. declare var APP: Object;
  15. declare var config: Object;
  16. /**
  17. * Implementation of secondary toolbar React component.
  18. *
  19. * @class SecondaryToolbar
  20. * @extends Component
  21. */
  22. class SecondaryToolbar extends Component {
  23. state: Object;
  24. /**
  25. * Secondary toolbar property types.
  26. *
  27. * @static
  28. */
  29. static propTypes = {
  30. /**
  31. * Handler dispatching local "Raise hand".
  32. */
  33. _onLocalRaiseHandChanged: React.PropTypes.func,
  34. /**
  35. * Handler setting profile button unclickable.
  36. */
  37. _onSetProfileButtonUnclickable: React.PropTypes.func,
  38. /**
  39. * Handler for showing recording button.
  40. */
  41. _onShowRecordingButton: React.PropTypes.func,
  42. /**
  43. * Handler dispatching toggle toolbar container.
  44. */
  45. _onSideToolbarContainerToggled: React.PropTypes.func,
  46. /**
  47. * Contains map of secondary toolbar buttons.
  48. */
  49. _secondaryToolbarButtons: React.PropTypes.instanceOf(Map),
  50. /**
  51. * Shows whether toolbox is visible.
  52. */
  53. _visible: React.PropTypes.bool
  54. };
  55. /**
  56. * Constructs instance of SecondaryToolbar component.
  57. *
  58. * @param {Object} props - React component properties.
  59. */
  60. constructor(props) {
  61. super(props);
  62. const buttonHandlers = {
  63. /**
  64. * Mount handler for profile button.
  65. *
  66. * @type {Object}
  67. */
  68. profile: {
  69. onMount: () =>
  70. APP.tokenData.isGuest
  71. || this.props._onSetProfileButtonUnclickable(true)
  72. },
  73. /**
  74. * Mount/Unmount handlers for raisehand button.
  75. *
  76. * @type {button}
  77. */
  78. raisehand: {
  79. onMount: () =>
  80. APP.UI.addListener(
  81. UIEvents.LOCAL_RAISE_HAND_CHANGED,
  82. this.props._onLocalRaiseHandChanged),
  83. onUnmount: () =>
  84. APP.UI.removeListener(
  85. UIEvents.LOCAL_RAISE_HAND_CHANGED,
  86. this.props._onLocalRaiseHandChanged)
  87. },
  88. /**
  89. * Mount handler for recording button.
  90. *
  91. * @type {Object}
  92. */
  93. recording: {
  94. onMount: () =>
  95. config.enableRecording
  96. && this.props._onShowRecordingButton()
  97. }
  98. };
  99. this.state = {
  100. /**
  101. * Object containing on mount/unmount handlers for toolbar buttons.
  102. *
  103. * @type {Object}
  104. */
  105. buttonHandlers
  106. };
  107. }
  108. /**
  109. * Register legacy UI listener.
  110. *
  111. * @returns {void}
  112. */
  113. componentDidMount(): void {
  114. APP.UI.addListener(
  115. UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
  116. this.props._onSideToolbarContainerToggled);
  117. }
  118. /**
  119. * Unregisters legacy UI listener.
  120. *
  121. * @returns {void}
  122. */
  123. componentWillUnmount(): void {
  124. APP.UI.removeListener(
  125. UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
  126. this.props._onSideToolbarContainerToggled);
  127. }
  128. /**
  129. * Renders secondary toolbar component.
  130. *
  131. * @returns {ReactElement}
  132. */
  133. render(): ReactElement<*> | null {
  134. const { _secondaryToolbarButtons } = this.props;
  135. // The number of buttons to show in the toolbar isn't fixed, it depends
  136. // on the availability of features and configuration parameters. So
  137. // there may be nothing to render.
  138. if (_secondaryToolbarButtons.size === 0) {
  139. return null;
  140. }
  141. const { buttonHandlers } = this.state;
  142. const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
  143. return (
  144. <Toolbar
  145. buttonHandlers = { buttonHandlers }
  146. className = { secondaryToolbarClassName }
  147. toolbarButtons = { _secondaryToolbarButtons }
  148. tooltipPosition = { 'right' }>
  149. <FeedbackButton />
  150. </Toolbar>
  151. );
  152. }
  153. }
  154. /**
  155. * Maps some of Redux actions to component's props.
  156. *
  157. * @param {Function} dispatch - Redux action dispatcher.
  158. * @returns {{
  159. * _onLocalRaiseHandChanged: Function,
  160. * _onSetProfileButtonUnclickable: Function,
  161. * _onShowRecordingButton: Function,
  162. * _onSideToolbarContainerToggled
  163. * }}
  164. * @private
  165. */
  166. function _mapDispatchToProps(dispatch: Function): Object {
  167. return {
  168. /**
  169. * Dispatches an action that 'hand' is raised.
  170. *
  171. * @param {boolean} isRaisedHand - Show whether hand is raised.
  172. * @returns {Object} Dispatched action.
  173. */
  174. _onLocalRaiseHandChanged(isRaisedHand: boolean) {
  175. return dispatch(changeLocalRaiseHand(isRaisedHand));
  176. },
  177. /**
  178. * Dispatches an action signalling to set profile button unclickable.
  179. *
  180. * @param {boolean} unclickable - Flag showing whether unclickable
  181. * property is true.
  182. * @returns {Object} Dispatched action.
  183. */
  184. _onSetProfileButtonUnclickable(unclickable: boolean) {
  185. return dispatch(setProfileButtonUnclickable(unclickable));
  186. },
  187. /**
  188. * Dispatches an action signalling that recording button should be
  189. * shown.
  190. *
  191. * @returns {Object} Dispatched action.
  192. */
  193. _onShowRecordingButton() {
  194. return dispatch(showRecordingButton());
  195. },
  196. /**
  197. * Dispatches an action signalling that side toolbar container is
  198. * toggled.
  199. *
  200. * @param {string} containerId - Id of side toolbar container.
  201. * @returns {Object} Dispatched action.
  202. */
  203. _onSideToolbarContainerToggled(containerId: string) {
  204. return dispatch(toggleSideToolbarContainer(containerId));
  205. }
  206. };
  207. }
  208. /**
  209. * Maps part of Redux state to component's props.
  210. *
  211. * @param {Object} state - Snapshot of Redux store.
  212. * @returns {{
  213. * _secondaryToolbarButtons: Map,
  214. * _visible: boolean
  215. * }}
  216. * @private
  217. */
  218. function _mapStateToProps(state: Object): Object {
  219. const {
  220. secondaryToolbarButtons,
  221. visible
  222. } = state['features/toolbox'];
  223. return {
  224. /**
  225. * Default toolbar buttons for secondary toolbar.
  226. *
  227. * @private
  228. * @type {Map}
  229. */
  230. _secondaryToolbarButtons: secondaryToolbarButtons,
  231. /**
  232. * Shows whether toolbar is visible.
  233. *
  234. * @private
  235. * @type {boolean}
  236. */
  237. _visible: visible
  238. };
  239. }
  240. export default connect(_mapStateToProps, _mapDispatchToProps)(SecondaryToolbar);