Browse Source

[RN] Add remote video menu

efficient_tiling
Bettenbuk Zoltan 6 years ago
parent
commit
6b68fba220
27 changed files with 582 additions and 65 deletions
  1. 2
    0
      lang/main.json
  2. 41
    0
      react/features/base/dialog/components/native/styles.js
  3. 6
    0
      react/features/base/react/components/AbstractContainer.js
  4. 3
    1
      react/features/base/react/components/native/Container.js
  5. 31
    0
      react/features/filmstrip/components/native/Thumbnail.js
  6. 14
    0
      react/features/remote-video-menu/actions.js
  7. 0
    0
      react/features/remote-video-menu/components/MuteRemoteParticipantDialog.native.js
  8. 3
    0
      react/features/remote-video-menu/components/index.native.js
  9. 3
    0
      react/features/remote-video-menu/components/index.web.js
  10. 46
    0
      react/features/remote-video-menu/components/native/KickButton.js
  11. 84
    0
      react/features/remote-video-menu/components/native/KickRemoteParticipantDialog.js
  12. 116
    0
      react/features/remote-video-menu/components/native/MuteButton.js
  13. 80
    0
      react/features/remote-video-menu/components/native/MuteRemoteParticipantDialog.js
  14. 109
    0
      react/features/remote-video-menu/components/native/RemoteVideoMenu.js
  15. 3
    0
      react/features/remote-video-menu/components/native/index.js
  16. 20
    0
      react/features/remote-video-menu/components/native/styles.js
  17. 3
    3
      react/features/remote-video-menu/components/web/KickButton.js
  18. 3
    3
      react/features/remote-video-menu/components/web/MuteButton.js
  19. 4
    4
      react/features/remote-video-menu/components/web/MuteRemoteParticipantDialog.js
  20. 2
    2
      react/features/remote-video-menu/components/web/RemoteControlButton.js
  21. 0
    0
      react/features/remote-video-menu/components/web/RemoteVideoMenu.js
  22. 0
    0
      react/features/remote-video-menu/components/web/RemoteVideoMenuButton.js
  23. 1
    1
      react/features/remote-video-menu/components/web/RemoteVideoMenuTriggerButton.js
  24. 0
    0
      react/features/remote-video-menu/components/web/VolumeSlider.js
  25. 2
    0
      react/features/remote-video-menu/components/web/index.js
  26. 6
    3
      react/features/toolbox/components/native/OverflowMenu.js
  27. 0
    48
      react/features/toolbox/components/native/styles.js

+ 2
- 0
lang/main.json View File

@@ -385,8 +385,10 @@
385 385
         "externalInstallationMsg": "You need to install our desktop sharing extension.",
386 386
         "inlineInstallationMsg": "You need to install our desktop sharing extension.",
387 387
         "inlineInstallExtension": "Install now",
388
+        "kickParticipantDialog": "Are you sure you want to kick this participant?",
388 389
         "muteParticipantTitle": "Mute this member?",
389 390
         "muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
391
+        "muteParticipantDialog": "Are you sure you want to mute this participant? You won't be able to unmute them, but they can unmute themselves at any time.",
390 392
         "muteParticipantButton": "Mute",
391 393
         "liveStreamingDisabledTooltip": "Start live stream disabled.",
392 394
         "liveStreamingDisabledForGuestTooltip": "Guests can't start live streaming.",

+ 41
- 0
react/features/base/dialog/components/native/styles.js View File

@@ -12,6 +12,47 @@ const DIALOG_BORDER_COLOR = 'rgba(255, 255, 255, 0.2)';
12 12
 export const FIELD_UNDERLINE = ColorPalette.transparent;
13 13
 export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
14 14
 
