Selaa lähdekoodia

Remote video menu post-PR improvements

j8
Bettenbuk Zoltan 6 vuotta sitten
vanhempi
commit
5c0ae10ccb
23 muutettua tiedostoa jossa 534 lisäystä ja 547 poistoa
  1. 4
    0
      lang/main.json
  2. 15
    5
      react/features/base/dialog/components/native/styles.js
  3. 0
    6
      react/features/base/react/components/AbstractContainer.js
  4. 28
    14
      react/features/base/react/components/native/Container.js
  5. 16
    0
      react/features/base/tracks/functions.js
  6. 55
    46
      react/features/filmstrip/components/native/Thumbnail.js
  7. 2
    1
      react/features/mobile/audio-mode/components/styles.js
  8. 46
    0
      react/features/remote-video-menu/components/AbstractKickButton.js
  9. 66
    0
      react/features/remote-video-menu/components/AbstractKickRemoteParticipantDialog.js
  10. 105
    0
      react/features/remote-video-menu/components/AbstractMuteButton.js
  11. 70
    0
      react/features/remote-video-menu/components/AbstractMuteRemoteParticipantDialog.js
  12. 6
    37
      react/features/remote-video-menu/components/native/KickButton.js
  13. 4
    55
      react/features/remote-video-menu/components/native/KickRemoteParticipantDialog.js
  14. 6
    107
      react/features/remote-video-menu/components/native/MuteButton.js
  15. 4
    51
      react/features/remote-video-menu/components/native/MuteRemoteParticipantDialog.js
  16. 1
    1
      react/features/remote-video-menu/components/native/RemoteVideoMenu.js
  17. 6
    0
      react/features/remote-video-menu/components/native/index.js
  18. 8
    3
      react/features/remote-video-menu/components/native/styles.js
  19. 18
    65
      react/features/remote-video-menu/components/web/KickButton.js
  20. 39
    0
      react/features/remote-video-menu/components/web/KickRemoteParticipantDialog.js
  21. 21
    74
      react/features/remote-video-menu/components/web/MuteButton.js
  22. 8
    82
      react/features/remote-video-menu/components/web/MuteRemoteParticipantDialog.js
  23. 6
    0
      react/features/remote-video-menu/components/web/index.js

+ 4
- 0
lang/main.json Näytä tiedosto

@@ -93,6 +93,7 @@
93 93
             "fullScreen": "Toggle full screen",
94 94
             "hangup": "Leave the call",
95 95
             "invite": "Invite people",
96
+            "kick": "Kick participant",
96 97
             "localRecording": "Toggle local recording controls",
97 98
             "lockRoom": "Toggle room lock",
98 99
             "moreActions": "Toggle more actions menu",
@@ -102,6 +103,7 @@
102 103
             "profile": "Edit your profile",
103 104
             "raiseHand": "Toggle raise hand",
104 105
             "recording": "Toggle recording",
106
+            "remoteMute": "Mute participant",
105 107
             "Settings": "Toggle settings",
106 108
             "sharedvideo": "Toggle Youtube video sharing",
107 109
             "shareRoom": "Invite someone",
@@ -385,7 +387,9 @@
385 387
         "externalInstallationMsg": "You need to install our desktop sharing extension.",
386 388
         "inlineInstallationMsg": "You need to install our desktop sharing extension.",
387 389
         "inlineInstallExtension": "Install now",
390
+        "kickParticipantButton": "Kick",
388 391
         "kickParticipantDialog": "Are you sure you want to kick this participant?",
392
+        "kickParticipantTitle": "Kick this member?",
389 393
         "muteParticipantTitle": "Mute this member?",
390 394
         "muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
391 395
         "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.",

+ 15
- 5
react/features/base/dialog/components/native/styles.js Näytä tiedosto

@@ -10,6 +10,16 @@ const BORDER_RADIUS = 5;
10 10
 const DIALOG_BORDER_COLOR = 'rgba(255, 255, 255, 0.2)';
11 11
 
12 12
 export const FIELD_UNDERLINE = ColorPalette.transparent;
13
+
14
+/**
15
+ * NOTE: These Material guidelines based values are currently only used in
16
+ * dialogs (and related) but later on it would be nice to export it into a base
17
+ * Material feature.
18
+ */
19
+export const MD_FONT_SIZE = 16;
20
+export const MD_ITEM_HEIGHT = 48;
21
+export const MD_ITEM_MARGIN_PADDING = 16;
22
+
13 23
 export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
14 24
 
