mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-08-06 08:43:17 +02:00
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:
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user