feat: Add Quote button to chat messages

Adds a Quote button next to Reply that allows quoting a message.
- Messages ≤20 bytes are quoted in full
- Longer messages are truncated with "..."
- Format: @[Username] "quoted text"
- Uses UTF-8 byte counting for accurate truncation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-01-19 10:15:35 +01:00
parent ffbcd8eead
commit 936698ca46

View File

@@ -683,6 +683,9 @@ function createMessageElement(msg) {
<button class="btn btn-outline-secondary btn-msg-action" onclick="replyTo('${escapeHtml(msg.sender)}')" title="Reply">
<i class="bi bi-reply"></i>
</button>
<button class="btn btn-outline-secondary btn-msg-action" onclick='quoteTo(${JSON.stringify(msg.sender)}, ${JSON.stringify(msg.content)})' title="Quote">
<i class="bi bi-quote"></i>
</button>
${contactsGeoCache[msg.sender] ? `
<button class="btn btn-outline-primary btn-msg-action" onclick="showContactOnMap('${escapeHtml(msg.sender)}', ${contactsGeoCache[msg.sender].lat}, ${contactsGeoCache[msg.sender].lon})" title="Show on map">
<i class="bi bi-geo-alt"></i>
@@ -750,6 +753,40 @@ function replyTo(username) {
input.focus();
}
/**
* Quote a user's message
* @param {string} username - Username to mention
* @param {string} content - Original message content to quote
*/
function quoteTo(username, content) {
const input = document.getElementById('messageInput');
const maxQuoteBytes = 20;
// Calculate UTF-8 byte length
const encoder = new TextEncoder();
const contentBytes = encoder.encode(content);
let quotedText;
if (contentBytes.length <= maxQuoteBytes) {
quotedText = content;
} else {
// Truncate to ~maxQuoteBytes, being careful with multi-byte characters
let truncated = '';
let byteCount = 0;
for (const char of content) {
const charBytes = encoder.encode(char).length;
if (byteCount + charBytes > maxQuoteBytes) break;
truncated += char;
byteCount += charBytes;
}
quotedText = truncated + '...';
}
input.value = `@[${username}] "${quotedText}" `;
updateCharCounter();
input.focus();
}
/**
* Load connection status
*/