Fix UI bug with chat.html

This commit is contained in:
Pablo Revilla
2025-05-23 10:31:42 -07:00
parent dadcad3af3
commit 5f8c78cf98
+93 -101
View File
@@ -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 %}