diff --git a/zebra-report/index.html b/zebra-report/index.html
index 9bd4811..c1ce370 100644
--- a/zebra-report/index.html
+++ b/zebra-report/index.html
@@ -1680,27 +1680,29 @@ async function sendCurrentMsg() {
if (!msg) return;
if (!carrierOn) { logLine('err', 'start carrier first'); return; }
const mode = currentMode();
+ if (mode === 'passphrase' && !groupKey) { logLine('err', 'no room key'); return; }
+ if (mode === 'pubkey' && !Array.from(peers.values()).some(p => p.sharedKey)) {
+ logLine('err', 'no pubkey peers ready'); return;
+ }
/* must match the inbound decoder, which stays at ZEBRA_BAUD_HANDSHAKE for the
* life of the link — data sent at any other baud won't decode on the far side. */
const baud = ZEBRA_BAUD_HANDSHAKE;
+ const handle = handleIn.value.trim() || 'me';
+ /* echo immediately so the sender sees the message without waiting for the
+ * (slow, multi-second at low baud) transmit to finish */
+ logLine('me', `${escapeHtml(handle)}: ${escapeHtml(msg)}`);
+ $('msg-in').value = '';
try {
if (mode === 'passphrase') {
- if (!groupKey) { logLine('err', 'no room key'); return; }
const ct = await aesEncrypt(groupKey, msg);
await txFrame(await buildDataFrame(ct), baud);
} else {
- let sent = 0;
for (const p of peers.values()) {
if (!p.sharedKey) continue;
const ct = await aesEncrypt(p.sharedKey, msg);
await txFrame(await buildDataFrame(ct), baud);
- sent++;
}
- if (sent === 0) { logLine('err', 'no pubkey peers ready'); return; }
}
- const handle = handleIn.value.trim() || 'me';
- logLine('me', `${escapeHtml(handle)}: ${escapeHtml(msg)}`);
- $('msg-in').value = '';
} catch (e) {
logLine('err', 'send failed: ' + e.message);
}