mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-03-30 17:05:58 +00:00
fix: rewrite favorites filter — correct packet matching + feed list filtering
This commit is contained in:
@@ -89,7 +89,7 @@
|
||||
<script src="nodes.js?v=1774290000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="traces.js?v=1774290000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="analytics.js?v=1774290000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1774260000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1774350000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observers.js?v=1774290000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observer-detail.js?v=1774028201" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="node-analytics.js?v=1774042199" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
|
||||
119
public/live.js
119
public/live.js
@@ -1192,28 +1192,72 @@
|
||||
if (heatLayer) { map.removeLayer(heatLayer); heatLayer = null; }
|
||||
}
|
||||
|
||||
function getLiveFavorites() {
|
||||
try { return new Set(JSON.parse(localStorage.getItem('meshcore-favorites') || '[]')); } catch { return new Set(); }
|
||||
function getFavoritePubkeys() {
|
||||
let favs = [];
|
||||
try { favs = favs.concat(JSON.parse(localStorage.getItem('meshcore-favorites') || '[]')); } catch {}
|
||||
try { favs = favs.concat(JSON.parse(localStorage.getItem('meshcore-my-nodes') || '[]').map(n => n.pubkey)); } catch {}
|
||||
return favs.filter(Boolean);
|
||||
}
|
||||
function getLiveMyNodes() {
|
||||
try { return new Set(JSON.parse(localStorage.getItem('meshcore-my-nodes') || '[]')); } catch { return new Set(); }
|
||||
}
|
||||
function isNodeFavorited(pubkey) {
|
||||
const favs = getLiveFavorites();
|
||||
const mine = getLiveMyNodes();
|
||||
return favs.has(pubkey) || mine.has(pubkey);
|
||||
}
|
||||
function applyFavoritesFilter() {
|
||||
// All markers always visible — favorites filter only affects packet animations
|
||||
Object.keys(nodeMarkers).forEach(key => {
|
||||
const marker = nodeMarkers[key];
|
||||
if (!marker) return;
|
||||
if (!nodesLayer.hasLayer(marker)) { marker.addTo(nodesLayer); if (marker._glowMarker) marker._glowMarker.addTo(nodesLayer); }
|
||||
});
|
||||
const _el2 = document.getElementById('liveNodeCount');
|
||||
if (_el2) {
|
||||
_el2.textContent = Object.keys(nodeMarkers).length;
|
||||
|
||||
function packetInvolvesFavorite(pkt) {
|
||||
const favs = getFavoritePubkeys();
|
||||
if (favs.length === 0) return false;
|
||||
const decoded = pkt.decoded || {};
|
||||
const payload = decoded.payload || {};
|
||||
const hops = decoded.path?.hops || [];
|
||||
|
||||
// Full pubkeys: sender
|
||||
if (payload.pubKey && favs.some(f => f === payload.pubKey)) return true;
|
||||
|
||||
// Observer: may be name or pubkey
|
||||
const obs = pkt.observer_name || pkt.observer || '';
|
||||
if (obs) {
|
||||
if (favs.some(f => f === obs)) return true;
|
||||
for (const nd of Object.values(nodeData)) {
|
||||
if ((nd.name === obs || nd.public_key === obs) && favs.some(f => f === nd.public_key)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Hops are truncated hex prefixes — match by prefix in either direction
|
||||
for (const hop of hops) {
|
||||
const h = (hop.id || hop.public_key || hop).toString().toLowerCase();
|
||||
if (favs.some(f => f.toLowerCase().startsWith(h) || h.startsWith(f.toLowerCase()))) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isNodeFavorited(pubkey) {
|
||||
return getFavoritePubkeys().some(f => f === pubkey);
|
||||
}
|
||||
|
||||
function rebuildFeedList() {
|
||||
const feed = document.getElementById('liveFeed');
|
||||
if (!feed) return;
|
||||
// Remove all feed items but keep the hide button and resize handle
|
||||
feed.querySelectorAll('.live-feed-item').forEach(el => el.remove());
|
||||
// Re-add from VCR buffer (most recent first, up to 25)
|
||||
const entries = VCR.buffer.slice(-100).reverse();
|
||||
let count = 0;
|
||||
for (const entry of entries) {
|
||||
if (count >= 25) break;
|
||||
const pkt = entry.pkt;
|
||||
if (showOnlyFavorites && !packetInvolvesFavorite(pkt)) continue;
|
||||
const decoded = pkt.decoded || {};
|
||||
const header = decoded.header || {};
|
||||
const payload = decoded.payload || {};
|
||||
const typeName = header.payloadTypeName || 'UNKNOWN';
|
||||
const icon = PAYLOAD_ICONS[typeName] || '📦';
|
||||
const hops = decoded.path?.hops || [];
|
||||
const color = TYPE_COLORS[typeName] || '#6b7280';
|
||||
addFeedItemDOM(icon, typeName, payload, hops, color, pkt, feed);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
function applyFavoritesFilter() {
|
||||
// Node markers always stay visible — only rebuild the feed list
|
||||
rebuildFeedList();
|
||||
}
|
||||
|
||||
function addNodeMarker(n) {
|
||||
@@ -1304,12 +1348,8 @@
|
||||
playSound(typeName);
|
||||
addFeedItem(icon, typeName, payload, hops, color, pkt);
|
||||
|
||||
// Favorites filter: skip animation if no involved nodes are favorited
|
||||
if (showOnlyFavorites) {
|
||||
const involvedKeys = hops.map(h => h.id || h.public_key).filter(Boolean);
|
||||
if (payload.pubKey) involvedKeys.push(payload.pubKey);
|
||||
if (!involvedKeys.some(k => isNodeFavorited(k))) return;
|
||||
}
|
||||
// Favorites filter: skip animation if packet doesn't involve a favorited node
|
||||
if (showOnlyFavorites && !packetInvolvesFavorite(pkt)) return;
|
||||
|
||||
// If ADVERT, ensure node appears on map
|
||||
if (typeName === 'ADVERT' && payload.pubKey) {
|
||||
@@ -1342,6 +1382,9 @@
|
||||
pktTimestamps.push(Date.now());
|
||||
const _el = document.getElementById('livePktCount'); if (_el) _el.textContent = packetCount;
|
||||
|
||||
// Favorites filter: skip if none of the packets involve a favorite
|
||||
if (showOnlyFavorites && !packets.some(p => packetInvolvesFavorite(p))) return;
|
||||
|
||||
playSound(typeName);
|
||||
|
||||
// Ensure ADVERT nodes appear
|
||||
@@ -1697,10 +1740,34 @@
|
||||
if (heatLayer) { map.removeLayer(heatLayer); heatLayer = null; }
|
||||
}
|
||||
|
||||
function addFeedItemDOM(icon, typeName, payload, hops, color, pkt, feed) {
|
||||
const text = payload.text || payload.name || '';
|
||||
const preview = text ? ' ' + (text.length > 35 ? text.slice(0, 35) + '…' : text) : '';
|
||||
const hopStr = hops.length ? `<span class="feed-hops">${hops.length}⇢</span>` : '';
|
||||
const obsBadge = pkt.observation_count > 1 ? `<span class="badge badge-obs" style="font-size:10px;margin-left:4px">👁 ${pkt.observation_count}</span>` : '';
|
||||
const item = document.createElement('div');
|
||||
item.className = 'live-feed-item';
|
||||
item.setAttribute('tabindex', '0');
|
||||
item.setAttribute('role', 'button');
|
||||
item.style.cursor = 'pointer';
|
||||
item.innerHTML = `
|
||||
<span class="feed-icon" style="color:${color}">${icon}</span>
|
||||
<span class="feed-type" style="color:${color}">${typeName}</span>
|
||||
${hopStr}${obsBadge}
|
||||
<span class="feed-text">${escapeHtml(preview)}</span>
|
||||
<span class="feed-time">${new Date(pkt._ts || Date.now()).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit',second:'2-digit'})}</span>
|
||||
`;
|
||||
item.addEventListener('click', () => showFeedCard(item, pkt, color));
|
||||
feed.appendChild(item);
|
||||
}
|
||||
|
||||
function addFeedItem(icon, typeName, payload, hops, color, pkt) {
|
||||
const feed = document.getElementById('liveFeed');
|
||||
if (!feed) return;
|
||||
|
||||
// Favorites filter: skip feed item if packet doesn't involve a favorite
|
||||
if (showOnlyFavorites && !packetInvolvesFavorite(pkt)) return;
|
||||
|
||||
const text = payload.text || payload.name || '';
|
||||
const preview = text ? ' ' + (text.length > 35 ? text.slice(0, 35) + '…' : text) : '';
|
||||
const hopStr = hops.length ? `<span class="feed-hops">${hops.length}⇢</span>` : '';
|
||||
|
||||
Reference in New Issue
Block a user