15
+/**
16
+ * Default styles for the items of a {@code BottomSheet}-based menu.
17
+ *
18
+ * These have been implemented as per the Material Design guidelines:
19
+ * {@link https://material.io/guidelines/components/bottom-sheets.html}.
20
+ */
21
+const bottomSheetItemStyles = createStyleSheet({
22
+    /**
23
+     * Container style for a generic item rendered in the menu.
24
+     */
25
+    style: {
26
+        alignItems: 'center',
27
+        flexDirection: 'row',
28
+        height: 48
29
+    },
30
+
31
+    /**
32
+     * Style for the {@code Icon} element in a generic item of the menu.
33
+     */
34
+    iconStyle: {
35
+        color: ColorPalette.white,
36
+        fontSize: 24
37
+    },
38
+
39
+    /**
40
+     * Style for the label in a generic item rendered in the menu.
41
+     */
42
+    labelStyle: {
43
+        color: ColorPalette.white,
44
+        flexShrink: 1,
45
+        fontSize: 16,
46
+        marginLeft: 32,
47
+        opacity: 0.90
48
+    }
49
+});
50
+
51
+export const bottomSheetItemStylesCombined = {
52
+    ...bottomSheetItemStyles,
53
+    underlayColor: ColorPalette.overflowMenuItemUnderlay
54
+};
55
+
15 56
 /**
16 57
  * The React {@code Component} styles of {@code BottomSheet}. These have
17 58
  * been implemented as per the Material Design guidelines:

+ 6
- 0
react/features/base/react/components/AbstractContainer.js View File

@@ -31,6 +31,12 @@ export type Props = {
31 31
      */
32 32
     onClick?: ?Function,
33 33
 
34
+    /**
35
+     * The event handler/listener to be invoked when this
36
+     * {@code AbstractContainer} is long pressed on React Native.
37
+     */
38
+    onLongPress?: ?Function,
39
+
34 40
     /**
35 41
      * The style (as in stylesheet) to be applied to this
36 42
      * {@code AbstractContainer}.

+ 3
- 1
react/features/base/react/components/native/Container.js View File

@@ -27,6 +27,7 @@ export default class Container<P: Props> extends AbstractContainer<P> {
27 27
             accessibilityLabel,
28 28
             accessible,
29 29
             onClick,
30
+            onLongPress,
30 31
             touchFeedback = onClick,
31 32
             underlayColor,
32 33
             visible = true,
@@ -38,7 +39,7 @@ export default class Container<P: Props> extends AbstractContainer<P> {
38 39
             return null;
39 40
         }
40 41
 
41
-        const onClickOrTouchFeedback = onClick || touchFeedback;
42
+        const onClickOrTouchFeedback = onClick || onLongPress || touchFeedback;
42 43
         let element
43 44
             = super._render(
44 45
                 View,
@@ -57,6 +58,7 @@ export default class Container<P: Props> extends AbstractContainer<P> {
57 58
                     {
58 59
                         accessibilityLabel,
59 60
                         accessible,
61
+                        onLongPress,
60 62
                         onPress: onClick,
61 63
                         ...touchFeedback && { underlayColor }
62 64
                     },

+ 31
- 0
react/features/filmstrip/components/native/Thumbnail.js View File

@@ -3,15 +3,19 @@
3 3
 import React, { Component } from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
+import { openDialog } from '../../../base/dialog';
6 7
 import { Audio, MEDIA_TYPE } from '../../../base/media';
7 8
 import {
8 9
     PARTICIPANT_ROLE,
9 10
     ParticipantView,
11
+    isLocalParticipantModerator,
10 12
     pinParticipant
11 13
 } from '../../../base/participants';
12 14
 import { Container } from '../../../base/react';
13 15
 import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
14 16
 
17
+import { RemoteVideoMenu } from '../../../remote-video-menu';
18
+
15 19
 import AudioMutedIndicator from './AudioMutedIndicator';
16 20
 import DominantSpeakerIndicator from './DominantSpeakerIndicator';
17 21
 import ModeratorIndicator from './ModeratorIndicator';
@@ -29,6 +33,11 @@ type Props = {
29 33
      */
30 34
     _audioTrack: Object,
31 35
 
36
+    /**
37
+     * True if the local participant is a moderator.
38
+     */
39
+    _isModerator: boolean,
40
+
32 41
     /**
33 42
      * The Redux representation of the state "features/large-video".
34 43
      */
@@ -84,6 +93,7 @@ class Thumbnail extends Component<Props> {
84 93
 
85 94
         // Bind event handlers so they are only bound once for every instance.
86 95
         this._onClick = this._onClick.bind(this);
96
+        this._onShowRemoteVideoMenu = this._onShowRemoteVideoMenu.bind(this);
87 97
     }
88 98
 
