Show non-spotlight participants in the plenary audience strip.
Deploy Ladill Meet / deploy (push) Successful in 38s

Include speakers and attendees below the stage, resolve avatars with the same fallbacks as video tiles, and refresh the strip when poll data updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 23:23:12 +00:00
co-authored by Cursor
parent 6f00103c35
commit 815f277cc3
2 changed files with 83 additions and 26 deletions
+4
View File
@@ -201,6 +201,10 @@ html.meet-room-page {
white-space: nowrap;
}
.meet-room-page .meet-audience-avatar--speaker {
border-color: rgb(139 92 246 / 0.55);
}
.meet-room-page .meet-audio-grid {
place-content: center;
place-items: center;
+79 -26
View File
@@ -550,24 +550,30 @@ function meetRoom() {
return person?.display_name || participant.name || participant.identity;
},
avatarUrlForParticipant(participant) {
const person = this.participantForIdentity(participant.identity);
avatarUrlForPerson(person) {
if (!person) {
return null;
}
if (person?.avatar_url) {
if (person.avatar_url) {
return person.avatar_url;
}
if (person && ['host', 'co_host'].includes(person.role) && this.roomHost?.avatar_url) {
if (['host', 'co_host'].includes(person.role) && this.roomHost?.avatar_url) {
return this.roomHost.avatar_url;
}
if (this.roomHost?.user_ref && person?.user_ref === this.roomHost.user_ref && this.roomHost.avatar_url) {
if (this.roomHost?.user_ref && person.user_ref === this.roomHost.user_ref && this.roomHost.avatar_url) {
return this.roomHost.avatar_url;
}
return null;
},
avatarUrlForParticipant(participant) {
return this.avatarUrlForPerson(this.participantForIdentity(participant.identity));
},
updateTileAvatarCircle(tile, participant) {
const circle = tile.querySelector('[data-tile-avatar-circle]');
if (!circle) {
@@ -662,6 +668,71 @@ function meetRoom() {
return [...this.audienceParticipants()].sort((a, b) => a.display_name.localeCompare(b.display_name));
},
resolveSpotlightParticipantUuid() {
const spotlightRef = this.resolveSpotlightSpeakerRef();
if (spotlightRef) {
const match = this.speakerParticipants().find((person) => person.user_ref === spotlightRef);
if (match) {
return match.uuid;
}
}
return this.speakerParticipantsSorted()[0]?.uuid || null;
},
plenaryStripParticipants() {
const spotlightUuid = this.resolveSpotlightParticipantUuid();
return this.inCallParticipants()
.filter((person) => person.uuid !== spotlightUuid)
.sort((a, b) => {
const aSpeaker = this.isSpeakerPerson(a);
const bSpeaker = this.isSpeakerPerson(b);
if (aSpeaker !== bSpeaker) {
return aSpeaker ? -1 : 1;
}
return a.display_name.localeCompare(b.display_name);
});
},
createStripInitials(person) {
const initials = document.createElement('span');
initials.className = 'meet-audience-avatar__initials';
initials.style.background = this.avatarStyle(person.display_name).background;
initials.textContent = this.participantInitials(person.display_name);
return initials;
},
appendStripAvatarItem(strip, person, index, total) {
const item = document.createElement('div');
item.className = 'meet-audience-avatar';
if (this.isSpeakerPerson(person)) {
item.classList.add('meet-audience-avatar--speaker');
}
item.style.zIndex = String(total - index);
item.title = person.display_name;
const avatarUrl = this.avatarUrlForPerson(person);
if (avatarUrl) {
const img = document.createElement('img');
img.src = avatarUrl;
img.alt = '';
img.className = 'meet-audience-avatar__image';
img.addEventListener('error', () => {
img.replaceWith(this.createStripInitials(person));
}, { once: true });
item.appendChild(img);
} else {
item.appendChild(this.createStripInitials(person));
}
strip.appendChild(item);
},
resolveSpotlightSpeakerRef() {
const speakers = this.speakerParticipants();
@@ -773,7 +844,7 @@ function meetRoom() {
return;
}
const audience = this.audienceParticipantsSorted();
const audience = this.plenaryStripParticipants();
if (audience.length === 0) {
return;
}
@@ -783,26 +854,7 @@ function meetRoom() {
const overflow = audience.length - visible.length;
visible.forEach((person, index) => {
const item = document.createElement('div');
item.className = 'meet-audience-avatar';
item.style.zIndex = String(visible.length - index);
item.title = person.display_name;
if (person.avatar_url) {
const img = document.createElement('img');
img.src = person.avatar_url;
img.alt = '';
img.className = 'meet-audience-avatar__image';
item.appendChild(img);
} else {
const initials = document.createElement('span');
initials.className = 'meet-audience-avatar__initials';
initials.style.background = this.avatarStyle(person.display_name).background;
initials.textContent = this.participantInitials(person.display_name);
item.appendChild(initials);
}
strip.appendChild(item);
this.appendStripAvatarItem(strip, person, index, visible.length);
});
if (overflow > 0) {
@@ -1811,6 +1863,7 @@ function meetRoom() {
this.sessionParticipants = data.participants;
this.pruneTilesFromSession();
this.refreshParticipantTileAvatars();
this.renderAudienceStrip();
}
if (typeof data.uses_stage_layout === 'boolean' || typeof data.stage_layout === 'string') {
this.mergeStageConfig(data);