jiti-meet/react/features/participants-pane/components/web/ParticipantItem.js

203 lines
4.5 KiB
JavaScript

// @flow
import { makeStyles } from '@material-ui/styles';
import React, { type Node, useCallback } from 'react';
import { Avatar } from '../../../base/avatar';
import { ListItem } from '../../../base/components';
import { translate } from '../../../base/i18n';
import {
ACTION_TRIGGER,
AudioStateIcons,
MEDIA_STATE,
type ActionTrigger,
type MediaState,
VideoStateIcons
} from '../../constants';
import { RaisedHandIndicator } from './RaisedHandIndicator';
type Props = {
/**
* Type of trigger for the participant actions.
*/
actionsTrigger?: ActionTrigger,
/**
* Media state for audio.
*/
audioMediaState?: MediaState,
/**
* React children.
*/
children?: Node,
/**
* Whether or not to disable the moderator indicator.
*/
disableModeratorIndicator: boolean,
/**
* The name of the participant. Used for showing lobby names.
*/
displayName: string,
/**
* Is this item highlighted/raised.
*/
isHighlighted?: boolean,
/**
* Whether or not the participant is a moderator.
*/
isModerator: boolean,
/**
* True if the participant is local.
*/
local: boolean,
/**
* Opens a drawer with participant actions.
*/
openDrawerForParticipant?: Function,
/**
* Callback for when the mouse leaves this component.
*/
onLeave?: Function,
/**
* If an overflow drawer can be opened.
*/
overflowDrawer?: boolean,
/**
* The ID of the participant.
*/
participantID: string,
/**
* True if the participant have raised hand.
*/
raisedHand?: boolean,
/**
* Media state for video.
*/
videoMediaState?: MediaState,
/**
* Invoked to obtain translated strings.
*/
t: Function,
/**
* The translated "you" text.
*/
youText?: string
}
const useStyles = makeStyles(theme => {
return {
nameContainer: {
display: 'flex',
flex: 1,
overflow: 'hidden'
},
name: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
},
moderatorLabel: {
...theme.typography.labelRegular,
lineHeight: `${theme.typography.labelRegular.lineHeight}px`,
color: theme.palette.text03
}
};
});
/**
* A component representing a participant entry in ParticipantPane and Lobby.
*
* @param {Props} props - The props of the component.
* @returns {ReactNode}
*/
function ParticipantItem({
actionsTrigger = ACTION_TRIGGER.HOVER,
audioMediaState = MEDIA_STATE.NONE,
children,
disableModeratorIndicator,
displayName,
isHighlighted,
isModerator,
local,
onLeave,
openDrawerForParticipant,
overflowDrawer,
participantID,
raisedHand,
t,
videoMediaState = MEDIA_STATE.NONE,
youText
}: Props) {
const onClick = useCallback(
() => openDrawerForParticipant && openDrawerForParticipant({
participantID,
displayName
}));
const styles = useStyles();
const icon = (
<Avatar
className = 'participant-avatar'
displayName = { displayName }
participantId = { participantID }
size = { 32 } />
);
const text = (
<>
<div className = { styles.nameContainer }>
<div className = { styles.name }>
{displayName}
</div>
{local ? <span>&nbsp;({youText})</span> : null}
</div>
{isModerator && !disableModeratorIndicator && <div className = { styles.moderatorLabel }>
{t('videothumbnail.moderator')}
</div>}
</>
);
const indicators = (
<>
{raisedHand && <RaisedHandIndicator />}
{VideoStateIcons[videoMediaState]}
{AudioStateIcons[audioMediaState]}
</>
);
return (
<ListItem
actions = { children }
hideActions = { local }
icon = { icon }
id = { `participant-item-${participantID}` }
indicators = { indicators }
isHighlighted = { isHighlighted }
onClick = { !local && overflowDrawer ? onClick : undefined }
onMouseLeave = { onLeave }
textChildren = { text }
trigger = { actionsTrigger } />
);
}
export default translate(ParticipantItem);