feat(native-participants-pane) created meeting participant list

This commit is contained in:
Calin Chitu 2021-05-26 10:15:37 +03:00 committed by Hristo Terezov
parent e7280e5040
commit f49c05c666
6 changed files with 169 additions and 77 deletions

View File

@ -2,6 +2,7 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux';
@ -30,20 +31,22 @@ export const LobbyParticipantItem = ({ participant: p }: Props) => {
audioMuteState = { MediaState.Muted }
participant = { p }
videoMuteState = { MediaState.ForceMuted }>
<Button
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
onPress = { admit }
style = { styles.participantActionsButtonAdmit }>
{t('lobby.admit')}
</Button>
<Button
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
onPress = { reject }
style = { styles.participantActionsButtonReject }>
{t('lobby.reject')}
</Button>
<View style = { styles.lobbyParticipantItem }>
<Button
children = { t('lobby.admit') }
contentStyle = { styles.participantActionsButtonContent }
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
onPress = { admit }
style = { styles.participantActionsButtonAdmit } />
<Button
children = { t('lobby.reject') }
contentStyle = { styles.participantActionsButtonContent }
labelStyle = { styles.participantActionsButtonText }
mode = 'contained'
onPress = { reject }
style = { styles.participantActionsButtonReject } />
</View>
</ParticipantItem>
);
};

View File

@ -0,0 +1,33 @@
// @flow
import React from 'react';
import { useSelector } from 'react-redux';
import {
getIsParticipantAudioMuted,
getIsParticipantVideoMuted
} from '../../../base/tracks';
import { MediaState } from '../../constants';
import ParticipantItem from './ParticipantItem';
type Props = {
/**
* Participant reference
*/
participant: Object
};
export const MeetingParticipantItem = ({ participant }: Props) => {
const isAudioMuted = useSelector(getIsParticipantAudioMuted(participant));
const isVideoMuted = useSelector(getIsParticipantVideoMuted(participant));
return (
<ParticipantItem
audioMuteState = { isAudioMuted ? MediaState.Muted : MediaState.Unmuted }
participant = { participant }
videoMuteState = { isVideoMuted ? MediaState.Muted : MediaState.Unmuted } />
);
};

View File

@ -0,0 +1,41 @@
// @flow
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { Button } from 'react-native-paper';
import { Icon, IconInviteMore } from '../../../base/icons';
import { MeetingParticipantItem } from './MeetingParticipantItem';
import { participants } from './participants';
import styles from './styles';
export const MeetingParticipantList = () => {
const { t } = useTranslation();
return (
<View style = { styles.lobbyList }>
<Text style = { styles.lobbyListDescription }>
{t('participantsPane.headings.participantsList',
{ count: participants.length })}
</Text>
<Button
children = { t('participantsPane.actions.invite') }
/* eslint-disable-next-line react/jsx-no-bind */
icon = { () =>
(<Icon
size = { 24 }
src = { IconInviteMore } />)
}
labelStyle = { styles.inviteLabel }
mode = 'contained'
style = { styles.inviteButton } />
{ participants.map(p => (
<MeetingParticipantItem
key = { p.id }
participant = { p } />)
)}
</View>
);
};

View File

