Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

LocalVideoMenuTriggerButton.tsx 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import React, { useCallback } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { batch, connect } from 'react-redux';
  4. import { makeStyles } from 'tss-react/mui';
  5. import { IReduxState, IStore } from '../../../app/types';
  6. import { isMobileBrowser } from '../../../base/environment/utils';
  7. import { IconDotsHorizontal } from '../../../base/icons/svg';
  8. import { getLocalParticipant } from '../../../base/participants/functions';
  9. import Popover from '../../../base/popover/components/Popover.web';
  10. import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
  11. import { getHideSelfView } from '../../../base/settings/functions.web';
  12. import { getLocalVideoTrack } from '../../../base/tracks/functions';
  13. import Button from '../../../base/ui/components/web/Button';
  14. import ContextMenu from '../../../base/ui/components/web/ContextMenu';
  15. import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
  16. import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
  17. import { THUMBNAIL_TYPE } from '../../../filmstrip/constants';
  18. import { isStageFilmstripAvailable } from '../../../filmstrip/functions.web';
  19. import { renderConnectionStatus } from '../../actions.web';
  20. import ConnectionStatusButton from './ConnectionStatusButton';
  21. import FlipLocalVideoButton from './FlipLocalVideoButton';
  22. import HideSelfViewVideoButton from './HideSelfViewVideoButton';
  23. import TogglePinToStageButton from './TogglePinToStageButton';
  24. /**
  25. * The type of the React {@code Component} props of
  26. * {@link LocalVideoMenuTriggerButton}.
  27. */
  28. interface IProps {
  29. /**
  30. * The id of the local participant.
  31. */
  32. _localParticipantId: string;
  33. /**
  34. * The position relative to the trigger the local video menu should display
  35. * from.
  36. */
  37. _menuPosition: string;
  38. /**
  39. * Whether to display the Popover as a drawer.
  40. */
  41. _overflowDrawer: boolean;
  42. /**
  43. * Whether to render the connection info pane.
  44. */
  45. _showConnectionInfo: boolean;
  46. /**
  47. * Whether to render the hide self view button.
  48. */
  49. _showHideSelfViewButton: boolean;
  50. /**
  51. * Shows/hides the local video flip button.
  52. */
  53. _showLocalVideoFlipButton: boolean;
  54. /**
  55. * Whether to render the pin to stage button.
  56. */
  57. _showPinToStage: boolean;
  58. /**
  59. * Whether or not the button should be visible.
  60. */
  61. buttonVisible: boolean;
  62. /**
  63. * The redux dispatch function.
  64. */
  65. dispatch: IStore['dispatch'];
  66. /**
  67. * Hides popover.
  68. */
  69. hidePopover?: Function;
  70. /**
  71. * Whether the popover is visible or not.
  72. */
  73. popoverVisible?: boolean;
  74. /**
  75. * Shows popover.
  76. */
  77. showPopover?: Function;
  78. /**
  79. * The type of the thumbnail.
  80. */
  81. thumbnailType: string;
  82. }
  83. const useStyles = makeStyles()(() => {
  84. return {
  85. triggerButton: {
  86. padding: '3px !important',
  87. borderRadius: '4px',
  88. '& svg': {
  89. width: '18px',
  90. height: '18px'
  91. }
  92. },
  93. contextMenu: {
  94. position: 'relative',
  95. marginTop: 0,
  96. right: 'auto',
  97. padding: '0',
  98. minWidth: '200px'
  99. },
  100. flipText: {
  101. marginLeft: '36px'
  102. }
  103. };
  104. });
  105. const LocalVideoMenuTriggerButton = ({
  106. _localParticipantId,
  107. _menuPosition,
  108. _overflowDrawer,
  109. _showConnectionInfo,
  110. _showHideSelfViewButton,
  111. _showLocalVideoFlipButton,
  112. _showPinToStage,
  113. buttonVisible,
  114. dispatch,
  115. hidePopover,
  116. showPopover,
  117. popoverVisible
  118. }: IProps) => {
  119. const { classes } = useStyles();
  120. const { t } = useTranslation();
  121. const _onPopoverOpen = useCallback(() => {
  122. showPopover?.();
  123. dispatch(setParticipantContextMenuOpen(true));
  124. }, []);
  125. const _onPopoverClose = useCallback(() => {
  126. hidePopover?.();
  127. batch(() => {
  128. dispatch(setParticipantContextMenuOpen(false));
  129. dispatch(renderConnectionStatus(false));
  130. });
  131. }, []);
  132. const content = _showConnectionInfo
  133. ? <ConnectionIndicatorContent participantId = { _localParticipantId } />
  134. : (
  135. <ContextMenu
  136. className = { classes.contextMenu }
  137. hidden = { false }
  138. inDrawer = { _overflowDrawer }>
  139. <ContextMenuItemGroup>
  140. {_showLocalVideoFlipButton
  141. && <FlipLocalVideoButton
  142. className = { _overflowDrawer ? classes.flipText : '' }
  143. onClick = { hidePopover } />
  144. }
  145. {_showHideSelfViewButton
  146. && <HideSelfViewVideoButton
  147. className = { _overflowDrawer ? classes.flipText : '' }
  148. onClick = { hidePopover } />
  149. }
  150. {
  151. _showPinToStage && <TogglePinToStageButton
  152. className = { _overflowDrawer ? classes.flipText : '' }
  153. noIcon = { true }
  154. onClick = { hidePopover }
  155. participantID = { _localParticipantId } />
  156. }
  157. {isMobileBrowser()
  158. && <ConnectionStatusButton participantId = { _localParticipantId } />
  159. }
  160. </ContextMenuItemGroup>
  161. </ContextMenu>
  162. );
  163. return (
  164. isMobileBrowser() || _showLocalVideoFlipButton || _showHideSelfViewButton
  165. ? <Popover
  166. content = { content }
  167. headingLabel = { t('dialog.localUserControls') }
  168. id = 'local-video-menu-trigger'
  169. onPopoverClose = { _onPopoverClose }
  170. onPopoverOpen = { _onPopoverOpen }
  171. position = { _menuPosition }
  172. visible = { Boolean(popoverVisible) }>
  173. {buttonVisible && !isMobileBrowser() && (
  174. <Button
  175. accessibilityLabel = { t('dialog.localUserControls') }
  176. className = { classes.triggerButton }
  177. icon = { IconDotsHorizontal }
  178. size = 'small' />
  179. )}
  180. </Popover>
  181. : null
  182. );
  183. };
  184. /**
  185. * Maps (parts of) the Redux state to the associated {@code LocalVideoMenuTriggerButton}'s props.
  186. *
  187. * @param {Object} state - The Redux state.
  188. * @param {Object} ownProps - The own props of the component.
  189. * @private
  190. * @returns {IProps}
  191. */
  192. function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
  193. const { thumbnailType } = ownProps;
  194. const localParticipant = getLocalParticipant(state);
  195. const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
  196. const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
  197. const { overflowDrawer } = state['features/toolbox'];
  198. const { showConnectionInfo } = state['features/base/connection'];
  199. const showHideSelfViewButton = !disableSelfViewSettings && !getHideSelfView(state);
  200. let _menuPosition;
  201. switch (thumbnailType) {
  202. case THUMBNAIL_TYPE.TILE:
  203. _menuPosition = 'left-start';
  204. break;
  205. case THUMBNAIL_TYPE.VERTICAL:
  206. _menuPosition = 'left-start';
  207. break;
  208. case THUMBNAIL_TYPE.HORIZONTAL:
  209. _menuPosition = 'top-start';
  210. break;
  211. default:
  212. _menuPosition = 'auto';
  213. }
  214. return {
  215. _menuPosition,
  216. _showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
  217. _showHideSelfViewButton: showHideSelfViewButton,
  218. _overflowDrawer: overflowDrawer,
  219. _localParticipantId: localParticipant?.id ?? '',
  220. _showConnectionInfo: Boolean(showConnectionInfo),
  221. _showPinToStage: isStageFilmstripAvailable(state)
  222. };
  223. }
  224. export default connect(_mapStateToProps)(LocalVideoMenuTriggerButton);