feat(participants-pane) separated participants into collapsible lists
This commit is contained in:
parent
b1a2ac66b0
commit
73f3409f0d
|
@ -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';
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -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';
|
||||||
|
|
|
@ -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'
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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 = {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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 {
|
|
@ -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 = {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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';
|
|
@ -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;
|
|
@ -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,10 +35,7 @@ const LobbyParticipantList = ({ theme }: Props) => {
|
||||||
if (!lobbyEnabled || !participants.length) {
|
if (!lobbyEnabled || !participants.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const title = (
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style = { styles.lobbyListContainer } >
|
|
||||||
<View style = { styles.lobbyListDetails } >
|
<View style = { styles.lobbyListDetails } >
|
||||||
<Text style = { styles.lobbyListDescription }>
|
<Text style = { styles.lobbyListDescription }>
|
||||||
{t('participantsPane.headings.waitingLobby',
|
{t('participantsPane.headings.waitingLobby',
|
||||||
|
@ -55,6 +53,15 @@ const LobbyParticipantList = ({ theme }: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</View>
|
</View>
|
||||||
|
);
|
||||||
|
const style = participants.length > 1 && styles.lobbyListContent;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CollapsibleList
|
||||||
|
title = { title }>
|
||||||
|
<ScrollView
|
||||||
|
bounces = { false }
|
||||||
|
style = { style } >
|
||||||
{
|
{
|
||||||
participants.map(p => (
|
participants.map(p => (
|
||||||
<LobbyParticipantItem
|
<LobbyParticipantItem
|
||||||
|
@ -62,7 +69,8 @@ const LobbyParticipantList = ({ theme }: Props) => {
|
||||||
participant = { p } />)
|
participant = { p } />)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</View>
|
</ScrollView>
|
||||||
|
</CollapsibleList>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style = { styles.meetingListContainer }>
|
|
||||||
<Text style = { styles.meetingListDescription }>
|
|
||||||
{_currentRoom?.name
|
|
||||||
|
|
||||||
// $FlowExpectedError
|
// $FlowExpectedError
|
||||||
? `${_currentRoom.name} (${_participantsCount})`
|
? `${_currentRoom.name} (${_participantsCount})`
|
||||||
: t('participantsPane.headings.participantsList', { count: _participantsCount })}
|
: t('participantsPane.headings.participantsList',
|
||||||
</Text>
|
{ count: _participantsCount });
|
||||||
|
const containerStyle
|
||||||
|
= _participantsCount > 3 && styles.meetingListContainer;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CollapsibleList
|
||||||
|
containerStyle = { containerStyle }
|
||||||
|
title = { title } >
|
||||||
{
|
{
|
||||||
_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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }>
|
|
||||||
<ScrollView bounces = { false }>
|
|
||||||
<LobbyParticipantList />
|
<LobbyParticipantList />
|
||||||
<MeetingParticipantList
|
<MeetingParticipantList
|
||||||
searchString = { searchString }
|
searchString = { searchString }
|
||||||
setSearchString = { setSearchString } />
|
setSearchString = { setSearchString } />
|
||||||
{!inBreakoutRoom
|
{
|
||||||
&& isLocalModerator
|
autoAssign && <AutoAssignButton />
|
||||||
&& participantsCount > 2
|
}
|
||||||
&& rooms.length > 1
|
{
|
||||||
&& <AutoAssignButton />}
|
inBreakoutRoom && <LeaveBreakoutRoomButton />
|
||||||
{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 />}
|
{
|
||||||
</ScrollView>
|
addBreakoutRoom && <AddBreakoutRoomButton />
|
||||||
|
}
|
||||||
{
|
{
|
||||||
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 }
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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';
|
||||||
|
|
Loading…
Reference in New Issue