Fix meeting audio attach, prune left tiles, drop Ladill Meet eyebrow.
Deploy Ladill Meet / deploy (push) Successful in 30s
Deploy Ladill Meet / deploy (push) Successful in 30s
Attach remote audio tracks for playback, remove stale participant cards on leave, and remove the redundant Ladill Meet label from kiosk join pages. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+99
-12
@@ -175,9 +175,6 @@ function meetRoom() {
|
||||
|
||||
room.on(RoomEvent.TrackSubscribed, (track, publication, participant) => {
|
||||
this.attachTrack(track, publication, participant);
|
||||
if (track.kind === Track.Kind.Audio) {
|
||||
this.ensureAudioPlayback();
|
||||
}
|
||||
});
|
||||
room.on(RoomEvent.TrackUnsubscribed, (track, publication, participant) => {
|
||||
track.detach();
|
||||
@@ -191,6 +188,7 @@ function meetRoom() {
|
||||
this.updateParticipantTile(participant);
|
||||
}
|
||||
if (publication.kind === Track.Kind.Audio) {
|
||||
publication.track?.detach();
|
||||
this.updateParticipantTile(participant);
|
||||
}
|
||||
if (participant === room.localParticipant) {
|
||||
@@ -201,7 +199,8 @@ function meetRoom() {
|
||||
if (publication.kind === Track.Kind.Video && publication.track) {
|
||||
this.attachTrack(publication.track, publication, participant);
|
||||
}
|
||||
if (publication.kind === Track.Kind.Audio) {
|
||||
if (publication.kind === Track.Kind.Audio && publication.track) {
|
||||
this.attachTrack(publication.track, publication, participant);
|
||||
this.updateParticipantTile(participant);
|
||||
}
|
||||
if (participant === room.localParticipant) {
|
||||
@@ -221,8 +220,14 @@ function meetRoom() {
|
||||
}
|
||||
this.syncLocalMediaState();
|
||||
});
|
||||
room.on(RoomEvent.ParticipantConnected, () => this.syncParticipants());
|
||||
room.on(RoomEvent.ParticipantDisconnected, () => this.syncParticipants());
|
||||
room.on(RoomEvent.ParticipantConnected, (participant) => {
|
||||
this.attachExistingTracks(participant);
|
||||
this.syncParticipants();
|
||||
});
|
||||
room.on(RoomEvent.ParticipantDisconnected, (participant) => {
|
||||
this.removeParticipantTile(participant.identity);
|
||||
this.syncParticipants();
|
||||
});
|
||||
room.on(RoomEvent.Disconnected, () => {
|
||||
this.connectionStatus = 'Disconnected';
|
||||
});
|
||||
@@ -261,12 +266,9 @@ function meetRoom() {
|
||||
|
||||
this.setupCaptionPipeline();
|
||||
|
||||
this.updateParticipantTile(room.localParticipant);
|
||||
room.localParticipant.videoTrackPublications.forEach((pub) => {
|
||||
if (pub.track && !pub.isMuted && pub.source !== Track.Source.ScreenShare) {
|
||||
this.attachTrack(pub.track, pub, room.localParticipant);
|
||||
}
|
||||
});
|
||||
this.attachExistingTracks(room.localParticipant);
|
||||
room.remoteParticipants.forEach((participant) => this.attachExistingTracks(participant));
|
||||
this.syncParticipants();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.connectionStatus = this.connectionErrorMessage(e);
|
||||
@@ -472,6 +474,13 @@ function meetRoom() {
|
||||
await this.poll();
|
||||
},
|
||||
|
||||
removeParticipantTile(identity) {
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid || !identity) return;
|
||||
|
||||
grid.querySelector(`[data-participant-tile="${identity}"]`)?.remove();
|
||||
},
|
||||
|
||||
getOrCreateParticipantTile(participant) {
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid) return null;
|
||||
@@ -686,7 +695,40 @@ function meetRoom() {
|
||||
});
|
||||
},
|
||||
|
||||
attachExistingTracks(participant) {
|
||||
if (!participant) return;
|
||||
|
||||
const isLocal = room && participant === room.localParticipant;
|
||||
|
||||
if (!isLocal) {
|
||||
participant.audioTrackPublications.forEach((pub) => {
|
||||
if (pub.track && !pub.isMuted) {
|
||||
this.attachTrack(pub.track, pub, participant);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
participant.videoTrackPublications.forEach((pub) => {
|
||||
if (pub.track && !pub.isMuted && pub.source !== Track.Source.ScreenShare) {
|
||||
this.attachTrack(pub.track, pub, participant);
|
||||
}
|
||||
});
|
||||
|
||||
this.updateParticipantTile(participant);
|
||||
},
|
||||
|
||||
attachTrack(track, publication, participant) {
|
||||
if (track.kind === Track.Kind.Audio) {
|
||||
if (participant === room?.localParticipant) return;
|
||||
if (publication?.isMuted) return;
|
||||
|
||||
const element = track.attach();
|
||||
element.className = 'meet-remote-audio';
|
||||
this.getAudioContainer().appendChild(element);
|
||||
this.ensureAudioPlayback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (track.kind !== Track.Kind.Video) return;
|
||||
|
||||
const isScreen = publication?.source === Track.Source.ScreenShare
|
||||
@@ -711,11 +753,55 @@ function meetRoom() {
|
||||
this.attachVideoToTile(participant, track);
|
||||
},
|
||||
|
||||
getAudioContainer() {
|
||||
let container = document.getElementById('meet-audio-elements');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.id = 'meet-audio-elements';
|
||||
container.className = 'sr-only';
|
||||
container.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
syncParticipants() {
|
||||
if (!room) return;
|
||||
|
||||
const all = [room.localParticipant, ...room.remoteParticipants.values()];
|
||||
const activeIdentities = new Set(all.map((p) => p.identity));
|
||||
|
||||
this.participants = all.map((p) => ({ identity: p.identity, name: p.name }));
|
||||
all.forEach((participant) => this.updateParticipantTile(participant));
|
||||
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid) return;
|
||||
|
||||
grid.querySelectorAll('[data-participant-tile]').forEach((tile) => {
|
||||
if (!activeIdentities.has(tile.dataset.participantTile)) {
|
||||
tile.remove();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
pruneTilesFromSession() {
|
||||
const joinedIds = new Set(
|
||||
this.sessionParticipants
|
||||
.filter((p) => p.status === 'joined')
|
||||
.map((p) => p.uuid),
|
||||
);
|
||||
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid) return;
|
||||
|
||||
grid.querySelectorAll('[data-participant-tile]').forEach((tile) => {
|
||||
const identity = tile.dataset.participantTile;
|
||||
if (room?.localParticipant?.identity === identity) return;
|
||||
if (!joinedIds.has(identity)) {
|
||||
tile.remove();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async toggleMute() {
|
||||
@@ -862,6 +948,7 @@ function meetRoom() {
|
||||
const data = await res.json();
|
||||
if (data.participants) {
|
||||
this.sessionParticipants = data.participants;
|
||||
this.pruneTilesFromSession();
|
||||
}
|
||||
this.updateChatFromPoll(data.messages || []);
|
||||
this.qaItems = data.qa || [];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<x-meet-kiosk-layout :title="'Meeting cancelled'" :organization="$organization ?? null" eyebrow="Ladill Meet">
|
||||
<x-meet-kiosk-layout :title="'Meeting cancelled'" :organization="$organization ?? null">
|
||||
<div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center text-center">
|
||||
<div class="w-full max-w-md rounded-3xl border border-slate-200 bg-white p-8 shadow-sm">
|
||||
<h1 class="text-2xl font-bold text-slate-900">{{ $room->title }}</h1>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<x-meet-kiosk-layout :title="'Access denied · '.$room->title" :organization="$organization" eyebrow="Ladill Meet">
|
||||
<x-meet-kiosk-layout :title="'Access denied · '.$room->title" :organization="$organization">
|
||||
<div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center text-center">
|
||||
<div class="w-full max-w-md rounded-3xl border border-slate-200 bg-white p-8 shadow-sm">
|
||||
<div class="mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-amber-50 text-amber-600">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<x-meet-kiosk-layout :title="'Join · '.$room->title" :organization="$organization" eyebrow="Ladill Meet">
|
||||
<x-meet-kiosk-layout :title="'Join · '.$room->title" :organization="$organization">
|
||||
<div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center text-center">
|
||||
<div class="w-full max-w-lg">
|
||||
<h1 class="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl">{{ $room->title }}</h1>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<x-meet-kiosk-layout :title="'Thank you'" :organization="$organization" eyebrow="Ladill Meet">
|
||||
<x-meet-kiosk-layout :title="'Thank you'" :organization="$organization">
|
||||
<div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center text-center">
|
||||
<div class="w-full max-w-md rounded-3xl border border-slate-200 bg-white p-8 shadow-sm">
|
||||
<div class="mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-emerald-50 text-emerald-600">
|
||||
|
||||
Reference in New Issue
Block a user