Ver código fonte

feat(external-api) add breakout room configs to hide auto assign and footer menu buttons (#11443)

* hideAutoAssignButton
* hideFooterMenu
* hideModeratorSettingsTab
* hideMoreActionsButton
* hideMuteAllButton
factor2
Mihaela Dumitru 3 anos atrás
pai
commit
02aca27c46
Nenhuma conta vinculada ao e-mail do autor do commit

+ 11
- 1
config.js Ver arquivo

@@ -1103,8 +1103,18 @@ var config = {
1103 1103
     // breakoutRooms: {
1104 1104
     //     // Hides the add breakout room button. This replaces `hideAddRoomButton`.
1105 1105
     //     hideAddRoomButton: false,
1106
+    //     // Hides the auto assign participants button.
1107
+    //     hideAutoAssignButton: false,
1108
+    //     // Hides the participants pane footer menu.
1109
+    //     hideFooterMenu: false,
1106 1110
     //     // Hides the join breakout room button.
1107
-    //     hideJoinRoomButton: false
1111
+    //     hideJoinRoomButton: false,
1112
+    //     // Hides the moderator settings tab.
1113
+    //     hideModeratorSettingsTab: false,
1114
+    //     // Hides the more actions button.
1115
+    //     hideMoreActionsButton: false,
1116
+    //     // Hides the mute all button.
1117
+    //     hideMuteAllButton: false
1108 1118
     // },
1109 1119
 
1110 1120
     // When true the user cannot add more images to be used as virtual background.

+ 38
- 0
react/features/breakout-rooms/functions.js Ver arquivo

@@ -3,6 +3,7 @@
3 3
 import _ from 'lodash';
4 4
 
5 5
 import { getCurrentConference } from '../base/conference';
6
+import { getParticipantCount, isLocalParticipantModerator } from '../base/participants';
6 7
 import { toState } from '../base/redux';
7 8
 
8 9
 import { FEATURE_KEY } from './constants';
@@ -85,3 +86,40 @@ export const getBreakoutRoomsConfig = (stateful: Function | Object) => {
85 86
 
86 87
     return breakoutRooms;
87 88
 };
89
+
90
+/**
91
+ * Returns whether the add breakout room button is visible.
92
+ *
93
+ * @param {Function | Object} stateful - Global state.
94
+ * @returns {boolean}
95
+ */
96
+export const isAddBreakoutRoomButtonVisible = (stateful: Function | Object) => {
97
+    const state = toState(stateful);
98
+    const isLocalModerator = isLocalParticipantModerator(state);
99
+    const { conference } = state['features/base/conference'];
100
+    const isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
101
+    const { hideAddRoomButton } = getBreakoutRoomsConfig(state);
102
+
103
+    return isLocalModerator && isBreakoutRoomsSupported && !hideAddRoomButton;
104
+};
105
+
106
+/**
107
+ * Returns whether the auto assign participants to breakout rooms button is visible.
108
+ *
109
+ * @param {Function | Object} stateful - Global state.
110
+ * @returns {boolean}
111
+ */
112
+export const isAutoAssignParticipantsVisible = (stateful: Function | Object) => {
113
+    const state = toState(stateful);
114
+    const rooms = getBreakoutRooms(state);
115
+    const inBreakoutRoom = isInBreakoutRoom(state);
116
+    const isLocalModerator = isLocalParticipantModerator(state);
117
+    const participantsCount = getParticipantCount(state);
118
+    const { hideAutoAssignButton } = getBreakoutRoomsConfig(state);
119
+
120
+    return !inBreakoutRoom
121
+        && isLocalModerator
122
+        && participantsCount > 2
123
+        && Object.keys(rooms).length > 1
124
+        && !hideAutoAssignButton;
125
+};

+ 5
- 8
react/features/participants-pane/components/breakout-rooms/components/web/RoomList.js Ver arquivo

@@ -4,13 +4,14 @@ import React, { useCallback } from 'react';
4 4
 import { useSelector } from 'react-redux';
5 5
 
6 6
 import useContextMenu from '../../../../../base/components/context-menu/useContextMenu';
7
-import { getParticipantCount, isLocalParticipantModerator } from '../../../../../base/participants';
7
+import { isLocalParticipantModerator } from '../../../../../base/participants';
8 8
 import { equals } from '../../../../../base/redux';
9 9
 import {
10 10
     getBreakoutRooms,
11 11
     isInBreakoutRoom,
12 12
     getCurrentRoomId,
13
-    getBreakoutRoomsConfig
13
+    getBreakoutRoomsConfig,
14
+    isAutoAssignParticipantsVisible
14 15
 } from '../../../../../breakout-rooms/functions';
15 16
 import { showOverflowDrawer } from '../../../../../toolbox/functions';
16 17
 
@@ -36,7 +37,7 @@ export const RoomList = ({ searchString }: Props) => {
36 37
                     .sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || ''));
37 38
     const inBreakoutRoom = useSelector(isInBreakoutRoom);
38 39
     const isLocalModerator = useSelector(isLocalParticipantModerator);
39
-    const participantsCount = useSelector(getParticipantCount);
40
+    const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
40 41
     const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig);
