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.

RemoteVideoMenu.js 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // @flow
  2. import React, { PureComponent } from 'react';
  3. import { Text, View } from 'react-native';
  4. import { Divider } from 'react-native-paper';
  5. import { Avatar } from '../../../base/avatar';
  6. import { BottomSheet, isDialogOpen } from '../../../base/dialog';
  7. import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
  8. import { KICK_OUT_ENABLED, getFeatureFlag } from '../../../base/flags';
  9. import { translate } from '../../../base/i18n';
  10. import {
  11. getParticipantById,
  12. getParticipantDisplayName
  13. } from '../../../base/participants';
  14. import { connect } from '../../../base/redux';
  15. import { getBreakoutRooms, getCurrentRoomId } from '../../../breakout-rooms/functions';
  16. import PrivateMessageButton from '../../../chat/components/native/PrivateMessageButton';
  17. import { hideRemoteVideoMenu } from '../../actions.native';
  18. import ConnectionStatusButton from '../native/ConnectionStatusButton';
  19. import AskUnmuteButton from './AskUnmuteButton';
  20. import GrantModeratorButton from './GrantModeratorButton';
  21. import KickButton from './KickButton';
  22. import MuteButton from './MuteButton';
  23. import MuteEveryoneElseButton from './MuteEveryoneElseButton';
  24. import MuteVideoButton from './MuteVideoButton';
  25. import PinButton from './PinButton';
  26. import SendToBreakoutRoom from './SendToBreakoutRoom';
  27. import styles from './styles';
  28. // import VolumeSlider from './VolumeSlider';
  29. /**
  30. * Size of the rendered avatar in the menu.
  31. */
  32. const AVATAR_SIZE = 24;
  33. type Props = {
  34. /**
  35. * The Redux dispatch function.
  36. */
  37. dispatch: Function,
  38. /**
  39. * The ID of the participant for which this menu opened for.
  40. */
  41. participantId: String,
  42. /**
  43. * The id of the current room.
  44. */
  45. _currentRoomId: String,
  46. /**
  47. * Whether or not to display the kick button.
  48. */
  49. _disableKick: boolean,
  50. /**
  51. * Whether or not to display the send private message button.
  52. */
  53. _disablePrivateChat: Boolean,
  54. /**
  55. * Whether or not to display the remote mute buttons.
  56. */
  57. _disableRemoteMute: boolean,
  58. /**
  59. * Whether or not to display the grant moderator button.
  60. */
  61. _disableGrantModerator: Boolean,
  62. /**
  63. * True if the menu is currently open, false otherwise.
  64. */
  65. _isOpen: boolean,
  66. /**
  67. * Whether the participant is present in the room or not.
  68. */
  69. _isParticipantAvailable?: boolean,
  70. /**
  71. * Display name of the participant retrieved from Redux.
  72. */
  73. _participantDisplayName: string,
  74. /**
  75. * Array containing the breakout rooms.
  76. */
  77. _rooms: Array<Object>,
  78. /**
  79. * Translation function.
  80. */
  81. t: Function
  82. }
  83. // eslint-disable-next-line prefer-const
  84. let RemoteVideoMenu_;
  85. /**
  86. * Class to implement a popup menu that opens upon long pressing a thumbnail.
  87. */
  88. class RemoteVideoMenu extends PureComponent<Props> {
  89. /**
  90. * Constructor of the component.
  91. *
  92. * @inheritdoc
  93. */
  94. constructor(props: Props) {
  95. super(props);
  96. this._onCancel = this._onCancel.bind(this);
  97. this._renderMenuHeader = this._renderMenuHeader.bind(this);
  98. }
  99. /**
  100. * Implements {@code Component#render}.
  101. *
  102. * @inheritdoc
  103. */
  104. render() {
  105. const {
  106. _disableKick,
  107. _disablePrivateChat,
  108. _disableRemoteMute,
  109. _disableGrantModerator,
  110. _isParticipantAvailable,
  111. _rooms,
  112. _currentRoomId,
  113. participantId,
  114. t
  115. } = this.props;
  116. const buttonProps = {
  117. afterClick: this._onCancel,
  118. showLabel: true,
  119. participantID: participantId,
  120. styles: bottomSheetStyles.buttons
  121. };
  122. return (
  123. <BottomSheet
  124. onCancel = { this._onCancel }
  125. renderHeader = { this._renderMenuHeader }
  126. showSlidingView = { _isParticipantAvailable }>
  127. <AskUnmuteButton { ...buttonProps } />
  128. { !_disableRemoteMute && <MuteButton { ...buttonProps } /> }
  129. <MuteEveryoneElseButton { ...buttonProps } />
  130. { !_disableRemoteMute && <MuteVideoButton { ...buttonProps } /> }
  131. <Divider style = { styles.divider } />
  132. { !_disableKick && <KickButton { ...buttonProps } /> }
  133. { !_disableGrantModerator && <GrantModeratorButton { ...buttonProps } /> }
  134. <PinButton { ...buttonProps } />
  135. { !_disablePrivateChat && <PrivateMessageButton { ...buttonProps } /> }
  136. <ConnectionStatusButton { ...buttonProps } />
  137. {_rooms.length > 1 && <>
  138. <Divider style = { styles.divider } />
  139. <View style = { styles.contextMenuItem }>
  140. <Text style = { styles.contextMenuItemText }>
  141. {t('breakoutRooms.actions.sendToBreakoutRoom')}
  142. </Text>
  143. </View>
  144. {_rooms.map(room => _currentRoomId !== room.id && (<SendToBreakoutRoom
  145. key = { room.id }
  146. room = { room }
  147. { ...buttonProps } />))}
  148. </>}
  149. {/* <VolumeSlider participantID = { participantId } />*/}
  150. </BottomSheet>
  151. );
  152. }
  153. _onCancel: () => boolean;
  154. /**
  155. * Callback to hide the {@code RemoteVideoMenu}.
  156. *
  157. * @private
  158. * @returns {boolean}
  159. */
  160. _onCancel() {
  161. if (this.props._isOpen) {
  162. this.props.dispatch(hideRemoteVideoMenu());
  163. return true;
  164. }
  165. return false;
  166. }
  167. _renderMenuHeader: () => React$Element<any>;
  168. /**
  169. * Function to render the menu's header.
  170. *
  171. * @returns {React$Element}
  172. */
  173. _renderMenuHeader() {
  174. const { participantId } = this.props;
  175. return (
  176. <View
  177. style = { [
  178. bottomSheetStyles.sheet,
  179. styles.participantNameContainer ] }>
  180. <Avatar
  181. participantId = { participantId }
  182. size = { AVATAR_SIZE } />
  183. <Text style = { styles.participantNameLabel }>
  184. { this.props._participantDisplayName }
  185. </Text>
  186. </View>
  187. );
  188. }
  189. }
  190. /**
  191. * Function that maps parts of Redux state tree into component props.
  192. *
  193. * @param {Object} state - Redux state.
  194. * @param {Object} ownProps - Properties of component.
  195. * @private
  196. * @returns {Props}
  197. */
  198. function _mapStateToProps(state, ownProps) {
  199. const kickOutEnabled = getFeatureFlag(state, KICK_OUT_ENABLED, true);
  200. const { participantId } = ownProps;
  201. const { remoteVideoMenu = {}, disableRemoteMute } = state['features/base/config'];
  202. const isParticipantAvailable = getParticipantById(state, participantId);
  203. const { disableKick, disablePrivateChat } = remoteVideoMenu;
  204. const _rooms = Object.values(getBreakoutRooms(state));
  205. const _currentRoomId = getCurrentRoomId(state);
  206. const shouldDisableKick = disableKick || !kickOutEnabled;
  207. return {
  208. _currentRoomId,
  209. _disableKick: Boolean(shouldDisableKick),
  210. _disableRemoteMute: Boolean(disableRemoteMute),
  211. _disablePrivateChat: Boolean(disablePrivateChat),
  212. _isOpen: isDialogOpen(state, RemoteVideoMenu_),
  213. _isParticipantAvailable: Boolean(isParticipantAvailable),
  214. _participantDisplayName: getParticipantDisplayName(state, participantId),
  215. _rooms
  216. };
  217. }
  218. RemoteVideoMenu_ = translate(connect(_mapStateToProps)(RemoteVideoMenu));
  219. export default RemoteVideoMenu_;