Fix mute and enable-audio controls in audio rooms.
Deploy Ladill Meet / deploy (push) Successful in 43s

Space speaker tiles use a different DOM than video tiles; updateParticipantTile
was throwing on missing cam badges. Also stop using the hidden attribute on
toolbar buttons so Alpine can show mic controls after promotion, and let listeners
dismiss the playback banner without needing publish access.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-04 01:47:42 +00:00
co-authored by Cursor
parent 57802ff7f6
commit 21092015b8
2 changed files with 45 additions and 17 deletions
+35 -7
View File
@@ -304,6 +304,7 @@ function meetRoom() {
this.applyStageLayout();
this.$nextTick(() => {
this.syncToolbarConditionalVisibility();
document.querySelector('.meet-toolbar__track')?.classList.add('is-ready');
});
},
@@ -588,7 +589,11 @@ function meetRoom() {
const unlock = async () => {
await this.ensureAudioPlayback();
if (this.needsMediaUnlock) {
if (this.canPublish && this.showMicrophoneControl()) {
await this.unlockLocalMicrophone();
} else {
this.needsMediaUnlock = false;
}
}
if (!this.audioPlaybackBlocked && !this.needsMediaUnlock) {
document.removeEventListener('click', unlock, true);
@@ -602,8 +607,14 @@ function meetRoom() {
async unlockAllAudio() {
await this.ensureAudioPlayback();
if (this.needsMediaUnlock) {
if (!this.needsMediaUnlock) {
return;
}
if (this.canPublish && this.showMicrophoneControl()) {
await this.unlockLocalMicrophone();
} else {
this.needsMediaUnlock = false;
}
},
@@ -1616,18 +1627,27 @@ function meetRoom() {
const tile = this.getOrCreateParticipantTile(participant);
if (!tile) return;
if (tile.classList.contains('meet-space-tile')) {
const person = this.participantForIdentity(participant.identity);
if (person) {
this.updateSessionParticipantTile(person, participant, tile);
}
return;
}
const stage = tile.querySelector('[data-tile-stage]');
const avatar = tile.querySelector('[data-tile-avatar]');
const micBadge = tile.querySelector('[data-tile-mic]');
const camBadge = tile.querySelector('[data-tile-cam]');
const hasVideo = this.isParticipantVideoActive(participant);
micBadge.classList.toggle('hidden', !this.isParticipantMuted(participant));
camBadge.classList.toggle('hidden', hasVideo || this.audioOnly);
micBadge?.classList.toggle('hidden', !this.isParticipantMuted(participant));
camBadge?.classList.toggle('hidden', hasVideo || this.audioOnly);
if (hasVideo) {
avatar.classList.add('hidden');
if (!stage.querySelector('video')) {
avatar?.classList.add('hidden');
if (!stage?.querySelector('video')) {
const publication = Array.from(participant.videoTrackPublications.values())
.find((pub) => pub.source !== Track.Source.ScreenShare && pub.track && !pub.isMuted);
if (publication?.track) {
@@ -1638,9 +1658,9 @@ function meetRoom() {
return;
}
avatar.classList.remove('hidden');
avatar?.classList.remove('hidden');
this.updateTileAvatarCircle(tile, participant);
stage.innerHTML = '';
stage?.replaceChildren();
},
attachVideoToTile(participant, track) {
@@ -2042,6 +2062,7 @@ function meetRoom() {
this.usesStageLayout = Boolean(media.uses_stage_layout);
this.breakoutRoomName = media.breakout?.name || '';
this.breakoutClosesAt = media.breakout?.closes_at || '';
this.syncToolbarConditionalVisibility();
},
async syncMediaSessionFromPoll(data) {
@@ -2433,6 +2454,12 @@ function meetRoom() {
return true;
},
syncToolbarConditionalVisibility() {
document.querySelectorAll('[data-toolbar-conditional]').forEach((element) => {
element.removeAttribute('hidden');
});
},
showVideoControl() {
return this.canPublish && !this.audioOnly && !this.audioOnlyPublish;
},
@@ -2502,6 +2529,7 @@ function meetRoom() {
if (participant.uuid === this.config.participantUuid) {
this.canPublish = ['host', 'co_host', 'panelist'].includes(participant.role);
this.speakRequested = Boolean(participant.speak_requested);
this.syncToolbarConditionalVisibility();
}
if (this.isSpace && !this.usesStageLayout) {
+9 -9
View File
@@ -399,7 +399,7 @@
<button @click="toggleMute()" type="button"
x-show="showMicrophoneControl()"
data-toolbar-conditional
@unless($toolbarShowMic) hidden @endunless
@unless($toolbarShowMic) style="display:none" @endunless
class="rounded-full p-3 transition-colors"
:class="isMuted ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isMuted ? 'Unmute' : 'Mute'">
@@ -409,7 +409,7 @@
<button @click="toggleVideo()" type="button"
x-show="showVideoControl()"
data-toolbar-conditional
@unless($toolbarShowVideo) hidden @endunless
@unless($toolbarShowVideo) style="display:none" @endunless
class="rounded-full p-3 transition-colors"
:class="isVideoOff ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isVideoOff ? 'Turn camera on' : 'Turn camera off'">
@@ -419,7 +419,7 @@
<button @click="toggleScreenShare()" type="button"
x-show="showVideoControl()"
data-toolbar-conditional
@unless($toolbarShowVideo) hidden @endunless
@unless($toolbarShowVideo) style="display:none" @endunless
class="rounded-full p-3 transition-colors"
:class="isScreenSharing ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="Share screen">
@@ -428,7 +428,7 @@
<button @click="raiseHand()" type="button"
x-show="showPrimaryToolbarAudienceControls()"
data-toolbar-conditional
@unless($toolbarShowAudiencePrimary) hidden @endunless
@unless($toolbarShowAudiencePrimary) style="display:none" @endunless
class="rounded-full bg-slate-700 p-3 hover:bg-slate-600"
title="Raise hand">
@include('meet.room.partials.meet-icon', ['icon' => 'raise-hand'])
@@ -436,7 +436,7 @@
<button @click="sendReaction('thumbs')" type="button"
x-show="showPrimaryToolbarAudienceControls()"
data-toolbar-conditional
@unless($toolbarShowAudiencePrimary) hidden @endunless
@unless($toolbarShowAudiencePrimary) style="display:none" @endunless
class="rounded-full bg-slate-700 p-3 hover:bg-slate-600"
title="Applause — sound plays when others join in">
@include('meet.room.partials.meet-icon', ['icon' => 'applause'])
@@ -444,7 +444,7 @@
<button @click="sendReaction('heart')" type="button"
x-show="showPrimaryToolbarAudienceControls() && !(usesSpeakAccess && speakGranted && audioOnlyPublish)"
data-toolbar-conditional
@unless($toolbarShowReactPrimary) hidden @endunless
@unless($toolbarShowReactPrimary) style="display:none" @endunless
class="rounded-full bg-slate-700 p-3 hover:bg-slate-600"
title="React">
@include('meet.room.partials.meet-icon', ['icon' => 'react'])
@@ -477,13 +477,13 @@
@endif
</div>
<button @click="raiseHand()" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) hidden @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Raise hand">
<button @click="raiseHand()" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) style="display:none" @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Raise hand">
@include('meet.room.partials.meet-icon', ['icon' => 'raise-hand'])
</button>
<button @click="sendReaction('thumbs')" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) hidden @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Applause — sound plays when others join in">
<button @click="sendReaction('thumbs')" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) style="display:none" @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Applause — sound plays when others join in">
@include('meet.room.partials.meet-icon', ['icon' => 'applause'])
</button>
<button @click="sendReaction('heart')" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) hidden @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="React">
<button @click="sendReaction('heart')" type="button" x-show="showAudienceControls()" data-toolbar-conditional @unless($toolbarShowAudienceDesktop) style="display:none" @endunless class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="React">
@include('meet.room.partials.meet-icon', ['icon' => 'react'])
</button>
@unless ($isSpace ?? false)