Mesh chat: autoscroll toggle, hostname/slot toggle, and a formatting row behind one button

Style validation moves to one shared function so the sender and receiver cannot drift on what a style is.
This commit is contained in:
Gmer4Lfe
2026-08-17 16:51:17 -04:00
parent ecded4a8a7
commit d88fe381db
4 changed files with 161 additions and 35 deletions
+18 -4
View File
@@ -61,6 +61,23 @@ define('VV_NC_KEEP', 300); // messages retained per channel, per node
function vv_nc_me(): string { return strtolower(vv_detect_host()); }
// One validator, used by both the sender and the receiver.
//
// Both ends must agree on what a style is, and they had two copies of the rules — the sender's
// and the receiver's. Two copies of a whitelist is one that drifts, and the half that drifts is
// the half a partner running newer code writes into. Every value here ends up interpolated into
// a style attribute, so the allowed set is closed rather than sanitised.
function vv_nc_clean_style(array $s): array {
return [
'color' => preg_match('/^#[0-9a-f]{6}$/i', $s['color'] ?? '') ? strtolower($s['color']) : '',
'font' => in_array($s['font'] ?? '', ['mono', 'sans', 'serif'], true) ? $s['font'] : '',
'size' => in_array($s['size'] ?? '', ['sm', 'lg'], true) ? $s['size'] : '',
'bold' => !empty($s['bold']),
'italic' => !empty($s['italic']),
'underline' => !empty($s['underline']),
];
}
// host1/host2/... → the channels this host can see. Global plus one DM per other node.
function vv_nc_channels(): array {
$me = vv_nc_me();
@@ -189,10 +206,7 @@ function vv_nc_send(string $channelId, string $text, array $style = []): ?array
// migration. Everything written today is a message.
'kind' => 'msg',
'text' => mb_substr(trim($text), 0, 4000),
'style' => [
'color' => preg_match('/^#[0-9a-f]{6}$/i', $style['color'] ?? '') ? $style['color'] : '',
'font' => in_array($style['font'] ?? '', ['mono', 'sans', 'serif'], true) ? $style['font'] : '',
],
'style' => vv_nc_clean_style($style),
];
vv_nc_append($channelId, $msg);