From dd867c9fac5c6e7b262eab29649faa36a5f71d99 Mon Sep 17 00:00:00 2001 From: MarekWo Date: Sun, 21 Dec 2025 20:50:08 +0100 Subject: [PATCH] Fix: Change message length counter from characters to UTF-8 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated the message length validation to count actual UTF-8 bytes instead of Unicode characters. This ensures accurate enforcement of the 200-byte LoRa limit, preventing message truncation. Changes: - Frontend: Use TextEncoder to count UTF-8 bytes in real-time - Backend: Validate byte length using text.encode('utf-8') - HTML: Increased maxlength to 500 to allow more ASCII while JS enforces 200 bytes Example: "zażółć gęślą jaźń 😀😁" - Before: ~22 chars ❌ - After: ~35 bytes ✅ (Polish chars = 2 bytes, emoji = 4 bytes each) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- app/routes/api.py | 6 ++++-- app/static/js/app.js | 15 +++++++++------ app/templates/index.html | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/routes/api.py b/app/routes/api.py index 42cbdc9..92110f9 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -96,10 +96,12 @@ def send_message(): }), 400 # MeshCore message length limit (~180-200 bytes for LoRa) - if len(text) > 200: + # Count UTF-8 bytes, not Unicode characters + byte_length = len(text.encode('utf-8')) + if byte_length > 200: return jsonify({ 'success': False, - 'error': f'Message too long ({len(text)} chars). Maximum 200 characters allowed due to LoRa constraints.' + 'error': f'Message too long ({byte_length} bytes). Maximum 200 bytes allowed due to LoRa constraints.' }), 400 reply_to = data.get('reply_to') diff --git a/app/static/js/app.js b/app/static/js/app.js index 208d327..a696ac3 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -398,21 +398,24 @@ function formatTime(timestamp) { } /** - * Update character counter + * Update character counter (counts UTF-8 bytes, not characters) */ function updateCharCounter() { const input = document.getElementById('messageInput'); const counter = document.getElementById('charCounter'); - const length = input.value.length; - const maxLength = 200; - counter.textContent = `${length} / ${maxLength}`; + // Count UTF-8 bytes, not Unicode characters + const encoder = new TextEncoder(); + const byteLength = encoder.encode(input.value).length; + const maxBytes = 200; + + counter.textContent = `${byteLength} / ${maxBytes}`; // Visual warning when approaching limit - if (length >= maxLength * 0.9) { + if (byteLength >= maxBytes * 0.9) { counter.classList.remove('text-muted', 'text-warning'); counter.classList.add('text-danger', 'fw-bold'); - } else if (length >= maxLength * 0.75) { + } else if (byteLength >= maxBytes * 0.75) { counter.classList.remove('text-muted', 'text-danger'); counter.classList.add('text-warning', 'fw-bold'); } else { diff --git a/app/templates/index.html b/app/templates/index.html index 6ef7a52..158fd44 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -31,7 +31,7 @@ class="form-control" placeholder="Type a message..." rows="2" - maxlength="200" + maxlength="500" required >