89 99
     /**
@@ -95,6 +105,7 @@ class Thumbnail extends Component<Props> {
95 105
     render() {
96 106
         const {
97 107
             _audioTrack: audioTrack,
108
+            _isModerator,
98 109
             _largeVideo: largeVideo,
99 110
             _videoTrack: videoTrack,
100 111
             disablePin,
@@ -114,10 +125,13 @@ class Thumbnail extends Component<Props> {
114 125
         const participantInLargeVideo
115 126
             = participantId === largeVideo.participantId;
116 127
         const videoMuted = !videoTrack || videoTrack.muted;
128
+        const showRemoteVideoMenu = _isModerator && !participant.local;
117 129
 
118 130
         return (
119 131
             <Container
120 132
                 onClick = { disablePin ? undefined : this._onClick }
133
+                onLongPress = {
134
+                    showRemoteVideoMenu && this._onShowRemoteVideoMenu }
121 135
                 style = { [
122 136
                     styles.thumbnail,
123 137
                     participant.pinned && !disablePin
@@ -167,6 +181,21 @@ class Thumbnail extends Component<Props> {
167 181
         // TODO The following currently ignores interfaceConfig.filmStripOnly.
168 182
         dispatch(pinParticipant(participant.pinned ? null : participant.id));
169 183
     }
184
+
185
+    _onShowRemoteVideoMenu: () => void;
186
+
187
+    /**
188
+     * Handles long press on the thumbnail.
189
+     *
190
+     * @returns {void}
191
+     */
192
+    _onShowRemoteVideoMenu() {
193
+        const { dispatch, participant } = this.props;
194
+
195
+        dispatch(openDialog(RemoteVideoMenu, {
196
+            participant
197
+        }));
198
+    }
170 199
 }
171 200
 
172 201
 /**
@@ -177,6 +206,7 @@ class Thumbnail extends Component<Props> {
177 206
  * @private
178 207
  * @returns {{
179 208
  *      _audioTrack: Track,
209
+ *      _isModerator: boolean,
180 210
  *      _largeVideo: Object,
181 211
  *      _videoTrack: Track
182 212
  *  }}
@@ -195,6 +225,7 @@ function _mapStateToProps(state, ownProps) {
195 225
 
196 226
     return {
197 227
         _audioTrack: audioTrack,
228
+        _isModerator: isLocalParticipantModerator(state),
198 229
         _largeVideo: largeVideo,
199 230
         _videoTrack: videoTrack
200 231
     };

+ 14
- 0
react/features/remote-video-menu/actions.js View File

@@ -0,0 +1,14 @@
1
+// @flow
2
+
3
+import { hideDialog } from '../base/dialog';
4
+
5
+import { RemoteVideoMenu } from './components';
6
+
7
+/**
8
+ * Hides the remote video menu.
9
+ *
10
+ * @returns {Function}
11
+ */
12
+export function hideRemoteVideoMenu() {
13
+    return hideDialog(RemoteVideoMenu);
14
+}

+ 0
- 0
react/features/remote-video-menu/components/MuteRemoteParticipantDialog.native.js View File


+ 3
- 0
react/features/remote-video-menu/components/index.native.js View File

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export * from './native';

+ 3
- 0
react/features/remote-video-menu/components/index.web.js View File

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export * from './web';

+ 46
- 0
react/features/remote-video-menu/components/native/KickButton.js View File

@@ -0,0 +1,46 @@
1
+// @flow
2
+
3
+import { connect } from 'react-redux';
4
+
5
+import { openDialog } from '../../../base/dialog';
6
+import { translate } from '../../../base/i18n';
7
+import { AbstractButton } from '../../../base/toolbox';
8
+import type { AbstractButtonProps } from '../../../base/toolbox';
9
+
10
+import KickRemoteParticipantDialog from './KickRemoteParticipantDialog';
11
+
12
+type Props = AbstractButtonProps & {
13
+
14
+    /**
15
+     * The redux {@code dispatch} function.
16
+     */
17
+    dispatch: Function,
18
+
19
+    /**
20
+     * The participant object that this button is supposed to kick.
21
+     */
22
+    participant: Object
23
+};
24
+
25
+/**
26
+ * A remote video menu button which kicks the remote participant.
27
+ */
28
+class KickButton extends AbstractButton<Props, *> {
29
+    accessibilityLabel = 'toolbar.accessibilityLabel.audioRoute';
30
+    iconName = 'icon-kick';
31
+    label = 'videothumbnail.kick';
32
+
33
+    /**
34
+     * Handles clicking / pressing the button, and kicks the participant.
35
+     *
36
+     * @private
37
+     * @returns {void}
38
+     */
39
+    _handleClick() {
40
+        const { dispatch, participant } = this.props;
41
+
42
+        dispatch(openDialog(KickRemoteParticipantDialog, { participant }));
43
+    }
44
+}
45
+
46
+export default translate(connect()(KickButton));

