From d16976e5d1adc6d7420519d94df1eb829aab3331 Mon Sep 17 00:00:00 2001 From: pablorevilla-meshtastic Date: Fri, 3 Apr 2026 11:55:50 -0700 Subject: [PATCH] filter at chat.html --- meshview/lang/en.json | 4 ++- meshview/lang/es.json | 4 ++- meshview/templates/chat.html | 66 +++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/meshview/lang/en.json b/meshview/lang/en.json index ccfb0c9..1b2691a 100644 --- a/meshview/lang/en.json +++ b/meshview/lang/en.json @@ -51,7 +51,9 @@ "chat": { "chat_title": "Chats:", "replying_to": "Replying to:", - "view_packet_details": "View packet details" + "view_packet_details": "View packet details", + "channel": "Channel", + "all_channels": "All Channels" }, "nodelist": { "search_placeholder": "Search by name or ID...", diff --git a/meshview/lang/es.json b/meshview/lang/es.json index dfe32d4..e3d6eb3 100644 --- a/meshview/lang/es.json +++ b/meshview/lang/es.json @@ -52,7 +52,9 @@ "chat": { "chat_title": "Conversaciones:", "replying_to": "Respondiendo a:", - "view_packet_details": "Ver detalles del paquete" + "view_packet_details": "Ver detalles del paquete", + "channel": "Canal", + "all_channels": "Todos los canales" }, "nodelist": { diff --git a/meshview/templates/chat.html b/meshview/templates/chat.html index bd719fb..d724afe 100644 --- a/meshview/templates/chat.html +++ b/meshview/templates/chat.html @@ -46,6 +46,13 @@ padding-left: 10px; } .replying-to .reply-preview { color: #aaa; } +.chat-controls { + gap: 12px; + margin-bottom: 10px; +} +.chat-filter { + min-width: 220px; +} {% endblock %} {% block body %} @@ -53,10 +60,19 @@
-

- 💬 - -

+
+

+ 💬 + +

+ +
+ + +
+
@@ -68,6 +84,7 @@ document.addEventListener("DOMContentLoaded", async () => { if (!chatContainer) return console.error("#chat-log not found"); let lastTime = null; + let selectedChannel = ""; const renderedPacketIds = new Set(); const packetMap = new Map(); let chatLang = {}; @@ -99,6 +116,26 @@ document.addEventListener("DOMContentLoaded", async () => { } } + async function loadChannels() { + try { + const res = await fetch("/api/channels"); + if (!res.ok) return; + + const data = await res.json(); + const select = document.getElementById("channel-filter"); + const channels = data.channels || []; + + for (const channel of channels) { + const option = document.createElement("option"); + option.value = channel; + option.textContent = channel; + select.appendChild(option); + } + } catch (err) { + console.error("Failed loading channels:", err); + } + } + /* ========================================================== SAFE HTML ========================================================== */ @@ -191,6 +228,18 @@ document.addEventListener("DOMContentLoaded", async () => { if (highlight) setTimeout(() => div.classList.remove("flash"), 2500); } + function matchesSelectedChannel(packet) { + if (!selectedChannel) return true; + return (packet.channel || "").toLowerCase() === selectedChannel.toLowerCase(); + } + + function resetChat() { + lastTime = null; + renderedPacketIds.clear(); + packetMap.clear(); + chatContainer.innerHTML = ""; + } + function renderPacketsEnsureDescending(packets, highlight=false) { if (!Array.isArray(packets) || packets.length===0) return; const sortedDesc = packets.slice().sort((a,b)=>{ @@ -199,6 +248,7 @@ document.addEventListener("DOMContentLoaded", async () => { return bTime - aTime; }); for (let i=sortedDesc.length-1; i>=0; i--) { + if (!matchesSelectedChannel(sortedDesc[i])) continue; renderPacket(sortedDesc[i], highlight); } } @@ -235,6 +285,14 @@ document.addEventListener("DOMContentLoaded", async () => { INIT ========================================================== */ await loadChatLang(); // load translations FIRST + await loadChannels(); + + document.getElementById("channel-filter").addEventListener("change", async (e) => { + selectedChannel = e.target.value; + resetChat(); + await fetchInitial(); + }); + await fetchInitial(); // then fetch initial packets setInterval(fetchUpdates, 5000);