Browse Source

feat(rn) add mute everyone / (else) capabilities

j8
tmoldovan8x8 4 years ago
parent
commit
71fb5aef6c
No account linked to committer's email address

+ 102
- 0
react/features/remote-video-menu/components/AbstractMuteEveryoneDialog.js View File

@@ -0,0 +1,102 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+
5
+import { Dialog } from '../../base/dialog';
6
+import { getLocalParticipant, getParticipantDisplayName } from '../../base/participants';
7
+import { muteAllParticipants } from '../actions';
8
+
9
+import AbstractMuteRemoteParticipantDialog, {
10
+    type Props as AbstractProps
11
+} from './AbstractMuteRemoteParticipantDialog';
12
+
13
+/**
14
+ * The type of the React {@code Component} props of
15
+ * {@link AbstractMuteEveryoneDialog}.
16
+ */
17
+export type Props = AbstractProps & {
18
+
19
+    content: string,
20
+    exclude: Array<string>,
21
+    title: string
22
+};
23
+
24
+/**
25
+ *
26
+ * An abstract Component with the contents for a dialog that asks for confirmation
27
+ * from the user before muting all remote participants.
28
+ *
29
+ * @extends AbstractMuteRemoteParticipantDialog
30
+ */
31
+export default class AbstractMuteEveryoneDialog<P: Props> extends AbstractMuteRemoteParticipantDialog<P> {
32
+    static defaultProps = {
33
+        exclude: [],
34
+        muteLocal: false
35
+    };
36
+
37
+    /**
38
+     * Implements React's {@link Component#render()}.
39
+     *
40
+     * @inheritdoc
41
+     * @returns {ReactElement}
42
+     */
43
+    render() {
44
+        const { content, title } = this.props;
45
+
46
+        return (
47
+            <Dialog
48
+                okKey = 'dialog.muteParticipantButton'
49
+                onSubmit = { this._onSubmit }
50
+                titleString = { title }
51
+                width = 'small'>
52
+                <div>
53
+                    { content }
54
+                </div>
55
+            </Dialog>
56
+        );
57
+    }
58
+
59
+    _onSubmit: () => boolean;
60
+
61
+    /**
62
+     * Callback to be invoked when the value of this dialog is submitted.
63
+     *
64
+     * @returns {boolean}
65
+     */
66
+    _onSubmit() {
67
+        const {
68
+            dispatch,
69
+            exclude
70
+        } = this.props;
71
+
72
+        dispatch(muteAllParticipants(exclude));
73
+
74
+        return true;
75
+    }
76
+}
77
+
78
+/**
79
+ * Maps (parts of) the Redux state to the associated {@code AbstractMuteEveryoneDialog}'s props.
80
+ *
81
+ * @param {Object} state - The redux state.
82
+ * @param {Object} ownProps - The properties explicitly passed to the component.
83
+ * @returns {Props}
84
+ */
85
+export function abstractMapStateToProps(state: Object, ownProps: Props) {
86
+    const { exclude, t } = ownProps;
87
+
88
+    const whom = exclude
89
+        // eslint-disable-next-line no-confusing-arrow
90
+        .map(id => id === getLocalParticipant(state).id
91
+            ? t('dialog.muteEveryoneSelf')
92
+            : getParticipantDisplayName(state, id))
93
+        .join(', ');
94
+
95
+    return whom.length ? {
96
+        content: t('dialog.muteEveryoneElseDialog'),
97
+        title: t('dialog.muteEveryoneElseTitle', { whom })
98
+    } : {
99
+        content: t('dialog.muteEveryoneDialog'),
100
+        title: t('dialog.muteEveryoneTitle')
101
+    };
102
+}

+ 48
- 0
react/features/remote-video-menu/components/AbstractMuteEveryoneElseButton.js View File