15 25
 /**
@@ -25,7 +35,7 @@ const bottomSheetItemStyles = createStyleSheet({
25 35
     style: {
26 36
         alignItems: 'center',
27 37
         flexDirection: 'row',
28
-        height: 48
38
+        height: MD_ITEM_HEIGHT
29 39
     },
30 40
 
31 41
     /**
@@ -42,7 +52,7 @@ const bottomSheetItemStyles = createStyleSheet({
42 52
     labelStyle: {
43 53
         color: ColorPalette.white,
44 54
         flexShrink: 1,
45
-        fontSize: 16,
55
+        fontSize: MD_FONT_SIZE,
46 56
         marginLeft: 32,
47 57
         opacity: 0.90
48 58
     }
@@ -92,7 +102,7 @@ export const bottomSheetStyles = createStyleSheet({
92 102
     sheet: {
93 103
         backgroundColor: 'rgb(0, 3, 6)',
94 104
         flex: 1,
95
-        paddingHorizontal: 16,
105
+        paddingHorizontal: MD_ITEM_MARGIN_PADDING,
96 106
         paddingVertical: 8
97 107
     }
98 108
 });
@@ -134,7 +144,7 @@ export const brandedDialog = createStyleSheet({
134 144
 
135 145
     closeStyle: {
136 146
         color: ColorPalette.white,
137
-        fontSize: 16
147
+        fontSize: MD_FONT_SIZE
138 148
     },
139 149
 
140 150
     closeWrapper: {
@@ -173,7 +183,7 @@ export const brandedDialog = createStyleSheet({
173 183
 
174 184
     text: {
175 185
         color: ColorPalette.white,
176
-        fontSize: 16,
186
+        fontSize: MD_FONT_SIZE,
177 187
         textAlign: 'center'
178 188
     }
179 189
 });

+ 0
- 6
react/features/base/react/components/AbstractContainer.js Näytä tiedosto

@@ -31,12 +31,6 @@ 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
-
40 34
     /**
41 35
      * The style (as in stylesheet) to be applied to this
42 36
      * {@code AbstractContainer}.

+ 28
- 14
react/features/base/react/components/native/Container.js Näytä tiedosto

@@ -8,7 +8,16 @@ import {
8 8
 } from 'react-native';
9 9
 
10 10
 import AbstractContainer from '../AbstractContainer';
11
-import type { Props } from '../AbstractContainer';
11
+import type { Props as AbstractProps } from '../AbstractContainer';
12
+
13
+type Props = AbstractProps & {
14
+
15
+    /**
16
+     * The event handler/listener to be invoked when this
17
+     * {@code AbstractContainer} is long pressed on React Native.
18
+     */
19
+    onLongPress?: ?Function,
20
+};
12 21
 
13 22
 /**
14 23
  * Represents a container of React Native/mobile {@link Component} children.
@@ -28,7 +37,7 @@ export default class Container<P: Props> extends AbstractContainer<P> {
28 37
             accessible,
29 38
             onClick,
30 39
             onLongPress,
31
-            touchFeedback = onClick,
40
+            touchFeedback = Boolean(onClick || onLongPress),
32 41
             underlayColor,
33 42
             visible = true,
34 43
             ...props
@@ -50,19 +59,24 @@ export default class Container<P: Props> extends AbstractContainer<P> {
50 59
 
51 60
         // onClick & touchFeedback
52 61
         if (element && onClickOrTouchFeedback) {
62
+            const touchableProps = {
63
+                accessibilityLabel,
64
+                accessible,
65
+                onLongPress,
66
+                onPress: onClick
67
+            };
68
+
53 69
             element
54
-                = React.createElement(
55
-                    touchFeedback
56
-                        ? TouchableHighlight
57
-                        : TouchableWithoutFeedback,
58
-                    {
59
-                        accessibilityLabel,
60
-                        accessible,
61
-                        onLongPress,
62
-                        onPress: onClick,
63
-                        ...touchFeedback && { underlayColor }
64
-                    },
65
-                    element);
70
+                = touchFeedback
71
+                    ? React.createElement(
72
+                        TouchableHighlight,
73
+                        {
74
+                            ...touchableProps,
75
+                            underlayColor
76
+                        },
77
+                        element)
78
+                    : React.createElement(
79
+                        TouchableWithoutFeedback, touchableProps, element);
66 80
         }
67 81
 
68 82
         return element;

+ 16
- 0
react/features/base/tracks/functions.js Näytä tiedosto

@@ -209,6 +209,22 @@ export function isLocalTrackMuted(tracks, mediaType) {
209 209
     return !track || track.muted;
210 210
 }
211 211
 
212
+/**
213
+ * Returns true if the remote track of the given media type and the given
214
+ * participant is muted, false otherwise.
215
+ *
216
+ * @param {Track[]} tracks - List of all tracks.
217
+ * @param {MEDIA_TYPE} mediaType - The media type of tracks to be checked.
218
+ * @param {*} participantId - Participant ID.
219
+ * @returns {boolean}
220
+ */
221
+export function isRemoteTrackMuted(tracks, mediaType, participantId) {
222
+    const track = getTrackByMediaTypeAndParticipant(
223
+        tracks, mediaType, participantId);
224
+
225
+    return !track || track.muted;
226
+}
227
+
212 228
 /**
213 229
  * Mutes or unmutes a specific {@code JitsiLocalTrack}. If the muted state of
214 230
  * the specified {@code track} is already in accord with the specified

+ 55
- 46
react/features/filmstrip/components/native/Thumbnail.js Näytä tiedosto

@@ -43,6 +43,16 @@ type Props = {
43 43
      */
44 44
     _largeVideo: Object,
45 45
 
46
+    /**
47
+     * Handles click/tap event on the thumbnail.
48
+     */
49
+    _onClick: ?Function,
50
+
51
+    /**
52
+     * Handles long press on the thumbnail.
53
+     */
54
+    _onShowRemoteVideoMenu: ?Function,
55
+
46 56
     /**
47 57
      * The Redux representation of the participant's video track.
48 58
      */
