Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

LocalVideoMenuTriggerButton.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { batch } from 'react-redux';
  4. import { isMobileBrowser } from '../../../base/environment/utils';
  5. import { translate } from '../../../base/i18n';
  6. import { Icon, IconMenuThumb } from '../../../base/icons';
  7. import {
  8. getLocalParticipant
  9. } from '../../../base/participants';
  10. import { Popover } from '../../../base/popover';
  11. import { connect } from '../../../base/redux';
  12. import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
  13. import { getLocalVideoTrack } from '../../../base/tracks';
  14. import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
  15. import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
  16. import { renderConnectionStatus } from '../../actions.web';
  17. import ConnectionStatusButton from './ConnectionStatusButton';
  18. import FlipLocalVideoButton from './FlipLocalVideoButton';
  19. import HideSelfViewVideoButton from './HideSelfViewVideoButton';
  20. import VideoMenu from './VideoMenu';
  21. /**
  22. * The type of the React {@code Component} props of
  23. * {@link LocalVideoMenuTriggerButton}.
  24. */
  25. type Props = {
  26. /**
  27. * The redux dispatch function.
  28. */
  29. dispatch: Function,
  30. /**
  31. * Gets a ref to the current component instance.
  32. */
  33. getRef: Function,
  34. /**
  35. * Hides popover.
  36. */
  37. hidePopover: Function,
  38. /**
  39. * Whether the popover is visible or not.
  40. */
  41. popoverVisible: boolean,
  42. /**
  43. * Shows popover.
  44. */
  45. showPopover: Function,
  46. /**
  47. * The id of the local participant.
  48. */
  49. _localParticipantId: string,
  50. /**
  51. * The position relative to the trigger the local video menu should display
  52. * from. Valid values are those supported by AtlasKit
  53. * {@code InlineDialog}.
  54. */
  55. _menuPosition: string,
  56. /**
  57. * Whether to display the Popover as a drawer.
  58. */
  59. _overflowDrawer: boolean,
  60. /**
  61. * Whether to render the connection info pane.
  62. */
  63. _showConnectionInfo: boolean,
  64. /**
  65. * Shows/hides the local video flip button.
  66. */
  67. _showLocalVideoFlipButton: boolean,
  68. /**
  69. * Invoked to obtain translated strings.
  70. */
  71. t: Function
  72. };
  73. /**
  74. * React Component for displaying an icon associated with opening the
  75. * the video menu for the local participant.
  76. *
  77. * @augments {Component}
  78. */
  79. class LocalVideoMenuTriggerButton extends Component<Props> {
  80. /**
  81. * Initializes a new LocalVideoMenuTriggerButton instance.
  82. *
  83. * @param {Object} props - The read-only React Component props with which
  84. * the new instance is to be initialized.
  85. */
  86. constructor(props: Props) {
  87. super(props);
  88. this._onPopoverClose = this._onPopoverClose.bind(this);
  89. this._onPopoverOpen = this._onPopoverOpen.bind(this);
  90. }
  91. /**
  92. * Implements React's {@link Component#render()}.
  93. *
  94. * @inheritdoc
  95. * @returns {ReactElement}
  96. */
  97. render() {
  98. const {
  99. _localParticipantId,
  100. _menuPosition,
  101. _showConnectionInfo,
  102. _overflowDrawer,
  103. _showLocalVideoFlipButton,
  104. hidePopover,
  105. popoverVisible,
  106. t
  107. } = this.props;
  108. const content = _showConnectionInfo
  109. ? <ConnectionIndicatorContent participantId = { _localParticipantId } />
  110. : (
  111. <VideoMenu id = 'localVideoMenu'>
  112. <FlipLocalVideoButton onClick = { hidePopover } />
  113. <HideSelfViewVideoButton onClick = { hidePopover } />
  114. { isMobileBrowser()
  115. && <ConnectionStatusButton participantId = { _localParticipantId } />
  116. }
  117. </VideoMenu>
  118. );
  119. return (
  120. isMobileBrowser() || _showLocalVideoFlipButton
  121. ? <Popover
  122. content = { content }
  123. id = 'local-video-menu-trigger'
  124. onPopoverClose = { this._onPopoverClose }
  125. onPopoverOpen = { this._onPopoverOpen }
  126. overflowDrawer = { _overflowDrawer }
  127. position = { _menuPosition }
  128. visible = { popoverVisible }>
  129. {!_overflowDrawer && (
  130. <span
  131. className = 'popover-trigger local-video-menu-trigger'>
  132. {!isMobileBrowser() && <Icon
  133. ariaLabel = { t('dialog.localUserControls') }
  134. role = 'button'
  135. size = '1.4em'
  136. src = { IconMenuThumb }
  137. tabIndex = { 0 }
  138. title = { t('dialog.localUserControls') } />
  139. }
  140. </span>
  141. )}
  142. </Popover>
  143. : null
  144. );
  145. }
  146. _onPopoverOpen: () => void;
  147. /**
  148. * Disable and hide toolbox while context menu is open.
  149. *
  150. * @returns {void}
  151. */
  152. _onPopoverOpen() {
  153. const { dispatch, showPopover } = this.props;
  154. showPopover();
  155. dispatch(setParticipantContextMenuOpen(true));
  156. }
  157. _onPopoverClose: () => void;
  158. /**
  159. * Render normal context menu next time popover dialog opens.
  160. *
  161. * @returns {void}
  162. */
  163. _onPopoverClose() {
  164. const { hidePopover, dispatch } = this.props;
  165. hidePopover();
  166. batch(() => {
  167. dispatch(setParticipantContextMenuOpen(false));
  168. dispatch(renderConnectionStatus(false));
  169. });
  170. }
  171. }
  172. /**
  173. * Maps (parts of) the Redux state to the associated {@code LocalVideoMenuTriggerButton}'s props.
  174. *
  175. * @param {Object} state - The Redux state.
  176. * @private
  177. * @returns {Props}
  178. */
  179. function _mapStateToProps(state) {
  180. const currentLayout = getCurrentLayout(state);
  181. const localParticipant = getLocalParticipant(state);
  182. const { disableLocalVideoFlip } = state['features/base/config'];
  183. const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
  184. const { overflowDrawer } = state['features/toolbox'];
  185. const { showConnectionInfo } = state['features/base/connection'];
  186. let _menuPosition;
  187. switch (currentLayout) {
  188. case LAYOUTS.TILE_VIEW:
  189. _menuPosition = 'left-start';
  190. break;
  191. case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
  192. _menuPosition = 'left-end';
  193. break;
  194. case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
  195. _menuPosition = 'top';
  196. break;
  197. default:
  198. _menuPosition = 'auto';
  199. }
  200. return {
  201. _menuPosition,
  202. _showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
  203. _overflowDrawer: overflowDrawer,
  204. _localParticipantId: localParticipant.id,
  205. _showConnectionInfo: showConnectionInfo
  206. };
  207. }
  208. export default translate(connect(_mapStateToProps)(LocalVideoMenuTriggerButton));