mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-08-05 16:33:30 +02:00
filter at chat.html
This commit is contained in:
@@ -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...",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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 @@
|
||||
|
||||
<!-- ⭐ CHAT TITLE WITH ICON, aligned to container ⭐ -->
|
||||
<div class="container px-2">
|
||||
<h2 style="color:white; margin:0 0 10px 0;">
|
||||
<span class="icon">💬</span>
|
||||
<span data-translate="chat_title"></span>
|
||||
</h2>
|
||||
<div class="d-flex align-items-center justify-content-between chat-controls">
|
||||
<h2 style="color:white; margin:0;">
|
||||
<span class="icon">💬</span>
|
||||
<span data-translate="chat_title"></span>
|
||||
</h2>
|
||||
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<label for="channel-filter" class="mb-0" data-translate="channel">Channel</label>
|
||||
<select id="channel-filter" class="form-select form-select-sm chat-filter">
|
||||
<option value="" data-translate="all_channels">All Channels</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" id="chat-log"></div>
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user