Fix overlapping speaker cards in audio rooms with a proper grid layout.
Deploy Ladill Meet / deploy (push) Successful in 41s
Deploy Ladill Meet / deploy (push) Successful in 41s
Use display grid for speaker tiles, show only host/co-host/panelist on stage, and re-layout when roles change so cards stay in separate cells. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+46
-3
@@ -336,10 +336,53 @@ html.meet-room-page {
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-grid {
|
||||
place-content: center;
|
||||
place-items: center;
|
||||
grid-template-columns: repeat(auto-fill, minmax(7rem, 9rem));
|
||||
display: grid;
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
align-content: start;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem;
|
||||
grid-template-columns: repeat(2, minmax(0, 9.5rem));
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.meet-room-page .meet-audio-grid {
|
||||
gap: 1.25rem;
|
||||
padding: 1rem;
|
||||
grid-template-columns: repeat(auto-fill, minmax(8.5rem, 10rem));
|
||||
align-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-grid.meet-audio-grid--solo {
|
||||
grid-template-columns: minmax(0, 10rem);
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-grid [data-participant-tile] {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 10rem;
|
||||
justify-self: center;
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-tile {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
box-shadow: 0 4px 14px rgb(0 0 0 / 0.25);
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-tile [data-tile-body] {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-tile [data-tile-footer] {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.meet-room-page .meet-audio-tile [data-tile-avatar-circle] {
|
||||
|
||||
@@ -903,6 +903,13 @@ function meetRoom() {
|
||||
|
||||
getTileContainerForIdentity(identity) {
|
||||
if (!this.usesStageLayout) {
|
||||
if (this.isSpace) {
|
||||
const person = this.sessionParticipants.find((entry) => entry.uuid === identity);
|
||||
if (!person || !['host', 'co_host', 'panelist'].includes(person.role)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return document.getElementById('video-grid');
|
||||
}
|
||||
|
||||
@@ -980,6 +987,30 @@ function meetRoom() {
|
||||
if (!this.usesStageLayout) {
|
||||
document.getElementById('meet-stage-spotlight')?.replaceChildren();
|
||||
document.getElementById('meet-audience-strip')?.replaceChildren();
|
||||
|
||||
if (room) {
|
||||
const all = [room.localParticipant, ...room.remoteParticipants.values()];
|
||||
all.forEach((participant) => {
|
||||
const target = this.getTileContainerForIdentity(participant.identity);
|
||||
if (!target) {
|
||||
this.removeParticipantTile(participant.identity);
|
||||
return;
|
||||
}
|
||||
|
||||
const tile = this.getOrCreateParticipantTile(participant);
|
||||
if (!tile) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tile.parentElement !== target) {
|
||||
target.appendChild(tile);
|
||||
}
|
||||
|
||||
this.updateParticipantTile(participant);
|
||||
});
|
||||
}
|
||||
|
||||
this.updateAudioGridLayout();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1292,7 +1323,7 @@ function meetRoom() {
|
||||
tile = document.createElement('div');
|
||||
tile.dataset.participantTile = identity;
|
||||
tile.className = this.audioOnly
|
||||
? 'meet-audio-tile relative flex aspect-square w-full max-w-[9rem] flex-col overflow-hidden rounded-2xl bg-slate-900'
|
||||
? 'meet-audio-tile relative flex aspect-square w-full flex-col overflow-hidden rounded-2xl bg-slate-900'
|
||||
: 'relative flex aspect-video w-full flex-col overflow-hidden rounded-xl bg-slate-900 min-h-0';
|
||||
tile.innerHTML = `
|
||||
<div data-tile-body class="relative min-h-0 flex-1">
|
||||
@@ -2030,9 +2061,20 @@ function meetRoom() {
|
||||
|
||||
this.applyStageLayout();
|
||||
this.updateGalleryGridLayout();
|
||||
this.updateAudioGridLayout();
|
||||
this.syncActiveSpeakers(room.activeSpeakers ?? []);
|
||||
},
|
||||
|
||||
updateAudioGridLayout() {
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid || !this.audioOnly || this.usesStageLayout) {
|
||||
return;
|
||||
}
|
||||
|
||||
const count = grid.querySelectorAll('[data-participant-tile]').length;
|
||||
grid.classList.toggle('meet-audio-grid--solo', count === 1);
|
||||
},
|
||||
|
||||
updateGalleryGridLayout() {
|
||||
const grid = document.getElementById('video-grid');
|
||||
if (!grid || this.usesStageLayout || this.audioOnly) {
|
||||
@@ -2060,6 +2102,14 @@ function meetRoom() {
|
||||
}
|
||||
});
|
||||
|
||||
if (room) {
|
||||
[room.localParticipant, ...room.remoteParticipants.values()].forEach((participant) => {
|
||||
if (!this.getTileContainerForIdentity(participant.identity)) {
|
||||
this.removeParticipantTile(participant.identity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.applyStageLayout();
|
||||
},
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@
|
||||
<main class="relative flex min-h-0 min-w-0 flex-1 flex-col p-4 pb-2 meet-room-main">
|
||||
<div id="meet-stage" class="flex h-full min-h-0 flex-1 flex-col gap-3" :class="usesStageLayout ? 'meet-stage meet-stage--' + stageLayout : ''">
|
||||
<div id="meet-stage-spotlight" class="meet-stage-spotlight relative min-h-0 flex-1 overflow-hidden rounded-xl bg-slate-900"></div>
|
||||
<div id="video-grid" class="min-h-0 h-full" :class="audioOnly ? 'meet-audio-grid' : (usesStageLayout ? 'meet-stage-panel-grid flex-1' : 'meet-gallery-grid')"></div>
|
||||
<div id="video-grid" class="min-h-0 min-w-0" :class="audioOnly ? 'meet-audio-grid flex-1' : (usesStageLayout ? 'meet-stage-panel-grid flex-1 h-full' : 'meet-gallery-grid h-full')"></div>
|
||||
<div id="meet-audience-strip" class="meet-audience-strip shrink-0"></div>
|
||||
</div>
|
||||
<div id="screen-share" class="absolute inset-4 hidden rounded-xl bg-black"></div>
|
||||
|
||||
Reference in New Issue
Block a user