zebra-report: stream toggle uses its own top-row grid column

Moves the ◉/○ DJ-stream button out of the bottom mod-actions stack
into the dedicated `strm` grid column on the top row (next to the
mic icon). No more extra sub-row per speaker for the self-monitor or
host-controlled stream toggle — fixes the vertical scroll regression
when many members were in the room.
This commit is contained in:
russell@unturf.com 2026-06-03 19:39:11 -04:00
parent 29beeb71d7
commit d91e908eb3
No known key found for this signature in database

View file

@ -4153,7 +4153,14 @@ function renderRoom(){
* - OTHER rows: host only (room-wide control)
* Speakers/cohosts get self-monitor only. Listeners get NO button
* at all — they're locked into DJ mode unconditionally for the
* glitch-free playback fox: 'epic, never choppy'. */
* glitch-free playback fox: 'epic, never choppy'.
*
* Lives in its own `strm` grid column on the TOP row (alongside the
* mic icon), NOT in the .acts-primary stack — putting it there made
* every speaker row grow a third sub-row of mod-actions even for
* non-mods (just-self-monitor self-rows), which fox flagged as
* causing vertical scroll. Single-char glyph keeps the column 1.4rem. */
let streamEl = null;
if (canSpeak(m.role) && m.pubkey){
let mPubHex = '';
try { mPubHex = hex(unb64(m.pubkey)); } catch(_){}
@ -4161,21 +4168,20 @@ function renderRoom(){
const isSelf = (m.uuid === myUUID);
const canStreamThisRow = isSelf || myRole === 'host';
if (canStreamThisRow){
const sb = document.createElement('button'); sb.className = 'small';
const on = streamMode.has(mPubHex);
sb.textContent = on ? '◉ stream' : '○ stream';
streamEl = document.createElement('button');
streamEl.className = 'stream-toggle' + (on ? ' on' : '');
streamEl.textContent = on ? '◉' : '○';
if (isSelf){
sb.title = on
? 'monitoring your own DJ stream — click to stop (feedback risk on open speakers!)'
streamEl.title = on
? 'monitoring your DJ stream — click to stop (feedback risk on open speakers!)'
: 'preview what listeners hear of YOUR mic (~2s delay) — headphones recommended';
} else {
sb.title = on
? 'streaming — click to switch back to live (low-latency WebRTC)'
: 'switch to HTTP Ogg/Opus stream (~2s delay, glitch-free for DJ sets)';
streamEl.title = on
? 'streaming — click to switch back to live WebRTC'
: 'switch this speaker to HTTP Ogg/Opus stream (~2s delay, glitch-free)';
}
if (on) sb.classList.add('invert');
sb.onclick = () => toggleStreamFor(m.uuid, mPubHex);
actsPrimary.appendChild(sb);
streamEl.onclick = () => toggleStreamFor(m.uuid, mPubHex);
}
}
}
@ -4221,7 +4227,13 @@ function renderRoom(){
acts.appendChild(actsPrimary);
acts.appendChild(actsRemoval);
row.appendChild(badge); row.appendChild(handle); row.appendChild(pub);
row.appendChild(micEl); row.appendChild(meter); row.appendChild(acts);
row.appendChild(micEl);
/* stream toggle (when rendered) goes between mic and meter so it
* lands in the `strm` grid column on the top row. If absent the
* column collapses to its 1.4rem track width (small whitespace
* gap, no row-height change). */
if (streamEl) row.appendChild(streamEl);
row.appendChild(meter); row.appendChild(acts);
wrap.appendChild(row);
}
/* keep listener UI in sync */
@ -4697,8 +4709,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> &nbsp;·&nbsp; built <span class="stamp-date">2026-06-03</span><br>
md5 <span class="stamp-md5">36b2a99bd1e9a1a82eda9aed928ce9a7</span><br>
sha256 <span class="stamp-sha">de1bca01eb57cba4947e55e1fcb439d62ab2f3953ea01d35decc6fc9e604bebd</span><br>
md5 <span class="stamp-md5">a9cbd8ef7da5690b94b8b76a9e69fd92</span><br>
sha256 <span class="stamp-sha">b47ce1db998fae78a00c5f01ecb32f68a853a989babd8831290041776b854a40</span><br>
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
</footer>