mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-08-08 01:42:44 +02:00
Fix UI bug with chat.html
This commit is contained in:
+93
-101
@@ -2,140 +2,132 @@
|
||||
|
||||
{% block css %}
|
||||
.timestamp {
|
||||
min-width:10em;
|
||||
min-width: 10em;
|
||||
}
|
||||
.chat-packet:nth-of-type(odd){
|
||||
background-color: #3a3a3a; /* Lighter than #2a2a2a */
|
||||
.chat-packet:nth-of-type(odd) {
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
.chat-packet {
|
||||
border-bottom: 1px solid #555;
|
||||
padding: 8px;
|
||||
border-radius: 8px; /* Adjust the value to make the corners more or less rounded */
|
||||
border-radius: 8px;
|
||||
}
|
||||
.chat-packet:nth-of-type(even){
|
||||
background-color: #333333; /* Slightly lighter than the previous #181818 */
|
||||
.chat-packet:nth-of-type(even) {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
0% { background-color: #ffe066; }
|
||||
100% { background-color: inherit; }
|
||||
0% { background-color: #ffe066; }
|
||||
100% { background-color: inherit; }
|
||||
}
|
||||
|
||||
.chat-packet.flash {
|
||||
animation: flash 3.5s ease-out;
|
||||
animation: flash 3.5s ease-out;
|
||||
}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container" id="chat">
|
||||
{% for packet in packets %}
|
||||
<div
|
||||
class="row chat-packet"
|
||||
data-packet-id="{{ packet.id }}"
|
||||
role="article"
|
||||
aria-label="Chat message from {{ packet.from_node.long_name or (packet.from_node_id | node_id_to_hex) }}"
|
||||
>
|
||||
<span class="col-2 timestamp" title="{{ packet.import_time.isoformat() }}">
|
||||
{{ packet.import_time.strftime('%-I:%M:%S %p - %m/%d/%Y') }}
|
||||
</span>
|
||||
<span class="col-2 channel">
|
||||
<a href="/packet/{{ packet.id }}" title="View packet details">✉️</a> {{ packet.from_node.channel }}
|
||||
</span>
|
||||
<span class="col-2 username">
|
||||
<a href="/packet_list/{{ packet.from_node_id }}" title="View all packets from this node">
|
||||
{{ packet.from_node.long_name or (packet.from_node_id | node_id_to_hex) }}
|
||||
</a>
|
||||
</span>
|
||||
<span class="col-5 message">
|
||||
{{ packet.payload }}
|
||||
</span>
|
||||
</div>
|
||||
{% else %}
|
||||
No packets found.
|
||||
{% endfor %}
|
||||
<div id="chat-container">
|
||||
<div class="container" id="chat-log">
|
||||
{% for packet in packets %}
|
||||
<div
|
||||
class="row chat-packet"
|
||||
data-packet-id="{{ packet.id }}"
|
||||
role="article"
|
||||
aria-label="Chat message from {{ packet.from_node.long_name or (packet.from_node_id | node_id_to_hex) }}"
|
||||
>
|
||||
<span class="col-2 timestamp" title="{{ packet.import_time.isoformat() }}">
|
||||
{{ packet.import_time.strftime('%-I:%M:%S %p - %m/%d/%Y') }}
|
||||
</span>
|
||||
<span class="col-2 channel">
|
||||
<a href="/packet/{{ packet.id }}" title="View packet details">✉️</a>
|
||||
{{ packet.from_node.channel }}
|
||||
</span>
|
||||
<span class="col-2 username">
|
||||
<a href="/packet_list/{{ packet.from_node_id }}" title="View all packets from this node">
|
||||
{{ packet.from_node.long_name or (packet.from_node_id | node_id_to_hex) }}
|
||||
</a>
|
||||
</span>
|
||||
<span class="col-5 message">
|
||||
{{ packet.payload }}
|
||||
</span>
|
||||
</div>
|
||||
{% else %}
|
||||
No packets found.
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let lastTime = null;
|
||||
// Initialize lastTime from DOM
|
||||
const firstPacket = document.querySelector(".chat-packet");
|
||||
if (firstPacket) {
|
||||
let lastTime = null;
|
||||
const chatContainer = document.querySelector("#chat-log");
|
||||
|
||||
// Initialize lastTime from DOM
|
||||
const firstPacket = chatContainer.querySelector(".chat-packet");
|
||||
if (firstPacket) {
|
||||
lastTime = firstPacket.querySelector(".timestamp")?.getAttribute("title");
|
||||
console.log("Initialized lastTime from DOM:", lastTime);
|
||||
}
|
||||
// Track rendered packets
|
||||
const renderedPacketIds = new Set();
|
||||
document.querySelectorAll(".chat-packet").forEach(div => {
|
||||
}
|
||||
|
||||
// Track rendered packet IDs
|
||||
const renderedPacketIds = new Set();
|
||||
document.querySelectorAll(".chat-packet").forEach(div => {
|
||||
const id = div.dataset.packetId;
|
||||
if (id) renderedPacketIds.add(id);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
function escapeHtml(text) {
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUpdates() {
|
||||
async function fetchUpdates() {
|
||||
try {
|
||||
const url = new URL("/chat/updates", window.location.origin);
|
||||
if (lastTime) {
|
||||
url.searchParams.set("last_time", lastTime);
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
const chatContainer = document.querySelector(".container");
|
||||
if (!chatContainer) return;
|
||||
|
||||
if (data.packets && data.packets.length > 0) {
|
||||
for (const packet of data.packets) {
|
||||
if (renderedPacketIds.has(packet.id)) continue;
|
||||
renderedPacketIds.add(packet.id);
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "row chat-packet";
|
||||
div.dataset.packetId = packet.id;
|
||||
|
||||
div.innerHTML = `
|
||||
<span class="col-2 timestamp" title="${packet.import_time}">
|
||||
${new Date(packet.import_time).toLocaleString()}
|
||||
</span>
|
||||
<span class="col-2 channel">
|
||||
<a href="/packet/${packet.id}" title="View packet details">✉️</a> ${packet.channel}
|
||||
</span>
|
||||
<span class="col-2 username">
|
||||
<a href="/packet_list/${packet.from_node_id}" title="View all packets from this node">
|
||||
${packet.long_name ? packet.long_name : parseInt(packet.from_node_id).toString(16)}
|
||||
</a>
|
||||
</span>
|
||||
<span class="col-5 message">${escapeHtml(packet.payload)}</span>
|
||||
`;
|
||||
|
||||
chatContainer.prepend(div);
|
||||
|
||||
// Trigger flash animation
|
||||
div.classList.add("flash");
|
||||
|
||||
// Optionally remove the class after animation ends
|
||||
setTimeout(() => div.classList.remove("flash"), 2500);
|
||||
|
||||
const url = new URL("/chat/updates", window.location.origin);
|
||||
if (lastTime) {
|
||||
url.searchParams.set("last_time", lastTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.latest_import_time) {
|
||||
lastTime = data.latest_import_time;
|
||||
}
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.packets && data.packets.length > 0) {
|
||||
for (const packet of data.packets) {
|
||||
if (renderedPacketIds.has(packet.id)) continue;
|
||||
renderedPacketIds.add(packet.id);
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "row chat-packet flash";
|
||||
div.dataset.packetId = packet.id;
|
||||
|
||||
div.innerHTML = `
|
||||
<span class="col-2 timestamp" title="${packet.import_time}">
|
||||
${new Date(packet.import_time).toLocaleString()}
|
||||
</span>
|
||||
<span class="col-2 channel">
|
||||
<a href="/packet/${packet.id}" title="View packet details">✉️</a> ${packet.channel}
|
||||
</span>
|
||||
<span class="col-2 username">
|
||||
<a href="/packet_list/${packet.from_node_id}" title="View all packets from this node">
|
||||
${packet.long_name ? packet.long_name : parseInt(packet.from_node_id).toString(16)}
|
||||
</a>
|
||||
</span>
|
||||
<span class="col-5 message">${escapeHtml(packet.payload)}</span>
|
||||
`;
|
||||
|
||||
chatContainer.prepend(div);
|
||||
setTimeout(() => div.classList.remove("flash"), 2500);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.latest_import_time) {
|
||||
lastTime = data.latest_import_time;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Fetch error:", err);
|
||||
console.error("Fetch error:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(fetchUpdates, 5000); // Poll every 5 seconds
|
||||
setInterval(fetchUpdates, 5000); // Poll every 5 seconds
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user