Commit Graph

44 Commits

Author SHA1 Message Date
you 3016493089 fix: use last_heard||last_seen for status in nodes table and map
renderRows() in nodes.js and three places in map.js were using only
n.last_seen to compute active/stale status, ignoring the more recent
n.last_heard from in-memory packets. This caused nodes that were recently
heard but had an old DB last_seen to incorrectly show as stale.

Also adds 29 unit tests for the aging system (getNodeStatus,
getStatusInfo, getStatusTooltip, threshold values).
2026-03-23 23:32:01 +00:00
you 1254aa904a M3: Add tooltips to status labels explaining active/stale thresholds
- Add getStatusTooltip() helper with role-aware explanations
- Tooltips on status labels in: node badges, status explanation, detail table
- Tooltips on map legend active/stale counts per role
- Native title attributes (long-press on mobile)
- Bump cache busters
2026-03-23 22:51:11 +00:00
you 418e1a761a Node Aging M2: status filters + localStorage persistence
- Nodes page: Add Active/Stale/All pill button filter
- Nodes page: Expand Last Heard dropdown (Any,1h,2h,6h,12h,24h,48h,3d,7d,14d,30d)
- Map page: Add Active/Stale/All status filter (hides markers, not just fades)
- Map legend: Show active/stale counts per role (e.g. '420 active, 42 stale')
- localStorage persistence for all filters:
  - meshcore-nodes-status-filter
  - meshcore-nodes-last-heard
  - meshcore-map-status-filter
- Bump cache busters
2026-03-23 22:37:52 +00:00
you 5c487204e7 feat: node aging M1 — visual aging on map + list
Two-state node freshness: Active vs Stale

- roles.js: add getNodeStatus(role, lastSeenMs) helper returning 'active'/'stale'
  - Repeaters/Rooms: stale after 72h
  - Companions/Sensors: stale after 24h
  - Backward compat: getHealthThresholds() with degradedMs/silentMs still works

- map.js: stale markers get .marker-stale CSS class (opacity 0.35, grayscale 70%)
  - Applied to both SVG shape markers and hash label markers
  - makeMarkerIcon() and makeRepeaterLabelIcon() accept isStale parameter

- nodes.js: visual aging in table, side pane, and full detail
  - Table: Last Seen column colored green (active) or muted (stale)
  - Side pane: status shows 🟢 Active or  Stale (was 🟢/🟡/🔴)
  - Full detail: Status row with role-appropriate explanation
    - Stale repeaters: 'not heard for Xd — repeaters typically advertise every 12-24h'
    - Stale companions: 'companions only advertise when user initiates'
  - Fixed lastHeard fallback to n.last_seen when health API has no stats

- style.css: .marker-stale, .last-seen-active, .last-seen-stale classes
2026-03-23 19:56:22 +00:00
you ebcdb994ef fix: map markers use role color always, not gray when hash_size is missing
Nodes without hash_size (older instances, no adverts seen) were showing
as gray #888 instead of their role color. Now always uses ROLE_STYLE color.
2026-03-23 19:21:30 +00:00
you 1cb3baf4ab fix: replace all hardcoded colors with CSS variables
- Move --status-green/yellow/red from home.css to style.css :root (light+dark)
- Replace hardcoded status colors in style.css (.tl-snr, .health-dot, .byop-err,
  .badge-hash-*, .fav-star.on, .spark-fill) with CSS variable references
- Replace hardcoded colors in live.css (VCR mode, stat pills, fdc-link, playhead)
- Replace --primary/--bg-secondary/--text-primary/--text-secondary dead vars with
  canonical --accent/--input-bg/--text/--text-muted in style.css, map.js, live.js,
  traces.js, packets.js
- Fix nodes.js legend colors to use ROLE_COLORS globals instead of hardcoded hex
- Replace hardcoded hex in home.js (SNR), perf.js (indicators), map.js (accuracy
  circles) with CSS variable references via getComputedStyle or var()
