Переглянути джерело

feat(native-participants-pane) context menu for meeting participant

master
Calin Chitu 4 роки тому
джерело
коміт
0b3991d9e1

+ 14
- 3
react/features/participants-pane/actions.native.js Переглянути файл

@@ -1,13 +1,24 @@
1 1
 import { openDialog } from '../base/dialog';
2 2
 
3
-import { ContextMenuReject } from './components/native/ContextMenuReject';
3
+import { ContextMenuLobbyParticipantReject, ContextMenuMeetingParticipantDetails } from './components/native';
4 4
 
5 5
 /**
6 6
  * Displays the context menu for the selected lobby participant.
7 7
  *
8
- * @param {string} participant - The selected participant's id.
8
+ * @param {Object} participant - The selected lobby participant.
9 9
  * @returns {Function}
10 10
  */
11 11
 export function showContextMenuReject(participant) {
12
-    return openDialog(ContextMenuReject, { participant });
12
+    return openDialog(ContextMenuLobbyParticipantReject, { participant });
13
+}
14
+
15
+
16
+/**
17
+ * Displays the context menu for the selected meeting participant.
18
+ *
19
+ * @param {Object} participant - The selected meeting participant.
20
+ * @returns {Function}
21
+ */
22
+export function showContextMenuDetails(participant) {
23
+    return openDialog(ContextMenuMeetingParticipantDetails, { participant });
13 24
 }

react/features/participants-pane/components/native/ContextMenuReject.js → react/features/participants-pane/components/native/ContextMenuLobbyParticipantReject.js Переглянути файл

@@ -23,7 +23,7 @@ type Props = {
23 23
     participant: Object
24 24
 };
25 25
 
