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.0KB

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