zebra-spaces: stream toggle into its own top-row column (no vertical stretch)
The .stream-toggle CSS class and `strm` grid column were already in place but the JS still appended the button into .acts-primary — which lives in the bottom-row mod-actions stack. That meant every speaker row (including self-monitor on non-mod rows) grew a third sub-row just to host the single ◉ glyph, adding scroll height. Render it as a sibling of micEl in the row so it lands in the `strm` grid column on the TOP row, alongside the mic icon. Single character text (○ / ◉) keeps the column tight, and the .stream-toggle styles already shipped pick it up. For rows that don't qualify (listeners, non-host-viewers on other speakers), the streamEl is null → not appended → strm column collapses to its 1.4rem track width. No row-height penalty. The mod-actions stack stays as-is for actual mod actions (mic-invite, role transitions, kick, ban). Self rows and non-mod self-monitor rows no longer carry an empty mod-actions row at all.
This commit is contained in:
parent
55d5e52797
commit
e1e2c8daa9
1 changed files with 26 additions and 14 deletions
|
|
@ -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> · 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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue