Track visitor activity presence

This commit is contained in:
rajchales-monito
2026-07-24 12:19:41 +02:00
parent 5adb220b6e
commit f052bca3ad
4 changed files with 113 additions and 15 deletions
+12 -5
View File
@@ -321,7 +321,7 @@ function renderConversations() {
<span class="visitor-name-wrap">
<span class="unread-dot" aria-label="${item.hasUnread ? "Neprecteno" : "Precteno"}"></span>
<strong>${escapeHtml(conversationVisitorName(item))}</strong>
${item.visitorOnline ? `<span class="online-dot" aria-label="Online" title="Online"></span>` : ""}
${presenceDot(item.visitorPresence)}
</span>
${item.imageCount ? `<span class="photo-count">foto ${item.imageCount}</span>` : ""}
</span>
@@ -344,10 +344,11 @@ function renderConversations() {
function syncConversationVisitors() {
if (!state.visitorsLoaded) return;
const onlineIds = new Set(state.visitors.map((visitor) => visitor.id));
const visitorsById = new Map(state.visitors.map((visitor) => [visitor.id, visitor]));
state.conversations = state.conversations.map((item) => ({
...item,
visitorOnline: onlineIds.has(item.visitorToken)
visitorOnline: visitorsById.has(item.visitorToken),
visitorPresence: visitorsById.get(item.visitorToken)?.presence || "offline"
}));
}
@@ -360,7 +361,7 @@ function renderVisitors() {
const botCount = state.visitors.filter((visitor) => visitor.isBot).length;
$("#hideBotsToggle").classList.toggle("active", state.hideBots);
$("#hideBotsToggle").textContent = state.hideBots ? "Skryt boty" : "Boty videt";
$("#visitorCount").textContent = `${visitors.length} online${state.hideBots && botCount ? ` · ${botCount} bot` : ""}`;
$("#visitorCount").textContent = `${visitors.length} na webu${state.hideBots && botCount ? ` · ${botCount} bot` : ""}`;
$("#visitorList").innerHTML = visitors.length ? visitors.map((visitor) => `
<article class="visitor-card ${visitor.lastConversationId ? "clickable" : ""} ${visitor.lastConversationId === state.activeId ? "active" : ""} ${visitor.isBot ? "bot" : ""}" data-visitor-conversation="${escapeHtml(visitor.lastConversationId || "")}">
<div class="visitor-card-head">
@@ -369,7 +370,7 @@ function renderVisitors() {
<strong>${escapeHtml(visitor.label || "Navstevnik")}</strong>
<small>${escapeHtml(visitor.isBot ? `bot: ${visitor.botReason || "crawler"}` : browserLabel(visitor.device))}</small>
</div>
<span class="online-dot" title="Online"></span>
${presenceDot(visitor.presence)}
</div>
<div class="visitor-compact-meta">
<span>${visitor.countryFlag || escapeHtml(visitor.countryCode || "?")}</span>
@@ -383,6 +384,12 @@ function renderVisitors() {
`).join("") : `<p class="empty-list">Zatim nikdo online.</p>`;
}
function presenceDot(presence) {
const value = ["active", "idle", "offline"].includes(presence) ? presence : "offline";
const label = value === "active" ? "Aktivni" : value === "idle" ? "Neaktivni" : "Offline";
return `<span class="presence-dot ${value}" aria-label="${label}" title="${label}"></span>`;
}
function pageTitle(visitor) {
const history = Array.isArray(visitor.browsingHistory) ? visitor.browsingHistory : [];
const current = history.find((item) => item.url === visitor.currentUrl) || history[history.length - 1];