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 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-01-26 20:46:03 +01:00
parent 2ef9e94ab8
commit 38f51b909a
6 changed files with 57 additions and 9 deletions
+1 -1
View File
@@ -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"
+13
View File
@@ -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;
+17 -1
View File
@@ -702,6 +702,11 @@ function createMessageElement(msg) {
<div class="message-footer own">
<span class="message-time">${time}</span>
</div>
<div class="message-actions justify-content-end">
<button class="btn btn-outline-secondary btn-msg-action" onclick='resendMessage(${JSON.stringify(msg.content)})' title="Resend">
<i class="bi bi-arrow-repeat"></i>
</button>
</div>
</div>
`;
} 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}`;
+24 -5
View File
@@ -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 = `<div class="dm-meta">${parts.join(' | ')}</div>`;
}
}
// Resend button for own messages
const resendBtn = msg.is_own ? `
<div class="dm-actions">
<button class="btn btn-outline-secondary btn-sm dm-action-btn" onclick='resendMessage(${JSON.stringify(msg.content)})' title="Resend">
<i class="bi bi-arrow-repeat"></i>
</button>
</div>
` : '';
div.innerHTML = `
<div class="d-flex justify-content-between align-items-center" style="font-size: 0.7rem;">
<span class="text-muted">${formatTime(msg.timestamp)}</span>
@@ -433,6 +439,7 @@ function displayMessages(messages) {
</div>
<div>${processMessageContent(msg.content)}</div>
${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
*/
+1 -1
View File
@@ -113,7 +113,7 @@
<div id="dmEmojiPickerPopup" class="emoji-picker-popup hidden"></div>
</div>
<div class="d-flex justify-content-end">
<small class="text-muted"><span id="dmCharCounter">0</span> / 140</small>
<small class="text-muted"><span id="dmCharCounter">0</span> / 150</small>
</div>
</form>
</div>
+1 -1
View File
@@ -116,7 +116,7 @@
</div>
</div>
<div class="d-flex justify-content-end">
<small id="charCounter" class="text-muted">0 / 140</small>
<small id="charCounter" class="text-muted">0 / 135</small>
</div>
</form>
</div>