diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index 7981630..94842ce 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -979,23 +979,30 @@ function meetRoom() { if (room) { const all = [room.localParticipant, ...room.remoteParticipants.values()]; all.forEach((participant) => { - const tile = this.findParticipantTile(participant.identity); - if (!tile) return; - const target = this.getTileContainerForIdentity(participant.identity); - if (target) { - if (tile.parentElement !== target) { - target.appendChild(tile); - } + if (!target) { + this.removeParticipantTile(participant.identity); + return; + } - const isSpotlightTile = target === spotlight; + const existingTile = this.findParticipantTile(participant.identity); + const previousParent = existingTile?.parentElement ?? null; + const tile = this.getOrCreateParticipantTile(participant); + if (!tile) { + return; + } - tile.classList.toggle('meet-stage-spotlight-tile', isSpotlightTile); - tile.classList.toggle('meet-stage-panel-tile', target === grid && this.stageLayout === 'panel'); - tile.classList.toggle('aspect-video', !isSpotlightTile && !this.audioOnly); - tile.classList.toggle('rounded-xl', !isSpotlightTile && !this.audioOnly); + const isSpotlightTile = target === spotlight; + + tile.classList.toggle('meet-stage-spotlight-tile', isSpotlightTile); + tile.classList.toggle('meet-stage-panel-tile', target === grid && this.stageLayout === 'panel'); + tile.classList.toggle('aspect-video', !isSpotlightTile && !this.audioOnly); + tile.classList.toggle('rounded-xl', !isSpotlightTile && !this.audioOnly); + + if (!existingTile || previousParent !== target) { + this.reattachParticipantVideo(participant); } else { - tile.remove(); + this.updateParticipantTile(participant); } }); } @@ -1353,6 +1360,14 @@ function meetRoom() { if (hasVideo) { 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) { + this.attachVideoToTile(participant, publication.track); + } + } + return; } @@ -1379,6 +1394,22 @@ function meetRoom() { stage.appendChild(el); }, + reattachParticipantVideo(participant) { + if (this.audioOnly || !participant) { + return; + } + + const publication = Array.from(participant.videoTrackPublications.values()) + .find((pub) => pub.source !== Track.Source.ScreenShare && pub.track && !pub.isMuted); + + if (publication?.track) { + this.attachVideoToTile(participant, publication.track); + return; + } + + this.updateParticipantTile(participant); + }, + setupCaptionPipeline() { if (!this.liveCaptions || !this.config.captionUrl) return; if (room?.localParticipant?.isMicrophoneEnabled) return; @@ -2019,6 +2050,15 @@ function meetRoom() { return !this.canPublish || this.audioOnlyPublish; }, + /** Mobile primary toolbar — webinars/conferences only; meetings use More for extras. */ + showPrimaryToolbarAudienceControls() { + if (!this.usesSpeakAccess) { + return false; + } + + return this.showAudienceControls(); + }, + showStagePublisherControls() { return this.usesSpeakAccess && this.canPublish && !this.audioOnlyPublish; }, diff --git a/resources/views/meet/room/show.blade.php b/resources/views/meet/room/show.blade.php index 3ebef27..6b7b150 100644 --- a/resources/views/meet/room/show.blade.php +++ b/resources/views/meet/room/show.blade.php @@ -375,19 +375,19 @@ @include('meet.room.partials.meet-icon', ['icon' => 'screen-share'])