@@ -83,19 +93,6 @@ type Props = {
83 93
  * @extends Component
84 94
  */
85 95
 class Thumbnail extends Component<Props> {
86
-    /**
87
-     * Initializes new Video Thumbnail component.
88
-     *
89
-     * @param {Object} props - Component props.
90
-     */
91
-    constructor(props: Props) {
92
-        super(props);
93
-
94
-        // Bind event handlers so they are only bound once for every instance.
95
-        this._onClick = this._onClick.bind(this);
96
-        this._onShowRemoteVideoMenu = this._onShowRemoteVideoMenu.bind(this);
97
-    }
98
-
99 96
     /**
100 97
      * Implements React's {@link Component#render()}.
101 98
      *
@@ -107,6 +104,8 @@ class Thumbnail extends Component<Props> {
107 104
             _audioTrack: audioTrack,
108 105
             _isModerator,
109 106
             _largeVideo: largeVideo,
107
+            _onClick,
108
+            _onShowRemoteVideoMenu,
110 109
             _videoTrack: videoTrack,
111 110
             disablePin,
112 111
             disableTint,
@@ -129,10 +128,10 @@ class Thumbnail extends Component<Props> {
129 128
 
130 129
         return (
131 130
             <Container
132
-                onClick = { disablePin ? undefined : this._onClick }
131
+                onClick = { disablePin ? undefined : _onClick }
133 132
                 onLongPress = {
134 133
                     showRemoteVideoMenu
135
-                        ? this._onShowRemoteVideoMenu : undefined }
134
+                        ? _onShowRemoteVideoMenu : undefined }
136 135
                 style = { [
137 136
                     styles.thumbnail,
138 137
                     participant.pinned && !disablePin
@@ -169,43 +168,53 @@ class Thumbnail extends Component<Props> {
169 168
             </Container>
170 169
         );
171 170
     }
171
+}
172 172
 
173
-    _onClick: () => void;
174
-
175
-    /**
176
-     * Handles click/tap event on the thumbnail.
177
-     *
178
-     * @returns {void}
179
-     */
180
-    _onClick() {
181
-        const { dispatch, participant } = this.props;
182
-
183
-        // TODO The following currently ignores interfaceConfig.filmStripOnly.
184
-        dispatch(pinParticipant(participant.pinned ? null : participant.id));
185
-    }
186
-
187
-    _onShowRemoteVideoMenu: () => void;
188
-
189
-    /**
190
-     * Handles long press on the thumbnail.
191
-     *
192
-     * @returns {void}
193
-     */
194
-    _onShowRemoteVideoMenu() {
195
-        const { dispatch, participant } = this.props;
196
-
197
-        dispatch(openDialog(RemoteVideoMenu, {
198
-            participant
199
-        }));
200
-    }
173
+/**
174
+ * Maps part of redux actions to component's props.
175
+ *
176
+ * @param {Function} dispatch - Redux's {@code dispatch} function.
177
+ * @param {Props} ownProps - The own props of the component.
178
+ * @returns {{
179
+ *     _onClick: Function,
180
+ *     _onShowRemoteVideoMenu: Function
181
+ * }}
182
+ */
183
+function _mapDispatchToProps(dispatch: Function, ownProps): Object {
184
+    return {
185
+        /**
186
+         * Handles click/tap event on the thumbnail.
187
+         *
188
+         * @protected
189
+         * @returns {void}
190
+         */
191
+        _onClick() {
192
+            const { participant } = ownProps;
193
+
194
+            dispatch(
195
+                pinParticipant(participant.pinned ? null : participant.id));
196
+        },
197
+
198
+        /**
199
+         * Handles long press on the thumbnail.
200
+         *
201
+         * @returns {void}
202
+         */
203
+        _onShowRemoteVideoMenu() {
204
+            const { participant } = ownProps;
205
+
206
+            dispatch(openDialog(RemoteVideoMenu, {
207
+                participant
208
+            }));
209
+        }
210
+    };
201 211
 }
202 212
 
203 213
 /**
204 214
  * Function that maps parts of Redux state tree into component props.
205 215
  *
206 216
  * @param {Object} state - Redux state.
207
- * @param {Object} ownProps - Properties of component.
208
- * @private
217
+ * @param {Props} ownProps - Properties of component.
209 218
  * @returns {{
210 219
  *      _audioTrack: Track,
211 220
  *      _isModerator: boolean,
@@ -233,4 +242,4 @@ function _mapStateToProps(state, ownProps) {
233 242
     };
234 243
 }
235 244
 
236
-export default connect(_mapStateToProps)(Thumbnail);
245
+export default connect(_mapStateToProps, _mapDispatchToProps)(Thumbnail);

+ 2
- 1
react/features/mobile/audio-mode/components/styles.js Näytä tiedosto

@@ -1,5 +1,6 @@
1 1
 // @flow
2 2
 
3
+import { MD_ITEM_HEIGHT } from '../../../base/dialog';
3 4
 import { ColorPalette, createStyleSheet } from '../../../base/styles';
4 5
 
5 6
 /**
@@ -16,7 +17,7 @@ export default createStyleSheet({
16 17
     deviceRow: {
17 18
         alignItems: 'center',
18 19
         flexDirection: 'row',
19
-        height: 48
20
+        height: MD_ITEM_HEIGHT
20 21
     },
21 22
 
22 23
     /**

+ 46
- 0
react/features/remote-video-menu/components/AbstractKickButton.js Näytä tiedosto

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

+ 66
- 0
react/features/remote-video-menu/components/AbstractKickRemoteParticipantDialog.js Näytä tiedosto

@@ -0,0 +1,66 @@
1
+// @flow
2
+
3
+import { Component } from 'react';
4
+
5
+import {
6
+    createRemoteVideoMenuButtonEvent,
7
+    sendAnalytics
8
+} from '../../analytics';
9
+import { kickParticipant } from '../../base/participants';
10
+
11
+type Props = {
12
+
13
+    /**
14
+     * The Redux dispatch function.
15
+     */
16
+    dispatch: Function,
17
+
18
+    /**
19
+     * The ID of the remote participant to be kicked.
20
+     */
21
+    participantID: string,
22
+
23
+    /**
24
+     * Function to translate i18n labels.
25
+     */
26
+    t: Function
27
+};
28
+
29
+/**
30
+ * Abstract dialog to confirm a remote participant kick action.
31
+ */
32
+export default class AbstractKickRemoteParticipantDialog
33
+    extends Component<Props> {
34
+    /**
35
+     * Initializes a new {@code AbstractKickRemoteParticipantDialog} instance.
36
+     *
37
+     * @inheritdoc
38
+     */
39
+    constructor(props: Props) {
40
+        super(props);
41
+
42
+        this._onSubmit = this._onSubmit.bind(this);
43
+    }
44
+
45
+    _onSubmit: () => boolean;
46
+
47
+    /**
48
+     * Callback for the confirm button.
49
+     *
50
+     * @private
51
+     * @returns {boolean} - True (to note that the modal should be closed).
52
+     */
53
+    _onSubmit() {
54
+        const { dispatch, participantID } = this.props;
55
+
56
+        sendAnalytics(createRemoteVideoMenuButtonEvent(
57
+            'kick.button',
58
+            {
59
+                'participant_id': participantID
60
+            }));
61
+
62
+        dispatch(kickParticipant(participantID));
63
+
64
+        return true;
65
+    }
66
+}

+ 105
- 0
react/features/remote-video-menu/components/AbstractMuteButton.js Näytä tiedosto

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

+ 70
- 0
react/features/remote-video-menu/components/AbstractMuteRemoteParticipantDialog.js Näytä tiedosto

@@ -0,0 +1,70 @@
1
+// @flow
2
+
3
+import { Component } from 'react';
4
+
5
+import {
6
+    createRemoteMuteConfirmedEvent,
7
+    sendAnalytics
8
+} from '../../analytics';
9
+import { muteRemoteParticipant } from '../../base/participants';
10
+
11
+/**
12
+ * The type of the React {@code Component} props of
13
+ * {@link AbstractMuteRemoteParticipantDialog}.
14
+ */
15
+type Props = {
16
+
17
+    /**
18
+     * The Redux dispatch function.
19
+     */
20
+    dispatch: Function,
21
+
22
+    /**
23
+     * The ID of the remote participant to be muted.
24
+     */
25
+    participantID: string,
26
+
27
+    /**
28
+     * Function to translate i18n labels.
29
+     */
30
+    t: Function
31
+};
32
+
33
+/**
34
+ * Abstract dialog to confirm a remote participant mute action.
35
+ *
36
+ * @extends Component
37
+ */
38
+export default class AbstractMuteRemoteParticipantDialog
39
+    extends Component<Props> {
40
+    /**
41
+     * Initializes a new {@code AbstractMuteRemoteParticipantDialog} instance.
42
+     *
43
+     * @param {Object} props - The read-only properties with which the new
44
+     * instance is to be initialized.
45
+     */
46
+    constructor(props: Props) {
47
+        super(props);
48
+
49
+        // Bind event handlers so they are only bound once per instance.
50
+        this._onSubmit = this._onSubmit.bind(this);
51
+    }
52
+
53
+    _onSubmit: () => boolean;
54
+
55
+    /**
56
+     * Handles the submit button action.
57
+     *
58
+     * @private
59
+     * @returns {boolean} - True (to note that the modal should be closed).
60
+     */
61
+    _onSubmit() {
62
+        const { dispatch, participantID } = this.props;
63
+
64
+        sendAnalytics(createRemoteMuteConfirmedEvent(participantID));
65
+
66
+        dispatch(muteRemoteParticipant(participantID));
67
+
68
+        return true;
69
+    }
70
+}

+ 6
- 37
react/features/remote-video-menu/components/native/KickButton.js Näytä tiedosto

@@ -2,45 +2,14 @@
2 2
 
3 3
 import { connect } from 'react-redux';
4 4
 
5
-import { openDialog } from '../../../base/dialog';
6 5
 import { translate } from '../../../base/i18n';
7
-import { AbstractButton } from '../../../base/toolbox';
8
-import type { AbstractButtonProps } from '../../../base/toolbox';
9 6
 
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
-};
7
+import AbstractKickButton from '../AbstractKickButton';
24 8
 
