diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index 04c0ef6..d252ac8 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -52,6 +52,7 @@ function meetRoom() { spotlightSpeakerRef: '', panelSetupOpen: false, savingStageLayout: false, + _stageSnapshot: null, qaItems: [], activePolls: [], breakoutBroadcast: '', @@ -932,8 +933,9 @@ function meetRoom() { } const data = await res.json(); - this.mergeStageConfig(data); + this._stageSnapshot = null; this.panelSetupOpen = false; + this.mergeStageConfig(data); this.applyStageLayout(); } finally { this.savingStageLayout = false; @@ -981,7 +983,7 @@ function meetRoom() { setActivePanel(panelId) { this.activePanelId = panelId; this.stageLayout = 'panel'; - this.applyStageLayout(); + this.panelDiscussions = true; }, togglePanelSpeaker(panel, userRef) { @@ -1891,6 +1893,100 @@ function meetRoom() { return this.isConference ? 'conference' : 'meeting'; }, + stageLayoutLabel() { + return this.stageLayout === 'panel' ? 'Panel discussion' : 'Plenary'; + }, + + conferenceStatusLabel() { + if (this.isGreenRoom) { + if (this.usesStageLayout) { + return `Green room · ${this.stageLayoutLabel()}`; + } + + return 'Green room'; + } + + if (!this.usesStageLayout) { + return 'Conference live'; + } + + return this.stageLayout === 'panel' ? 'Panel discussion live' : 'Plenary live'; + }, + + conferenceStatusClass() { + if (this.isGreenRoom) { + return 'text-violet-400/90'; + } + + if (this.stageLayout === 'panel') { + return 'text-violet-400/90'; + } + + return 'text-sky-400/90'; + }, + + stageLayoutDescription() { + if (this.stageLayout === 'panel') { + const panelName = this.activePanelName(); + if (panelName) { + return `Showing ${panelName} — multiple speakers in a split grid.`; + } + + return 'Multiple speakers shown together in a split-screen grid.'; + } + + return 'One main speaker on stage. Others appear in the strip below.'; + }, + + activePanelName() { + if (!this.activePanelId) { + return ''; + } + + const panel = this.panels.find((entry) => entry.id === this.activePanelId); + + return panel?.name || ''; + }, + + openPanelSetup() { + this._stageSnapshot = { + stageLayout: this.stageLayout, + panels: JSON.parse(JSON.stringify(this.panels)), + activePanelId: this.activePanelId, + panelDiscussions: this.panelDiscussions, + }; + this.panelSetupOpen = true; + }, + + cancelPanelSetup() { + if (this._stageSnapshot) { + this.stageLayout = this._stageSnapshot.stageLayout; + this.panels = JSON.parse(JSON.stringify(this._stageSnapshot.panels)); + this.activePanelId = this._stageSnapshot.activePanelId; + this.panelDiscussions = this._stageSnapshot.panelDiscussions; + this.applyStageLayout(); + } + + this._stageSnapshot = null; + this.panelSetupOpen = false; + }, + + selectStageLayout(layout) { + this.stageLayout = layout; + + if (layout === 'panel') { + this.panelDiscussions = true; + + if (this.panels.length === 0) { + this.addPanel(); + } + + if (!this.activePanelId && this.panels[0]) { + this.activePanelId = this.panels[0].id; + } + } + }, + sessionNounTitle() { return this.isConference ? 'Conference' : 'Meeting'; }, diff --git a/resources/views/meet/room/show.blade.php b/resources/views/meet/room/show.blade.php index b235934..faf79f7 100644 --- a/resources/views/meet/room/show.blade.php +++ b/resources/views/meet/room/show.blade.php @@ -102,8 +102,8 @@

Audio room

@elseif ($isConference ?? false)

+ :class="conferenceStatusClass()" + x-text="conferenceStatusLabel()">

@endif

Green room

Only hosts and speakers are visible. Attendees join after you go live.

+

+ Stage layout: + +

-
-
-
@@ -506,31 +526,41 @@
-
+ @keydown.escape.window="cancelPanelSetup()"> +
-

Stage & panels

-

Switch between plenary and panel layouts. Assign speakers to each panel before going live.

+

Stage layout

+

Choose how speakers appear on stage. Changes apply when you save.

-
-
- -
+

+ Switching to panel discussion changes the live stage to a multi-speaker grid for everyone in the room. +

+