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.

ContextMenuMeetingParticipantDetails.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // @flow
  2. import React, { useCallback } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import { TouchableOpacity, View } from 'react-native';
  5. import { Divider, Text } from 'react-native-paper';
  6. import { useDispatch, useSelector } from 'react-redux';
  7. import { Avatar } from '../../../base/avatar';
  8. import { hideDialog, openDialog } from '../../../base/dialog/actions';
  9. import BottomSheet from '../../../base/dialog/components/native/BottomSheet';
  10. import {
  11. Icon, IconCloseCircle, IconMessage,
  12. IconMicrophoneEmptySlash,
  13. IconMuteEveryoneElse, IconVideoOff
  14. } from '../../../base/icons';
  15. import {
  16. isLocalParticipantModerator
  17. } from '../../../base/participants';
  18. import { getIsParticipantVideoMuted } from '../../../base/tracks';
  19. import { openChat } from '../../../chat/actions.native';
  20. import {
  21. KickRemoteParticipantDialog,
  22. MuteEveryoneDialog,
  23. MuteRemoteParticipantDialog,
  24. MuteRemoteParticipantsVideoDialog,
  25. VolumeSlider
  26. } from '../../../video-menu';
  27. import styles from './styles';
  28. type Props = {
  29. /**
  30. * Participant reference
  31. */
  32. participant: Object
  33. };
  34. export const ContextMenuMeetingParticipantDetails = ({ participant: p }: Props) => {
  35. const dispatch = useDispatch();
  36. const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
  37. const displayName = p.name;
  38. const isLocalModerator = useSelector(isLocalParticipantModerator);
  39. const isParticipantVideoMuted = useSelector(getIsParticipantVideoMuted(p));
  40. const kickRemoteParticipant = useCallback(() => {
  41. dispatch(openDialog(KickRemoteParticipantDialog, {
  42. participantID: p.id
  43. }));
  44. }, [ dispatch, p ]);
  45. const muteAudio = useCallback(() => {
  46. dispatch(openDialog(MuteRemoteParticipantDialog, {
  47. participantID: p.id
  48. }));
  49. }, [ dispatch, p ]);
  50. const muteEveryoneElse = useCallback(() => {
  51. dispatch(openDialog(MuteEveryoneDialog, {
  52. exclude: [ p.id ]
  53. }));
  54. }, [ dispatch, p ]);
  55. const muteVideo = useCallback(() => {
  56. dispatch(openDialog(MuteRemoteParticipantsVideoDialog, {
  57. participantID: p.id
  58. }));
  59. }, [ dispatch, p ]);
  60. const sendPrivateMessage = useCallback(() => {
  61. dispatch(hideDialog());
  62. dispatch(openChat(p));
  63. }, [ dispatch, p ]);
  64. const { t } = useTranslation();
  65. return (
  66. <BottomSheet
  67. onCancel = { cancel }
  68. style = { styles.contextMenuMeetingParticipantDetails }>
  69. <View
  70. style = { styles.contextMenuItemSectionAvatar }>
  71. <Avatar
  72. className = 'participant-avatar'
  73. participantId = { p.id }
  74. size = { 30 } />
  75. <View style = { styles.contextMenuItemAvatarText }>
  76. <Text style = { styles.contextMenuItemName }>
  77. { displayName }
  78. </Text>
  79. </View>
  80. </View>
  81. <Divider style = { styles.divider } />
  82. {
  83. isLocalModerator
  84. && <TouchableOpacity
  85. onPress = { muteAudio }
  86. style = { styles.contextMenuItem }>
  87. <Icon
  88. size = { 24 }
  89. src = { IconMicrophoneEmptySlash }
  90. style = { styles.contextMenuItemIcon } />
  91. <Text style = { styles.contextMenuItemText }>
  92. { t('participantsPane.actions.mute') }
  93. </Text>
  94. </TouchableOpacity>
  95. }
  96. {
  97. isLocalModerator
  98. && <TouchableOpacity
  99. onPress = { muteEveryoneElse }
  100. style = { styles.contextMenuItem }>
  101. <Icon
  102. size = { 24 }
  103. src = { IconMuteEveryoneElse }
  104. style = { styles.contextMenuItemIcon } />
  105. <Text style = { styles.contextMenuItemText }>
  106. { t('participantsPane.actions.muteEveryoneElse') }
  107. </Text>
  108. </TouchableOpacity>
  109. }
  110. <Divider style = { styles.divider } />
  111. {
  112. isLocalModerator && (
  113. isParticipantVideoMuted
  114. || <TouchableOpacity
  115. onPress = { muteVideo }
  116. style = { styles.contextMenuItemSection }>
  117. <Icon
  118. size = { 24 }
  119. src = { IconVideoOff }
  120. style = { styles.contextMenuItemIcon } />
  121. <Text style = { styles.contextMenuItemText }>
  122. { t('participantsPane.actions.stopVideo') }
  123. </Text>
  124. </TouchableOpacity>
  125. )
  126. }
  127. {
  128. isLocalModerator
  129. && <TouchableOpacity
  130. onPress = { kickRemoteParticipant }
  131. style = { styles.contextMenuItem }>
  132. <Icon
  133. size = { 24 }
  134. src = { IconCloseCircle }
  135. style = { styles.contextMenuItemIcon } />
  136. <Text style = { styles.contextMenuItemText }>
  137. { t('videothumbnail.kick') }
  138. </Text>
  139. </TouchableOpacity>
  140. }
  141. <TouchableOpacity
  142. onPress = { sendPrivateMessage }
  143. style = { styles.contextMenuItem }>
  144. <Icon
  145. size = { 24 }
  146. src = { IconMessage }
  147. style = { styles.contextMenuItemIcon } />
  148. <Text style = { styles.contextMenuItemText }>
  149. { t('toolbar.accessibilityLabel.privateMessage') }
  150. </Text>
  151. </TouchableOpacity>
  152. {/* We need design specs for this*/}
  153. {/* <TouchableOpacity*/}
  154. {/* style = { styles.contextMenuItemSection }>*/}
  155. {/* <Icon*/}
  156. {/* size = { 20 }*/}
  157. {/* src = { IconConnectionActive }*/}
  158. {/* style = { styles.contextMenuItemIcon } />*/}
  159. {/* <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.networkStats') }</Text>*/}
  160. {/* </TouchableOpacity>*/}
  161. <Divider style = { styles.divider } />
  162. <VolumeSlider participant = { p } />
  163. </BottomSheet>
  164. );
  165. };