diff --git a/app/routes/api.py b/app/routes/api.py index 04253a3..952b0e2 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -72,6 +72,13 @@ def send_message(): 'error': 'Message text cannot be empty' }), 400 + # MeshCore message length limit (~180-200 bytes for LoRa) + if len(text) > 200: + return jsonify({ + 'success': False, + 'error': f'Message too long ({len(text)} chars). Maximum 200 characters allowed due to LoRa constraints.' + }), 400 + reply_to = data.get('reply_to') # Send message via meshcli diff --git a/app/static/js/app.js b/app/static/js/app.js index 3d4cc37..5fee59b 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -45,6 +45,11 @@ function setupEventListeners() { } }); + // Character counter + input.addEventListener('input', function() { + updateCharCounter(); + }); + // Manual refresh button document.getElementById('refreshBtn').addEventListener('click', function() { loadMessages(); @@ -183,6 +188,7 @@ async function sendMessage() { if (data.success) { input.value = ''; + updateCharCounter(); showNotification('Message sent', 'success'); // Reload messages after short delay @@ -205,6 +211,7 @@ async function sendMessage() { function replyTo(username) { const input = document.getElementById('messageInput'); input.value = `@[${username}] `; + updateCharCounter(); input.focus(); } @@ -362,6 +369,30 @@ function formatTime(timestamp) { } } +/** + * Update character counter + */ +function updateCharCounter() { + const input = document.getElementById('messageInput'); + const counter = document.getElementById('charCounter'); + const length = input.value.length; + const maxLength = 200; + + counter.textContent = `${length} / ${maxLength}`; + + // Visual warning when approaching limit + if (length >= maxLength * 0.9) { + counter.classList.remove('text-muted', 'text-warning'); + counter.classList.add('text-danger', 'fw-bold'); + } else if (length >= maxLength * 0.75) { + counter.classList.remove('text-muted', 'text-danger'); + counter.classList.add('text-warning', 'fw-bold'); + } else { + counter.classList.remove('text-warning', 'text-danger', 'fw-bold'); + counter.classList.add('text-muted'); + } +} + /** * Escape HTML to prevent XSS */ diff --git a/app/templates/index.html b/app/templates/index.html index 9e83c67..c8a53bf 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -31,13 +31,17 @@ class="form-control" placeholder="Type a message..." rows="2" + maxlength="200" required > - Press Shift+Enter for new line, Enter to send +