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.8KB

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