Add live speaker invites for audio rooms and simplify the toolbar.
Deploy Ladill Meet / deploy (push) Successful in 1m9s

Let hosts promote raised-hand listeners from People, remove the empty More menu in spaces, and put People and recording on the bottom bar.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-04 00:40:09 +00:00
co-authored by Cursor
parent c51e59945e
commit 46af4f93b6
8 changed files with 270 additions and 3 deletions
+63
View File
@@ -122,6 +122,8 @@ function meetRoom() {
speakGrantUrl: el.dataset.speakGrantUrl,
speakRevokeUrl: el.dataset.speakRevokeUrl,
speakDismissUrl: el.dataset.speakDismissUrl,
spacePromoteUrl: el.dataset.spacePromoteUrl,
spaceDemoteUrl: el.dataset.spaceDemoteUrl,
recordingStartUrl: el.dataset.recordingStartUrl,
recordingStopUrl: el.dataset.recordingStopUrl,
lockUrl: el.dataset.lockUrl,
@@ -2172,6 +2174,67 @@ function meetRoom() {
return this.inCallParticipants().filter((person) => person.speak_requested && !person.speak_granted);
},
handRaisedParticipants() {
return this.inCallParticipants().filter((person) => person.hand_raised && person.role === 'attendee');
},
spaceSpeakerUrl(template, participantUuid) {
return template?.replace('__UUID__', participantUuid) || '';
},
mergeSessionParticipant(participant) {
if (!participant?.uuid) {
return;
}
const index = this.sessionParticipants.findIndex((person) => person.uuid === participant.uuid);
if (index >= 0) {
this.sessionParticipants[index] = { ...this.sessionParticipants[index], ...participant };
}
if (participant.uuid === this.config.participantUuid) {
this.canPublish = ['host', 'co_host', 'panelist'].includes(participant.role);
}
},
async promoteSpaceSpeaker(participantUuid) {
const url = this.spaceSpeakerUrl(this.config.spacePromoteUrl, participantUuid);
if (!this.isSpace || !this.isHost || !url) {
return;
}
const res = await fetch(url, {
method: 'POST',
headers: this.headers(),
});
if (!res.ok) {
return;
}
const data = await res.json();
this.mergeSessionParticipant(data.participant);
},
async demoteSpaceSpeaker(participantUuid) {
const url = this.spaceSpeakerUrl(this.config.spaceDemoteUrl, participantUuid);
if (!this.isSpace || !this.isHost || !url) {
return;
}
const res = await fetch(url, {
method: 'DELETE',
headers: this.headers(),
});
if (!res.ok) {
return;
}
const data = await res.json();
this.mergeSessionParticipant(data.participant);
},
syncSelfSpeakState() {
const self = this.sessionParticipants.find((person) => person.uuid === this.config.participantUuid);
if (!self) {