Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

ContextMenuMeetingParticipantDetails.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // @flow
  2. import React, { useCallback, useState } 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, useStore } 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. // eslint-disable-next-line no-unused-vars
  12. Icon, IconCloseCircle, IconConnectionActive, IconMessage,
  13. IconMicrophoneEmptySlash,
  14. IconMuteEveryoneElse, IconVideoOff
  15. } from '../../../base/icons';
  16. import { isLocalParticipantModerator } from '../../../base/participants';
  17. import { getIsParticipantVideoMuted } from '../../../base/tracks';
  18. import { openChat } from '../../../chat/actions.native';
  19. import {
  20. KickRemoteParticipantDialog,
  21. MuteEveryoneDialog,
  22. MuteRemoteParticipantDialog,
  23. MuteRemoteParticipantsVideoDialog,
  24. VolumeSlider
  25. } from '../../../video-menu';
  26. import styles from './styles';
  27. type Props = {
  28. /**
  29. * Participant reference
  30. */
  31. participant: Object
  32. };
  33. export const ContextMenuMeetingParticipantDetails = ({ participant: p }: Props) => {
  34. const [ volume, setVolume ] = useState(undefined);
  35. const store = useStore();
  36. const startSilent = store.getState['features/base/config'];
  37. const dispatch = useDispatch();
  38. const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
  39. const changeVolume = useCallback(() => setVolume(volume), [ volume ]);
  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 onVolumeChange = startSilent ? undefined : changeVolume;
  64. const sendPrivateMessage = useCallback(() => {
  65. dispatch(hideDialog());
  66. dispatch(openChat(p));
  67. }, [ dispatch, p ]);
  68. const { t } = useTranslation();
  69. return (
  70. <BottomSheet
  71. onCancel = { cancel }
  72. style = { styles.contextMenuMore }>
  73. <View
  74. style = { styles.contextMenuItemSection }>
  75. <Avatar
  76. className = 'participant-avatar'
  77. participantId = { p.id }
  78. size = { 20 } />
  79. <View style = { styles.contextMenuItemText }>
  80. <Text style = { styles.contextMenuItemName }>
  81. { displayName }
  82. </Text>
  83. </View>
  84. </View>
  85. <Divider style = { styles.divider } />
  86. {
  87. isLocalModerator
  88. && <TouchableOpacity
  89. onPress = { muteAudio }
  90. style = { styles.contextMenuItem }>
  91. <Icon
  92. size = { 20 }
  93. src = { IconMicrophoneEmptySlash }
  94. style = { styles.contextMenuItemIcon } />
  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. style = { styles.contextMenuItemIcon } />
  109. <Text style = { styles.contextMenuItemText }>
  110. { t('participantsPane.actions.muteEveryoneElse') }
  111. </Text>
  112. </TouchableOpacity>
  113. }
  114. <Divider style = { styles.divider } />
  115. {
  116. isLocalModerator && (
  117. isParticipantVideoMuted
  118. || <TouchableOpacity
  119. onPress = { muteVideo }
  120. style = { styles.contextMenuItemSection }>
  121. <Icon
  122. size = { 20 }
  123. src = { IconVideoOff }
  124. style = { styles.contextMenuItemIcon } />
  125. <Text style = { styles.contextMenuItemText }>
  126. { t('participantsPane.actions.stopVideo') }
  127. </Text>
  128. </TouchableOpacity>
  129. )
  130. }
  131. {
  132. isLocalModerator
  133. && <TouchableOpacity
  134. onPress = { kickRemoteParticipant }
  135. style = { styles.contextMenuItem }>
  136. <Icon
  137. size = { 20 }
  138. src = { IconCloseCircle }
  139. style = { styles.contextMenuItemIcon } />
  140. <Text style = { styles.contextMenuItemText }>
  141. { t('videothumbnail.kick') }
  142. </Text>
  143. </TouchableOpacity>
  144. }
  145. <TouchableOpacity
  146. onPress = { sendPrivateMessage }
  147. style = { styles.contextMenuItem }>
  148. <Icon
  149. size = { 20 }
  150. src = { IconMessage }
  151. style = { styles.contextMenuItemIcon } />
  152. <Text style = { styles.contextMenuItemText }>
  153. { t('toolbar.accessibilityLabel.privateMessage') }
  154. </Text>
  155. </TouchableOpacity>
  156. {/* We need design specs for this*/}
  157. {/* <TouchableOpacity*/}
  158. {/* style = { styles.contextMenuItemSection }>*/}
  159. {/* <Icon*/}
  160. {/* size = { 20 }*/}
  161. {/* src = { IconConnectionActive }*/}
  162. {/* style = { styles.contextMenuItemIcon } />*/}
  163. {/* <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.networkStats') }</Text>*/}
  164. {/* </TouchableOpacity>*/}
  165. <Divider style = { styles.divider } />
  166. <VolumeSlider
  167. initialValue = { volume }
  168. onChange = { onVolumeChange } />
  169. </BottomSheet>
  170. );
  171. };