+ 84
- 0
react/features/remote-video-menu/components/native/KickRemoteParticipantDialog.js View File

@@ -0,0 +1,84 @@
1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { connect } from 'react-redux';
5
+
6
+import {
7
+    createRemoteVideoMenuButtonEvent,
8
+    sendAnalytics
9
+} from '../../../analytics';
10
+import { ConfirmDialog } from '../../../base/dialog';
11
+import { translate } from '../../../base/i18n';
12
+import { kickParticipant } from '../../../base/participants';
13
+
14
+type Props = {
15
+
16
+    /**
17
+     * The Redux dispatch function.
18
+     */
19
+    dispatch: Function,
20
+
21
+    /**
22
+     * The remote participant to be kicked.
23
+     */
24
+    participant: Object,
25
+
26
+    /**
27
+     * Function to translate i18n labels.
28
+     */
29
+    t: Function
30
+};
31
+
32
+/**
33
+ * Dialog to confirm a remote participant kick action.
34
+ */
35
+class KickRemoteParticipantDialog extends Component<Props> {
36
+    /**
37
+     * Initializes a new {@code KickRemoteParticipantDialog} instance.
38
+     *
39
+     * @inheritdoc
40
+     */
41
+    constructor(props: Props) {
42
+        super(props);
43
+
44
+        this._onSubmit = this._onSubmit.bind(this);
45
+    }
46
+
47
+    /**
48
+     * Implements React's {@link Component#render()}.
49
+     *
50
+     * @inheritdoc
51
+     * @returns {ReactElement}
52
+     */
53
+    render() {
54
+        return (
55
+            <ConfirmDialog
56
+                contentKey = 'dialog.kickParticipantDialog'
57
+                onSubmit = { this._onSubmit } />
58
+        );
59
+    }
60
+
61
+    _onSubmit: () => boolean;
62
+
63
+    /**
64
+     * Callback for the confirm button.
65
+     *
66
+     * @private
67
+     * @returns {boolean} - True (to note that the modal should be closed).
68
+     */
69
+    _onSubmit() {
70
+        const { dispatch, participant } = this.props;
71
+
72
+        sendAnalytics(createRemoteVideoMenuButtonEvent(
73
+            'kick.button',
74
+            {
75
+                'participant_id': participant.id
76
+            }));
77
+
78
+        dispatch(kickParticipant(participant.id));
79
+
80
+        return true;
81
+    }
82
+}
83
+
84
+export default translate(connect()(KickRemoteParticipantDialog));

+ 116
- 0
react/features/remote-video-menu/components/native/MuteButton.js View File