25 9
 /**
26
- * A remote video menu button which kicks the remote participant.
10
+ * We don't need any further implementation for this on mobile, but we keep it
11
+ * here for clarity and consistency with web. Once web uses the
12
+ * {@code AbstractButton} base class, we can remove all these and just use
13
+ * the {@code AbstractKickButton} as {@KickButton}.
27 14
  */
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));
15
+export default translate(connect()(AbstractKickButton));

+ 4
- 55
react/features/remote-video-menu/components/native/KickRemoteParticipantDialog.js Näytä tiedosto

@@ -1,49 +1,18 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import {
7
-    createRemoteVideoMenuButtonEvent,
8
-    sendAnalytics
9
-} from '../../../analytics';
10 6
 import { ConfirmDialog } from '../../../base/dialog';
11 7
 import { translate } from '../../../base/i18n';
12
-import { kickParticipant } from '../../../base/participants';
13 8
 
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
-};
9
+import AbstractKickRemoteParticipantDialog
10
+    from '../AbstractKickRemoteParticipantDialog';
31 11
 
32 12
 /**
33 13
  * Dialog to confirm a remote participant kick action.
34 14
  */
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
-
15
+class KickRemoteParticipantDialog extends AbstractKickRemoteParticipantDialog {
47 16
     /**
48 17
      * Implements React's {@link Component#render()}.
49 18
      *
@@ -59,26 +28,6 @@ class KickRemoteParticipantDialog extends Component<Props> {
59 28
     }
60 29
 
61 30
     _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 31
 }
83 32
 
84 33
 export default translate(connect()(KickRemoteParticipantDialog));

+ 6
- 107
react/features/remote-video-menu/components/native/MuteButton.js Näytä tiedosto

@@ -2,115 +2,14 @@
2 2
 
3 3
 import { connect } from 'react-redux';
4 4
 
5
-import {
6
-    createRemoteVideoMenuButtonEvent,
7
-    sendAnalytics
8
-} from '../../../analytics';
9
-import { openDialog } from '../../../base/dialog';
10 5
 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 6
 
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
-}
7
+import AbstractMuteButton, { _mapStateToProps } from '../AbstractMuteButton';
94 8
 
95 9
 /**
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
- *  }}
10
+ * We don't need any further implementation for this on mobile, but we keep it
11
+ * here for clarity and consistency with web. Once web uses the
12
+ * {@code AbstractButton} base class, we can remove all these and just use
13
+ * the {@code AbstractMuteButton} as {@MuteButton}.
104 14
  */
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));
15
+export default translate(connect(_mapStateToProps)(AbstractMuteButton));