@@ -0,0 +1,48 @@
1
+// @flow
2
+
3
+import { createToolbarEvent, sendAnalytics } from '../../analytics';
4
+import { openDialog } from '../../base/dialog';
5
+import { IconMuteEveryone } from '../../base/icons';
6
+import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
7
+
8
+import { MuteEveryoneDialog } from '.';
9
+
10
+export type Props = AbstractButtonProps & {
11
+
12
+    /**
13
+     * The redux {@code dispatch} function.
14
+     */
15
+    dispatch: Function,
16
+
17
+    /**
18
+     * The ID of the participant object that this button is supposed to keep unmuted.
19
+     */
20
+    participantID: string,
21
+
22
+    /**
23
+     * The function to be used to translate i18n labels.
24
+     */
25
+    t: Function
26
+};
27
+
28
+/**
29
+ * An abstract remote video menu button which mutes all the other participants.
30
+ */
31
+export default class AbstractMuteEveryoneElseButton extends AbstractButton<Props, *> {
32
+    accessibilityLabel = 'toolbar.accessibilityLabel.muteEveryoneElse';
33
+    icon = IconMuteEveryone;
34
+    label = 'videothumbnail.domuteOthers';
35
+
36
+    /**
37
+     * Handles clicking / pressing the button, and opens a confirmation dialog.
38
+     *
39
+     * @private
40
+     * @returns {void}
41
+     */
42
+    _handleClick() {
43
+        const { dispatch, participantID } = this.props;
44
+
45
+        sendAnalytics(createToolbarEvent('mute.everyoneelse.pressed'));
46
+        dispatch(openDialog(MuteEveryoneDialog, { exclude: [ participantID ] }));
47
+    }
48
+}

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

@@ -0,0 +1,67 @@
1
+// @flow
2
+
3
+import React from 'react';
4
+import { Text } from 'react-native';
5
+
6
+import { ColorSchemeRegistry } from '../../../base/color-scheme';
7
+import { ConfirmDialog } from '../../../base/dialog';
8
+import { translate } from '../../../base/i18n';
9
+import { connect } from '../../../base/redux';
10
+import { StyleType } from '../../../base/styles';
11
+import AbstractMuteEveryoneDialog, {
12
+    abstractMapStateToProps,
13
+    type Props as AbstractProps } from '../AbstractMuteEveryoneDialog';
14
+
15
+type Props = AbstractProps & {
16
+
17
+    /**
18
+     * The color-schemed stylesheet of the base/dialog feature.
19
+     */
20
+    _dialogStyles: StyleType
21
+}
22
+
23
+/**
24
+ * A React Component with the contents for a dialog that asks for confirmation
25
+ * from the user before muting all remote participants.
26
+ *
27
+ * @extends AbstractMuteEveryoneDialog
28
+ */
29
+class MuteEveryoneDialog extends AbstractMuteEveryoneDialog<Props> {
30
+
31
+    /**
32
+     * Implements {@code Component#render}.
33
+     *
34
+     * @inheritdoc
35
+     */
36
+    render() {
37
+        return (
38
+            <ConfirmDialog
39
+                okKey = 'dialog.muteParticipantButton'
40
+                onSubmit = { this._onSubmit } >
41
+                <Text style = { this.props._dialogStyles.text }>
42
+                    { `${this.props.title} \n\n ${this.props.content}` }
43
+                </Text>
44
+            </ConfirmDialog>
45
+        );
46
+    }
47
+
48
+    _onSubmit: () => boolean;
49
+}
50
+
51
+/**
52
+ * Maps part of the Redux state to the props of this component.
53
+ *
54
+ * @param {Object} state - The Redux state.
55
+ * @param {Props} ownProps - The own props of the component.
56
+ * @returns {{
57
+    *     _dialogStyles: StyleType
58
+    * }}
59
+ */
60
+function _mapStateToProps(state: Object, ownProps: Props) {
61
+    return {
62
+        ...abstractMapStateToProps(state, ownProps),
63
+        _dialogStyles: ColorSchemeRegistry.get(state, 'Dialog')
64
+    };
65
+}
66
+
67
+export default translate(connect(_mapStateToProps)(MuteEveryoneDialog));

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

@@ -0,0 +1,20 @@
1
+// @flow
2
+
3
+import { translate } from '../../../base/i18n';
4
+import { isLocalParticipantModerator } from '../../../base/participants';
5
+import { connect } from '../../../base/redux';
6
+import AbstractMuteEveryoneElseButton from '../AbstractMuteEveryoneElseButton';
7
+
8
+/**
9
+ * Maps part of the Redux state to the props of this component.
10
+ *
11
+ * @param {Object} state - The Redux state.
12
+ * @returns {Props}
13
+ */
14
+function _mapStateToProps(state) {
15
+    return {
16
+        visible: isLocalParticipantModerator(state)
17
+    };
18
+}
19
+
20
+export default translate(connect(_mapStateToProps)(AbstractMuteEveryoneElseButton));

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

@@ -16,6 +16,7 @@ import { hideRemoteVideoMenu } from '../../actions';
16 16
 import GrantModeratorButton from './GrantModeratorButton';
17 17
 import KickButton from './KickButton';
