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

* hideAutoAssignButton
* hideFooterMenu
* hideModeratorSettingsTab
* hideMoreActionsButton
* hideMuteAllButton
This commit is contained in:
Mihaela Dumitru 2022-04-29 19:51:46 +03:00 committed by GitHub
parent ab0bdaae70
commit 2bf526afa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 193 additions and 71 deletions

View File

@ -1093,8 +1093,18 @@ var config = {
// breakoutRooms: {
// // Hides the add breakout room button. This replaces `hideAddRoomButton`.
// hideAddRoomButton: false,
// // Hides the auto assign participants button.
// hideAutoAssignButton: false,
// // Hides the participants pane footer menu.
// hideFooterMenu: false,
// // Hides the join breakout room button.
// hideJoinRoomButton: false
// hideJoinRoomButton: false,
// // Hides the moderator settings tab.
// hideModeratorSettingsTab: false,
// // Hides the more actions button.
// hideMoreActionsButton: false,
// // Hides the mute all button.
// hideMuteAllButton: false
// },
// When true the user cannot add more images to be used as virtual background.

View File

@ -3,6 +3,7 @@
import _ from 'lodash';
import { getCurrentConference } from '../base/conference';
import { getParticipantCount, isLocalParticipantModerator } from '../base/participants';
import { toState } from '../base/redux';
import { FEATURE_KEY } from './constants';
@ -85,3 +86,40 @@ export const getBreakoutRoomsConfig = (stateful: Function | Object) => {
return breakoutRooms;
};
/**
* Returns whether the add breakout room button is visible.
*
* @param {Function | Object} stateful - Global state.
* @returns {boolean}
*/
export const isAddBreakoutRoomButtonVisible = (stateful: Function | Object) => {
const state = toState(stateful);
const isLocalModerator = isLocalParticipantModerator(state);
const { conference } = state['features/base/conference'];
const isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
const { hideAddRoomButton } = getBreakoutRoomsConfig(state);
return isLocalModerator && isBreakoutRoomsSupported && !hideAddRoomButton;
};
/**
* Returns whether the auto assign participants to breakout rooms button is visible.
*
* @param {Function | Object} stateful - Global state.
* @returns {boolean}
*/
export const isAutoAssignParticipantsVisible = (stateful: Function | Object) => {
const state = toState(stateful);
const rooms = getBreakoutRooms(state);
const inBreakoutRoom = isInBreakoutRoom(state);
const isLocalModerator = isLocalParticipantModerator(state);
const participantsCount = getParticipantCount(state);
const { hideAutoAssignButton } = getBreakoutRoomsConfig(state);
return !inBreakoutRoom
&& isLocalModerator
&& participantsCount > 2
&& Object.keys(rooms).length > 1
&& !hideAutoAssignButton;
};

View File

@ -4,13 +4,14 @@ import React, { useCallback } from 'react';
import { useSelector } from 'react-redux';
import useContextMenu from '../../../../../base/components/context-menu/useContextMenu';
import { getParticipantCount, isLocalParticipantModerator } from '../../../../../base/participants';
import { isLocalParticipantModerator } from '../../../../../base/participants';
import { equals } from '../../../../../base/redux';
import {
getBreakoutRooms,
isInBreakoutRoom,
getCurrentRoomId,
getBreakoutRoomsConfig
getBreakoutRoomsConfig,
isAutoAssignParticipantsVisible
} from '../../../../../breakout-rooms/functions';
import { showOverflowDrawer } from '../../../../../toolbox/functions';
@ -36,7 +37,7 @@ export const RoomList = ({ searchString }: Props) => {
.sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || ''));
const inBreakoutRoom = useSelector(isInBreakoutRoom);
const isLocalModerator = useSelector(isLocalParticipantModerator);
const participantsCount = useSelector(getParticipantCount);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const { hideJoinRoomButton } = useSelector(getBreakoutRoomsConfig);
const _overflowDrawer = useSelector(showOverflowDrawer);
const [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ] = useContextMenu();
@ -46,11 +47,7 @@ export const RoomList = ({ searchString }: Props) => {
return (
<>
{inBreakoutRoom && <LeaveButton />}
{!inBreakoutRoom
&& isLocalModerator
&& participantsCount > 2
&& rooms.length > 1
&& <AutoAssignButton />}
{showAutoAssign && <AutoAssignButton />}
<div id = 'breakout-rooms-list'>
{rooms.map((room: Object) => (
<React.Fragment key = { room.id }>

View File

@ -8,20 +8,19 @@ import { useDispatch, useSelector } from 'react-redux';
import { openDialog } from '../../../base/dialog';
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
import {
getParticipantCount,
isLocalParticipantModerator
} from '../../../base/participants';
import { isLocalParticipantModerator } from '../../../base/participants';
import { equals } from '../../../base/redux';
import {
getBreakoutRooms,
getBreakoutRoomsConfig,
getCurrentRoomId,
isAddBreakoutRoomButtonVisible,
isAutoAssignParticipantsVisible,
isInBreakoutRoom
} from '../../../breakout-rooms/functions';
import { getKnockingParticipants } from '../../../lobby/functions';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { isFooterMenuVisible, isMoreActionsVisible, isMuteAllVisible } from '../../functions';
import {
AddBreakoutRoomButton,
AutoAssignButton,
@ -49,21 +48,18 @@ const ParticipantsPane = () => {
[ dispatch ]);
const { t } = useTranslation();
const { hideAddRoomButton } = useSelector(getBreakoutRoomsConfig);
const { conference } = useSelector(state => state['features/base/conference']);
// $FlowExpectedError
const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
const currentRoomId = useSelector(getCurrentRoomId);
const rooms: Array<Object> = Object.values(useSelector(getBreakoutRooms, equals))
.filter((room: Object) => room.id !== currentRoomId)
.sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || ''));
const inBreakoutRoom = useSelector(isInBreakoutRoom);
const participantsCount = useSelector(getParticipantCount);
const autoAssign = !inBreakoutRoom && isLocalModerator
&& participantsCount > 2 && rooms.length > 1;
const addBreakoutRoom
= _isBreakoutRoomsSupported && !hideAddRoomButton && isLocalModerator;
const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const showFooterMenu = useSelector(isFooterMenuVisible);
const showMoreActions = useSelector(isMoreActionsVisible);
const showMuteAll = useSelector(isMuteAllVisible);
const lobbyParticipants = useSelector(getKnockingParticipants);
return (
@ -76,7 +72,7 @@ const ParticipantsPane = () => {
searchString = { searchString }
setSearchString = { setSearchString } />
{
autoAssign && <AutoAssignButton />
showAutoAssign && <AutoAssignButton />
}
{
inBreakoutRoom && <LeaveBreakoutRoomButton />
@ -89,23 +85,31 @@ const ParticipantsPane = () => {
searchString = { searchString } />))
}
{
addBreakoutRoom && <AddBreakoutRoomButton />
showAddBreakoutRoom && <AddBreakoutRoomButton />
}
{
isLocalModerator
showFooterMenu
&& <View style = { styles.participantsPaneFooter }>
<Button
children = { t('participantsPane.actions.muteAll') }
labelStyle = { styles.muteAllLabel }
mode = 'contained'
onPress = { muteAll }
style = { styles.muteAllMoreButton } />
<Button
icon = { HorizontalDotsIcon }
labelStyle = { styles.moreIcon }
mode = 'contained'
onPress = { openMoreMenu }
style = { styles.moreButton } />
{
showMuteAll && (
<Button
children = { t('participantsPane.actions.muteAll') }
labelStyle = { styles.muteAllLabel }
mode = 'contained'
onPress = { muteAll }
style = { styles.muteAllMoreButton } />
)
}
{
showMoreActions && (
<Button
icon = { HorizontalDotsIcon }
labelStyle = { styles.moreIcon }
mode = 'contained'
onPress = { openMoreMenu }
style = { styles.moreButton } />
)
}
</View>
}
</JitsiScreen>

View File

@ -249,6 +249,7 @@ export default {
bottom: 0,
flexDirection: 'row',
height: BaseTheme.spacing[12],
justifyContent: 'flex-end',
left: 0,
right: 0,
position: 'absolute',
@ -277,7 +278,8 @@ export default {
},
moreButton: {
...smallButton
...smallButton,
marginLeft: BaseTheme.spacing[3]
},
moreIcon: {
@ -291,8 +293,7 @@ export default {
},
muteAllMoreButton: {
...muteAllButton,
right: BaseTheme.spacing[3]
...muteAllButton
},
muteAllLabel: {

View File

@ -7,12 +7,17 @@ import participantsPaneTheme from '../../../base/components/themes/participantsP
import { openDialog } from '../../../base/dialog';
import { translate } from '../../../base/i18n';
import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons';
import { isLocalParticipantModerator } from '../../../base/participants';
import { connect } from '../../../base/redux';
import { getBreakoutRoomsConfig } from '../../../breakout-rooms/functions';
import { isAddBreakoutRoomButtonVisible } from '../../../breakout-rooms/functions';
import { MuteEveryoneDialog } from '../../../video-menu/components/';
import { close } from '../../actions';
import { findAncestorByClass, getParticipantsPaneOpen } from '../../functions';
import {
findAncestorByClass,
getParticipantsPaneOpen,
isFooterMenuVisible,
isMoreActionsVisible,
isMuteAllVisible
} from '../../functions';
import { AddBreakoutRoomButton } from '../breakout-rooms/components/web/AddBreakoutRoomButton';
import { RoomList } from '../breakout-rooms/components/web/RoomList';
@ -36,15 +41,25 @@ type Props = {
*/
_overflowDrawer: boolean,
/**
* Is the participants pane open.
*/
_paneOpen: boolean,
/**
* Should the add breakout room button be displayed?
*/
_showAddRoomButton: boolean,
/**
* Is the participants pane open.
* Whether to show the more actions button.
*/
_paneOpen: boolean,
_showMoreActionsButton: boolean,
/**
* Whether to show the mute all button.
*/
_showMuteAllButton: boolean,
/**
* Whether to show the footer menu.
@ -202,6 +217,8 @@ class ParticipantsPane extends Component<Props, State> {
_paneOpen,
_showAddRoomButton,
_showFooter,
_showMoreActionsButton,
_showMuteAllButton,
classes,
t
} = this.props;
@ -240,24 +257,28 @@ class ParticipantsPane extends Component<Props, State> {
</div>
{_showFooter && (
<div className = { classes.footer }>
<FooterButton
accessibilityLabel = { t('participantsPane.actions.muteAll') }
onClick = { this._onMuteAll }>
{t('participantsPane.actions.muteAll')}
</FooterButton>
<div className = { classes.footerMoreContainer }>
{_showMuteAllButton && (
<FooterButton
accessibilityLabel = { t('participantsPane.actions.moreModerationActions') }
id = 'participants-pane-context-menu'
isIconButton = { true }
onClick = { this._onToggleContext }>
<Icon src = { IconHorizontalPoints } />
accessibilityLabel = { t('participantsPane.actions.muteAll') }
onClick = { this._onMuteAll }>
{t('participantsPane.actions.muteAll')}
</FooterButton>
<FooterContextMenu
isOpen = { contextOpen }
onDrawerClose = { this._onDrawerClose }
onMouseLeave = { this._onToggleContext } />
</div>
)}
{_showMoreActionsButton && (
<div className = { classes.footerMoreContainer }>
<FooterButton
accessibilityLabel = { t('participantsPane.actions.moreModerationActions') }
id = 'participants-pane-context-menu'
isIconButton = { true }
onClick = { this._onToggleContext }>
<Icon src = { IconHorizontalPoints } />
</FooterButton>
<FooterContextMenu
isOpen = { contextOpen }
onDrawerClose = { this._onDrawerClose }
onMouseLeave = { this._onToggleContext } />
</div>
)}
</div>
)}
</div>
@ -374,18 +395,16 @@ class ParticipantsPane extends Component<Props, State> {
*/
function _mapStateToProps(state: Object) {
const isPaneOpen = getParticipantsPaneOpen(state);
const { hideAddRoomButton } = getBreakoutRoomsConfig(state);
const { conference } = state['features/base/conference'];
// $FlowExpectedError
const _isBreakoutRoomsSupported = conference?.getBreakoutRooms()?.isSupported();
const _isLocalParticipantModerator = isLocalParticipantModerator(state);
return {
_isBreakoutRoomsSupported,
_paneOpen: isPaneOpen,
_showAddRoomButton: _isBreakoutRoomsSupported && !hideAddRoomButton && _isLocalParticipantModerator,
_showFooter: isPaneOpen && isLocalParticipantModerator(state)
_showAddRoomButton: isAddBreakoutRoomButtonVisible(state),
_showFooter: isFooterMenuVisible(state),
_showMuteAllButton: isMuteAllVisible(state),
_showMoreActionsButton: isMoreActionsVisible(state)
};
}

View File

@ -18,7 +18,7 @@ import {
} from '../base/participants/functions';
import { toState } from '../base/redux';
import { normalizeAccents } from '../base/util/strings';
import { isInBreakoutRoom } from '../breakout-rooms/functions';
import { getBreakoutRoomsConfig, isInBreakoutRoom } from '../breakout-rooms/functions';
import { QUICK_ACTION_BUTTON, REDUCER_KEY, MEDIA_STATE } from './constants';
@ -261,3 +261,49 @@ export function participantMatchesSearch(participant: Object, searchString: stri
return false;
}
/**
* Returns whether the participants pane footer menu is visible.
*
* @param {Object} state - Global state.
* @returns {boolean}
*/
export const isFooterMenuVisible = (state: Object) => {
const isLocalModerator = isLocalParticipantModerator(state);
const inBreakoutRoom = isInBreakoutRoom(state);
const { hideFooterMenu } = getBreakoutRoomsConfig(state);
return inBreakoutRoom
? !hideFooterMenu && isLocalModerator
: isLocalModerator;
};
/**
* Returns whether the more actions button is visible.
*
* @param {Object} state - Global state.
* @returns {boolean}
*/
export const isMoreActionsVisible = (state: Object) => {
const inBreakoutRoom = isInBreakoutRoom(state);
const { hideMoreActionsButton } = getBreakoutRoomsConfig(state);
return inBreakoutRoom
? !hideMoreActionsButton
: true;
};
/**
* Returns whether the mute all button is visible.
*
* @param {Object} state - Global state.
* @returns {boolean}
*/
export const isMuteAllVisible = (state: Object) => {
const inBreakoutRoom = isInBreakoutRoom(state);
const { hideMuteAllButton } = getBreakoutRoomsConfig(state);
return inBreakoutRoom
? !hideMuteAllButton
: true;
};

View File

@ -11,6 +11,7 @@ import {
import { toState } from '../base/redux';
import { getHideSelfView } from '../base/settings';
import { parseStandardURIString } from '../base/util';
import { getBreakoutRoomsConfig, isInBreakoutRoom } from '../breakout-rooms/functions';
import { isFollowMeActive } from '../follow-me';
import { isReactionsEnabled } from '../reactions/functions.any';
@ -177,10 +178,16 @@ export function getModeratorTabProps(stateful: Object | Function) {
*/
export function shouldShowModeratorSettings(stateful: Object | Function) {
const state = toState(stateful);
return Boolean(
const inBreakoutRoom = isInBreakoutRoom(state);
const { hideModeratorSettingsTab } = getBreakoutRoomsConfig(state);
const hasModeratorRights = Boolean(
isSettingEnabled('moderator')
&& isLocalParticipantModerator(state));
&& isLocalParticipantModerator(state)
);
return inBreakoutRoom
? hasModeratorRights && !hideModeratorSettingsTab
: hasModeratorRights;
}
/**