diff --git a/resources/css/app.css b/resources/css/app.css index 2833fad..7e63c88 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -59,16 +59,46 @@ html.meet-room-page { } .meet-room-page .meet-stage--plenary .meet-stage-spotlight { - flex: 1 1 auto; - min-height: min(70vh, 100%); + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: column; } .meet-room-page .meet-stage--plenary .meet-stage-spotlight-tile { height: 100%; width: 100%; + max-height: 100%; aspect-ratio: auto; } +.meet-room-page [data-participant-tile] { + display: flex; + flex-direction: column; + min-height: 0; +} + +.meet-room-page [data-tile-body] { + position: relative; + min-height: 0; + flex: 1 1 0; +} + +.meet-room-page [data-tile-footer] { + flex-shrink: 0; +} + +.meet-room-page .meet-audience-strip { + display: flex; + align-items: center; + flex-shrink: 0; + align-self: stretch; + min-height: 2.75rem; + margin-top: 0.25rem; + padding: 0.5rem 0 0.25rem; + border-top: 1px solid rgb(30 41 59 / 0.8); +} + .meet-room-page .meet-stage--panel #meet-stage-spotlight, .meet-room-page .meet-stage--panel #meet-audience-strip { display: none; @@ -87,13 +117,6 @@ html.meet-room-page { min-height: 12rem; } -.meet-room-page .meet-audience-strip { - display: flex; - align-items: center; - min-height: 2.75rem; - padding: 0.25rem 0; -} - .meet-room-page .meet-audience-avatar { position: relative; display: flex; diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index ffe9b27..664b5ad 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -540,6 +540,82 @@ function meetRoom() { }; }, + participantForIdentity(identity) { + return this.sessionParticipants.find((entry) => entry.uuid === identity); + }, + + displayNameForParticipant(participant) { + const person = this.participantForIdentity(participant.identity); + + return person?.display_name || participant.name || participant.identity; + }, + + avatarUrlForParticipant(participant) { + const person = this.participantForIdentity(participant.identity); + + if (person?.avatar_url) { + return person.avatar_url; + } + + if (person && ['host', 'co_host'].includes(person.role) && this.roomHost?.avatar_url) { + return this.roomHost.avatar_url; + } + + if (this.roomHost?.user_ref && person?.user_ref === this.roomHost.user_ref && this.roomHost.avatar_url) { + return this.roomHost.avatar_url; + } + + return null; + }, + + updateTileAvatarCircle(tile, participant) { + const circle = tile.querySelector('[data-tile-avatar-circle]'); + if (!circle) { + return; + } + + const displayName = this.displayNameForParticipant(participant); + const avatarUrl = this.avatarUrlForParticipant(participant); + const isAudioTile = tile.classList.contains('meet-audio-tile'); + const sizeClass = isAudioTile ? 'h-[4.5rem] w-[4.5rem] text-xl' : 'h-20 w-20 text-2xl'; + + circle.replaceChildren(); + + if (avatarUrl) { + circle.className = `flex ${sizeClass} shrink-0 items-center justify-center overflow-hidden rounded-full shadow-lg`; + circle.style.background = ''; + + const img = document.createElement('img'); + img.src = avatarUrl; + img.alt = ''; + img.className = 'h-full w-full object-cover'; + circle.appendChild(img); + + return; + } + + const hue = this.avatarHue(displayName); + circle.className = `flex ${sizeClass} shrink-0 items-center justify-center rounded-full font-semibold text-white shadow-lg`; + circle.style.background = `linear-gradient(135deg, hsl(${hue} 45% 42%), hsl(${(hue + 40) % 360} 50% 28%))`; + circle.textContent = this.participantInitials(displayName); + }, + + refreshParticipantTileAvatars() { + if (!room) { + return; + } + + [room.localParticipant, ...room.remoteParticipants.values()].forEach((participant) => { + const tile = this.findParticipantTile(participant.identity); + if (tile) { + this.updateTileAvatarCircle(tile, participant); + tile.querySelector('[data-tile-name]')?.replaceChildren( + document.createTextNode(this.displayNameForParticipant(participant)), + ); + } + }); + }, + isSpeakerPerson(person) { if (!person) return false; @@ -1020,14 +1096,16 @@ 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 items-center justify-center overflow-hidden rounded-2xl bg-slate-900' - : 'relative aspect-video w-full overflow-hidden rounded-xl bg-slate-900'; + ? 'meet-audio-tile relative flex aspect-square w-full max-w-[9rem] 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 = ` -
-
-
+
+
+
+
+
-
+
-
-
+
+