18 18
 import MuteButton from './MuteButton';
19
+import MuteEveryoneElseButton from './MuteEveryoneElseButton';
19 20
 import PinButton from './PinButton';
20 21
 import styles from './styles';
21 22
 
@@ -104,6 +105,7 @@ class RemoteVideoMenu extends PureComponent<Props> {
104 105
                 <GrantModeratorButton { ...buttonProps } />
105 106
                 <PinButton { ...buttonProps } />
106 107
                 <PrivateMessageButton { ...buttonProps } />
108
+                <MuteEveryoneElseButton { ...buttonProps } />
107 109
             </BottomSheet>
108 110
         );
109 111
     }

+ 4
- 9
react/features/remote-video-menu/components/native/index.js View File

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

+ 7
- 89
react/features/remote-video-menu/components/web/MuteEveryoneDialog.js View File

@@ -5,53 +5,15 @@ import React from 'react';
5 5
 import { Dialog } from '../../../base/dialog';
6 6
 import { translate } from '../../../base/i18n';
7 7
 import { connect } from '../../../base/redux';
8
-import { muteAllParticipants } from '../../actions';
9
-import AbstractMuteRemoteParticipantDialog, {
10
-    type Props as AbstractProps
11
-} from '../AbstractMuteRemoteParticipantDialog';
12
-
13
-declare var APP: Object;
14
-
15
-/**
16
- * The type of the React {@code Component} props of
17
- * {@link MuteEveryoneDialog}.
18
- */
19
-type Props = AbstractProps & {
20
-
21
-    /**
22
-     * The IDs of the remote participants to exclude from being muted.
23
-     */
24
-    exclude: Array<string>
25
-};
26
-
27
-/**
28
- * Translations needed for dialog rendering.
29
- */
30
-type Translations = {
31
-
32
-    /**
33
-     * Content text.
34
-     */
35
-    content: string,
36
-
37
-    /**
38
-     * Title text.
39
-     */
40
-    title: string
41
-}
8
+import AbstractMuteEveryoneDialog, { abstractMapStateToProps, type Props } from '../AbstractMuteEveryoneDialog';
42 9
 
43 10
 /**
44 11
  * A React Component with the contents for a dialog that asks for confirmation
45
- * from the user before muting a remote participant.
12
+ * from the user before muting all remote participants.
46 13
  *
47
- * @extends Component
14
+ * @extends AbstractMuteEveryoneDialog
48 15
  */
