From 38f51b909a999ff71d7d648cdf397da39edb0b4a Mon Sep 17 00:00:00 2001 From: MarekWo Date: Mon, 26 Jan 2026 20:46:03 +0100 Subject: [PATCH] feat: Add resend button and adjust message byte limits - Add Resend button under own messages in channel chat and DM (allows easy re-sending of failed messages) - Change channel chat limit from 140 to 135 bytes - Change DM limit from 140 to 150 bytes (experimentally verified Meshcore limits) - Remove misleading Hops info from DM message bubbles - Update README with new byte limits Co-Authored-By: Claude Opus 4.5 --- README.md | 2 +- app/static/css/style.css | 13 +++++++++++++ app/static/js/app.js | 18 +++++++++++++++++- app/static/js/dm.js | 29 ++++++++++++++++++++++++----- app/templates/dm.html | 2 +- app/templates/index.html | 2 +- 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6844349..0015b00 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ For detailed feature documentation, see the [User Guide](docs/user-guide.md). ## Basic Usage 1. **View messages** - Main page shows chat history with auto-refresh every 10 seconds -2. **Send messages** - Type in the text field and press Enter (140 byte limit) +2. **Send messages** - Type in the text field and press Enter (135 bytes for channels, 150 bytes for DM) 3. **Switch channels** - Use the dropdown in navbar 4. **Direct Messages** - Access via menu (☰) → "Direct Messages" 5. **Manage contacts** - Access via menu (☰) → "Contact Management" diff --git a/app/static/css/style.css b/app/static/css/style.css index 8c76215..8053e53 100644 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -526,6 +526,19 @@ main { color: #dc3545; } +/* DM Action Buttons */ +.dm-actions { + display: flex; + justify-content: flex-end; + margin-top: 0.25rem; +} + +.dm-action-btn { + padding: 0.15rem 0.4rem; + font-size: 0.75rem; + line-height: 1; +} + /* DM Conversation List Item */ .dm-conversation-item { padding: 0.75rem; diff --git a/app/static/js/app.js b/app/static/js/app.js index a69e673..827758e 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -702,6 +702,11 @@ function createMessageElement(msg) { +
+ +
`; } else { @@ -834,6 +839,17 @@ function quoteTo(username, content) { input.focus(); } +/** + * Resend a message (paste content back to input) + * @param {string} content - Message content to resend + */ +function resendMessage(content) { + const input = document.getElementById('messageInput'); + input.value = content; + updateCharCounter(); + input.focus(); +} + /** * Load connection status */ @@ -1596,7 +1612,7 @@ function updateCharCounter() { // Count UTF-8 bytes, not Unicode characters const encoder = new TextEncoder(); const byteLength = encoder.encode(input.value).length; - const maxBytes = 140; + const maxBytes = 135; counter.textContent = `${byteLength} / ${maxBytes}`; diff --git a/app/static/js/dm.js b/app/static/js/dm.js index bc8799f..ceade09 100644 --- a/app/static/js/dm.js +++ b/app/static/js/dm.js @@ -418,14 +418,20 @@ function displayMessages(messages) { if (msg.snr !== null && msg.snr !== undefined) { parts.push(`SNR: ${msg.snr.toFixed(1)}`); } - if (msg.path_len !== null && msg.path_len !== undefined) { - parts.push(`Hops: ${msg.path_len}`); - } if (parts.length > 0) { meta = `
${parts.join(' | ')}
`; } } + // Resend button for own messages + const resendBtn = msg.is_own ? ` +
+ +
+ ` : ''; + div.innerHTML = `
${formatTime(msg.timestamp)} @@ -433,6 +439,7 @@ function displayMessages(messages) {
${processMessageContent(msg.content)}
${meta} + ${resendBtn} `; container.appendChild(div); @@ -539,7 +546,7 @@ async function checkForNewMessages() { } /** - * Update character counter (counts UTF-8 bytes, limit is 140) + * Update character counter (counts UTF-8 bytes, limit is 150) */ function updateCharCounter() { const input = document.getElementById('dmMessageInput'); @@ -548,7 +555,7 @@ function updateCharCounter() { const encoder = new TextEncoder(); const byteLength = encoder.encode(input.value).length; - const maxBytes = 140; + const maxBytes = 150; counter.textContent = byteLength; // Visual warning when approaching limit @@ -564,6 +571,18 @@ function updateCharCounter() { } } +/** + * Resend a message (paste content back to input) + * @param {string} content - Message content to resend + */ +function resendMessage(content) { + const input = document.getElementById('dmMessageInput'); + if (!input) return; + input.value = content; + updateCharCounter(); + input.focus(); +} + /** * Setup emoji picker */ diff --git a/app/templates/dm.html b/app/templates/dm.html index 8f5c2f2..83e0fc4 100644 --- a/app/templates/dm.html +++ b/app/templates/dm.html @@ -113,7 +113,7 @@
- 0 / 140 + 0 / 150
diff --git a/app/templates/index.html b/app/templates/index.html index 723407c..40f6e4c 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -116,7 +116,7 @@
- 0 / 140 + 0 / 135