@@ -0,0 +1,116 @@
1
+// @flow
2
+
3
+import { connect } from 'react-redux';
4
+
5
+import {
6
+    createRemoteVideoMenuButtonEvent,
7
+    sendAnalytics
8
+} from '../../../analytics';
9
+import { openDialog } from '../../../base/dialog';
10
+import { translate } from '../../../base/i18n';
11
+import { MEDIA_TYPE } from '../../../base/media';
12
+import {
13
+    AbstractButton,
14
+    type AbstractButtonProps
15
+} from '../../../base/toolbox';
16
+import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
17
+
18
+import MuteRemoteParticipantDialog from './MuteRemoteParticipantDialog';
19
+
20
+type Props = AbstractButtonProps & {
21
+
22
+    /**
23
+     * The audio track of the participant.
24
+     */
25
+    _audioTrack: ?Object,
26
+
27
+    /**
28
+     * The redux {@code dispatch} function.
29
+     */
30
+    dispatch: Function,
31
+
32
+    /**
33
+     * The participant object that this button is supposed to mute/unmute.
34
+     */
35
+    participant: Object
36
+};
37
+
38
+/**
39
+ * A remote video menu button which mutes the remote participant.
40
+ */
41
+class MuteButton extends AbstractButton<Props, *> {
42
+    accessibilityLabel = 'toolbar.accessibilityLabel.audioRoute';
43
+    iconName = 'icon-mic-disabled';
44
+    label = 'videothumbnail.domute';
45
+    toggledLabel = 'videothumbnail.muted';
46
+
47
+    /**
48
+     * Handles clicking / pressing the button, and mutes the participant.
49
+     *
50
+     * @private
51
+     * @returns {void}
52
+     */
53
+    _handleClick() {
54
+        const { dispatch, participant } = this.props;
55
+
56
+        sendAnalytics(createRemoteVideoMenuButtonEvent(
57
+            'mute.button',
58
+            {
59
+                'participant_id': participant.id
60
+            }));
61
+
62
+        dispatch(openDialog(MuteRemoteParticipantDialog, { participant }));
63
+    }
64
+
65
+    /**
66
+     * Renders the item disabled if the participant is muted.
67
+     *
68
+     * @inheritdoc
69
+     */
70
+    _isDisabled() {
71
+        return this._isMuted();
72
+    }
73
+
74
+    /**
75
+     * Returns true if the participant is muted, false otherwise.
76
+     *
77
+     * @returns {boolean}
78
+     */
79
+    _isMuted() {
80
+        const { _audioTrack } = this.props;
81
+
82
+        return !_audioTrack || _audioTrack.muted;
83
+    }
84
+
85
+    /**
86
+     * Renders the item toggled if the participant is muted.
87
+     *
88
+     * @inheritdoc
89
+     */
90
+    _isToggled() {
91
+        return this._isMuted();
92
+    }
93
+}
94
+
95
+/**
96
+ * Function that maps parts of Redux state tree into component props.
97
+ *
98
+ * @param {Object} state - Redux state.
99
+ * @param {Object} ownProps - Properties of component.
100
+ * @private
101
+ * @returns {{
102
+ *      _audioTrack: Track
103
+ *  }}
104
+ */
105
+function _mapStateToProps(state, ownProps) {
106
+    const tracks = state['features/base/tracks'];
107
+    const audioTrack
108
+        = getTrackByMediaTypeAndParticipant(
109
+            tracks, MEDIA_TYPE.AUDIO, ownProps.participant.id);
110
+
111
+    return {
112
+        _audioTrack: audioTrack
113
+    };
114
+}
115
+
116
+export default translate(connect(_mapStateToProps)(MuteButton));

+ 80
- 0
react/features/remote-video-menu/components/native/MuteRemoteParticipantDialog.js View File

@@ -0,0 +1,80 @@
1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { connect } from 'react-redux';
5
+
6
+import {
7
+    createRemoteMuteConfirmedEvent,
8
+    sendAnalytics
9
+} from '../../../analytics';
10
+import { ConfirmDialog } from '../../../base/dialog';
11
+import { translate } from '../../../base/i18n';
12
+import { muteRemoteParticipant } from '../../../base/participants';
13
+
14
+type Props = {
15
+
16
+    /**
17
+     * The Redux dispatch function.
18
+     */
19
+    dispatch: Function,
20
+
21
+    /**
22
+     * The remote participant to be muted.
23
+     */
24
+    participant: Object,
25
+
26
+    /**
27
+     * Function to translate i18n labels.
28
+     */
29
+    t: Function
30
+};
31
+
32
+/**
33
+ * Dialog to confirm a remote participant mute action.
34
+ */
35
+class MuteRemoteParticipantDialog extends Component<Props> {
36
+    /**
37
+     * Initializes a new {@code MuteRemoteParticipantDialog} instance.
38
+     *
39
+     * @inheritdoc
40
+     */
41
+    constructor(props: Props) {
42
+        super(props);
43
+
44
+        this._onSubmit = this._onSubmit.bind(this);
45
+    }
46
+
47
+    /**
48
+     * Implements React's {@link Component#render()}.
49
+     *
50
+     * @inheritdoc
51
+     * @returns {ReactElement}
52
+     */
53
+    render() {
54
+        return (
55
+            <ConfirmDialog
56
+                contentKey = 'dialog.muteParticipantDialog'
57
+                onSubmit = { this._onSubmit } />
58
+        );
59
+    }
60
+
61
+    _onSubmit: () => boolean;
62
+
63
+    /**
64
+     * Callback for the confirm button.
65
+     *
66
+     * @private
67
+     * @returns {boolean} - True (to note that the modal should be closed).
68
+     */
69
+    _onSubmit() {
70
+        const { dispatch, participant } = this.props;
71
+
72
+        sendAnalytics(createRemoteMuteConfirmedEvent(participant.id));
73
+
74
+        dispatch(muteRemoteParticipant(participant.id));
75
+
76
+        return true;
77
+    }
78
+}
79
+
80
+export default translate(connect()(MuteRemoteParticipantDialog));

