feat(participants-pane) separated participants into collapsible lists

This commit is contained in:
Calin Chitu 2022-01-12 18:29:58 +02:00 committed by Calinteodor
parent b1a2ac66b0
commit 73f3409f0d
26 changed files with 260 additions and 157 deletions

View File

@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createBreakoutRoom } from '../../actions'; import { createBreakoutRoom } from '../../../../../breakout-rooms/actions';
import styles from './styles'; import styles from './styles';

View File

@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { autoAssignToBreakoutRooms } from '../../actions'; import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions';
import styles from './styles'; import styles from './styles';

View File

@ -6,17 +6,17 @@ import { TouchableOpacity } from 'react-native';
import { Text } from 'react-native-paper'; import { Text } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import { hideDialog } from '../../../base/dialog/actions'; import { hideDialog } from '../../../../../base/dialog/actions';
import BottomSheet from '../../../base/dialog/components/native/BottomSheet'; import BottomSheet from '../../../../../base/dialog/components/native/BottomSheet';
import { import {
Icon, Icon,
IconClose, IconClose,
IconRingGroup IconRingGroup
} from '../../../base/icons'; } from '../../../../../base/icons';
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../../../base/participants';
import styles from '../../../participants-pane/components/native/styles'; import { closeBreakoutRoom, moveToRoom, removeBreakoutRoom } from '../../../../../breakout-rooms/actions';
import { closeBreakoutRoom, moveToRoom, removeBreakoutRoom } from '../../actions'; import styles from '../../../native/styles';
type Props = { type Props = {

View File

@ -3,8 +3,8 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { isParticipantModerator } from '../../../base/participants'; import { isParticipantModerator } from '../../../../../base/participants';
import ParticipantItem from '../../../participants-pane/components/native/ParticipantItem'; import ParticipantItem from '../../../native/ParticipantItem';
type Props = { type Props = {

View File

@ -1,17 +1,17 @@
// @flow // @flow
import React, { useCallback, useState } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FlatList, Text, TouchableOpacity, View } from 'react-native'; import { FlatList } from 'react-native';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { openDialog } from '../../../base/dialog'; import { openDialog } from '../../../../../base/dialog';
import { Icon, IconArrowDown, IconArrowUp } from '../../../base/icons'; import { participantMatchesSearch } from '../../../../functions';
import { participantMatchesSearch } from '../../../participants-pane/functions'; import CollapsibleList from '../../../native/CollapsibleList';
import styles from '../../../native/styles';
import BreakoutRoomContextMenu from './BreakoutRoomContextMenu'; import BreakoutRoomContextMenu from './BreakoutRoomContextMenu';
import BreakoutRoomParticipantItem from './BreakoutRoomParticipantItem'; import BreakoutRoomParticipantItem from './BreakoutRoomParticipantItem';
import styles from './styles';
type Props = { type Props = {
@ -39,33 +39,23 @@ function _keyExtractor(item: Object) {
export const CollapsibleRoom = ({ room, searchString }: Props) => { export const CollapsibleRoom = ({ room, searchString }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [ collapsed, setCollapsed ] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const _toggleCollapsed = useCallback(() => {
setCollapsed(!collapsed);
}, [ collapsed ]);
const _openContextMenu = useCallback(() => { const _openContextMenu = useCallback(() => {
dispatch(openDialog(BreakoutRoomContextMenu, { room })); dispatch(openDialog(BreakoutRoomContextMenu, { room }));
}, [ room ]); }, [ room ]);
const roomParticipantsNr = Object.values(room.participants || {}).length;
const title
= `${room.name
|| t('breakoutRooms.mainRoom')} (${roomParticipantsNr})`;
const containerStyle
= roomParticipantsNr > 3 && styles.collapsibleRoomContainer;
return ( return (
<View> <CollapsibleList
<TouchableOpacity containerStyle = { containerStyle }
onLongPress = { _openContextMenu } onLongPress = { _openContextMenu }
onPress = { _toggleCollapsed } title = { title }>
style = { styles.collapsibleRoom }> <FlatList
<TouchableOpacity
onPress = { _toggleCollapsed }
style = { styles.arrowIcon }>
<Icon
size = { 18 }
src = { collapsed ? IconArrowDown : IconArrowUp } />
</TouchableOpacity>
<Text style = { styles.roomName }>
{`${room.name || t('breakoutRooms.mainRoom')} (${Object.values(room.participants || {}).length})`}
</Text>
</TouchableOpacity>
{!collapsed && <FlatList
bounces = { false } bounces = { false }
data = { Object.values(room.participants || {}) } data = { Object.values(room.participants || {}) }
horizontal = { false } horizontal = { false }
@ -73,8 +63,9 @@ export const CollapsibleRoom = ({ room, searchString }: Props) => {
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
renderItem = { ({ item: participant }) => participantMatchesSearch(participant, searchString) renderItem = { ({ item: participant }) => participantMatchesSearch(participant, searchString)
&& <BreakoutRoomParticipantItem item = { participant } /> } && <BreakoutRoomParticipantItem item = { participant } /> }
scrollEnabled = { true }
showsHorizontalScrollIndicator = { false } showsHorizontalScrollIndicator = { false }
windowSize = { 2 } />} windowSize = { 2 } />
</View> </CollapsibleList>
); );
}; };

View File

@ -5,8 +5,8 @@ import { useTranslation } from 'react-i18next';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import { moveToRoom } from '../../actions'; import { moveToRoom } from '../../../../../breakout-rooms/actions';
import styles from './styles'; import styles from './styles';

View File

@ -1,4 +1,4 @@
import BaseTheme from '../../../base/ui/components/BaseTheme.native'; import BaseTheme from '../../../../../base/ui/components/BaseTheme';
const baseButton = { const baseButton = {
borderRadius: BaseTheme.shape.borderRadius, borderRadius: BaseTheme.shape.borderRadius,
@ -36,6 +36,16 @@ export default {
alignItems: 'center' alignItems: 'center'
}, },
collapsibleList: {
alignItems: 'center',
borderRadius: BaseTheme.shape.borderRadius,
display: 'flex',
flexDirection: 'row',
height: BaseTheme.spacing[7],
marginHorizontal: BaseTheme.spacing[3],
marginTop: BaseTheme.spacing[3]
},
arrowIcon: { arrowIcon: {
backgroundColor: BaseTheme.palette.ui03, backgroundColor: BaseTheme.palette.ui03,
height: BaseTheme.spacing[5], height: BaseTheme.spacing[5],
@ -53,6 +63,13 @@ export default {
marginLeft: BaseTheme.spacing[2] marginLeft: BaseTheme.spacing[2]
}, },
listTile: {
fontSize: 15,
color: BaseTheme.palette.text01,
fontWeight: 'bold',
marginLeft: BaseTheme.spacing[2]
},
transparentButton: { transparentButton: {
...baseButton, ...baseButton,
backgroundColor: 'transparent' backgroundColor: 'transparent'

View File

@ -5,8 +5,8 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import ParticipantPaneBaseButton from '../../../participants-pane/components/web/ParticipantPaneBaseButton'; import { createBreakoutRoom } from '../../../../../breakout-rooms/actions';
import { createBreakoutRoom } from '../../actions'; import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
const useStyles = makeStyles(() => { const useStyles = makeStyles(() => {
return { return {

View File

@ -5,8 +5,8 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import ParticipantPaneBaseButton from '../../../participants-pane/components/web/ParticipantPaneBaseButton'; import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions';
import { autoAssignToBreakoutRooms } from '../../actions'; import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
const useStyles = makeStyles(theme => { const useStyles = makeStyles(theme => {
return { return {

View File

@ -6,11 +6,11 @@ import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { ListItem } from '../../../base/components'; import { ListItem } from '../../../../../base/components';
import { Icon, IconArrowDown, IconArrowUp } from '../../../base/icons'; import { Icon, IconArrowDown, IconArrowUp } from '../../../../../base/icons';
import ParticipantItem from '../../../participants-pane/components/web/ParticipantItem'; import { ACTION_TRIGGER } from '../../../../constants';
import { ACTION_TRIGGER } from '../../../participants-pane/constants'; import { participantMatchesSearch } from '../../../../functions';
import { participantMatchesSearch } from '../../../participants-pane/functions'; import ParticipantItem from '../../../web/ParticipantItem';
type Props = { type Props = {

View File

@ -5,9 +5,9 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import { QuickActionButton } from '../../../base/components'; import { QuickActionButton } from '../../../../../base/components';
import { moveToRoom } from '../../actions'; import { moveToRoom } from '../../../../../breakout-rooms/actions';
type Props = { type Props = {

View File

@ -5,9 +5,9 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import ParticipantPaneBaseButton from '../../../participants-pane/components/web/ParticipantPaneBaseButton'; import { moveToRoom } from '../../../../../breakout-rooms/actions';
import { moveToRoom } from '../../actions'; import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
const useStyles = makeStyles(theme => { const useStyles = makeStyles(theme => {
return { return {

View File

@ -4,8 +4,8 @@ import { makeStyles } from '@material-ui/styles';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { QuickActionButton } from '../../../base/components'; import { QuickActionButton } from '../../../../../base/components';
import { Icon, IconHorizontalPoints } from '../../../base/icons'; import { Icon, IconHorizontalPoints } from '../../../../../base/icons';
type Props = { type Props = {

View File

@ -4,15 +4,15 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../analytics'; import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
import { ContextMenu, ContextMenuItemGroup } from '../../../base/components'; import { ContextMenu, ContextMenuItemGroup } from '../../../../../base/components';
import { import {
IconClose, IconClose,
IconRingGroup IconRingGroup
} from '../../../base/icons'; } from '../../../../../base/icons';
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../../../base/participants';
import { showOverflowDrawer } from '../../../toolbox/functions.web'; import { closeBreakoutRoom, moveToRoom, removeBreakoutRoom } from '../../../../../breakout-rooms/actions';
import { closeBreakoutRoom, moveToRoom, removeBreakoutRoom } from '../../actions'; import { showOverflowDrawer } from '../../../../../toolbox/functions';
type Props = { type Props = {

View File

@ -3,11 +3,11 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import useContextMenu from '../../../base/components/context-menu/useContextMenu'; import useContextMenu from '../../../../../base/components/context-menu/useContextMenu';
import { getParticipantCount, isLocalParticipantModerator } from '../../../base/participants'; import { getParticipantCount, isLocalParticipantModerator } from '../../../../../base/participants';
import { equals } from '../../../base/redux'; import { equals } from '../../../../../base/redux';
import { showOverflowDrawer } from '../../../toolbox/functions.web'; import { getBreakoutRooms, isInBreakoutRoom, getCurrentRoomId } from '../../../../../breakout-rooms/functions';
import { getBreakoutRooms, isInBreakoutRoom, getCurrentRoomId } from '../../functions'; import { showOverflowDrawer } from '../../../../../toolbox/functions';
import { AutoAssignButton } from './AutoAssignButton'; import { AutoAssignButton } from './AutoAssignButton';
import { CollapsibleRoom } from './CollapsibleRoom'; import { CollapsibleRoom } from './CollapsibleRoom';

View File

@ -0,0 +1,65 @@
// @flow
import React, { useCallback, useState } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { Icon, IconArrowDown, IconArrowUp } from '../../../base/icons';
import { StyleType } from '../../../base/styles';
import styles from '../breakout-rooms/components/native/styles';
type Props = {
/**
* The children to be displayed within this list.
*/
children: React$Node,
/**
* Additional style to be appended to the CollapsibleList container.
*/
containerStyle?: StyleType,
/**
* Callback to invoke when the {@code CollapsibleList} is long pressed.
*/
onLongPress?: Function,
/**
* Collapsable list title.
*/
title: Object
}
const CollapsibleList = ({ children, containerStyle, onLongPress, title }: Props) => {
const [ collapsed, setCollapsed ] = useState(true);
const _toggleCollapsed = useCallback(() => {
setCollapsed(!collapsed);
}, [ collapsed ]);
return (
<View style = { !collapsed && containerStyle }>
<TouchableOpacity
onLongPress = { onLongPress }
onPress = { _toggleCollapsed }
style = { styles.collapsibleList }>
<TouchableOpacity
onPress = { _toggleCollapsed }
style = { styles.arrowIcon }>
<Icon
size = { 18 }
src = { collapsed ? IconArrowDown : IconArrowUp } />
</TouchableOpacity>
<Text style = { styles.listTile }>
{
title
}
</Text>
</TouchableOpacity>
{
!collapsed && children
}
</View>
);
};
export default CollapsibleList;

View File

@ -2,13 +2,14 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native'; import { ScrollView, Text, View } from 'react-native';
import { Button, withTheme } from 'react-native-paper'; import { Button, withTheme } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { admitMultiple } from '../../../lobby/actions.native'; import { admitMultiple } from '../../../lobby/actions.native';
import { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions'; import { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions';
import CollapsibleList from './CollapsibleList';
import { LobbyParticipantItem } from './LobbyParticipantItem'; import { LobbyParticipantItem } from './LobbyParticipantItem';
import styles from './styles'; import styles from './styles';
@ -34,36 +35,43 @@ const LobbyParticipantList = ({ theme }: Props) => {
if (!lobbyEnabled || !participants.length) { if (!lobbyEnabled || !participants.length) {
return null; return null;
} }
const title = (
return ( <View style = { styles.lobbyListDetails } >
<View <Text style = { styles.lobbyListDescription }>
style = { styles.lobbyListContainer } > {t('participantsPane.headings.waitingLobby',
<View style = { styles.lobbyListDetails } >
<Text style = { styles.lobbyListDescription }>
{t('participantsPane.headings.waitingLobby',
{ count: participants.length })} { count: participants.length })}
</Text> </Text>
{
participants.length > 1 && (
<Button
color = { palette.action02 }
labelStyle = { styles.admitAllParticipantsActionButtonLabel }
mode = 'text'
onPress = { admitAll }>
{t('lobby.admitAll')}
</Button>
)
}
</View>
{ {
participants.map(p => ( participants.length > 1 && (
<LobbyParticipantItem <Button
key = { p.id } color = { palette.action02 }
participant = { p } />) labelStyle = { styles.admitAllParticipantsActionButtonLabel }
mode = 'text'
onPress = { admitAll }>
{t('lobby.admitAll')}
</Button>
) )
} }
</View> </View>
); );
const style = participants.length > 1 && styles.lobbyListContent;
return (
<CollapsibleList
title = { title }>
<ScrollView
bounces = { false }
style = { style } >
{
participants.map(p => (
<LobbyParticipantItem
key = { p.id }
participant = { p } />)
)
}
</ScrollView>
</CollapsibleList>
);
}; };
export default withTheme(LobbyParticipantList); export default withTheme(LobbyParticipantList);

View File

@ -1,7 +1,7 @@
// @flow // @flow
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { FlatList, Text, View } from 'react-native'; import { FlatList } from 'react-native';
import { Button, withTheme } from 'react-native-paper'; import { Button, withTheme } from 'react-native-paper';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
@ -13,6 +13,7 @@ import { doInvitePeople } from '../../../invite/actions.native';
import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions'; import { participantMatchesSearch, shouldRenderInviteButton } from '../../functions';
import ClearableInput from './ClearableInput'; import ClearableInput from './ClearableInput';
import CollapsibleList from './CollapsibleList';
import MeetingParticipantItem from './MeetingParticipantItem'; import MeetingParticipantItem from './MeetingParticipantItem';
import styles from './styles'; import styles from './styles';
@ -181,17 +182,19 @@ class MeetingParticipantList extends PureComponent<Props> {
_sortedRemoteParticipants, _sortedRemoteParticipants,
t t
} = this.props; } = this.props;
const title = _currentRoom?.name
// $FlowExpectedError
? `${_currentRoom.name} (${_participantsCount})`
: t('participantsPane.headings.participantsList',
{ count: _participantsCount });
const containerStyle
= _participantsCount > 3 && styles.meetingListContainer;
return ( return (
<View <CollapsibleList
style = { styles.meetingListContainer }> containerStyle = { containerStyle }
<Text style = { styles.meetingListDescription }> title = { title } >
{_currentRoom?.name
// $FlowExpectedError
? `${_currentRoom.name} (${_participantsCount})`
: t('participantsPane.headings.participantsList', { count: _participantsCount })}
</Text>
{ {
_showInviteButton _showInviteButton
&& <Button && <Button
@ -212,11 +215,10 @@ class MeetingParticipantList extends PureComponent<Props> {
horizontal = { false } horizontal = { false }
keyExtractor = { this._keyExtractor } keyExtractor = { this._keyExtractor }
renderItem = { this._renderParticipant } renderItem = { this._renderParticipant }
scrollEnabled = { false } scrollEnabled = { true }
showsHorizontalScrollIndicator = { false } showsHorizontalScrollIndicator = { false }
style = { styles.meetingList }
windowSize = { 2 } /> windowSize = { 2 } />
</View> </CollapsibleList>
); );
} }
} }

View File

@ -2,7 +2,7 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ScrollView, View } from 'react-native'; import { View } from 'react-native';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@ -13,15 +13,15 @@ import {
isLocalParticipantModerator isLocalParticipantModerator
} from '../../../base/participants'; } from '../../../base/participants';
import { equals } from '../../../base/redux'; import { equals } from '../../../base/redux';
import { getBreakoutRooms, getCurrentRoomId, isInBreakoutRoom } from '../../../breakout-rooms/functions';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { import {
AddBreakoutRoomButton, AddBreakoutRoomButton,
AutoAssignButton, AutoAssignButton,
LeaveBreakoutRoomButton LeaveBreakoutRoomButton
} from '../../../breakout-rooms/components/native'; } from '../breakout-rooms/components/native';
import { CollapsibleRoom } from '../../../breakout-rooms/components/native/CollapsibleRoom'; import { CollapsibleRoom } from '../breakout-rooms/components/native/CollapsibleRoom';
import { getBreakoutRooms, getCurrentRoomId, isInBreakoutRoom } from '../../../breakout-rooms/functions';
import MuteEveryoneDialog
from '../../../video-menu/components/native/MuteEveryoneDialog';
import { ContextMenuMore } from './ContextMenuMore'; import { ContextMenuMore } from './ContextMenuMore';
import HorizontalDotsIcon from './HorizontalDotsIcon'; import HorizontalDotsIcon from './HorizontalDotsIcon';
@ -54,32 +54,36 @@ const ParticipantsPane = () => {
.sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || '')); .sort((p1: Object, p2: Object) => (p1?.name || '').localeCompare(p2?.name || ''));
const inBreakoutRoom = useSelector(isInBreakoutRoom); const inBreakoutRoom = useSelector(isInBreakoutRoom);
const participantsCount = useSelector(getParticipantCount); const participantsCount = useSelector(getParticipantCount);
const autoAssign = !inBreakoutRoom && isLocalModerator
&& participantsCount > 2 && rooms.length > 1;
const addBreakoutRoom
= _isBreakoutRoomsSupported && !hideAddRoomButton && isLocalModerator;
return ( return (
<JitsiScreen <JitsiScreen style = { styles.participantsPaneContainer }>
style = { styles.participantsPane }> <LobbyParticipantList />
<ScrollView bounces = { false }> <MeetingParticipantList
<LobbyParticipantList /> searchString = { searchString }
<MeetingParticipantList setSearchString = { setSearchString } />
searchString = { searchString } {
setSearchString = { setSearchString } /> autoAssign && <AutoAssignButton />
{!inBreakoutRoom }
&& isLocalModerator {
&& participantsCount > 2 inBreakoutRoom && <LeaveBreakoutRoomButton />
&& rooms.length > 1 }
&& <AutoAssignButton />} {
{inBreakoutRoom && <LeaveBreakoutRoomButton />} _isBreakoutRoomsSupported
{_isBreakoutRoomsSupported && rooms.map(room => (<CollapsibleRoom
&& rooms.map(room => (<CollapsibleRoom key = { room.id }
key = { room.id } room = { room }
room = { room } searchString = { searchString } />))
searchString = { searchString } />))} }
{_isBreakoutRoomsSupported && !hideAddRoomButton && isLocalModerator {
&& <AddBreakoutRoomButton />} addBreakoutRoom && <AddBreakoutRoomButton />
</ScrollView> }
{ {
isLocalModerator isLocalModerator
&& <View style = { styles.footer }> && <View style = { styles.participantsPaneFooter }>
<Button <Button
children = { t('participantsPane.actions.muteAll') } children = { t('participantsPane.actions.muteAll') }
labelStyle = { styles.muteAllLabel } labelStyle = { styles.muteAllLabel }

View File

@ -113,7 +113,9 @@ export default {
admitAllParticipantsActionButtonLabel: { admitAllParticipantsActionButtonLabel: {
...BaseTheme.typography.heading6, ...BaseTheme.typography.heading6,
color: BaseTheme.palette.link01, color: BaseTheme.palette.link01,
textTransform: 'capitalize' textTransform: 'capitalize',
marginRight: BaseTheme.spacing[5],
marginTop: BaseTheme.spacing[3]
}, },
participantContainer: { participantContainer: {
@ -167,12 +169,6 @@ export default {
paddingTop: BaseTheme.spacing[1] paddingTop: BaseTheme.spacing[1]
}, },
participantsPane: {
backgroundColor: BaseTheme.palette.ui01,
flex: 1,
justifyContent: 'center'
},
participantStatesContainer: { participantStatesContainer: {
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
@ -199,12 +195,15 @@ export default {
color: BaseTheme.palette.uiBackground color: BaseTheme.palette.uiBackground
}, },
lobbyListContainer: { lobbyListContent: {
position: 'relative' height: '20%'
}, },
lobbyListDescription: { lobbyListDescription: {
...participantListDescription fontSize: 15,
color: BaseTheme.palette.text01,
fontWeight: 'bold',
marginTop: BaseTheme.spacing[2]
}, },
lobbyListDetails: { lobbyListDetails: {
@ -213,13 +212,12 @@ export default {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
overflow: 'hidden', overflow: 'hidden',
paddingLeft: BaseTheme.spacing[3],
position: 'relative', position: 'relative',
width: '100%' width: '100%'
}, },
meetingListContainer: { meetingListContainer: {
flex: 1 height: '60%'
}, },
meetingListDescription: { meetingListDescription: {
@ -227,11 +225,28 @@ export default {
marginLeft: BaseTheme.spacing[3] marginLeft: BaseTheme.spacing[3]
}, },
footer: { collapsibleRoomContainer: {
height: '30%'
},
participantsPaneContainer: {
backgroundColor: BaseTheme.palette.ui01,
flex: 1,
justifyContent: 'center'
},
participantsPaneFooter: {
alignItems: 'center', alignItems: 'center',
backgroundColor: BaseTheme.palette.ui01,
bottom: 0,
flexDirection: 'row', flexDirection: 'row',
paddingHorizontal: BaseTheme.spacing[3], height: BaseTheme.spacing[12],
paddingVertical: BaseTheme.spacing[2] left: 0,
right: 0,
position: 'absolute',
paddingBottom: BaseTheme.spacing[2],
paddingLeft: BaseTheme.spacing[3],
paddingRight: BaseTheme.spacing[3]
}, },
headerCloseIcon: { headerCloseIcon: {
@ -242,9 +257,9 @@ export default {
backgroundColor: BaseTheme.palette.action01, backgroundColor: BaseTheme.palette.action01,
borderRadius: BaseTheme.shape.borderRadius, borderRadius: BaseTheme.shape.borderRadius,
height: BaseTheme.spacing[7], height: BaseTheme.spacing[7],
marginBottom: BaseTheme.spacing[4],
marginLeft: BaseTheme.spacing[3], marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3] marginRight: BaseTheme.spacing[3],
marginVertical: BaseTheme.spacing[3]
}, },
inviteLabel: { inviteLabel: {
@ -335,7 +350,8 @@ export default {
backgroundColor: BaseTheme.palette.uiBackground, backgroundColor: BaseTheme.palette.uiBackground,
borderRadius: BaseTheme.shape.borderRadius, borderRadius: BaseTheme.shape.borderRadius,
marginLeft: BaseTheme.spacing[3], marginLeft: BaseTheme.spacing[3],
marginRight: BaseTheme.spacing[3] marginRight: BaseTheme.spacing[3],
marginBottom: BaseTheme.spacing[4]
}, },
clearableInputFocus: { clearableInputFocus: {

View File

@ -9,11 +9,11 @@ import { translate } from '../../../base/i18n';
import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons'; import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons';
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { AddBreakoutRoomButton } from '../../../breakout-rooms/components/web/AddBreakoutRoomButton';
import { RoomList } from '../../../breakout-rooms/components/web/RoomList';
import { MuteEveryoneDialog } from '../../../video-menu/components/'; import { MuteEveryoneDialog } from '../../../video-menu/components/';
import { close } from '../../actions'; import { close } from '../../actions';
import { classList, findAncestorByClass, getParticipantsPaneOpen } from '../../functions'; import { classList, findAncestorByClass, getParticipantsPaneOpen } from '../../functions';
import { AddBreakoutRoomButton } from '../breakout-rooms/components/web/AddBreakoutRoomButton';
import { RoomList } from '../breakout-rooms/components/web/RoomList';
import FooterButton from './FooterButton'; import FooterButton from './FooterButton';
import { FooterContextMenu } from './FooterContextMenu'; import { FooterContextMenu } from './FooterContextMenu';