mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-03-30 13:35:42 +00:00
fix: 4 bugs - spark bars inline style, My Nodes filter field names, duplicate pin button, map dark mode
1. Spark bars: inline style override on td (max-width:none, min-width:80px) 2. My Nodes filter: pubkey→pubKey, to/from→srcPubKey/destPubKey/srcHash/destHash 3. Pin button: guard against duplicates in init, remove in destroy 4. Map page: CartoDB dark/light tiles with MutationObserver theme swap
This commit is contained in:
@@ -36,8 +36,7 @@
|
||||
"SJC": "San Jose, US",
|
||||
"SFO": "San Francisco, US",
|
||||
"OAK": "Oakland, US",
|
||||
"MRY": "Monterey, US",
|
||||
"LAR": "Los Angeles, US"
|
||||
"MRY": "Monterey, US"
|
||||
},
|
||||
"cacheTTL": {
|
||||
"stats": 10,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<meta name="twitter:title" content="MeshCore Analyzer">
|
||||
<meta name="twitter:description" content="Real-time MeshCore LoRa mesh network analyzer — live packet visualization, node tracking, channel decryption, and route analysis.">
|
||||
<meta name="twitter:image" content="https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/public/og-image.png">
|
||||
<link rel="stylesheet" href="style.css?v=1773998059">
|
||||
<link rel="stylesheet" href="style.css?v=1773998477">
|
||||
<link rel="stylesheet" href="home.css">
|
||||
<link rel="stylesheet" href="live.css?v=1773966856">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
@@ -81,14 +81,14 @@
|
||||
<script src="vendor/qrcode.js"></script>
|
||||
<script src="app.js?v=1773993532"></script>
|
||||
<script src="home.js?v=1773977027"></script>
|
||||
<script src="packets.js?v=1773993532"></script>
|
||||
<script src="map.js?v=1773977027" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="packets.js?v=1773998477"></script>
|
||||
<script src="map.js?v=1773998477" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="channels.js?v=1773977027" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="nodes.js?v=1773977027" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="traces.js?v=1773972187" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="analytics.js?v=1773996158" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1773964458" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observers.js?v=1773998059" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1773998477" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observers.js?v=1773998477" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observer-detail.js?v=1773993532" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="node-analytics.js?v=1773996158" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="perf.js?v=1773985649" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
|
||||
@@ -908,8 +908,8 @@
|
||||
const topNav = document.querySelector('.top-nav');
|
||||
if (topNav) { topNav.style.position = 'fixed'; topNav.style.width = '100%'; topNav.style.zIndex = '1100'; }
|
||||
_navCleanup = { timeout: null, fn: null, pinned: false };
|
||||
// Add pin button to nav
|
||||
if (topNav) {
|
||||
// Add pin button to nav (guard against duplicate)
|
||||
if (topNav && !document.getElementById('navPinBtn')) {
|
||||
const pinBtn = document.createElement('button');
|
||||
pinBtn.id = 'navPinBtn';
|
||||
pinBtn.className = 'nav-pin-btn';
|
||||
@@ -1466,6 +1466,8 @@
|
||||
if (appEl) appEl.style.height = '';
|
||||
const topNav = document.querySelector('.top-nav');
|
||||
if (topNav) { topNav.classList.remove('nav-autohide'); topNav.style.position = ''; topNav.style.width = ''; topNav.style.zIndex = ''; }
|
||||
const existingPin = document.getElementById('navPinBtn');
|
||||
if (existingPin) existingPin.remove();
|
||||
if (_navCleanup) {
|
||||
clearTimeout(_navCleanup.timeout);
|
||||
const livePage = document.querySelector('.live-page');
|
||||
|
||||
@@ -105,10 +105,21 @@
|
||||
try { const v = JSON.parse(savedView); initCenter = [v.lat, v.lng]; initZoom = v.zoom; } catch {}
|
||||
}
|
||||
map = L.map('leaflet-map', { zoomControl: true }).setView(initCenter, initZoom);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap',
|
||||
|
||||
const DARK_TILES = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
|
||||
const LIGHT_TILES = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png';
|
||||
const isDark = document.documentElement.getAttribute('data-theme') === 'dark' ||
|
||||
(document.documentElement.getAttribute('data-theme') !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
const tileLayer = L.tileLayer(isDark ? DARK_TILES : LIGHT_TILES, {
|
||||
attribution: '© OpenStreetMap © CartoDB',
|
||||
maxZoom: 19,
|
||||
}).addTo(map);
|
||||
const _mapThemeObs = new MutationObserver(function () {
|
||||
const dark = document.documentElement.getAttribute('data-theme') === 'dark' ||
|
||||
(document.documentElement.getAttribute('data-theme') !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
tileLayer.setUrl(dark ? DARK_TILES : LIGHT_TILES);
|
||||
});
|
||||
_mapThemeObs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
|
||||
|
||||
// Save position on move
|
||||
map.on('moveend', () => {
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
<td>${o.iata ? `<span class="badge-region">${o.iata}</span>` : '—'}</td>
|
||||
<td>${timeAgo(o.last_seen)}</td>
|
||||
<td>${(o.packet_count || 0).toLocaleString()}</td>
|
||||
<td class="col-spark">${sparkBar(o.packetsLastHour || 0, maxPktsHr)}</td>
|
||||
<td class="col-spark" style="max-width:none;overflow:visible;min-width:80px">${sparkBar(o.packetsLastHour || 0, maxPktsHr)}</td>
|
||||
<td>${uptimeStr(o.first_seen)}</td>
|
||||
</tr>`;
|
||||
}).join('')}</tbody>
|
||||
|
||||
@@ -598,10 +598,11 @@
|
||||
try {
|
||||
const d = JSON.parse(p.decoded_json || '{}');
|
||||
const pathHops = JSON.parse(p.path_json || '[]');
|
||||
// Check if any node key in decoded data or path matches
|
||||
return (d.pubkey && allKeys.has(d.pubkey)) ||
|
||||
(d.to && allKeys.has(d.to)) ||
|
||||
(d.from && allKeys.has(d.from)) ||
|
||||
return (d.pubKey && allKeys.has(d.pubKey)) ||
|
||||
(d.srcPubKey && allKeys.has(d.srcPubKey)) ||
|
||||
(d.destPubKey && allKeys.has(d.destPubKey)) ||
|
||||
(d.srcHash && allKeys.has(d.srcHash)) ||
|
||||
(d.destHash && allKeys.has(d.destHash)) ||
|
||||
pathHops.some(h => allKeys.has(h));
|
||||
} catch { return false; }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user