+ 109
- 0
react/features/remote-video-menu/components/native/RemoteVideoMenu.js View File

@@ -0,0 +1,109 @@
1
+// @flow
2
+
3
+import React, { Component } from 'react';
4
+import { Text, View } from 'react-native';
5
+import { connect } from 'react-redux';
6
+
7
+import {
8
+    BottomSheet,
9
+    bottomSheetItemStylesCombined
10
+} from '../../../base/dialog';
11
+import { getParticipantDisplayName } from '../../../base/participants';
12
+
13
+import { hideRemoteVideoMenu } from '../../actions';
14
+
15
+import KickButton from './KickButton';
16
+import MuteButton from './MuteButton';
17
+import styles from './styles';
18
+
19
+type Props = {
20
+
21
+    /**
22
+     * The Redux dispatch function.
23
+     */
24
+    dispatch: Function,
25
+
26
+    /**
27
+     * The participant for which this menu opened for.
28
+     */
29
+    participant: Object,
30
+
31
+    /**
32
+     * Display name of the participant retreived from Redux.
33
+     */
34
+    _participantDisplayName: string
35
+}
36
+
37
+/**
38
+ * Class to implement a popup menu that opens upon long pressing a thumbnail.
39
+ */
40
+class RemoteVideoMenu extends Component<Props> {
41
+    /**
42
+     * Constructor of the component.
43
+     *
44
+     * @inheritdoc
45
+     */
46
+    constructor(props: Props) {
47
+        super(props);
48
+
49
+        this._onCancel = this._onCancel.bind(this);
50
+    }
51
+
52
+    /**
53
+     * Implements {@code Component#render}.
54
+     *
55
+     * @inheritdoc
56
+     */
57
+    render() {
58
+        const buttonProps = {
59
+            afterClick: this._onCancel,
60
+            showLabel: true,
61
+            participant: this.props.participant,
62
+            styles: bottomSheetItemStylesCombined
63
+        };
64
+
65
+        return (
66
+            <BottomSheet onCancel = { this._onCancel }>
67
+                <View style = { styles.participantNameContainer }>
68
+                    <Text style = { styles.participantNameLabel }>
69
+                        { this.props._participantDisplayName }
70
+                    </Text>
71
+                </View>
72
+                <MuteButton { ...buttonProps } />
73
+                <KickButton { ...buttonProps } />
74
+            </BottomSheet>
75
+        );
76
+    }
77
+
78
+    _onCancel: () => void;
79
+
80
+    /**
81
+     * Callback to hide the {@code RemoteVideoMenu}.
82
+     *
83
+     * @private
84
+     * @returns {void}
85
+     */
86
+    _onCancel() {
87
+        this.props.dispatch(hideRemoteVideoMenu());
88
+    }
89
+}
90
+
91
+/**
92
+ * Function that maps parts of Redux state tree into component props.
93
+ *
94
+ * @param {Object} state - Redux state.
95
+ * @param {Object} ownProps - Properties of component.
96
+ * @private
97
+ * @returns {{
98
+ *      _participantDisplayName: string
99
+ *  }}
100
+ */
101
+function _mapStateToProps(state, ownProps) {
102
+    const { id } = ownProps.participant;
103
+
104
+    return {
105
+        _participantDisplayName: getParticipantDisplayName(state, id)
106
+    };
107
+}
108
+
109
+export default connect(_mapStateToProps)(RemoteVideoMenu);

+ 3
- 0
react/features/remote-video-menu/components/native/index.js View File