@ -3,7 +3,8 @@
import React from 'react';
import type { Node } from 'react';
import { useTranslation } from 'react-i18next';
import { Text, View } from 'react-native';
import { View } from 'react-native';
import { Text } from 'react-native-paper';
import { useSelector } from 'react-redux';
import { Avatar } from '../../../base/avatar';
@ -35,7 +36,7 @@ type Props = {
/**
* React children
*/
children: Node,
children?: Node,
/**
* Callback for when the mouse leaves this component
@ -86,7 +87,7 @@ function ParticipantItem({
<View style = { styles.participantStateAudio }>{AudioStateIcons[audioMuteState]}</View>
</View>
</View>
{ p.local ? <Text style = { styles.participantActions }> { children } </Text> : null }
{ children }
</View>
);
}

View File

@ -2,8 +2,8 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { View } from 'react-native';
import { Button, withTheme } from 'react-native-paper';
import { ScrollView, View } from 'react-native';
import { Button } from 'react-native-paper';
import { useDispatch } from 'react-redux';
import { hideDialog } from '../../../base/dialog';
@ -11,32 +11,20 @@ import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons';
import { JitsiModal } from '../../../base/modal';
import { LobbyParticipantList } from './LobbyParticipantList';
import { MeetingParticipantList } from './MeetingParticipantList';
import styles from './styles';
/**
* {@code ParticipantsPane}'s React {@code Component} prop types.
*/
type Props = {
/**
* Theme used for styles.
*/
theme: Object
}
/**
* Participant pane.
*
* @returns {React$Element<any>}
*/
function ParticipantsPane({ theme }: Props) {
export function ParticipantsPane() {
const dispatch = useDispatch();
const closePane = useCallback(
() => dispatch(hideDialog()),
[ dispatch ]);
const { t } = useTranslation();
const { palette } = theme;
return (
<JitsiModal
@ -53,21 +41,17 @@ function ParticipantsPane({ theme }: Props) {
}
mode = 'contained'
onPress = { closePane }
style = { styles.closeButton }
theme = {{
colors: {
primary: palette.action02
}
}} />
style = { styles.closeButton } />
</View>
<LobbyParticipantList />
<ScrollView>
<LobbyParticipantList />
<MeetingParticipantList />
</ScrollView>
<View style = { styles.footer }>
<Button
color = { palette.text01 }
contentStyle = { styles.muteAllContent }
style = { styles.muteAllButton } >
{ t('participantsPane.actions.muteAll') }
</Button>
children = { t('participantsPane.actions.muteAll') }
labelStyle = { styles.muteAllLabel }
style = { styles.muteAllButton } />
<Button
contentStyle = { styles.moreIcon }
/* eslint-disable-next-line react/jsx-no-bind */
@ -77,16 +61,11 @@ function ParticipantsPane({ theme }: Props) {
src = { IconHorizontalPoints } />)
}
mode = 'contained'
style = { styles.moreButton }
theme = {{
colors: {
primary: palette.action02
}
}} />
style = { styles.moreButton } />
</View>
</JitsiModal>
);
}
export default withTheme(ParticipantsPane);
export default ParticipantsPane;

View File

@ -18,17 +18,6 @@ const flexContent = {
flex: 1
};
/**
* The style of the participants pane buttons.
*/
const container = {
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
paddingRight: 16,
width: '100%'
};
/**
* The style of the participants pane buttons.
*/
@ -65,7 +54,8 @@ const buttonContent = {
*/
export default {
participantActions: {
lobbyParticipantItem: {
flexDirection: 'row',
position: 'absolute',
right: 0,
zIndex: 1
@ -110,7 +100,15 @@ export default {
height: 32
},
participantActionsButtonContent: {
alignItems: 'center',
display: 'flex',
height: 32
},
participantActionsButtonText: {
color: BaseTheme.palette.text01,
textTransform: 'capitalize'
},
allParticipantActionsButton: {
@ -134,7 +132,7 @@ export default {
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
height: '100%',
overflow: 'hidden',
width: '100%'
},
@ -144,7 +142,7 @@ export default {
flexDirection: 'row',
marginLeft: BaseTheme.spacing[2],
overflow: 'hidden',
width: 232
width: '63%'
},
participantName: {
@ -162,7 +160,8 @@ export default {
participantStatesContainer: {
display: 'flex',
flexDirection: 'row'
flexDirection: 'row',
marginLeft: 16
},
participantStateAudio: {
@ -170,7 +169,8 @@ export default {
},
participantStateVideo: {
...participantState
...participantState,
marginRight: 8
},
raisedHandIndicator: {
@ -187,33 +187,58 @@ export default {
},
lobbyList: {
marginLeft: 16,
marginRight: 16
marginRight: 16,
position: 'relative'
},
lobbyListDetails: {
alignItems: 'center',
display: 'flex',
flexDirection: 'row',
overflow: 'hidden',
paddingBottom: 16,
paddingTop: 16,
position: 'relative',
width: '100%'
},
lobbyListDescription: {
color: BaseTheme.palette.text01,
overflow: 'hidden',
width: 188
paddingBottom: 8,
paddingTop: 8,
position: 'relative',
width: '55%'
},
lobbyListActions: {
flexDirection: 'row'
flexDirection: 'row',
left: 0
},
header: {
...container
alignItems: 'center',
backgroundColor: BaseTheme.palette.ui01,
top: 0,
display: 'flex',
flexDirection: 'row',
height: 88,
paddingRight: 16,
position: 'absolute',
right: 0,
left: 0
},
footer: {
...container,
marginTop: 'auto'
alignItems: 'center',
backgroundColor: BaseTheme.palette.ui01,
bottom: 0,
display: 'flex',
flexDirection: 'row',
height: 88,
paddingRight: 16,
position: 'absolute',
right: 0,
left: 0
},
closeButton: {
@ -229,6 +254,15 @@ export default {
...smallButton
},
inviteButton: {
backgroundColor: BaseTheme.palette.action01
},
inviteLabel: {
...BaseTheme.typography.labelButtonLarge,
textTransform: 'capitalize'
},
moreIcon: {
...buttonContent,
left: 8
@ -239,7 +273,8 @@ export default {
left: 80
},
muteAllContent: {
...buttonContent
muteAllLabel: {
color: BaseTheme.palette.text01,
textTransform: 'capitalize'
}
};