26
-export const ContextMenuReject = ({ participant: p }: Props) => {
26
+export const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => {
27 27
     const dispatch = useDispatch();
28 28
     const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
29 29
     const displayName = p.name;
@@ -35,23 +35,24 @@ export const ContextMenuReject = ({ participant: p }: Props) => {
35 35
             onCancel = { cancel }
36 36
             style = { styles.contextMenuMore }>
37 37
             <View
38
-                style = { styles.contextMenuItemDetails }>
38
+                style = { styles.contextMenuItemSection }>
39 39
                 <Avatar
40 40
                     className = 'participant-avatar'
41 41
                     participantId = { p.id }
42 42
                     size = { 32 } />
43 43
                 <View style = { styles.contextMenuItemText }>
44
-                    <Text style = { styles.contextMenuItemParticipantName }>
44
+                    <Text style = { styles.contextMenuItemName }>
45 45
                         { displayName }
46 46
                     </Text>
47 47
                 </View>
48 48
             </View>
49 49
             <TouchableOpacity
50 50
                 onPress = { reject }
51
-                style = { styles.contextMenuItemReject }>
51
+                style = { styles.contextMenuItem }>
52 52
                 <Icon
53 53
                     size = { 24 }
54
-                    src = { IconClose } />
54
+                    src = { IconClose }
55
+                    style = { styles.contextMenuItemIcon } />
55 56
                 <Text style = { styles.contextMenuItemText }>{ t('lobby.reject') }</Text>
56 57
             </TouchableOpacity>
57 58
         </BottomSheet>

+ 105
- 0
react/features/participants-pane/components/native/ContextMenuMeetingParticipantDetails.js Переглянути файл

@@ -0,0 +1,105 @@
1
+// @flow
2
+
3
+import React, { useCallback } from 'react';
4
+import { useTranslation } from 'react-i18next';
5
+import { TouchableOpacity, View } from 'react-native';
6
+import { Text } from 'react-native-paper';
7
+import { useDispatch } from 'react-redux';
8
+
9
+import { Avatar } from '../../../base/avatar';
10
+import { hideDialog } from '../../../base/dialog';
11
+import BottomSheet from '../../../base/dialog/components/native/BottomSheet';
12
+import {
13
+    Icon, IconCloseCircle, IconConnectionActive, IconMessage,
14
+    IconMicrophoneEmptySlash,
15
+    IconMuteEveryoneElse, IconVideoOff
16
+} from '../../../base/icons';
17
+import { MEDIA_TYPE } from '../../../base/media';
18
+import { muteRemote } from '../../../video-menu/actions.any';
19
+
20
+import styles from './styles';
21
+
22
+type Props = {
23
+
24
+    /**
25
+     * Participant reference
26
+     */
27
+    participant: Object
28
+};
29
+
30
+export const ContextMenuMeetingParticipantDetails = ({ participant: p }: Props) => {
31
+    const dispatch = useDispatch();
32
+    const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
33
+    const displayName = p.name;
34
+    const muteAudio = useCallback(() => dispatch(muteRemote(p.id, MEDIA_TYPE.AUDIO)), [ dispatch ]);
35
+    const { t } = useTranslation();
36
+
37
+    return (
38
+        <BottomSheet
39
+            onCancel = { cancel }
40
+            style = { styles.contextMenuMore }>
41
+            <View
42
+                style = { styles.contextMenuItemSection }>
43
+                <Avatar
44
+                    className = 'participant-avatar'
45
+                    participantId = { p.id }
46
+                    size = { 32 } />
47
+                <View style = { styles.contextMenuItemText }>
48
+                    <Text style = { styles.contextMenuItemName }>
49
+                        { displayName }
50
+                    </Text>
51
+                </View>
52
+            </View>
53
+            <TouchableOpacity
54
+                onPress = { muteAudio }
55
+                style = { styles.contextMenuItem }>
56
+                <Icon
57
+                    size = { 24 }
58
+                    src = { IconMicrophoneEmptySlash }
59
+                    style = { styles.contextMenuItemIcon } />
60
+                <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.mute') }</Text>
61
+            </TouchableOpacity>
62
+            <TouchableOpacity
63
+                onPress = { muteAudio }
64
+                style = { styles.contextMenuItem }>
65
+                <Icon
66
+                    size = { 24 }
67
+                    src = { IconMuteEveryoneElse }
68
+                    style = { styles.contextMenuItemIcon } />
69
+                <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.muteEveryoneElse') }</Text>
70
+            </TouchableOpacity>
71
+            <TouchableOpacity
72
+                style = { styles.contextMenuItemSection }>
73
+                <Icon
74
+                    size = { 24 }
75
+                    src = { IconVideoOff }
76
+                    style = { styles.contextMenuItemIcon } />
77
+                <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.stopVideo') }</Text>
78
+            </TouchableOpacity>
79
+            <TouchableOpacity
80
+                style = { styles.contextMenuItem }>
81
+                <Icon
82
+                    size = { 24 }
83
+                    src = { IconCloseCircle }
84
+                    style = { styles.contextMenuItemIcon } />
85
+                <Text style = { styles.contextMenuItemText }>{ t('videothumbnail.kick') }</Text>
86
+            </TouchableOpacity>
87
+            <TouchableOpacity
88
+                style = { styles.contextMenuItem }>
89
+                <Icon
90
+                    size = { 24 }
91
+                    src = { IconMessage }
92
+                    style = { styles.contextMenuItemIcon } />
93
+                <Text style = { styles.contextMenuItemText }>{ t('toolbar.accessibilityLabel.privateMessage') }</Text>
94
+            </TouchableOpacity>
95
+            <TouchableOpacity
96
+                style = { styles.contextMenuItemSection }>
97
+                <Icon
98
+                    size = { 24 }
99
+                    src = { IconConnectionActive }
100
+                    style = { styles.contextMenuItemIcon } />
101
+                <Text style = { styles.contextMenuItemText }>{ t('participantsPane.actions.networkStats') }</Text>
102
+            </TouchableOpacity>
103
+        </BottomSheet>
104
+    );
105
+};

+ 2
- 2
react/features/participants-pane/components/native/ContextMenuMore.js Переглянути файл

@@ -41,14 +41,14 @@ export const ContextMenuMore = ({ exclude }: Props) => {
41 41
             style = { styles.contextMenuMore }>
42 42
             <TouchableOpacity
43 43
                 onPress = { muteEveryoneVideo }
44
-                style = { styles.contextMenuItemMuteVideo }>
44
+                style = { styles.contextMenuItem }>
45 45
                 <Icon
46 46
                     size = { 24 }
47 47
                     src = { IconVideoOff } />
48 48
                 <Text style = { styles.contextMenuItemText }>{t('participantsPane.actions.stopEveryonesVideo')}</Text>
49 49
             </TouchableOpacity>
50 50
             <TouchableOpacity
51
-                style = { styles.contextMenuItemDontAllowUnmute }>
51
+                style = { styles.contextMenuItem }>
52 52
                 <Icon
53 53
                     size = { 24 }
54 54
                     src = { IconMicDisabledHollow }

+ 6
- 2
react/features/participants-pane/components/native/MeetingParticipantItem.js Переглянути файл

@@ -1,12 +1,13 @@
1 1
 // @flow
2 2
 
3
-import React from 'react';
4
-import { useSelector } from 'react-redux';
3
+import React, { useCallback } from 'react';
4
+import { useSelector, useDispatch } from 'react-redux';
5 5
 
6 6
 import {
7 7
     getIsParticipantAudioMuted,
8 8
     getIsParticipantVideoMuted
9 9
 } from '../../../base/tracks';
10
+import { showContextMenuDetails } from '../../actions.native';
10 11
 import { MediaState } from '../../constants';
11 12
 
12 13
 import ParticipantItem from './ParticipantItem';
@@ -21,13 +22,16 @@ type Props = {
21 22
 };
22 23
 
23 24
 export const MeetingParticipantItem = ({ participant: p }: Props) => {
25
+    const dispatch = useDispatch();
24 26
     const isAudioMuted = useSelector(getIsParticipantAudioMuted(p));
25 27
     const isVideoMuted = useSelector(getIsParticipantVideoMuted(p));
28
+    const openContextMenuDetails = useCallback(() => dispatch(showContextMenuDetails(p), [ dispatch ]));
26 29
 
27 30
     return (
28 31
         <ParticipantItem
29 32
             audioMuteState = { isAudioMuted ? MediaState.Muted : MediaState.Unmuted }
30 33
             name = { p.name }
34
+            onPress = { openContextMenuDetails }
31 35
             participant = { p }
32 36
             videoMuteState = { isVideoMuted ? MediaState.Muted : MediaState.Unmuted } />
33 37
     );

+ 2
- 0
react/features/participants-pane/components/native/index.js Переглянути файл

@@ -2,3 +2,5 @@
2 2
 
3 3
 export { default as ParticipantsPane } from './ParticipantsPane';
4 4
 export { default as ParticipantsPaneButton } from './ParticipantsPaneButton';
5
+export { ContextMenuLobbyParticipantReject } from './ContextMenuLobbyParticipantReject';
6
+export { ContextMenuMeetingParticipantDetails } from './ContextMenuMeetingParticipantDetails';

+ 8
- 12
react/features/participants-pane/components/native/styles.js Переглянути файл

@@ -287,33 +287,29 @@ export default {
287 287
         textTransform: 'capitalize'
288 288
     },
289 289
 
290
-    contextMenuItemMuteVideo: {
290
+    contextMenuItem: {
291 291
         ...contextMenuItem
292 292
     },
293 293
 
294
-    contextMenuItemDontAllowUnmute: {
295
-        ...contextMenuItem
296
-    },
297
-
298
-    contextMenuItemDetails: {
294
+    contextMenuItemSection: {
299 295
         ...contextMenuItem,
300 296
         borderBottomColor: BaseTheme.palette.section01,
301 297
         borderBottomWidth: 1
302 298
     },
303 299
 
304
-    contextMenuItemReject: {
305
-        ...contextMenuItem
306
-    },
307
-
308 300
     contextMenuItemText: {
309 301
         ...BaseTheme.typography.bodyShortRegularLarge,
310 302
         alignSelf: 'center',
311 303
         color: BaseTheme.palette.text01,
312 304
         flexDirection: 'row',
313
-        marginLeft: 8
305
+        marginLeft: BaseTheme.spacing[3]
306
+    },
307
+
308
+    contextMenuItemIcon: {
309
+        marginLeft: BaseTheme.spacing[1]
314 310
     },
315 311
 
316
-    contextMenuItemParticipantName: {
312
+    contextMenuItemName: {
317 313
         ...BaseTheme.typography.bodyShortRegularLarge,
318 314
         color: BaseTheme.palette.text01
319 315
     },

+ 0
- 0
react/features/video-menu/components/native/VolumeSlider.js Переглянути файл


Завантаження…
Відмінити
Зберегти