@@ -0,0 +1,3 @@
1
+// @flow
2
+
3
+export { default as RemoteVideoMenu } from './RemoteVideoMenu';

+ 20
- 0
react/features/remote-video-menu/components/native/styles.js View File

@@ -0,0 +1,20 @@
1
+// @flow
2
+
3
+import { ColorPalette, createStyleSheet } from '../../../base/styles';
4
+
5
+export default createStyleSheet({
6
+    participantNameContainer: {
7
+        alignItems: 'center',
8
+        borderBottomColor: ColorPalette.darkGrey,
9
+        borderBottomWidth: 1,
10
+        flexDirection: 'row',
11
+        height: 48
12
+    },
13
+
14
+    participantNameLabel: {
15
+        color: ColorPalette.lightGrey,
16
+        flexShrink: 1,
17
+        fontSize: 16,
18
+        opacity: 0.90
19
+    }
20
+});

react/features/remote-video-menu/components/KickButton.js → react/features/remote-video-menu/components/web/KickButton.js View File

@@ -6,9 +6,9 @@ import { connect } from 'react-redux';
6 6
 import {
7 7
     createRemoteVideoMenuButtonEvent,
8 8
     sendAnalytics
9
-} from '../../analytics';
10
-import { translate } from '../../base/i18n';
11
-import { kickParticipant } from '../../base/participants';
9
+} from '../../../analytics';
10
+import { translate } from '../../../base/i18n';
11
+import { kickParticipant } from '../../../base/participants';
12 12
 
13 13
 import RemoteVideoMenuButton from './RemoteVideoMenuButton';
14 14
 

react/features/remote-video-menu/components/MuteButton.js → react/features/remote-video-menu/components/web/MuteButton.js View File

@@ -6,9 +6,9 @@ import { connect } from 'react-redux';
6 6
 import {
7 7
     createRemoteVideoMenuButtonEvent,
8 8
     sendAnalytics
9
-} from '../../analytics';
10
-import { translate } from '../../base/i18n';
11
-import { openDialog } from '../../base/dialog';
9
+} from '../../../analytics';
10
+import { translate } from '../../../base/i18n';
11
+import { openDialog } from '../../../base/dialog';
12 12
 
13 13
 import RemoteVideoMenuButton from './RemoteVideoMenuButton';
14 14
 import MuteRemoteParticipantDialog from './MuteRemoteParticipantDialog';

react/features/remote-video-menu/components/MuteRemoteParticipantDialog.web.js → react/features/remote-video-menu/components/web/MuteRemoteParticipantDialog.js View File

@@ -3,14 +3,14 @@
3 3
 import React, { Component } from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import { Dialog } from '../../base/dialog';
7
-import { translate } from '../../base/i18n';
6
+import { Dialog } from '../../../base/dialog';
7
+import { translate } from '../../../base/i18n';
8 8
 
9 9
 import {
10 10
     createRemoteMuteConfirmedEvent,
11 11
     sendAnalytics
12
-} from '../../analytics';
13
-import { muteRemoteParticipant } from '../../base/participants';
12
+} from '../../../analytics';
13
+import { muteRemoteParticipant } from '../../../base/participants';
14 14
 
