From 21092015b88ebcc31514d424578422208d9f34d7 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sat, 4 Jul 2026 01:47:42 +0000 Subject: [PATCH] Fix mute and enable-audio controls in audio rooms. 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 --- resources/js/meet-room.js | 44 +++++++++++++++++++----- resources/views/meet/room/show.blade.php | 18 +++++----- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index 1517204..99dadc2 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -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) { - await this.unlockLocalMicrophone(); + 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) { diff --git a/resources/views/meet/room/show.blade.php b/resources/views/meet/room/show.blade.php index 03c5d93..8bee178 100644 --- a/resources/views/meet/room/show.blade.php +++ b/resources/views/meet/room/show.blade.php @@ -399,7 +399,7 @@ - - @unless ($isSpace ?? false)