From b2e7e9a4bb18d55899943bfcd5b6c93c206b9970 Mon Sep 17 00:00:00 2001 From: Brandyn / Techy Date: Sun, 1 Nov 2026 14:17:30 -0600 Subject: [PATCH] Gateway page: live-page instructions (layout, audio, rename, group names, maximise); portal: maximise button per tab bar Co-Authored-By: Claude Fable 5.1 --- about/index.html | 10 ++++++++++ live/src/App.jsx | 4 +++- live/src/GroupActions.jsx | 16 ++++++++++++++++ live/src/styles.css | 3 +++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 live/src/GroupActions.jsx diff --git a/about/index.html b/about/index.html index 758e764..8f3e10c 100644 --- a/about/index.html +++ b/about/index.html @@ -40,6 +40,16 @@
  • Live: windows open as people go live and close when they stop. Click a window to hear it; the speaker button pins audio on; the slider is per window.
  • +
    Live page: windows, groups, names +
      +
    • Layout. Windows arrange themselves into an even grid whenever someone goes live or stops. Drag a tab to move a window, drag the bars between windows to resize, drop a tab onto another window to stack them as tabs. Arrange (top bar) snaps everything back to the grid.
    • +
    • Audio. Sound follows the window you click. The speaker button pins a window's audio on even when you click elsewhere; Mute all silences everything until you click a window; Follow focus clears pins.
    • +
    • Rename a stream. Double-click its tab, type a name, Enter. Escape cancels; an empty name goes back to user · title. Names stay in your browser and come back the next time that streamer uses the same title.
    • +
    • Name a group. Every tab bar starts with a + name slot. Double-click it, type, Enter. Group names last until you reload the page.
    • +
    • One window big. The ⛶ button at the right of a tab bar maximises that window; click it again to restore. Arranging (a stream joining or leaving, or the Arrange button) restores it too.
    • +
    • Timecode band. Streams with the timecode band on show it cropped off automatically; recordings never contain it.
    • +
    +
    diff --git a/live/src/App.jsx b/live/src/App.jsx index c8e2d9f..f7e8cf2 100644 --- a/live/src/App.jsx +++ b/live/src/App.jsx @@ -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() { )}
    + leftHeaderActionsComponent={GroupLabel} rightHeaderActionsComponent={GroupActions} onReady={onReady} />
    )} diff --git a/live/src/GroupActions.jsx b/live/src/GroupActions.jsx new file mode 100644 index 0000000..ef5704e --- /dev/null +++ b/live/src/GroupActions.jsx @@ -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 ( +
    e.stopPropagation()}> + +
    + ) +} diff --git a/live/src/styles.css b/live/src/styles.css index 6c08870..6887410 100644 --- a/live/src/styles.css +++ b/live/src/styles.css @@ -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); }