Mesh header mirrors the assistant's three checkboxes; composer controls move below and centre

Fixed pane height inherited from the card, so switching mode no longer resizes it.
This commit is contained in:
Gmer4Lfe
2026-08-17 17:19:29 -04:00
parent 10f2a0a8a4
commit 53d7784d5d
2 changed files with 44 additions and 32 deletions
+43 -31
View File
@@ -236,39 +236,40 @@ function vv_nc_flush_spool(): int {
// conversation surface and a switch, not two boxes competing for the same corner of the screen.
// Emitted once per page: there is one mesh store, so a second instance would be two views of the
// same thing fighting over the same element ids.
function vv_nc_pane_markup(string $prefix, bool $meshDefault = false): void {
function vv_nc_pane_markup(string $prefix, bool $meshDefault = false, string $height = '300px'): void {
static $done = false;
if ($done) return;
$done = true;
?>
<div id="<?= htmlspecialchars($prefix, ENT_QUOTES) ?>-pane-mesh" hidden>
<div id="<?= htmlspecialchars($prefix, ENT_QUOTES) ?>-pane-mesh" hidden
style="--vv-nc-h:<?= htmlspecialchars($height, ENT_QUOTES) ?>;">
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px;">
<select id="vv-nc-ch" class="vv-cf-sel" style="max-width:200px;font-size:11px;padding:3px 8px;"
onchange="vvNcSelect(this.value)"></select>
<!-- Three, in the same three positions the assistant uses: what to render, what to show,
whether to follow. Switching mode should move the eye no further than the labels.
Hostnames is a view preference too, but it is not one of the three and lives in the
Aa drawer rather than making this row a different length from the assistant's. -->
<label class="vv-ai-cb" style="font-size:10px;"
title="Show only what has arrived since you last looked. Unticked shows the whole conversation.">
<input type="checkbox" id="vv-nc-unread" onchange="vvNcRender()"> <span>Unread only</span>
title="Render colours, fonts and sizes as sent. Unticked shows every message as plain text.">
<input type="checkbox" id="vv-nc-fmt-on" checked onchange="vvNcPref('fmtOn');vvNcRender()"> <span>Formatting</span>
</label>
<label class="vv-ai-cb" style="font-size:10px;"
title="Show the machine's hostname instead of its slot — unRAID-Jayred36 rather than HOST2.">
<input type="checkbox" id="vv-nc-names" onchange="vvNcPref('names');vvNcRender()"> <span>Hostnames</span>
title="Show only what has arrived since you last looked. Unticked shows the whole conversation.">
<input type="checkbox" id="vv-nc-unread" onchange="vvNcRender()"> <span>Only New</span>
</label>
<label class="vv-ai-cb" style="font-size:10px;"
title="Follow the newest message. Unticks when you scroll up, re-ticks at the bottom.">
<input type="checkbox" id="vv-nc-follow" checked onchange="vvNcPref('follow')"> <span>Auto Scroll</span>
</label>
<!-- Reader's choice, not the sender's. Someone else's purple italic large is their idea of
emphasis, and on a wall-mounted dashboard it is just noise — this turns every message
back into plain text here without changing what they sent or what anyone else sees. -->
<label class="vv-ai-cb" style="font-size:10px;"
title="Render colours, fonts and bold as sent. Unticked shows every message as plain text.">
<input type="checkbox" id="vv-nc-fmt-on" checked onchange="vvNcPref('fmtOn');vvNcRender()"> <span>Formatting</span>
</label>
<span id="vv-nc-status" style="margin-left:auto;font-size:9px;color:#3a3a3a;"></span>
</div>
<!-- Fixed height, not max-height. The assistant's transcript is a fixed box, so a mesh log
that grew with its content made the card jump size every time the mode was switched or a
message arrived — and on a dashboard a card that resizes shifts everything under it. -->
<div id="vv-nc-log"
style="max-height:260px;overflow-y:auto;padding:6px 2px;font-size:12px;">
style="height:var(--vv-nc-h,300px);overflow-y:auto;padding:6px 2px;font-size:12px;">
<div style="color:#444;font-size:11px;">Loading…</div>
</div>
@@ -278,23 +279,29 @@ function vv_nc_pane_markup(string $prefix, bool $meshDefault = false): void {
style="flex:1 1 260px;min-width:0;background:#0d0d0d;border:1px solid #2a2a2a;
color:#ddd;border-radius:4px;padding:6px 8px;font-family:inherit;
font-size:12px;resize:vertical;"></textarea>
<div style="display:flex;flex-direction:column;gap:5px;">
<div style="display:flex;gap:5px;align-items:center;">
<!-- One button opens the formatting row, so the common case — type and send — is not
fronted by six controls nobody changes most of the time. -->
<button class="vv-pt-action-btn info" id="vv-nc-fmt-btn" style="font-size:10px;"
title="Text formatting" onclick="vvNcToggleFmt()">Aa ▸</button>
<select id="vv-nc-emoji" class="vv-cf-sel" style="font-size:12px;padding:2px 6px;"
title="Insert an emoji" onchange="vvNcEmoji(this)">
<option value="">🙂</option>
<option value="👍">👍</option><option value="👋">👋</option><option value="✅">✅</option>
<option value="⚠️">⚠️</option><option value="🔥">🔥</option><option value="🎉">🎉</option>
<option value="🛠️">🛠️</option><option value="💾">💾</option><option value="🔑">🔑</option>
<option value="😀">😀</option><option value="😅">😅</option><option value="🤔">🤔</option>
</select>
<button class="vv-pt-action-btn run" style="font-size:11px;" onclick="vvNcSend()">Send</button>
</div>
</div>
</div>
<!-- Under the input and centred, the way the assistant's controls sit. Same three-group
layout: equal-flex sides with the actions taking only what they need, so the middle is
centred against the input above rather than against whatever the left group measures. -->
<div class="vv-ai-ctrls" style="margin-top:7px;">
<span class="vv-ai-side"></span>
<span class="vv-ai-actions">
<!-- One button opens the formatting row, so the common case — type and send — is not
fronted by six controls nobody changes most of the time. -->
<button class="vv-pt-action-btn info" id="vv-nc-fmt-btn" style="font-size:10px;"
title="Text formatting and view options" onclick="vvNcToggleFmt()">Aa ▸</button>
<select id="vv-nc-emoji" class="vv-cf-sel" style="font-size:12px;padding:2px 6px;"
title="Insert an emoji" onchange="vvNcEmoji(this)">
<option value="">🙂</option>
<option value="👍">👍</option><option value="👋">👋</option><option value="✅">✅</option>
<option value="⚠️">⚠️</option><option value="🔥">🔥</option><option value="🎉">🎉</option>
<option value="🛠️">🛠️</option><option value="💾">💾</option><option value="🔑">🔑</option>
<option value="😀">😀</option><option value="😅">😅</option><option value="🤔">🤔</option>
</select>
<button class="vv-pt-action-btn run" style="font-size:11px;" onclick="vvNcSend()">Send</button>
</span>
<span class="vv-ai-side vv-ai-tail"></span>
</div>
<!-- Formatting row, hidden until asked for. Choices persist per browser so a house style
@@ -330,6 +337,11 @@ function vv_nc_pane_markup(string $prefix, bool $meshDefault = false): void {
<button class="vv-btn-sm" id="vv-nc-underline" onclick="vvNcTog('underline')"
style="text-decoration:underline;min-width:26px;">U</button>
<span id="vv-nc-preview" style="margin-left:6px;font-size:11px;color:#444;">preview</span>
<span style="width:1px;height:16px;background:#262626;margin:0 4px;"></span>
<label class="vv-ai-cb" style="font-size:10px;"
title="Show the machine's hostname instead of its slot — unRAID-Jayred36 rather than HOST2.">
<input type="checkbox" id="vv-nc-names" onchange="vvNcPref('names');vvNcRender()"> <span>Hostnames</span>
</label>
</div>
<div style="margin-top:5px;font-size:9px;color:#3a3a3a;line-height:1.5;">
Encrypted over Tailscale between mesh nodes only — but stored as plain text on every