Skip to main content

Participant list

In this lesson, we will add a panel with a list of participants in the conference. This list will be displayed on the left side of the screen and will show the name of each participant.

You can download the starter code from Step.08-Exercise-Participant-list.

App component

Open the file src/App.tsx and start editing it by adding the following imports:

import {
...
type Participant
} from '@pexip/infinity'

Define the state variables participants and me:

const [participants, setParticipants] = useState<Participant[]>([]);
const [me, setMe] = useState<Participant>();

The participants state will store the list of participants in the conference, and the me state will store the information about the current participant.

In the useEffect hook, add the following code to listen to the onParticipants and onMe signals. These signals will update the participants and me states when a new participant joins or leaves the conference:

useEffect(() => {
...
infinityClientSignals.onParticipants.add((event) => {
if (event.id === 'main') {
setParticipants(event.participants)
}
})

infinityClientSignals.onMe.add((event) => {
if (event.id === 'main') {
setMe(event.participant)
}
})
...
}, [])

Pass the participants and me states to the Conference component:

<Conference
localVideoStream={processedStream}
remoteStream={remoteStream}
presentationStream={presentationStream}
screenShared={screenShared}
devices={devices}
settings={{
audioInput,
audioOutput,
videoInput,
effect
}}
participants={participants}
me={me}
onAudioMute={handleAudioMute}
onVideoMute={handleVideoMute}
onScreenShare={handleScreenShare}
onSettingsChange={handleSettingsChange}
onDisconnect={handleDisconnect}
/>

Now the Conference component will receive the list of participants and the current participant.

Conference component

Edit the file src/components/Conference/Conference.css and add the following code to adapt the layout for small screens:

@media screen and (max-width: 550px) {
.Conference {
flex-direction: column-reverse;
height: calc(100% - 2em);
}

.Conference .VideoContainer {
flex: 0;
}

.Conference .Participants {
height: 10em;
flex: 1;
width: 100%;
max-width: none;
}
}

Edit the file src/components/Conference/Conference.tsx and add the following imports:

import {type Participant} from '@pexip/infinity';
import {Participants} from './Participants/Participants';

Add participants and me to the ConferenceProps interface:

interface ConferenceProps {
localVideoStream: MediaStream | undefined;
remoteStream: MediaStream | undefined;
presentationStream: MediaStream | undefined;
screenShared: boolean;
devices: MediaDeviceInfoLike[];
settings: Settings;
participants: Participant[];
me: Participant | undefined;
onAudioMute: (mute: boolean) => Promise<void>;
onVideoMute: (mute: boolean) => Promise<void>;
onScreenShare: () => Promise<void>;
onSettingsChange: (settings: Settings) => Promise<void>;
onDisconnect: () => Promise<void>;
}

Add the Participants component to the Conference component:

<Participants participants={props.participants} me={props.me} />

This component will display the list of participants in the conference and information about the current participant. This way the user can see who is in the conference and who they are.

Participants component

This component will use the list of participants and the current participant and display them in a list. Open the file src/components/Conference/Participants/Participants.tsx and start editing it by adding the following imports:

import {Box, BoxHeader, Icon, IconTypes, Tooltip} from '@pexip/components';
import {type Participant} from '@pexip/infinity';

Define the properties participants and me in the ParticipantsProps interface:

interface ParticipantsProps {
participants: Participant[];
me: Participant | undefined;
}

Add the following code to the Participants component to render the list of participants:

return (
<Box className="Participants">
<BoxHeader>Participants</BoxHeader>
<div className="ParticipantsBody">
<div className="ParticipantsInner">
{props.participants.map((participant) => (
<div className="Participant" key={participant.uuid}>
<span
className={
participant.uuid === props.me?.uuid ? 'selected' : ''
}
>
{participant.displayName}
{participant.uuid === props.me?.uuid && ' (You)'}
</span>

<span className="ParticipantStatus">
{participant.isMuted && (
<Tooltip text="Microphone Muted">
<Icon source={IconTypes.IconMicrophoneOff} size="compact" />
</Tooltip>
)}

{participant.isCameraMuted && (
<Tooltip text="Camera Muted">
<Icon source={IconTypes.IconVideoOff} size="compact" />
</Tooltip>
)}
</span>
</div>
))}
</div>
</div>
</Box>
)

The Participant component will display the name of the participant and an icon to indicate if the participant has muted their microphone or camera. If the participant is the current user, the component will display the text (You) next to the name.

As you can see, we read several properties from the Participant object:

  • uuid: The unique identifier of the participant.
  • displayName: The name of the participant.
  • isMuted: A boolean that indicates if the participant has muted their microphone.
  • isCameraMuted: A boolean that indicates if the participant has muted their camera.

Run the app

Now we have everything in place to test the new functionality. When the user joins the conference, they will see a list of participants on the left side of the screen.

You can compare your code with the solution in Step.08-Solution-Participant-list. You can also check the differences with the previous lesson in the git diff.

Participant list