選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Toolbox.tsx 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import React from 'react';
  2. import { View, ViewStyle } from 'react-native';
  3. import { SafeAreaView } from 'react-native-safe-area-context';
  4. import { connect } from 'react-redux';
  5. import { IReduxState, IStore } from '../../../app/types';
  6. import ColorSchemeRegistry from '../../../base/color-scheme/ColorSchemeRegistry';
  7. import Platform from '../../../base/react/Platform.native';
  8. import ChatButton from '../../../chat/components/native/ChatButton';
  9. import ReactionsMenuButton from '../../../reactions/components/native/ReactionsMenuButton';
  10. import { shouldDisplayReactionsButtons } from '../../../reactions/functions.any';
  11. import TileViewButton from '../../../video-layout/components/TileViewButton';
  12. import { iAmVisitor } from '../../../visitors/functions';
  13. import { customButtonPressed } from '../../actions.native';
  14. import { getMovableButtons, isToolboxVisible } from '../../functions.native';
  15. import HangupButton from '../HangupButton';
  16. import AudioMuteButton from './AudioMuteButton';
  17. import CustomOptionButton from './CustomOptionButton';
  18. import HangupMenuButton from './HangupMenuButton';
  19. import OverflowMenuButton from './OverflowMenuButton';
  20. import RaiseHandButton from './RaiseHandButton';
  21. import ScreenSharingButton from './ScreenSharingButton';
  22. import VideoMuteButton from './VideoMuteButton';
  23. import styles from './styles';
  24. /**
  25. * The type of {@link Toolbox}'s React {@code Component} props.
  26. */
  27. interface IProps {
  28. /**
  29. * Custom Toolbar buttons.
  30. */
  31. _customToolbarButtons?: Array<{ backgroundColor?: string; icon: string; id: string; text: string; }>;
  32. /**
  33. * Whether the end conference feature is supported.
  34. */
  35. _endConferenceSupported: boolean;
  36. /**
  37. * Whether we are in visitors mode.
  38. */
  39. _iAmVisitor: boolean;
  40. /**
  41. * Whether or not any reactions buttons should be visible.
  42. */
  43. _shouldDisplayReactionsButtons: boolean;
  44. /**
  45. * The color-schemed stylesheet of the feature.
  46. */
  47. _styles: any;
  48. /**
  49. * The indicator which determines whether the toolbox is visible.
  50. */
  51. _visible: boolean;
  52. /**
  53. * The width of the screen.
  54. */
  55. _width: number;
  56. /**
  57. * Redux store dispatch method.
  58. */
  59. dispatch: IStore['dispatch'];
  60. }
  61. /**
  62. * Implements the conference Toolbox on React Native.
  63. *
  64. * @param {Object} props - The props of the component.
  65. * @returns {React$Element}
  66. */
  67. function Toolbox(props: IProps) {
  68. const {
  69. _customToolbarButtons,
  70. _endConferenceSupported,
  71. _iAmVisitor,
  72. _shouldDisplayReactionsButtons,
  73. _styles,
  74. _visible,
  75. _width,
  76. dispatch
  77. } = props;
  78. if (!_visible) {
  79. return null;
  80. }
  81. const bottomEdge = Platform.OS === 'ios' && _visible;
  82. const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
  83. const additionalButtons = getMovableButtons(_width);
  84. const backgroundToggledStyle = {
  85. ...toggledButtonStyles,
  86. style: [
  87. toggledButtonStyles.style,
  88. _styles.backgroundToggle
  89. ]
  90. };
  91. const style = { ...styles.toolbox };
  92. // we have only hangup and raisehand button in _iAmVisitor mode
  93. if (_iAmVisitor) {
  94. additionalButtons.add('raisehand');
  95. style.justifyContent = 'center';
  96. }
  97. const renderCustomToolboxButtons = () => {
  98. if (!_customToolbarButtons?.length) {
  99. return;
  100. }
  101. return (
  102. <>
  103. {
  104. _customToolbarButtons.map(({ backgroundColor, id, text, icon }) => (
  105. <CustomOptionButton
  106. backgroundColor = { backgroundColor }
  107. /* eslint-disable react/jsx-no-bind */
  108. handleClick = { () => dispatch(customButtonPressed(id, text)) }
  109. icon = { icon }
  110. isToolboxButton = { true }
  111. key = { id } />
  112. ))
  113. }
  114. </>
  115. );
  116. };
  117. return (
  118. <View
  119. style = { styles.toolboxContainer as ViewStyle }>
  120. <SafeAreaView
  121. accessibilityRole = 'toolbar'
  122. // @ts-ignore
  123. edges = { [ bottomEdge && 'bottom' ].filter(Boolean) }
  124. pointerEvents = 'box-none'
  125. style = { style as ViewStyle }>
  126. {
  127. _customToolbarButtons
  128. ? <>
  129. { renderCustomToolboxButtons() }
  130. { !_iAmVisitor && <OverflowMenuButton
  131. styles = { buttonStylesBorderless }
  132. toggledStyles = { toggledButtonStyles } /> }
  133. </>
  134. : <>
  135. {!_iAmVisitor && <AudioMuteButton
  136. styles = { buttonStylesBorderless }
  137. toggledStyles = { toggledButtonStyles } />}
  138. {!_iAmVisitor && <VideoMuteButton
  139. styles = { buttonStylesBorderless }
  140. toggledStyles = { toggledButtonStyles } />}
  141. {additionalButtons.has('chat')
  142. && <ChatButton
  143. styles = { buttonStylesBorderless }
  144. toggledStyles = { backgroundToggledStyle } />}
  145. {!_iAmVisitor && additionalButtons.has('screensharing')
  146. && <ScreenSharingButton styles = { buttonStylesBorderless } />}
  147. {additionalButtons.has('raisehand') && (_shouldDisplayReactionsButtons
  148. ? <ReactionsMenuButton
  149. styles = { buttonStylesBorderless }
  150. toggledStyles = { backgroundToggledStyle } />
  151. : <RaiseHandButton
  152. styles = { buttonStylesBorderless }
  153. toggledStyles = { backgroundToggledStyle } />)}
  154. {additionalButtons.has('tileview')
  155. && <TileViewButton styles = { buttonStylesBorderless } />}
  156. {!_iAmVisitor && <OverflowMenuButton
  157. styles = { buttonStylesBorderless }
  158. toggledStyles = { toggledButtonStyles } />}
  159. { _endConferenceSupported
  160. ? <HangupMenuButton />
  161. : <HangupButton styles = { hangupButtonStyles } />}
  162. </>
  163. }
  164. </SafeAreaView>
  165. </View>
  166. );
  167. }
  168. /**
  169. * Maps parts of the redux state to {@link Toolbox} (React {@code Component})
  170. * props.
  171. *
  172. * @param {Object} state - The redux state of which parts are to be mapped to
  173. * {@code Toolbox} props.
  174. * @private
  175. * @returns {IProps}
  176. */
  177. function _mapStateToProps(state: IReduxState) {
  178. const { conference } = state['features/base/conference'];
  179. const endConferenceSupported = conference?.isEndConferenceSupported();
  180. return {
  181. _customToolbarButtons: state['features/base/config']?.customToolbarButtons,
  182. _endConferenceSupported: Boolean(endConferenceSupported),
  183. _styles: ColorSchemeRegistry.get(state, 'Toolbox'),
  184. _visible: isToolboxVisible(state),
  185. _iAmVisitor: iAmVisitor(state),
  186. _width: state['features/base/responsive-ui'].clientWidth,
  187. _shouldDisplayReactionsButtons: shouldDisplayReactionsButtons(state)
  188. };
  189. }
  190. export default connect(_mapStateToProps)(Toolbox);