+ 4
- 51
react/features/remote-video-menu/components/native/MuteRemoteParticipantDialog.js Näytä tiedosto

@@ -1,49 +1,18 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import {
7
-    createRemoteMuteConfirmedEvent,
8
-    sendAnalytics
9
-} from '../../../analytics';
10 6
 import { ConfirmDialog } from '../../../base/dialog';
11 7
 import { translate } from '../../../base/i18n';
12
-import { muteRemoteParticipant } from '../../../base/participants';
13 8
 
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
-};
9
+import AbstractMuteRemoteParticipantDialog
10
+    from '../AbstractMuteRemoteParticipantDialog';
31 11
 
32 12
 /**
33 13
  * Dialog to confirm a remote participant mute action.
34 14
  */
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
-
15
+class MuteRemoteParticipantDialog extends AbstractMuteRemoteParticipantDialog {
47 16
     /**
48 17
      * Implements React's {@link Component#render()}.
49 18
      *
@@ -59,22 +28,6 @@ class MuteRemoteParticipantDialog extends Component<Props> {
59 28
     }
60 29
 
61 30
     _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 31
 }
79 32
 
80 33
 export default translate(connect()(MuteRemoteParticipantDialog));

+ 1
- 1
react/features/remote-video-menu/components/native/RemoteVideoMenu.js Näytä tiedosto

@@ -72,7 +72,7 @@ class RemoteVideoMenu extends Component<Props> {
72 72
         const buttonProps = {
73 73
             afterClick: this._onCancel,
74 74
             showLabel: true,
75
-            participant: this.props.participant,
75
+            participantID: this.props.participant.id,
76 76
             styles: bottomSheetItemStylesCombined
77 77
         };
78 78
 

+ 6
- 0
react/features/remote-video-menu/components/native/index.js Näytä tiedosto

@@ -1,3 +1,9 @@
1 1
 // @flow
2 2
 
3
+export {
4
+    default as KickRemoteParticipantDialog
5
+} from './KickRemoteParticipantDialog';
6
+export {
7
+    default as MuteRemoteParticipantDialog
8
+} from './MuteRemoteParticipantDialog';
3 9
 export { default as RemoteVideoMenu } from './RemoteVideoMenu';

+ 8
- 3
react/features/remote-video-menu/components/native/styles.js Näytä tiedosto

@@ -1,5 +1,10 @@
1 1
 // @flow
2 2
 
3
+import {
4
+    MD_FONT_SIZE,
5
+    MD_ITEM_HEIGHT,
6
+    MD_ITEM_MARGIN_PADDING
7
+} from '../../../base/dialog';
3 8
 import { ColorPalette, createStyleSheet } from '../../../base/styles';
4 9
 
5 10
 export default createStyleSheet({
@@ -8,14 +13,14 @@ export default createStyleSheet({
8 13
         borderBottomColor: ColorPalette.darkGrey,
9 14
         borderBottomWidth: 1,
10 15
         flexDirection: 'row',
11
-        height: 48
16
+        height: MD_ITEM_HEIGHT
12 17
     },
13 18
 
14 19
     participantNameLabel: {
15 20
         color: ColorPalette.lightGrey,
16 21
         flexShrink: 1,
17
-        fontSize: 16,
18
-        marginLeft: 16,
22
+        fontSize: MD_FONT_SIZE,
23
+        marginLeft: MD_ITEM_MARGIN_PADDING,
19 24
         opacity: 0.90
20 25
     }
21 26
 });

+ 18
- 65
react/features/remote-video-menu/components/web/KickButton.js Näytä tiedosto

@@ -1,62 +1,36 @@
1 1
 /* @flow */
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import {
7
-    createRemoteVideoMenuButtonEvent,
8
-    sendAnalytics
9
-} from '../../../analytics';
10 6
 import { translate } from '../../../base/i18n';
11
-import { kickParticipant } from '../../../base/participants';
12 7
 
13
-import RemoteVideoMenuButton from './RemoteVideoMenuButton';
14
-
15
-/**
16
- * The type of the React {@code Component} state of {@link KickButton}.
17
- */
18
-type Props = {
19
-
20
-    /**
21
-     * Invoked to signal the participant with the passed in participantID
22
-     * should be removed from the conference.
23
-     */
24
-    dispatch: Dispatch<*>,
25
-
26
-    /**
27
-     * Callback to invoke when {@code KickButton} is clicked.
28
-     */
29
-    onClick: Function,
30
-
31
-    /**
32
-     * The ID of the participant linked to the onClick callback.
33
-     */
34
-    participantID: string,
8
+import AbstractKickButton, {
9
+    type Props
10
+} from '../AbstractKickButton';
35 11
 
36
-    /**
37
-     * Invoked to obtain translated strings.
38
-     */
39
-    t: Function,
40
-};
12
+import RemoteVideoMenuButton from './RemoteVideoMenuButton';
41 13
 
42 14
 /**
43 15
  * Implements a React {@link Component} which displays a button for kicking out
44 16
  * a participant from the conference.
45 17
  *
46
- * @extends Component
18
+ * NOTE: At the time of writing this is a button that doesn't use the
19
+ * {@code AbstractButton} base component, but is inherited from the same
20
+ * super class ({@code AbstractKickButton} that extends {@code AbstractButton})
21
+ * for the sake of code sharing between web and mobile. Once web uses the
22
+ * {@code AbstractButton} base component, this can be fully removed.
47 23
  */
48
-class KickButton extends Component<Props> {
24
+class KickButton extends AbstractKickButton {
49 25
     /**
50
-     * Initializes a new {@code KickButton} instance.
26
+     * Instantiates a new {@code Component}.
51 27
      *
52
-     * @param {Object} props - The read-only React Component props with which
53
-     * the new instance is to be initialized.
28
+     * @inheritdoc
54 29
      */
55
-    constructor(props) {
30
+    constructor(props: Props) {
56 31
         super(props);
57 32
 
58
-        // Bind event handlers so they are only bound once for every instance.
59
-        this._onClick = this._onClick.bind(this);
33
+        this._handleClick = this._handleClick.bind(this);
60 34
     }
61 35
 
62 36
     /**
@@ -73,33 +47,12 @@ class KickButton extends Component<Props> {
73 47
                 buttonText = { t('videothumbnail.kick') }
74 48
                 iconClass = 'icon-kick'
75 49
                 id = { `ejectlink_${participantID}` }
76
-                onClick = { this._onClick } />
50
+                // eslint-disable-next-line react/jsx-handler-names
51
+                onClick = { this._handleClick } />
77 52
         );
78 53
     }
79 54
 
80
-    _onClick: () => void;
81
-
82
-    /**
83
-     * Remove the participant with associated participantID from the conference.
84
-     *
85
-     * @private
86
-     * @returns {void}
87
-     */
88
-    _onClick() {
89
-        const { dispatch, onClick, participantID } = this.props;
90
-
91
-        sendAnalytics(createRemoteVideoMenuButtonEvent(
92
-            'kick.button',
93
-            {
94
-                'participant_id': participantID
95
-            }));
96
-
97
-        dispatch(kickParticipant(participantID));
98
-
99
-        if (onClick) {
100
-            onClick();
101
-        }
102
-    }
55
+    _handleClick: () => void
103 56
 }
104 57
 
105 58
 export default translate(connect()(KickButton));

+ 39
- 0
react/features/remote-video-menu/components/web/KickRemoteParticipantDialog.js Näytä tiedosto

@@ -0,0 +1,39 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { connect } from 'react-redux';
5
+
6
+import { Dialog } from '../../../base/dialog';
7
+import { translate } from '../../../base/i18n';
8
+
9
+import AbstractKickRemoteParticipantDialog
10
+    from '../AbstractKickRemoteParticipantDialog';
11
+
12
+/**
13
+ * Dialog to confirm a remote participant kick action.
14
+ */
15
+class KickRemoteParticipantDialog extends AbstractKickRemoteParticipantDialog {
16
+    /**
17
+     * Implements React's {@link Component#render()}.
18
+     *
19
+     * @inheritdoc
20
+     * @returns {ReactElement}
21
+     */
22
+    render() {
23
+        return (
24
+            <Dialog
25
+                okTitleKey = 'dialog.kickParticipantButton'
26
+                onSubmit = { this._onSubmit }
27
+                titleKey = 'dialog.kickParticipantTitle'
28
+                width = 'small'>
29
+                <div>
30
+                    { this.props.t('dialog.kickParticipantDialog') }
31
+                </div>
32
+            </Dialog>
33
+        );
34
+    }
35
+
36
+    _onSubmit: () => boolean;
37
+}
38
+
39
+export default translate(connect()(KickRemoteParticipantDialog));

+ 21
- 74
react/features/remote-video-menu/components/web/MuteButton.js Näytä tiedosto

@@ -1,68 +1,37 @@
1 1
 /* @flow */
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
-import {
7
-    createRemoteVideoMenuButtonEvent,
8
-    sendAnalytics
9
-} from '../../../analytics';
10 6
 import { translate } from '../../../base/i18n';
11
-import { openDialog } from '../../../base/dialog';
12 7
 
13
-import RemoteVideoMenuButton from './RemoteVideoMenuButton';
14
-import MuteRemoteParticipantDialog from './MuteRemoteParticipantDialog';
15
-
16
-/**
17
- * The type of the React {@code Component} props of {@link MuteButton}.
18
- */
19
-type Props = {
20
-
21
-    /**
22
-     * Invoked to send a request for muting the participant with the passed
23
-     * in participantID.
24
-     */
25
-    dispatch: Dispatch<*>,
26
-
27
-    /**
28
-     * Whether or not the participant is currently audio muted.
29
-     */
30
-    isAudioMuted: Function,
31
-
32
-    /**
33
-     * Callback to invoke when {@code MuteButton} is clicked.
34
-     */
35
-    onClick: Function,
36
-
37
-    /**
38
-     * The ID of the participant linked to the onClick callback.
39
-     */
40
-    participantID: string,
8
+import AbstractMuteButton, {
9
+    _mapStateToProps,
10
+    type Props
11
+} from '../AbstractMuteButton';
41 12
 
42
-    /**
43
-     * Invoked to obtain translated strings.
44
-     */
45
-    t: Function
46
-};
13
+import RemoteVideoMenuButton from './RemoteVideoMenuButton';
47 14
 
48 15
 /**
49 16
  * Implements a React {@link Component} which displays a button for audio muting
50 17
  * a participant in the conference.
51 18
  *
52
- * @extends Component
19
+ * NOTE: At the time of writing this is a button that doesn't use the
20
+ * {@code AbstractButton} base component, but is inherited from the same
21
+ * super class ({@code AbstractMuteButton} that extends {@code AbstractButton})
22
+ * for the sake of code sharing between web and mobile. Once web uses the
23
+ * {@code AbstractButton} base component, this can be fully removed.
53 24
  */
54
-class MuteButton extends Component<Props> {
25
+class MuteButton extends AbstractMuteButton {
55 26
     /**
56
-     * Initializes a new {@code MuteButton} instance.
27
+     * Instantiates a new {@code Component}.
57 28
      *
58
-     * @param {Object} props - The read-only React Component props with which
59
-     * the new instance is to be initialized.
29
+     * @inheritdoc
60 30
      */
61 31
     constructor(props: Props) {
62 32
         super(props);
63 33
 
64
-        // Bind event handlers so they are only bound once for every instance.
65
-        this._onClick = this._onClick.bind(this);
34
+        this._handleClick = this._handleClick.bind(this);
66 35
     }
67 36
 
68 37
     /**
@@ -72,8 +41,8 @@ class MuteButton extends Component<Props> {
72 41
      * @returns {ReactElement}
73 42
      */
74 43
     render() {
75
-        const { isAudioMuted, participantID, t } = this.props;
76
-        const muteConfig = isAudioMuted ? {
44
+        const { _audioTrackMuted, participantID, t } = this.props;
45
+        const muteConfig = _audioTrackMuted ? {
77 46
             translationKey: 'videothumbnail.muted',
78 47
             muteClassName: 'mutelink disabled'
79 48
         } : {
@@ -87,34 +56,12 @@ class MuteButton extends Component<Props> {
87 56
                 displayClass = { muteConfig.muteClassName }
88 57
                 iconClass = 'icon-mic-disabled'
89 58
                 id = { `mutelink_${participantID}` }
90
-                onClick = { this._onClick } />
59
+                // eslint-disable-next-line react/jsx-handler-names
60
+                onClick = { this._handleClick } />
91 61
         );
92 62
     }
93 63
 
94
-    _onClick: () => void;
95
-
96
-    /**
97
-     * Dispatches a request to mute the participant with the passed in
98
-     * participantID.
99
-     *
100
-     * @private
101
-     * @returns {void}
102
-     */
103
-    _onClick() {
104
-        const { dispatch, onClick, participantID } = this.props;
105
-
106
-        sendAnalytics(createRemoteVideoMenuButtonEvent(
107
-            'mute.button',
108
-            {
109
-                'participant_id': participantID
110
-            }));
111
-
112
-        dispatch(openDialog(MuteRemoteParticipantDialog, { participantID }));
113
-
114
-        if (onClick) {
115
-            onClick();
116
-        }
117
-    }
64
+    _handleClick: () => void
118 65
 }
119 66
 
120
-export default translate(connect()(MuteButton));
67
+export default translate(connect(_mapStateToProps)(MuteButton));

+ 8
- 82
react/features/remote-video-menu/components/web/MuteRemoteParticipantDialog.js Näytä tiedosto

@@ -1,39 +1,13 @@
1 1
 /* @flow */
2 2
 
3
-import React, { Component } from 'react';
3
+import React from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6 6
 import { Dialog } from '../../../base/dialog';
7 7
 import { translate } from '../../../base/i18n';
8 8
 
9
-import {
10
-    createRemoteMuteConfirmedEvent,
11
-    sendAnalytics
12
-} from '../../../analytics';
13
-import { muteRemoteParticipant } from '../../../base/participants';
14
-
15
-/**
16
- * The type of the React {@code Component} props of
17
- * {@link MuteRemoteParticipantDialog}.
18
- */
19
-type Props = {
20
-
21
-    /**
22
-     * Invoked to send a request for muting the participant with the passed
23
-     * in participantID.
24
-     */
25
-    dispatch: Dispatch<*>,
26
-
27
-    /**
28
-     * The ID of the participant linked to the onClick callback.
29
-     */
30
-    participantID: string,
31
-
32
-    /**
33
-     * Invoked to obtain translated strings.
34
-     */
35
-    t: Function
36
-};
9
+import AbstractMuteRemoteParticipantDialog
10
+    from '../AbstractMuteRemoteParticipantDialog';
37 11
 
38 12
 /**
39 13
  * A React Component with the contents for a dialog that asks for confirmation
@@ -41,21 +15,7 @@ type Props = {
41 15
  *
42 16
  * @extends Component
43 17
  */
44
-class MuteRemoteParticipantDialog extends Component<Props> {
45
-    /**
46
-     * Initializes a new {@code MuteRemoteParticipantDialog} instance.
47
-     *
48
-     * @param {Object} props - The read-only properties with which the new
49
-     * instance is to be initialized.
50
-     */
51
-    constructor(props: Props) {
52
-        super(props);
53
-
54
-        // Bind event handlers so they are only bound once per instance.
55
-        this._onSubmit = this._onSubmit.bind(this);
56
-        this._renderContent = this._renderContent.bind(this);
57
-    }
58
-
18
+class MuteRemoteParticipantDialog extends AbstractMuteRemoteParticipantDialog {
59 19
     /**
60 20
      * Implements React's {@link Component#render()}.
61 21
      *
@@ -69,48 +29,14 @@ class MuteRemoteParticipantDialog extends Component<Props> {
69 29
                 onSubmit = { this._onSubmit }
70 30
                 titleKey = 'dialog.muteParticipantTitle'
71 31
                 width = 'small'>
72
-                { this._renderContent() }
32
+                <div>
33
+                    { this.props.t('dialog.muteParticipantBody') }
34
+                </div>
73 35
             </Dialog>
74 36
         );
75 37
     }
76 38
 
77
-    _onSubmit: () => void;
78
-
79
-    /**
80
-     * Handles the submit button action.
81
-     *
82
-     * @private
83
-     * @returns {boolean} - True (to note that the modal should be closed).
84
-     */
85
-    _onSubmit() {
86
-        const { dispatch, participantID } = this.props;
87
-
88
-        sendAnalytics(createRemoteMuteConfirmedEvent(participantID));
89
-
90
-        dispatch(muteRemoteParticipant(participantID));
91
-
92
-        return true;
93
-    }
94
-
95
-    _renderContent: () => React$Element<*>;
96
-
97
-    /**
98
-     * Renders the content of the dialog.
99
-     *
100
-     * @private
101
-     * @returns {Component} The React {@code Component} which is the view of the
102
-     * dialog content.
103
-     */
104
-    _renderContent() {
105
-        const { t } = this.props;
106
-
107
-        return (
108
-            <div>
109
-                { t('dialog.muteParticipantBody') }
110
-            </div>
111
-        );
112
-    }
113
-
39
+    _onSubmit: () => boolean;
114 40
 }
115 41
 
116 42
 export default translate(connect()(MuteRemoteParticipantDialog));

+ 6
- 0
react/features/remote-video-menu/components/web/index.js Näytä tiedosto

@@ -1,7 +1,13 @@
1 1
 // @flow
2 2
 
3 3
 export { default as KickButton } from './KickButton';
4
+export {
5
+    default as KickRemoteParticipantDialog
6
+} from './KickRemoteParticipantDialog';
4 7
 export { default as MuteButton } from './MuteButton';
8
+export {
9
+    default as MuteRemoteParticipantDialog
10
+} from './MuteRemoteParticipantDialog';
5 11
 export {
6 12
     REMOTE_CONTROL_MENU_STATES,
7 13
     default as RemoteControlButton

Loading…
Peruuta
Tallenna