(feat): add admin indicator

This commit is contained in:
Alois 2026-05-01 00:08:58 +02:00
commit c7313da53f
3 changed files with 83 additions and 8 deletions

View file

@ -70,6 +70,10 @@ type Runtime = {
getUser: GetUserFn;
};
type ParticipantMetadata = {
isAdmin: boolean;
};
type CallStore = {
state: CallState;
view: CallView;
@ -86,6 +90,7 @@ type CallStore = {
watchedStreamParticipantIds: number[];
pendingWatchedParticipantIds: number[];
activeScreenShareParticipantIds: number[];
parsedParticipantMetadataById: Record<number, ParticipantMetadata>;
isEncrypted: boolean;
room: Room;
keyProvider: ExternalE2EEKeyProvider;
@ -181,6 +186,51 @@ function hasParticipant(participantId: number) {
);
}
function parseParticipantMetadata(
metadata: string | undefined,
): ParticipantMetadata | undefined {
if (!metadata) {
return undefined;
}
try {
return JSON.parse(metadata);
} catch {
return undefined;
}
}
function getParsedParticipantMetadataById(): Record<
number,
ParticipantMetadata
> {
return Object.fromEntries(
getAllParticipants()
.map((participant) => {
const participantId = getParticipantId(participant.identity);
if (participantId == null) {
return null;
}
return [
participantId,
parseParticipantMetadata(participant.metadata),
] as const;
})
.filter(
(entry): entry is readonly [number, ParticipantMetadata] =>
entry != null,
),
);
}
function syncParsedParticipantMetadata() {
useCall.setState({
parsedParticipantMetadataById: getParsedParticipantMetadataById(),
});
}
function syncScreenShareParticipants() {
const activeScreenShareParticipantIds = getActiveScreenShareParticipantIds();
const state = useCall.getState();
@ -231,6 +281,13 @@ export function syncParticipantState() {
});
syncScreenShareParticipants();
syncParsedParticipantMetadata();
}
export function getParsedParticipantMetadata(
participantId: number,
): ParticipantMetadata | undefined {
return useCall.getState().parsedParticipantMetadataById[participantId];
}
// set state functions
@ -468,6 +525,7 @@ export async function disconnect() {
watchedStreamParticipantIds: [],
pendingWatchedParticipantIds: [],
activeScreenShareParticipantIds: [],
parsedParticipantMetadataById: {},
});
room.remoteParticipants.forEach((participant) => {
@ -611,6 +669,7 @@ export function resetCallState() {
watchedStreamParticipantIds: [],
pendingWatchedParticipantIds: [],
activeScreenShareParticipantIds: [],
parsedParticipantMetadataById: {},
});
syncParticipantState();
@ -652,6 +711,7 @@ export const useCall = create<CallStore>(() => ({
watchedStreamParticipantIds: [],
pendingWatchedParticipantIds: [],
activeScreenShareParticipantIds: [],
parsedParticipantMetadataById: {},
isEncrypted:
room.localParticipant.isE2EEEnabled && room.localParticipant.isEncrypted,
room,