49
-class MuteEveryoneDialog extends AbstractMuteRemoteParticipantDialog<Props> {
50
-    static defaultProps = {
51
-        exclude: [],
52
-        muteLocal: false
53
-    };
54
-
16
+class MuteEveryoneDialog extends AbstractMuteEveryoneDialog<Props> {
55 17
     /**
56 18
      * Implements React's {@link Component#render()}.
57 19
      *
@@ -59,64 +21,20 @@ class MuteEveryoneDialog extends AbstractMuteRemoteParticipantDialog<Props> {
59 21
      * @returns {ReactElement}
60 22
      */
61 23
     render() {
62
-        const { content, title } = this._getTranslations();
63
-
64 24
         return (
65 25
             <Dialog
66 26
                 okKey = 'dialog.muteParticipantButton'
67 27
                 onSubmit = { this._onSubmit }
68
-                titleString = { title }
28
+                titleString = { this.props.title }
69 29
                 width = 'small'>
70 30
                 <div>
71
-                    { content }
31
+                    { this.props.content }
72 32
                 </div>
73 33
             </Dialog>
74 34
         );
75 35
     }
76 36
 
77 37
     _onSubmit: () => boolean;
78
-
79
-    /**
80
-     * Callback to be invoked when the value of this dialog is submitted.
81
-     *
82
-     * @returns {boolean}
83
-     */
84
-    _onSubmit() {
85
-        const {
86
-            dispatch,
87
-            exclude
88
-        } = this.props;
89
-
90
-        dispatch(muteAllParticipants(exclude));
91
-
92
-        return true;
93
-    }
94
-
95
-    /**
96
-     * Method to get translations depending on whether we have an exclusive
97
-     * mute or not.
98
-     *
99
-     * @returns {Translations}
100
-     * @private
101
-     */
102
-    _getTranslations(): Translations {
103
-        const { exclude, t } = this.props;
104
-        const { conference } = APP;
105
-        const whom = exclude
106
-            // eslint-disable-next-line no-confusing-arrow
107
-            .map(id => conference.isLocalId(id)
108
-                ? t('dialog.muteEveryoneSelf')
109
-                : conference.getParticipantDisplayName(id))
110
-            .join(', ');
111
-
112
-        return whom.length ? {
113
-            content: t('dialog.muteEveryoneElseDialog'),
114
-            title: t('dialog.muteEveryoneElseTitle', { whom })
115
-        } : {
116
-            content: t('dialog.muteEveryoneDialog'),
117
-            title: t('dialog.muteEveryoneTitle')
118
-        };
119
-    }
120 38
 }
121 39
 
122
-export default translate(connect()(MuteEveryoneDialog));
40
+export default translate(connect(abstractMapStateToProps)(MuteEveryoneDialog));

+ 5
- 22
react/features/remote-video-menu/components/web/MuteEveryoneElseButton.js View File

@@ -2,17 +2,13 @@
2 2
 
3 3
 import React from 'react';
4 4
 
5
-import { createToolbarEvent, sendAnalytics } from '../../../analytics';
6
-import { openDialog } from '../../../base/dialog';
7 5
 import { translate } from '../../../base/i18n';
8 6
 import { IconMuteEveryoneElse } from '../../../base/icons';
9 7
 import { connect } from '../../../base/redux';
10
-import AbstractMuteButton, {
11
-    _mapStateToProps,
8
+import AbstractMuteEveryoneElseButton, {
12 9
     type Props
13
-} from '../AbstractMuteButton';
10
+} from '../AbstractMuteEveryoneElseButton';
14 11
 
15
-import MuteEveryoneDialog from './MuteEveryoneDialog';
16 12
 import RemoteVideoMenuButton from './RemoteVideoMenuButton';
17 13
 
18 14
 /**
@@ -20,9 +16,9 @@ import RemoteVideoMenuButton from './RemoteVideoMenuButton';
20 16
  * every participant in the conference except the one with the given
21 17
  * participantID
22 18
  */
23
-class MuteEveryoneElseButton extends AbstractMuteButton {
19
+class MuteEveryoneElseButton extends AbstractMuteEveryoneElseButton {
24 20
     /**
25
-     * Instantiates a new {@code MuteEveryoneElseButton}.
21
+     * Instantiates a new {@code Component}.
26 22
      *
27 23
      * @inheritdoc
28 24
      */
@@ -53,19 +49,6 @@ class MuteEveryoneElseButton extends AbstractMuteButton {
53 49
     }
54 50
 
55 51
     _handleClick: () => void;
56
-
57
-    /**
58
-     * Handles clicking / pressing the button, and opens a confirmation dialog.
59
-     *
60
-     * @private
61
-     * @returns {void}
62
-     */
63
-    _handleClick() {
64
-        const { dispatch, participantID } = this.props;
65
-
66
-        sendAnalytics(createToolbarEvent('mute.everyoneelse.pressed'));
67
-        dispatch(openDialog(MuteEveryoneDialog, { exclude: [ participantID ] }));
68
-    }
69 52
 }
70 53
 
71
-export default translate(connect(_mapStateToProps)(MuteEveryoneElseButton));
54
+export default translate(connect()(MuteEveryoneElseButton));

+ 2
- 1
react/features/remote-video-menu/components/web/RemoteVideoMenuTriggerButton.js View File

@@ -9,10 +9,11 @@ import { Popover } from '../../../base/popover';
9 9
 import { connect } from '../../../base/redux';
10 10
 import { isRemoteTrackMuted } from '../../../base/tracks';
11 11
 
12
+import MuteEveryoneElseButton from './MuteEveryoneElseButton';
13
+
12 14
 import {
13 15
     GrantModeratorButton,
14 16
     MuteButton,
15
-    MuteEveryoneElseButton,
16 17
     KickButton,
17 18
     PrivateMessageMenuButton,
18 19
     RemoteControlButton,

+ 6
- 17
react/features/remote-video-menu/components/web/index.js View File

@@ -1,26 +1,15 @@
1 1
 // @flow
2 2
 
3 3
 export { default as GrantModeratorButton } from './GrantModeratorButton';
4
-export {
5
-    default as GrantModeratorDialog
6
-} from './GrantModeratorDialog';
4
+export { default as GrantModeratorDialog } from './GrantModeratorDialog';
7 5
 export { default as KickButton } from './KickButton';
8
-export {
9
-    default as KickRemoteParticipantDialog
10
-} from './KickRemoteParticipantDialog';
6
+export { default as KickRemoteParticipantDialog } from './KickRemoteParticipantDialog';
11 7
 export { default as MuteButton } from './MuteButton';
12
-export { default as MuteEveryoneElseButton } from './MuteEveryoneElseButton';
13 8
 export { default as MuteEveryoneDialog } from './MuteEveryoneDialog';
14
-export {
15
-    default as MuteRemoteParticipantDialog
16
-} from './MuteRemoteParticipantDialog';
9
+export { default as MuteEveryoneElseButton } from './MuteEveryoneElseButton';
10
+export { default as MuteRemoteParticipantDialog } from './MuteRemoteParticipantDialog';
17 11
 export { default as PrivateMessageMenuButton } from './PrivateMessageMenuButton';
18
-export {
19
-    REMOTE_CONTROL_MENU_STATES,
20
-    default as RemoteControlButton
21
-} from './RemoteControlButton';
12
+export { REMOTE_CONTROL_MENU_STATES, default as RemoteControlButton } from './RemoteControlButton';
22 13
 export { default as RemoteVideoMenu } from './RemoteVideoMenu';
23
-export {
24
-    default as RemoteVideoMenuTriggerButton
25
-} from './RemoteVideoMenuTriggerButton';
14
+export { default as RemoteVideoMenuTriggerButton } from './RemoteVideoMenuTriggerButton';
26 15
 export { default as VolumeSlider } from './VolumeSlider';

react/features/toolbox/components/web/MuteEveryoneButton.js → react/features/toolbox/components/MuteEveryoneButton.js View File

@@ -1,13 +1,13 @@
1 1
 // @flow
2 2
 
3
-import { createToolbarEvent, sendAnalytics } from '../../../analytics';
4
-import { openDialog } from '../../../base/dialog';
5
-import { translate } from '../../../base/i18n';
6
-import { IconMuteEveryone } from '../../../base/icons';
7
-import { getLocalParticipant, PARTICIPANT_ROLE } from '../../../base/participants';
8
-import { connect } from '../../../base/redux';
9
-import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
10
-import { MuteEveryoneDialog } from '../../../remote-video-menu';
3
+import { createToolbarEvent, sendAnalytics } from '../../analytics';
4
+import { openDialog } from '../../base/dialog';
5
+import { translate } from '../../base/i18n';
6
+import { IconMuteEveryone } from '../../base/icons';
7
+import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
8
+import { connect } from '../../base/redux';
9
+import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
10
+import { MuteEveryoneDialog } from '../../remote-video-menu/components';
11 11
 
12 12
 type Props = AbstractButtonProps & {
13 13
 

+ 2
- 0
react/features/toolbox/components/native/OverflowMenu.js View File

@@ -19,6 +19,7 @@ import { ClosedCaptionButton } from '../../../subtitles';
19 19
 import { TileViewButton } from '../../../video-layout';
20 20
 import { VideoShareButton } from '../../../youtube-player/components';
21 21
 import HelpButton from '../HelpButton';
22
+import MuteEveryoneButton from '../MuteEveryoneButton';
22 23
 
23 24
 import AudioOnlyButton from './AudioOnlyButton';
24 25
 import MoreOptionsButton from './MoreOptionsButton';
@@ -143,6 +144,7 @@ class OverflowMenu extends PureComponent<Props, State> {
143 144
                     <RoomLockButton { ...buttonProps } />
144 145
                     <ClosedCaptionButton { ...buttonProps } />
145 146
                     <SharedDocumentButton { ...buttonProps } />
147
+                    <MuteEveryoneButton { ...buttonProps } />
146 148
                     <HelpButton { ...buttonProps } />
147 149
                 </Collapsible>
148 150
             </BottomSheet>

+ 1
- 1
react/features/toolbox/components/web/Toolbox.js View File

@@ -79,9 +79,9 @@ import { isToolboxVisible } from '../../functions';
79 79
 import DownloadButton from '../DownloadButton';
80 80
 import HangupButton from '../HangupButton';
81 81
 import HelpButton from '../HelpButton';
82
+import MuteEveryoneButton from '../MuteEveryoneButton';
82 83
 
83 84
 import AudioSettingsButton from './AudioSettingsButton';
84
-import MuteEveryoneButton from './MuteEveryoneButton';
85 85
 import OverflowMenuButton from './OverflowMenuButton';
86 86
 import OverflowMenuProfileItem from './OverflowMenuProfileItem';
87 87
 import ToolbarButton from './ToolbarButton';

Loading…
Cancel
Save