41 42
     const _overflowDrawer = useSelector(showOverflowDrawer);
42 43
     const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu();
@@ -46,11 +47,7 @@ export const RoomList = ({ searchString }: Props) => {
46 47
     return (
47 48
         <>
48 49
             {inBreakoutRoom && <LeaveButton />}
49
-            {!inBreakoutRoom
50
-                && isLocalModerator
51
-                && participantsCount > 2
52
-                && rooms.length > 1
53
-                && <AutoAssignButton />}
50
+            {showAutoAssign && <AutoAssignButton />}
54 51
             <div id = 'breakout-rooms-list'>
55 52
                 {rooms.map((room: Object) => (
56 53
                     <React.Fragment key = { room.id }>

+ 32
- 28
react/features/participants-pane/components/native/ParticipantsPane.js Ver arquivo

@@ -8,20 +8,19 @@ import { useDispatch, useSelector } from 'react-redux';
8 8
 
9 9
 import { openDialog } from '../../../base/dialog';
10 10
 import JitsiScreen from '../../../base/modal/components/JitsiScreen';
11
-import {
12
-    getParticipantCount,
13
-    isLocalParticipantModerator
14
-} from '../../../base/participants';
11
+import { isLocalParticipantModerator } from '../../../base/participants';
15 12
 import { equals } from '../../../base/redux';
16 13
 import {
17 14
     getBreakoutRooms,
18
-    getBreakoutRoomsConfig,
19 15
     getCurrentRoomId,
16
+    isAddBreakoutRoomButtonVisible,
17
+    isAutoAssignParticipantsVisible,
20 18
     isInBreakoutRoom
21 19
 } from '../../../breakout-rooms/functions';
22 20
 import { getKnockingParticipants } from '../../../lobby/functions';
23 21
 import MuteEveryoneDialog
24 22
     from '../../../video-menu/components/native/MuteEveryoneDialog';
23
+import { isFooterMenuVisible, isMoreActionsVisible, isMuteAllVisible } from '../../functions';
25 24
 import {
26 25
     AddBreakoutRoomButton,
27 26
     AutoAssignButton,
@@ -49,21 +48,18 @@ const ParticipantsPane = () => {
49 48
         [ dispatch ]);
50 49
     const { t } = useTranslation();
51 50
 
52
-    const { hideAddRoomButton } = useSelector(getBreakoutRoomsConfig);
53 51
     const { conference } = useSelector(state => state['features/base/conference']);
54
-
55
-    // $FlowExpectedError
56 52
     const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
57 53
     const currentRoomId = useSelector(getCurrentRoomId);
58 54
     const rooms: Array<Object> = Object.values(useSelector(getBreakoutRooms, equals))
59 55
         .filter((room: Object) => room.id !== currentRoomId)
60 56
         .sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || ''));
61 57
     const inBreakoutRoom = useSelector(isInBreakoutRoom);
62
-    const participantsCount = useSelector(getParticipantCount);
63
-    const autoAssign = !inBreakoutRoom && isLocalModerator
64
-        && participantsCount > 2 && rooms.length > 1;
65
-    const addBreakoutRoom
66
-        = _isBreakoutRoomsSupported && !hideAddRoomButton && isLocalModerator;
58
+    const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible);
59
+    const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
60
+    const showFooterMenu = useSelector(isFooterMenuVisible);
61
+    const showMoreActions = useSelector(isMoreActionsVisible);
62
+    const showMuteAll = useSelector(isMuteAllVisible);
67 63
     const lobbyParticipants = useSelector(getKnockingParticipants);
68 64
 
69 65
     return (
@@ -76,7 +72,7 @@ const ParticipantsPane = () => {
76 72
                 searchString = { searchString }
77 73
                 setSearchString = { setSearchString } />
78 74
             {
79
-                autoAssign && <AutoAssignButton />
75
+                showAutoAssign && <AutoAssignButton />
80 76
             }
81 77
             {
82 78
                 inBreakoutRoom && <LeaveBreakoutRoomButton />
@@ -89,23 +85,31 @@ const ParticipantsPane = () => {
89 85
                     searchString = { searchString } />))
90 86
             }
91 87
             {
92
-                addBreakoutRoom && <AddBreakoutRoomButton />
88
+                showAddBreakoutRoom && <AddBreakoutRoomButton />
93 89
             }
94 90
             {
95
-                isLocalModerator
91
+                showFooterMenu
96 92
                 && <View style = { styles.participantsPaneFooter }>
97
-                    <Button
98
-                        children = { t('participantsPane.actions.muteAll') }
99
-                        labelStyle = { styles.muteAllLabel }
100
-                        mode = 'contained'
101
-                        onPress = { muteAll }
102
-                        style = { styles.muteAllMoreButton } />
103
-                    <Button
104
-                        icon = { HorizontalDotsIcon }
105
-                        labelStyle = { styles.moreIcon }
106
-                        mode = 'contained'
107
-                        onPress = { openMoreMenu }
108
-                        style = { styles.moreButton } />
93
+                    {
94
+                        showMuteAll && (
95
+                            <Button
96
+                                children = { t('participantsPane.actions.muteAll') }
97
+                                labelStyle = { styles.muteAllLabel }
98
+                                mode = 'contained'
99
+                                onPress = { muteAll }
100
+                                style = { styles.muteAllMoreButton } />
101
+                        )
102
+                    }
103
+                    {
104
+                        showMoreActions && (
105
+                            <Button
106
+                                icon = { HorizontalDotsIcon }
107
+                                labelStyle = { styles.moreIcon }
108
+                                mode = 'contained'
109
+                                onPress = { openMoreMenu }
110
+                                style = { styles.moreButton } />
111
+                        )
112
+                    }
109 113
                 </View>
110 114
             }
111 115
         </JitsiScreen>

+ 4
- 3
react/features/participants-pane/components/native/styles.js Ver arquivo

@@ -249,6 +249,7 @@ export default {
249 249
         bottom: 0,
250 250
         flexDirection: 'row',
251 251
         height: BaseTheme.spacing[12],
252
+        justifyContent: 'flex-end',
252 253
         left: 0,
253 254
         right: 0,
254 255
         position: 'absolute',
@@ -277,7 +278,8 @@ export default {
277 278
     },
278 279
 
279 280
     moreButton: {
280
-        ...smallButton
281
+        ...smallButton,
282
+        marginLeft: BaseTheme.spacing[3]
281 283
     },
282 284
 
283 285
     moreIcon: {
@@ -291,8 +293,7 @@ export default {
291 293
     },
292 294
 
293 295
     muteAllMoreButton: {
294
-        ...muteAllButton,
295
-        right: BaseTheme.spacing[3]
296
+        ...muteAllButton
296 297
     },
297 298
 
298 299
     muteAllLabel: {

+ 46
- 27
react/features/participants-pane/components/web/ParticipantsPane.js Ver arquivo

@@ -7,12 +7,17 @@ import participantsPaneTheme from '../../../base/components/themes/participantsP
7 7
 import { openDialog } from '../../../base/dialog';
8 8
 import { translate } from '../../../base/i18n';
9 9
 import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons';
10
-import { isLocalParticipantModerator } from '../../../base/participants';
11 10
 import { connect } from '../../../base/redux';
12
-import { getBreakoutRoomsConfig } from '../../../breakout-rooms/functions';
11
+import { isAddBreakoutRoomButtonVisible } from '../../../breakout-rooms/functions';
13 12
 import { MuteEveryoneDialog } from '../../../video-menu/components/';
14 13
 import { close } from '../../actions';
15
-import { findAncestorByClass, getParticipantsPaneOpen } from '../../functions';
14
+import {
15
+    findAncestorByClass,
16
+    getParticipantsPaneOpen,
17
+    isFooterMenuVisible,
18
+    isMoreActionsVisible,
19
+    isMuteAllVisible
20
+} from '../../functions';
16 21
 import { AddBreakoutRoomButton } from '../breakout-rooms/components/web/AddBreakoutRoomButton';
17 22
 import { RoomList } from '../breakout-rooms/components/web/RoomList';
18 23
 
@@ -36,15 +41,25 @@ type Props = {
36 41
      */
37 42
     _overflowDrawer: boolean,
38 43
 
44
+    /**
45
+     * Is the participants pane open.
46
+     */
47
+    _paneOpen: boolean,
48
+
39 49
     /**
40 50
      * Should the add breakout room button be displayed?
41 51
      */
42 52
     _showAddRoomButton: boolean,
43 53
 
44 54
     /**
45
-     * Is the participants pane open.
55
+     * Whether to show the more actions button.
46 56
      */
47
-    _paneOpen: boolean,
57
+    _showMoreActionsButton: boolean,
58
+
59
+    /**
60
+     * Whether to show the mute all button.
61
+     */
62
+    _showMuteAllButton: boolean,
48 63
 
49 64
     /**
50 65
      * Whether to show the footer menu.
@@ -202,6 +217,8 @@ class ParticipantsPane extends Component<Props, State> {
202 217
             _paneOpen,
203 218
             _showAddRoomButton,
204 219
             _showFooter,
220
+            _showMoreActionsButton,
221
+            _showMuteAllButton,
205 222
             classes,
206 223
             t
207 224
         } = this.props;
@@ -240,24 +257,28 @@ class ParticipantsPane extends Component<Props, State> {
240 257
                     </div>
241 258
                     {_showFooter && (
242 259
                         <div className = { classes.footer }>
243
-                            <FooterButton
244
-                                accessibilityLabel = { t('participantsPane.actions.muteAll') }
245
-                                onClick = { this._onMuteAll }>
246
-                                {t('participantsPane.actions.muteAll')}
247
-                            </FooterButton>
248
-                            <div className = { classes.footerMoreContainer }>
260
+                            {_showMuteAllButton && (
249 261
                                 <FooterButton
250
-                                    accessibilityLabel = { t('participantsPane.actions.moreModerationActions') }
251
-                                    id = 'participants-pane-context-menu'
252
-                                    isIconButton = { true }
253
-                                    onClick = { this._onToggleContext }>
254
-                                    <Icon src = { IconHorizontalPoints } />
262
+                                    accessibilityLabel = { t('participantsPane.actions.muteAll') }
263
+                                    onClick = { this._onMuteAll }>
264
+                                    {t('participantsPane.actions.muteAll')}
255 265
                                 </FooterButton>
256
-                                <FooterContextMenu
257
-                                    isOpen = { contextOpen }
258
-                                    onDrawerClose = { this._onDrawerClose }
259
-                                    onMouseLeave = { this._onToggleContext } />
260
-                            </div>
266
+                            )}
267
+                            {_showMoreActionsButton && (
268
+                                <div className = { classes.footerMoreContainer }>
269
+                                    <FooterButton
270
+                                        accessibilityLabel = { t('participantsPane.actions.moreModerationActions') }
271
+                                        id = 'participants-pane-context-menu'
272
+                                        isIconButton = { true }
273
+                                        onClick = { this._onToggleContext }>
274
+                                        <Icon src = { IconHorizontalPoints } />
275
+                                    </FooterButton>
276
+                                    <FooterContextMenu
277
+                                        isOpen = { contextOpen }
278
+                                        onDrawerClose = { this._onDrawerClose }
279
+                                        onMouseLeave = { this._onToggleContext } />
280
+                                </div>
281
+                            )}
261 282
                         </div>
262 283
                     )}
263 284
                 </div>
@@ -374,18 +395,16 @@ class ParticipantsPane extends Component<Props, State> {
374 395
  */
375 396
 function _mapStateToProps(state: Object) {
376 397
     const isPaneOpen = getParticipantsPaneOpen(state);
377
-    const { hideAddRoomButton } = getBreakoutRoomsConfig(state);
378 398
     const { conference } = state['features/base/conference'];
379
-
380
-    // $FlowExpectedError
381 399
     const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
382
-    const _isLocalParticipantModerator = isLocalParticipantModerator(state);
383 400
 
384 401
     return {
385 402
         _isBreakoutRoomsSupported,
386 403
         _paneOpen: isPaneOpen,
387
-        _showAddRoomButton: _isBreakoutRoomsSupported && !hideAddRoomButton && _isLocalParticipantModerator,
388
-        _showFooter: isPaneOpen && isLocalParticipantModerator(state)
404
+        _showAddRoomButton: isAddBreakoutRoomButtonVisible(state),
405
+        _showFooter: isFooterMenuVisible(state),
406
+        _showMuteAllButton: isMuteAllVisible(state),
407
+        _showMoreActionsButton: isMoreActionsVisible(state)
389 408
     };
390 409
 }
391 410
 

+ 47
- 1
react/features/participants-pane/functions.js Ver arquivo

@@ -18,7 +18,7 @@ import {
18 18
 } from '../base/participants/functions';
19 19
 import { toState } from '../base/redux';
20 20
 import { normalizeAccents } from '../base/util/strings';
21
-import { isInBreakoutRoom } from '../breakout-rooms/functions';
21
+import { getBreakoutRoomsConfig, isInBreakoutRoom } from '../breakout-rooms/functions';
22 22
 
23 23
 import { QUICK_ACTION_BUTTON, REDUCER_KEY, MEDIA_STATE } from './constants';
24 24
 
@@ -261,3 +261,49 @@ export function participantMatchesSearch(participant: Object, searchString: stri
261 261
 
262 262
     return false;
263 263
 }
264
+
265
+/**
266
+ * Returns whether the participants pane footer menu is visible.
267
+ *
268
+ * @param {Object} state - Global state.
269
+ * @returns {boolean}
270
+ */
271
+export const isFooterMenuVisible = (state: Object) => {
272
+    const isLocalModerator = isLocalParticipantModerator(state);
273
+    const inBreakoutRoom = isInBreakoutRoom(state);
274
+    const { hideFooterMenu } = getBreakoutRoomsConfig(state);
275
+
276
+    return inBreakoutRoom
277
+        ? !hideFooterMenu && isLocalModerator
278
+        : isLocalModerator;
279
+};
280
+
281
+/**
282
+ * Returns whether the more actions button is visible.
283
+ *
284
+ * @param {Object} state - Global state.
285
+ * @returns {boolean}
286
+ */
287
+export const isMoreActionsVisible = (state: Object) => {
288
+    const inBreakoutRoom = isInBreakoutRoom(state);
289
+    const { hideMoreActionsButton } = getBreakoutRoomsConfig(state);
290
+
291
+    return inBreakoutRoom
292
+        ? !hideMoreActionsButton
293
+        : true;
294
+};
295
+
296
+/**
297
+ * Returns whether the mute all button is visible.
298
+ *
299
+ * @param {Object} state - Global state.
300
+ * @returns {boolean}
301
+ */
302
+export const isMuteAllVisible = (state: Object) => {
303
+    const inBreakoutRoom = isInBreakoutRoom(state);
304
+    const { hideMuteAllButton } = getBreakoutRoomsConfig(state);
305
+
306
+    return inBreakoutRoom
307
+        ? !hideMuteAllButton
308
+        : true;
309
+};

+ 10
- 3
react/features/settings/functions.js Ver arquivo

@@ -11,6 +11,7 @@ import {
11 11
 import { toState } from '../base/redux';
12 12
 import { getHideSelfView } from '../base/settings';
13 13
 import { parseStandardURIString } from '../base/util';
14
+import { getBreakoutRoomsConfig, isInBreakoutRoom } from '../breakout-rooms/functions';
14 15
 import { isFollowMeActive } from '../follow-me';
15 16
 import { isReactionsEnabled } from '../reactions/functions.any';
16 17
 
@@ -177,10 +178,16 @@ export function getModeratorTabProps(stateful: Object | Function) {
177 178
  */
178 179
 export function shouldShowModeratorSettings(stateful: Object | Function) {
179 180
     const state = toState(stateful);
180
-
181
-    return Boolean(
181
+    const inBreakoutRoom = isInBreakoutRoom(state);
182
+    const { hideModeratorSettingsTab } = getBreakoutRoomsConfig(state);
183
+    const hasModeratorRights = Boolean(
182 184
         isSettingEnabled('moderator')
183
-        && isLocalParticipantModerator(state));
185
+        && isLocalParticipantModerator(state)
186
+    );
187
+
188
+    return inBreakoutRoom
189
+        ? hasModeratorRights && !hideModeratorSettingsTab
190
+        : hasModeratorRights;
184 191
 }
185 192
 
186 193
 /**

Carregando…
Cancelar
Salvar