- Add --detail-bg to customizer (THEME_CSS_MAP, DEFAULTS, ADVANCED_KEYS, labels)
- Move font/mono out of ADVANCED_KEYS into separate Fonts section in customizer
- Remove debug console.log lines from customize.js
- Bump cache busters in index.html
2026-03-23 03:29:38 +00:00
you 0e59712a53 Fix: color changes re-render in-place without page flash
theme-changed now dispatches theme-refresh event instead of
full navigate(). Map re-renders markers, packets re-renders
table rows. No teardown/rebuild, no flash.
2026-03-23 02:06:26 +00:00
you 396d875044 Fix: hoist targetNodeKey to module scope so loadNodes can access it 2026-03-22 23:05:56 +00:00
you 412e584133 Fix: delay popup open after setView, add debug logging
Leaflet needs map to settle after setView before popup can open.
Added 500ms delay + console.warn if target marker not found.
2026-03-22 23:01:18 +00:00
you 50d6a7b068 Fix: map node highlight uses _nodeKey instead of alt text matching
Store public_key on each Leaflet marker as _nodeKey. Match by
exact pubkey instead of fragile alt text substring search.
2026-03-22 22:55:46 +00:00
you f6b3676b65 Map: navigate to node by pubkey from packet detail
📍map link now uses #/map?node=PUBKEY. Map centers on the node
at zoom 14 and opens its popup. No fake markers — uses the
existing node marker already on the map.
2026-03-22 22:51:15 +00:00
you 333d1cf7eb Map: highlight pin when navigated from packet detail
Red circle marker with tooltip at the target coordinates,
fades out after 10 seconds. Makes it obvious where the
packet location is on the map.
2026-03-22 22:47:01 +00:00
you edab731b47 Location link points to our own map, not Google Maps
Packet detail 📍map link now navigates to #/map?lat=X&lon=Y&zoom=12.
Map page reads lat/lon/zoom from URL query params to center on
the linked location.
2026-03-22 22:43:29 +00:00
you 81275acff0 Make map default center/zoom configurable via config.json
Adds mapDefaults config option with center and zoom properties.
New /api/config/map endpoint serves the defaults. live.js and map.js
fetch the config with fallback to hardcoded Bay Area defaults.

Fixes Kpa-clawbot/meshcore-analyzer#115
2026-03-21 05:29:05 +00:00
you cf26079841 feat: label deconfliction on route view markers 2026-03-21 03:33:17 +00:00
you 8e373755c8 feat: improved route view - hide default markers, show origin node 2026-03-21 02:23:53 +00:00
you 4bbc61f0b1 fix: move hash prefix labels toggle to Display section 2026-03-21 01:17:57 +00:00
you 3f61713c0e fix: callout lines more visible — red, thicker, with dot at true position 2026-03-21 00:37:24 +00:00
you d48a7e7ab5 feat: show hash prefix in node popup (bold, with byte size) 2026-03-21 00:36:39 +00:00
you 4e7e0b1cd1 fix: deconfliction applies to ALL markers (not just labels), size-aware bounding boxes 2026-03-21 00:35:37 +00:00
you 82eae3f320 fix: rename toggle to 'Hash prefix labels' 2026-03-21 00:34:06 +00:00
you e38d1fa8f8 fix: map labels show short hash ID (e.g. 5B, BEEF), better deconfliction with spiral offsets 2026-03-21 00:30:25 +00:00
you 8a6923c3b3 Fix hash size labels and add label overlap prevention
- Show '?' with grey background for nodes with null hash_size instead of '1B'
- Add collision detection to offset overlapping repeater labels
- Draw callout lines from offset labels back to true position
- Re-deconflict labels on zoom change
2026-03-21 00:25:55 +00:00
you b114cd6eb0 Add hash size labels for repeater markers on map
- Compute hash_size from ADVERT packets in /api/nodes response
- Show colored rectangle markers with hash size (e.g. '2B') for repeaters
- Add 'Hash size labels' toggle in map controls (default ON, saved to localStorage)
- Non-repeater markers unchanged
2026-03-21 00:19:15 +00:00
you 4f7b02a91c fix: centralize hardcoded values — roles, thresholds, colors, tiles, limits — closes #104
- New public/roles.js shared module: ROLE_COLORS, ROLE_LABELS, ROLE_STYLE,
  ROLE_EMOJI, ROLE_SORT, HEALTH_THRESHOLDS, TILE_DARK/LIGHT, SNR_THRESHOLDS,
  DIST_THRESHOLDS, MAX_HOP_DIST, LIMITS — all configurable via /api/config/roles
