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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. getParticipantsById,
  17. isLocalParticipantModerator
  18. } from '../../../base/participants';
  19. import { getIsParticipantVideoMuted } from '../../../base/tracks';
  20. import { openChat } from '../../../chat/actions.native';
  21. import {
  22. KickRemoteParticipantDialog,
  23. MuteEveryoneDialog,
  24. MuteRemoteParticipantDialog,
  25. MuteRemoteParticipantsVideoDialog,
  26. VolumeSlider
  27. } from '../../../video-menu';
  28. import styles from './styles';
  29. type Props = {
  30. /**
  31. * Participant reference
  32. */
  33. participant: Object
  34. };
  35. export const ContextMenuMeetingParticipantDetails = ({ participant: p }: Props) => {
  36. const dispatch = useDispatch();
  37. const participantsIDArr = useSelector(getParticipantsById);
  38. const participantIsAvailable = participantsIDArr.find(partId => partId === p.id);
  39. const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
  40. const displayName = p.name;
  41. const isLocalModerator = useSelector(isLocalParticipantModerator);
  42. const isParticipantVideoMuted = useSelector(getIsParticipantVideoMuted(p));
  43. const kickRemoteParticipant = useCallback(() => {
  44. dispatch(openDialog(KickRemoteParticipantDialog, {
  45. participantID: p.id
  46. }));
  47. }, [ dispatch, p ]);
  48. const muteAudio = useCallback(() => {
  49. dispatch(openDialog(MuteRemoteParticipantDialog, {
  50. participantID: p.id
  51. }));
  52. }, [ dispatch, p ]);
  53. const muteEveryoneElse = useCallback(() => {
  54. dispatch(openDialog(MuteEveryoneDialog, {
  55. exclude: [ p.id ]
  56. }));
  57. }, [ dispatch, p ]);
  58. const muteVideo = useCallback(() => {
  59. dispatch(openDialog(MuteRemoteParticipantsVideoDialog, {
  60. participantID: p.id
  61. }));
  62. }, [ dispatch, p ]);
  63. const sendPrivateMessage = useCallback(() => {
  64. dispatch(hideDialog());
  65. dispatch(openChat(p));
  66. }, [ dispatch, p ]);
  67. const { t } = useTranslation();
  68. return (
  69. <BottomSheet
  70. addScrollViewPadding = { false }
  71. onCancel = { cancel }
  72. showSlidingView = { Boolean(participantIsAvailable) }
  73. style = { styles.contextMenuMeetingParticipantDetails }>
  74. <View
  75. style = { styles.contextMenuItemSectionAvatar }>
  76. <Avatar
  77. className = 'participant-avatar'
  78. participantId = { p.id }
  79. size = { 20 } />
  80. <View style = { styles.contextMenuItemAvatarText }>
  81. <Text style = { styles.contextMenuItemName }>
  82. { displayName }
  83. </Text>
  84. </View>
  85. </View>
  86. <Divider style = { styles.divider } />
  87. {
  88. isLocalModerator
  89. && <TouchableOpacity
  90. onPress = { muteAudio }
  91. style = { styles.contextMenuItem }>
  92. <Icon
  93. size = { 20 }
  94. src = { IconMicrophoneEmptySlash } />
  95. <Text style = { styles.contextMenuItemText }>
  96. { t('participantsPane.actions.mute') }
  97. </Text>
  98. </TouchableOpacity>
  99. }
  100. {
  101. isLocalModerator
  102. && <TouchableOpacity
  103. onPress = { muteEveryoneElse }
  104. style = { styles.contextMenuItem }>
  105. <Icon
  106. size = { 20 }
  107. src = { IconMuteEveryoneElse } />
  108. <Text style = { styles.contextMenuItemText }>
  109. { t('participantsPane.actions.muteEveryoneElse') }
  110. </Text>
  111. </TouchableOpacity>
  112. }
  113. <Divider style = { styles.divider } />
  114. {
  115. isLocalModerator && (
  116. isParticipantVideoMuted
  117. || <TouchableOpacity
  118. onPress = { muteVideo }
  119. style = { styles.contextMenuItemSection }>
  120. <Icon
  121. size = { 20 }
  122. src = { IconVideoOff } />
  123. <Text style = { styles.contextMenuItemText }>
  124. { t('participantsPane.actions.stopVideo') }
  125. </Text>
  126. </TouchableOpacity>
  127. )
  128. }
  129. {
  130. isLocalModerator
  131. && <TouchableOpacity
  132. onPress = { kickRemoteParticipant }
  133. style = { styles.contextMenuItem }>
  134. <Icon
  135. size = { 20 }
  136. src = { IconCloseCircle } />
  137. <Text style = { styles.contextMenuItemText }>
  138. { t('videothumbnail.kick') }
  139. </Text>
  140. </TouchableOpacity>
  141. }
  142. <TouchableOpacity
  143. onPress = { sendPrivateMessage }
  144. style = { styles.contextMenuItem }>
  145. <Icon
  146. size = { 20 }
  147. src = { IconMessage } />
  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. };