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.

Toolbox.js 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { View } from 'react-native';
  4. import { connect } from 'react-redux';
  5. import { Container } from '../../../base/react';
  6. import {
  7. isNarrowAspectRatio,
  8. makeAspectRatioAware
  9. } from '../../../base/responsive-ui';
  10. import { InviteButton } from '../../../invite';
  11. import AudioMuteButton from '../AudioMuteButton';
  12. import HangupButton from '../HangupButton';
  13. import OverflowMenuButton from './OverflowMenuButton';
  14. import styles, {
  15. hangupButtonStyles,
  16. toolbarButtonStyles,
  17. toolbarToggledButtonStyles
  18. } from './styles';
  19. import VideoMuteButton from '../VideoMuteButton';
  20. /**
  21. * The number of buttons to render in {@link Toolbox}.
  22. *
  23. * @private
  24. * @type number
  25. */
  26. const _BUTTON_COUNT = 4;
  27. /**
  28. * Factor relating the hangup button and other toolbar buttons.
  29. *
  30. * @private
  31. * @type number
  32. */
  33. const _BUTTON_SIZE_FACTOR = 0.8;
  34. /**
  35. * The type of {@link Toolbox}'s React {@code Component} props.
  36. */
  37. type Props = {
  38. /**
  39. * The indicator which determines whether the toolbox is visible.
  40. */
  41. _visible: boolean,
  42. /**
  43. * The redux {@code dispatch} function.
  44. */
  45. dispatch: Function
  46. };
  47. /**
  48. * The type of {@link Toolbox}'s React {@code Component} state.
  49. */
  50. type State = {
  51. /**
  52. * The detected width for this component.
  53. */
  54. width: number
  55. };
  56. /**
  57. * Implements the conference toolbox on React Native.
  58. */
  59. class Toolbox extends Component<Props, State> {
  60. state = {
  61. width: 0
  62. };
  63. /**
  64. * Initializes a new {@code Toolbox} instance.
  65. *
  66. * @inheritdoc
  67. */
  68. constructor(props: Props) {
  69. super(props);
  70. // Bind event handlers so they are only bound once per instance.
  71. this._onLayout = this._onLayout.bind(this);
  72. }
  73. /**
  74. * Implements React's {@link Component#render()}.
  75. *
  76. * @inheritdoc
  77. * @returns {ReactElement}
  78. */
  79. render() {
  80. const toolboxStyle
  81. = isNarrowAspectRatio(this)
  82. ? styles.toolboxNarrow
  83. : styles.toolboxWide;
  84. const { _visible } = this.props;
  85. let buttonStyles = toolbarButtonStyles;
  86. let toggledButtonStyles = toolbarToggledButtonStyles;
  87. if (_visible) {
  88. const buttonSize = this._calculateButtonSize();
  89. if (buttonSize > 0) {
  90. const extraButtonStyle = {
  91. borderRadius: buttonSize / 2,
  92. height: buttonSize,
  93. width: buttonSize
  94. };
  95. buttonStyles = {
  96. ...buttonStyles,
  97. style: [ buttonStyles.style, extraButtonStyle ]
  98. };
  99. toggledButtonStyles = {
  100. ...toggledButtonStyles,
  101. style: [ toggledButtonStyles.style, extraButtonStyle ]
  102. };
  103. }
  104. }
  105. return (
  106. <Container
  107. onLayout = { this._onLayout }
  108. style = { toolboxStyle }
  109. visible = { _visible }>
  110. <View
  111. pointerEvents = 'box-none'
  112. style = { styles.toolbar }>
  113. <InviteButton styles = { buttonStyles } />
  114. <AudioMuteButton
  115. styles = { buttonStyles }
  116. toggledStyles = { toggledButtonStyles } />
  117. <HangupButton styles = { hangupButtonStyles } />
  118. <VideoMuteButton
  119. styles = { buttonStyles }
  120. toggledStyles = { toggledButtonStyles } />
  121. <OverflowMenuButton
  122. styles = { buttonStyles }
  123. toggledStyles = { toggledButtonStyles } />
  124. </View>
  125. </Container>
  126. );
  127. }
  128. /**
  129. * Calculates how large our toolbar buttons can be, given the available
  130. * width. In the future we might want to have a size threshold, and once
  131. * it's passed a completely different style could be used, akin to the web.
  132. *
  133. * @private
  134. * @returns {number}
  135. */
  136. _calculateButtonSize() {
  137. const { width } = this.state;
  138. const hangupButtonSize = styles.hangupButton.width;
  139. let buttonSize
  140. = (width
  141. - hangupButtonSize
  142. - (_BUTTON_COUNT * styles.toolbarButton.margin * 2))
  143. / _BUTTON_COUNT;
  144. // Make sure it's an even number.
  145. buttonSize = 2 * Math.round(buttonSize / 2);
  146. // The button should be at most 80% of the hangup button's size.
  147. return Math.min(
  148. buttonSize,
  149. hangupButtonSize * _BUTTON_SIZE_FACTOR);
  150. }
  151. _onLayout: (Object) => void;
  152. /**
  153. * Handles the "on layout" View's event and stores the width as state.
  154. *
  155. * @param {Object} event - The "on layout" event object/structure passed
  156. * by react-native.
  157. * @private
  158. * @returns {void}
  159. */
  160. _onLayout({ nativeEvent: { layout: { width } } }) {
  161. this.setState({ width });
  162. }
  163. }
  164. /**
  165. * Maps parts of the redux state to {@link Toolbox} (React {@code Component})
  166. * props.
  167. *
  168. * @param {Object} state - The redux state of which parts are to be mapped to
  169. * {@code Toolbox} props.
  170. * @private
  171. * @returns {{
  172. * _visible: boolean
  173. * }}
  174. */
  175. function _mapStateToProps(state: Object): Object {
  176. const { enabled, visible } = state['features/toolbox'];
  177. return {
  178. _visible: enabled && visible
  179. };
  180. }
  181. export default connect(_mapStateToProps)(makeAspectRatioAware(Toolbox));