浏览代码

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

master
Calin Chitu 4 年前
父节点
当前提交
0b3991d9e1

+ 14
- 3
react/features/participants-pane/actions.native.js 查看文件

1
 import { openDialog } from '../base/dialog';
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
  * Displays the context menu for the selected lobby participant.
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
  * @returns {Function}
9
  * @returns {Function}
10
  */
10
  */
11
 export function showContextMenuReject(participant) {
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
     participant: Object
23
     participant: Object
24
 };
24
 };
25
 
25
 
26
-export const ContextMenuReject = ({ participant: p }: Props) => {
26
+export const ContextMenuLobbyParticipantReject = ({ participant: p }: Props) => {
27
     const dispatch = useDispatch();
27
     const dispatch = useDispatch();
28
     const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
28
     const cancel = useCallback(() => dispatch(hideDialog()), [ dispatch ]);
29
     const displayName = p.name;
29
     const displayName = p.name;
35
             onCancel = { cancel }
35
             onCancel = { cancel }
36
             style = { styles.contextMenuMore }>
36
             style = { styles.contextMenuMore }>
37
             <View
37
             <View
38
-                style = { styles.contextMenuItemDetails }>
38
+                style = { styles.contextMenuItemSection }>
39
                 <Avatar
39
                 <Avatar
40
                     className = 'participant-avatar'
40
                     className = 'participant-avatar'
41
                     participantId = { p.id }
41
                     participantId = { p.id }
42
                     size = { 32 } />
42
                     size = { 32 } />
43
                 <View style = { styles.contextMenuItemText }>
43
                 <View style = { styles.contextMenuItemText }>
44
-                    <Text style = { styles.contextMenuItemParticipantName }>
44
+                    <Text style = { styles.contextMenuItemName }>
45
                         { displayName }
45
                         { displayName }
46
                     </Text>
46
                     </Text>
47
                 </View>
47
                 </View>
48
             </View>
48
             </View>
49
             <TouchableOpacity
49
             <TouchableOpacity
50
                 onPress = { reject }
50
                 onPress = { reject }
51
-                style = { styles.contextMenuItemReject }>
51
+                style = { styles.contextMenuItem }>
52
                 <Icon
52
                 <Icon
53
                     size = { 24 }
53
                     size = { 24 }
54
-                    src = { IconClose } />
54
+                    src = { IconClose }
55
+                    style = { styles.contextMenuItemIcon } />
55
                 <Text style = { styles.contextMenuItemText }>{ t('lobby.reject') }</Text>
56
                 <Text style = { styles.contextMenuItemText }>{ t('lobby.reject') }</Text>
56
             </TouchableOpacity>
57
             </TouchableOpacity>
57
         </BottomSheet>
58
         </BottomSheet>

+ 105
- 0
react/features/participants-pane/components/native/ContextMenuMeetingParticipantDetails.js 查看文件

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
             style = { styles.contextMenuMore }>
41
             style = { styles.contextMenuMore }>
42
             <TouchableOpacity
42
             <TouchableOpacity
43
                 onPress = { muteEveryoneVideo }
43
                 onPress = { muteEveryoneVideo }
44
-                style = { styles.contextMenuItemMuteVideo }>
44
+                style = { styles.contextMenuItem }>
45
                 <Icon
45
                 <Icon
46
                     size = { 24 }
46
                     size = { 24 }
47
                     src = { IconVideoOff } />
47
                     src = { IconVideoOff } />
48
                 <Text style = { styles.contextMenuItemText }>{t('participantsPane.actions.stopEveryonesVideo')}</Text>
48
                 <Text style = { styles.contextMenuItemText }>{t('participantsPane.actions.stopEveryonesVideo')}</Text>
49
             </TouchableOpacity>
49
             </TouchableOpacity>
50
             <TouchableOpacity
50
             <TouchableOpacity
51
-                style = { styles.contextMenuItemDontAllowUnmute }>
51
+                style = { styles.contextMenuItem }>
52
                 <Icon
52
                 <Icon
53
                     size = { 24 }
53
                     size = { 24 }
54
                     src = { IconMicDisabledHollow }
54
                     src = { IconMicDisabledHollow }

+ 6
- 2
react/features/participants-pane/components/native/MeetingParticipantItem.js 查看文件

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

+ 2
- 0
react/features/participants-pane/components/native/index.js 查看文件

2
 
2
 
3
 export { default as ParticipantsPane } from './ParticipantsPane';
3
 export { default as ParticipantsPane } from './ParticipantsPane';
4
 export { default as ParticipantsPaneButton } from './ParticipantsPaneButton';
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
         textTransform: 'capitalize'
287
         textTransform: 'capitalize'
288
     },
288
     },
289
 
289
 
290
-    contextMenuItemMuteVideo: {
290
+    contextMenuItem: {
291
         ...contextMenuItem
291
         ...contextMenuItem
292
     },
292
     },
293
 
293
 
294
-    contextMenuItemDontAllowUnmute: {
295
-        ...contextMenuItem
296
-    },
297
-
298
-    contextMenuItemDetails: {
294
+    contextMenuItemSection: {
299
         ...contextMenuItem,
295
         ...contextMenuItem,
300
         borderBottomColor: BaseTheme.palette.section01,
296
         borderBottomColor: BaseTheme.palette.section01,
301
         borderBottomWidth: 1
297
         borderBottomWidth: 1
302
     },
298
     },
303
 
299
 
304
-    contextMenuItemReject: {
305
-        ...contextMenuItem
306
-    },
307
-
308
     contextMenuItemText: {
300
     contextMenuItemText: {
309
         ...BaseTheme.typography.bodyShortRegularLarge,
301
         ...BaseTheme.typography.bodyShortRegularLarge,
310
         alignSelf: 'center',
302
         alignSelf: 'center',
311
         color: BaseTheme.palette.text01,
303
         color: BaseTheme.palette.text01,
312
         flexDirection: 'row',
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
         ...BaseTheme.typography.bodyShortRegularLarge,
313
         ...BaseTheme.typography.bodyShortRegularLarge,
318
         color: BaseTheme.palette.text01
314
         color: BaseTheme.palette.text01
319
     },
315
     },

+ 0
- 0
react/features/video-menu/components/native/VolumeSlider.js 查看文件


正在加载...
取消
保存