feat(external-api) add breakout room configs to hide auto assign and footer menu buttons (#11443)
* hideAutoAssignButton * hideFooterMenu * hideModeratorSettingsTab * hideMoreActionsButton * hideMuteAllButton
This commit is contained in:
parent
9f3965800c
commit
02aca27c46
12
config.js
12
config.js
|
@ -1103,8 +1103,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.
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 }>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue