Gateway page: live-page instructions (layout, audio, rename, group names, maximise); portal: maximise button per tab bar

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 14:17:30 -06:00
parent d5b2ba502b
commit b2e7e9a4bb
4 changed files with 32 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import { audio } from './useAudio.js'
import GoLive from './GoLive.jsx'
import Tab from './Tab.jsx'
import GroupLabel from './GroupLabel.jsx'
import GroupActions from './GroupActions.jsx'
import { streamLabel } from './names.js'
const components = { player: Player }
@@ -18,6 +19,7 @@ const POLL_MS = 3000
export function arrange(api) {
const panels = [...api.panels].sort((a, b) => ((a.params?.since || '').localeCompare(b.params?.since || '')) || a.id.localeCompare(b.id))
const n = panels.length; if (n < 2) return
if (api.hasMaximizedGroup?.()) api.exitMaximizedGroup?.() // a maximised window would hide the new grid
const cols = Math.ceil(Math.sqrt(n))
for (let i = 1; i < n; i++) {
const r = Math.floor(i / cols), c = i % cols
@@ -92,7 +94,7 @@ export default function App() {
)}
<div className="dock" style={{ display: streams.length ? 'block' : 'none' }}>
<DockviewReact className="dockview-theme-vanguard" components={components} tabComponents={tabComponents}
leftHeaderActionsComponent={GroupLabel} onReady={onReady} />
leftHeaderActionsComponent={GroupLabel} rightHeaderActionsComponent={GroupActions} onReady={onReady} />
</div>
</>)}
</div>

16
live/src/GroupActions.jsx Normal file
View File

@@ -0,0 +1,16 @@
import React, { useEffect, useState } from 'react'
// Right end of every tab bar: maximise / restore this group.
export default function GroupActions({ api, containerApi }) {
const [max, setMax] = useState(() => api.isMaximized())
useEffect(() => {
const d = containerApi.onDidMaximizedGroupChange?.(() => setMax(api.isMaximized()))
return () => d?.dispose?.()
}, [api, containerApi])
const toggle = e => { e.stopPropagation(); if (api.isMaximized()) api.exitMaximized(); else api.maximize(); setMax(api.isMaximized()) }
return (
<div className="groupactions" onPointerDown={e => e.stopPropagation()}>
<button className="gbtn" onClick={toggle} title={max ? 'restore' : 'maximise this window'}>{max ? '🗗' : '⛶'}</button>
</div>
)
}

View File

@@ -71,3 +71,6 @@ html, body, #root { height:100%; margin:0; background:var(--bg); color:var(--fg)
.grouplabel { display:flex; align-items:center; height:100%; padding:0 10px; font-size:12px; white-space:nowrap; border-right:1px solid #2a2a2a; cursor:default; }
.grouplabel .gname { color:var(--acc); font-weight:700; }
.grouplabel .hint { color:#555; }
.groupactions { display:flex; align-items:center; height:100%; padding:0 6px; }
.gbtn { background:transparent; color:var(--mut); border:0; cursor:pointer; font-size:14px; padding:0 6px; line-height:1; }
.gbtn:hover { color:var(--fg); }