- Removed duplicate ROLE_COLORS from map.js, nodes.js, live.js, analytics.js
- Removed duplicate health thresholds from nodes.js, home.js, observer-detail.js
- Deduplicated CartoDB tile URLs (3 copies → 1 in roles.js)
- Removed hardcoded region names from map.js and packets.js
- channels.js uses ROLE_EMOJI/ROLE_LABELS instead of hardcoded emoji chains
- server.js reads healthThresholds from config.json with defaults
- Unknown roles get gray circle fallback instead of crashing
2026-03-20 17:36:41 +00:00
you f0db317051 fix: observer locations case-insensitive match, regions from API not hardcoded
- Observer ID is uppercase, node pubkey is lowercase — added COLLATE NOCASE
- New /api/config/regions endpoint merges config regions + observed IATAs
- map.js and packets.js fetch regions from API instead of hardcoded maps
2026-03-20 16:10:16 +00:00
you 76d63ffe75 feat: observers as map markers (purple stars) with computed locations
- Removed dead 'MQTT Connected Only' checkbox (never worked)
- Added 'observer' role type with purple star marker
- Observer locations computed from average of nodes they've seen
- Observer popup with name, IATA, packets, link to detail page
- Role filter checkbox includes observers with count
2026-03-20 14:56:08 +00:00
you db884f12eb 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
2026-03-20 09:21:17 +00:00
you de658bfb0d perf: configurable cache TTLs via config.json — server + client fetch from /api/config/cache
All cache TTLs now read from config.json cacheTTL section (seconds).
Client fetches config on load via GET /api/config/cache.
config.example.json updated with defaults.
Edit config.json, restart server — no code changes needed to tweak TTLs.
2026-03-20 03:23:58 +00:00
you 720d019a28 perf: align cache TTLs with real data rates — analytics 30min-1hr, nodes 5min, chat 10-15s, stats 10s, server debounce 30s 2026-03-20 03:20:33 +00:00
you e98e04553a feat: add frontend API response caching with TTL, in-flight dedup, and WebSocket invalidation
- Replace api() with caching version supporting TTL and request deduplication
- Add appropriate TTLs to all api() call sites across all frontend JS files:
  - /stats: 5s TTL (was called 962 times in 3 min)
  - /nodes/:pubkey: 15s, /health: 30s, /observers: 30s
  - /channels: 15s, messages: 10s
  - /analytics/*: 60s, /bulk-health: 60s, /network-status: 60s
  - /nodes?*: 10s
- Skip caching for real-time endpoints (/packets, /resolve-hops, /perf)
- Invalidate /stats, /nodes, /channels caches on WebSocket messages
- Deduplicate in-flight requests (same path returns same promise)
- Add cache hit rate to window.apiPerf() console debugging
- Update all cache busters in index.html
2026-03-20 02:03:25 +00:00
you 2cf11bea54 fix: map markers use distinct shapes (diamond/circle/square/triangle) + high-contrast colors for accessibility 2026-03-19 21:49:40 +00:00
you 8e3a860cb7 fix: restore geographic prefix disambiguation for route overlay 2026-03-19 21:41:58 +00:00
you 08d3fd3539 fix: don't fitBounds on initial load — respect Bay Area default center 2026-03-19 21:39:38 +00:00
you 6b8526548a Fix 10 UI bugs in map and nodes pages
- Map controls panel collapsible with toggle button, default collapsed on mobile (closes #16)
- jumpToRegion filters nodes by region observers instead of fitting all (closes #33)
- Detail panel Leaflet maps tracked and removed on re-selection (closes #34)
- Popup HTML uses semantic dl/dt/dd instead of table (closes #46)
- fitBounds now tracks user interaction instead of savedView const (closes #47)
- esc() replaced with safeEsc fallback for implicit global safety (closes #48)
- Checkboxes in map controls have explicit for/id association (closes #49)
- Sort columns have aria-sort attributes (closes #50)
- Filter selects have aria-label attributes (closes #51)
- Back button uses addEventListener instead of inline onclick (closes #52)
- Detail panel map height increased to 280px on desktop (closes #53)
2026-03-19 21:11:46 +00:00
you 72743fd9ee fix: WS debounce helper, clean up remaining window globals (closes #7, #8) 2026-03-19 16:51:34 +00:00
you 6e8c941396 Fix route map: bidirectional prefix match for full pubkeys
Packets page now passes server-disambiguated full pubkeys.
Map needs bidirectional prefix match since DB nodes may have
truncated (8-char) or full (64-char) keys. Removes redundant
client-side geographic disambiguation since packets page already
resolved via /api/resolve-hops.
2026-03-19 08:20:19 +00:00
you 0f06fe881d Clickable route hop markers with popup details + node link
Each hop marker shows: label (Origin/Hop N/Destination), node name,
role, pubkey, coordinates, and 'View Node →' link to node detail.
2026-03-19 08:07:55 +00:00
you 53117c79a7 Geographic prefix disambiguation for route overlay on map page 2026-03-19 08:05:55 +00:00
you a2cb5c4928 Map: default to Bay Area, save/restore user position+zoom
Defaults to [37.6, -122.1] zoom 9. Saves position to localStorage
on moveend. Restores on page load. Skips fitBounds when user has
saved position.
2026-03-19 06:33:50 +00:00
you e66aaebc54 Fix route overlay disappearing on zoom/pan — use separate routeLayer
Route markers and polyline were on markerLayer, which gets cleared
by renderMarkers() on any filter/zoom change. Now uses dedicated
routeLayer that persists independently.
2026-03-18 22:53:02 +00:00
you 429f3542f1 Fix View Route on Map — use sessionStorage instead of URL params
Hop hashes are 1-2 byte truncated values that don't work in URL params.
Now passes raw hops via sessionStorage; map page reads them after nodes
load and resolves via prefix match against full public keys.
2026-03-18 22:43:00 +00:00
you df87f24b7f Clickable hop links + View Route on Map from packet detail
- Hops in packet table are now clickable links to node detail (#/nodes/<hop>)
- Packet detail panel shows 'View route on map' link for packets with hops
- Map page reads ?highlight= query param and draws dashed route polyline
- Route shows numbered markers: green=origin, amber=hops, red=destination
- Map auto-fits to route bounds
2026-03-18 22:36:43 +00:00
you 46349172f6 Initial commit: MeshCore Analyzer
Bay Area MeshCore mesh network analyzer with:
- Live packet visualization with map, contrail animations, shockwave pulses
- VCR controls: pause/play/rewind/scrub timeline with speed control
- Packet browser with grouped view, detail panel, byte breakdown
- Channel message decryption (hashtag-derived PSKs)
- Node directory with health cards, favorites, search
- Analytics dashboard with network insights
- Observer management and BLE/companion bridge support
- Trace route visualization
- Dark theme, responsive design, accessibility
- SQLite storage, WebSocket live feed, REST API
2026-03-18 19:34:05 +00:00