15 15
 /**
16 16
  * The type of the React {@code Component} props of

react/features/remote-video-menu/components/RemoteControlButton.js → react/features/remote-video-menu/components/web/RemoteControlButton.js View File

@@ -5,8 +5,8 @@ import React, { Component } from 'react';
5 5
 import {
6 6
     createRemoteVideoMenuButtonEvent,
7 7
     sendAnalytics
8
-} from '../../analytics';
9
-import { translate } from '../../base/i18n';
8
+} from '../../../analytics';
9
+import { translate } from '../../../base/i18n';
10 10
 
11 11
 import RemoteVideoMenuButton from './RemoteVideoMenuButton';
12 12
 

react/features/remote-video-menu/components/RemoteVideoMenu.js → react/features/remote-video-menu/components/web/RemoteVideoMenu.js View File


react/features/remote-video-menu/components/RemoteVideoMenuButton.js → react/features/remote-video-menu/components/web/RemoteVideoMenuButton.js View File


react/features/remote-video-menu/components/RemoteVideoMenuTriggerButton.js → react/features/remote-video-menu/components/web/RemoteVideoMenuTriggerButton.js View File

@@ -2,7 +2,7 @@
2 2
 
3 3
 import React, { Component } from 'react';
4 4
 
5
-import { Popover } from '../../base/popover';
5
+import { Popover } from '../../../base/popover';
6 6
 
7 7
 import {
8 8
     MuteButton,

react/features/remote-video-menu/components/VolumeSlider.js → react/features/remote-video-menu/components/web/VolumeSlider.js View File


react/features/remote-video-menu/components/index.js → react/features/remote-video-menu/components/web/index.js View File

@@ -1,3 +1,5 @@
1
+// @flow
2
+
1 3
 export { default as KickButton } from './KickButton';
2 4
 export { default as MuteButton } from './MuteButton';
3 5
 export {

+ 6
- 3
react/features/toolbox/components/native/OverflowMenu.js View File

@@ -4,7 +4,11 @@ import React, { Component } from 'react';
4 4
 import { Platform } from 'react-native';
5 5
 import { connect } from 'react-redux';
6 6
 
7
-import { BottomSheet, hideDialog } from '../../../base/dialog';
7
+import {
8
+    BottomSheet,
9
+    bottomSheetItemStylesCombined,
10
+    hideDialog
11
+} from '../../../base/dialog';
8 12
 import { AudioRouteButton } from '../../../mobile/audio-mode';
9 13
 import { PictureInPictureButton } from '../../../mobile/picture-in-picture';
10 14
 import { LiveStreamButton, RecordButton } from '../../../recording';
@@ -13,7 +17,6 @@ import { ClosedCaptionButton } from '../../../subtitles';
13 17
 import { TileViewButton } from '../../../video-layout';
14 18
 
15 19
 import AudioOnlyButton from './AudioOnlyButton';
16
-import { overflowMenuItemStyles } from './styles';
17 20
 import ToggleCameraButton from './ToggleCameraButton';
18 21
 
19 22
 /**
@@ -63,7 +66,7 @@ class OverflowMenu extends Component<Props> {
63 66
         const buttonProps = {
64 67
             afterClick: this._onCancel,
65 68
             showLabel: true,
66
-            styles: overflowMenuItemStyles
69
+            styles: bottomSheetItemStylesCombined
67 70
         };
68 71
 
69 72
         return (

+ 0
- 48
react/features/toolbox/components/native/styles.js View File

@@ -130,51 +130,3 @@ export const toolbarToggledButtonStyles = {
130 130
     iconStyle: styles.whiteToolbarButtonIcon,
131 131
     style: styles.whiteToolbarButton
132 132
 };
133
-
134
-// Overflow menu:
135
-
136
-/**
137
- * Styles for the {@code OverflowMenu} items.
138
- *
139
- * These have been implemented as per the Material Design guidelines:
140
- * {@link https://material.io/guidelines/components/bottom-sheets.html}.
141
- */
142
-const overflowMenuStyles = createStyleSheet({
143
-    /**
144
-     * Container style for a {@code ToolboxItem} rendered in the
145
-     * {@code OverflowMenu}.
146
-     */
147
-    container: {
148
-        alignItems: 'center',
149
-        flexDirection: 'row',
150
-        height: 48
151
-    },
152
-
153
-    /**
154
-     * Style for the {@code Icon} element in a {@code ToolboxItem} rendered in
155
-     * the {@code OverflowMenu}.
156
-     */
157
-    icon: {
158
-        color: ColorPalette.white,
159
-        fontSize: 24
160
-    },
161
-
162
-    /**
163
-     * Style for the label in a {@code ToolboxItem} rendered in the
164
-     * {@code OverflowMenu}.
165
-     */
166
-    label: {
167
-        color: ColorPalette.white,
168
-        flexShrink: 1,
169
-        fontSize: 16,
170
-        marginLeft: 32,
171
-        opacity: 0.90
172
-    }
173
-});
174
-
175
-export const overflowMenuItemStyles = {
176
-    iconStyle: overflowMenuStyles.icon,
177
-    labelStyle: overflowMenuStyles.label,
178
-    style: overflowMenuStyles.container,
179
-    underlayColor: ColorPalette.overflowMenuItemUnderlay
180
-};

Loading…
Cancel
Save