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.

RemoteVideoMenuTriggerButton.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { Icon, IconMenuThumb } from '../../../base/icons';
  4. import { getLocalParticipant, PARTICIPANT_ROLE } from '../../../base/participants';
  5. import { Popover } from '../../../base/popover';
  6. import { connect } from '../../../base/redux';
  7. import {
  8. MuteButton,
  9. MuteEveryoneElseButton,
  10. KickButton,
  11. PrivateMessageMenuButton,
  12. RemoteControlButton,
  13. RemoteVideoMenu,
  14. VolumeSlider
  15. } from './';
  16. declare var $: Object;
  17. declare var interfaceConfig: Object;
  18. /**
  19. * The type of the React {@code Component} props of
  20. * {@link RemoteVideoMenuTriggerButton}.
  21. */
  22. type Props = {
  23. /**
  24. * Whether or not the participant is a conference moderator.
  25. */
  26. _isModerator: boolean,
  27. /**
  28. * A value between 0 and 1 indicating the volume of the participant's
  29. * audio element.
  30. */
  31. initialVolumeValue: number,
  32. /**
  33. * Whether or not the participant is currently muted.
  34. */
  35. isAudioMuted: boolean,
  36. /**
  37. * Callback to invoke when the popover has been displayed.
  38. */
  39. onMenuDisplay: Function,
  40. /**
  41. * Callback to invoke choosing to start a remote control session with
  42. * the participant.
  43. */
  44. onRemoteControlToggle: Function,
  45. /**
  46. * Callback to invoke when changing the level of the participant's
  47. * audio element.
  48. */
  49. onVolumeChange: Function,
  50. /**
  51. * The position relative to the trigger the remote menu should display
  52. * from. Valid values are those supported by AtlasKit
  53. * {@code InlineDialog}.
  54. */
  55. menuPosition: string,
  56. /**
  57. * The ID for the participant on which the remote video menu will act.
  58. */
  59. participantID: string,
  60. /**
  61. * The current state of the participant's remote control session.
  62. */
  63. remoteControlState: number
  64. };
  65. /**
  66. * React {@code Component} for displaying an icon associated with opening the
  67. * the {@code RemoteVideoMenu}.
  68. *
  69. * @extends {Component}
  70. */
  71. class RemoteVideoMenuTriggerButton extends Component<Props> {
  72. /**
  73. * The internal reference to topmost DOM/HTML element backing the React
  74. * {@code Component}. Accessed directly for associating an element as
  75. * the trigger for a popover.
  76. *
  77. * @private
  78. * @type {HTMLDivElement}
  79. */
  80. _rootElement = null;
  81. /**
  82. * Initializes a new {#@code RemoteVideoMenuTriggerButton} instance.
  83. *
  84. * @param {Object} props - The read-only properties with which the new
  85. * instance is to be initialized.
  86. */
  87. constructor(props: Object) {
  88. super(props);
  89. // Bind event handler so it is only bound once for every instance.
  90. this._onShowRemoteMenu = this._onShowRemoteMenu.bind(this);
  91. }
  92. /**
  93. * Implements React's {@link Component#render()}.
  94. *
  95. * @inheritdoc
  96. * @returns {ReactElement}
  97. */
  98. render() {
  99. const content = this._renderRemoteVideoMenu();
  100. if (!content) {
  101. return null;
  102. }
  103. return (
  104. <Popover
  105. content = { content }
  106. onPopoverOpen = { this._onShowRemoteMenu }
  107. position = { this.props.menuPosition }>
  108. <span
  109. className = 'popover-trigger remote-video-menu-trigger'>
  110. <Icon
  111. size = '1em'
  112. src = { IconMenuThumb }
  113. title = 'Remote user controls' />
  114. </span>
  115. </Popover>
  116. );
  117. }
  118. _onShowRemoteMenu: () => void;
  119. /**
  120. * Opens the {@code RemoteVideoMenu}.
  121. *
  122. * @private
  123. * @returns {void}
  124. */
  125. _onShowRemoteMenu() {
  126. this.props.onMenuDisplay();
  127. }
  128. /**
  129. * Creates a new {@code RemoteVideoMenu} with buttons for interacting with
  130. * the remote participant.
  131. *
  132. * @private
  133. * @returns {ReactElement}
  134. */
  135. _renderRemoteVideoMenu() {
  136. const {
  137. _isModerator,
  138. initialVolumeValue,
  139. isAudioMuted,
  140. onRemoteControlToggle,
  141. onVolumeChange,
  142. remoteControlState,
  143. participantID
  144. } = this.props;
  145. const buttons = [];
  146. if (_isModerator) {
  147. buttons.push(
  148. <MuteButton
  149. isAudioMuted = { isAudioMuted }
  150. key = 'mute'
  151. participantID = { participantID } />
  152. );
  153. buttons.push(
  154. <MuteEveryoneElseButton
  155. key = 'mute-others'
  156. participantID = { participantID } />
  157. );
  158. buttons.push(
  159. <KickButton
  160. key = 'kick'
  161. participantID = { participantID } />
  162. );
  163. }
  164. if (remoteControlState) {
  165. buttons.push(
  166. <RemoteControlButton
  167. key = 'remote-control'
  168. onClick = { onRemoteControlToggle }
  169. participantID = { participantID }
  170. remoteControlState = { remoteControlState } />
  171. );
  172. }
  173. buttons.push(
  174. <PrivateMessageMenuButton
  175. key = 'privateMessage'
  176. participantID = { participantID } />
  177. );
  178. if (onVolumeChange) {
  179. buttons.push(
  180. <VolumeSlider
  181. initialValue = { initialVolumeValue }
  182. key = 'volume-slider'
  183. onChange = { onVolumeChange } />
  184. );
  185. }
  186. if (buttons.length > 0) {
  187. return (
  188. <RemoteVideoMenu id = { participantID }>
  189. { buttons }
  190. </RemoteVideoMenu>
  191. );
  192. }
  193. return null;
  194. }
  195. }
  196. /**
  197. * Maps (parts of) the Redux state to the associated {@code RemoteVideoMenuTriggerButton}'s props.
  198. *
  199. * @param {Object} state - The Redux state.
  200. * @param {Object} ownProps - The own props of the component.
  201. * @private
  202. * @returns {{
  203. * _isModerator: boolean
  204. * }}
  205. */
  206. function _mapStateToProps(state) {
  207. const participant = getLocalParticipant(state);
  208. return {
  209. _isModerator: Boolean(participant?.role === PARTICIPANT_ROLE.MODERATOR)
  210. };
  211. }
  212. export default connect(_mapStateToProps)(RemoteVideoMenuTriggerButton);