Commit Graph
66 Commits
Author SHA1 Message Date
you 820caebb10 Geographic prefix collision disambiguation on live page
When a 1-byte hop prefix matches multiple nodes, pick the one
geographically closest to the center of other known hops in the
path — same logic as /api/resolve-hops but client-side.

Previously just took the first match, which could be a node in
Chicago matching a local Bay Area hop prefix.
2026-03-19 08:02:07 +00:00
you 688bbd29ae Fix heatmap remnants: clear nodesLayer and animLayer on scrub
Previous fix only removed markers tracked in nodeMarkers object,
missing glow circles and other elements added directly to nodesLayer.
2026-03-19 07:57:08 +00:00
you bf2befba25 Scrub replay fetches ALL packets from scrub point to now
No more 5-minute window or 200-packet limit. Fetches up to 10K
packets from the scrub point forward and replays them all.
When replay finishes, resumes live.
2026-03-19 07:56:12 +00:00
you eab7cccb99 Fix: clear nodeActivity+heatmap on scrub; hold playhead after replay ends
- nodeActivity cleared in clearNodeMarkers (removes ghost heatmap)
- When replay finishes, set scrubTs to last packet's timestamp so
  updateTimelinePlayhead holds position instead of snapping right
2026-03-19 07:55:07 +00:00
you 540f06bda5 Clear heatmap layer when clearing nodes for replay 2026-03-19 07:51:42 +00:00
you dedcdaf923 ADVERT packets during replay add nodes to map; simplify unpause
- animatePacket checks for ADVERT type and adds new nodes to map
  with marker if they have location data
- Unpause always resumes to live (removed missed packets prompt)
2026-03-19 07:51:02 +00:00
you 1cd95ce358 Time-travel map: filter nodes by replay timestamp
When scrubbing to a past time, only nodes that had advertised before
that time appear on the map. Nodes that hadn't been seen yet are
hidden.

- Added 'before' param to /api/nodes (filters first_seen <= before)
- loadNodes(beforeTs) accepts optional timestamp filter
- clearNodeMarkers() removes all markers and data
- vcrReplayFromTs clears and reloads nodes for replay time
- vcrResumeLive reloads all nodes (no filter)
2026-03-19 07:50:17 +00:00
you 28466db455 Real 7-segment LCD digits, live clock tick, remove confusing counter
- Canvas-based 7-segment digit renderer with ghost segments (dim
  background showing all segments like a real LCD)
- Clock ticks every second in LIVE mode
- Removed packet counter (1/182) from scrub/replay — only shows
  +N PKTS when paused with missed packets
2026-03-19 07:45:17 +00:00
you 416046a237 Add vintage LCD panel to VCR bar
Dark green-on-black LCD display on right side of VCR bar showing:
- Mode: LIVE / PAUSE / PLAY 2x (green)
- Time: HH:MM:SS with glow (green)
- Packet counter: +N PKTS when paused, N/total during replay (amber)

Styled with dark background, inset shadow, monospace font,
text-shadow glow — vintage VCR aesthetic.
2026-03-19 07:41:57 +00:00
you 12156297f8 Fix scrub replay: add 'until' filter to API, fetch correct time window
ROOT CAUSE: API query used ORDER BY timestamp DESC with no upper
bound — scrubbing to 3h ago fetched the newest 200 packets (from
now), not packets near the scrub target.

Fix:
- Added 'until' query param to /api/packets (both grouped and flat)
- vcrReplayFromTs fetches a 5-minute window around the scrub target
- Server restart required (old process was stale on port 3000)
2026-03-19 07:35:05 +00:00
you 893c74f266 Fix scrub: auto-replay on release, replay from correct timestamp
1. scrubRelease now calls vcrReplayFromTs directly (no pause step)
2. vcrReplayFromTs builds replay buffer from ONLY fetched DB packets,
   not merged with stale WS buffer entries. Starts playhead at 0
   (first fetched packet), not closest-match in mixed buffer.
   Fixes replay starting from session start (00:06) instead of
   scrub target.
2026-03-19 07:25:32 +00:00
you e0d0618759 Fix replay after scrub: fetch from DB and play from scrub point
Scrub + release now pauses (no fetch). Hitting play detects
VCR.scrubTs and fetches packets from DB around that timestamp,
then replays 50 packets from the closest match.
2026-03-19 07:22:51 +00:00
you 83a7e117ba Rewrite scrubber: simple pause on release, no async fetch
Previous approach tried to fetch packets from DB on scrub release,
causing race conditions, rubber-banding, and stale state. Replaced
with dead-simple approach:
- Drag: moves playhead visually + updates clock
- Release: pauses at that position (VCR.scrubTs holds timestamp)
- No async fetch, no replay on release
- updateTimelinePlayhead uses scrubTs to hold position
- Click LIVE to resume
2026-03-19 07:21:00 +00:00
you ab0414fb3b Add VCR digital clock display
Red monospace clock next to LIVE/mode indicator shows current
playhead time. Updates during drag, replay ticks, and on mode
changes. Retro VCR aesthetic with text-shadow glow.
2026-03-19 07:18:14 +00:00
you 8a364bcd42 Fix scrubber snap-back on release: keep dragging flag during fetch
VCR.dragging=false was set on mouseup before the async DB fetch
completed. During the fetch (~100-200ms), updateTimelinePlayhead
saw dragging=false, playhead=-1, fell to else→x=cw (right snap).

Fix: keep dragging=true until fetch resolves and replay starts.
2026-03-19 07:16:10 +00:00
you 18ad20354f Fix VCR scrubber: remove CSS transition causing drag lag
The playhead had 'transition: left 0.3s ease' which made it animate
300ms behind the mouse during drag (felt stuck) and ease to an offset
position on release (felt like rubber-banding). Removed.
2026-03-19 07:14:30 +00:00
you 8c3e5649b8 Fix VCR scrubber: freeze timeline reference during replay
THE root cause: timeline coordinate system uses Date.now() as right
edge, making it a sliding window. Playhead position = (packetTs -
(now - scope)) / scope — but 'now' advances every frame, sliding
all positions left continuously. Any scrub position drifts.

Fix: VCR.frozenNow captures Date.now() when leaving LIVE mode.
All timeline calculations use frozenNow instead of Date.now() during
REPLAY/PAUSED. Timeline stops sliding. Playhead stays put.
Cleared on return to LIVE.
2026-03-19 07:10:40 +00:00
you a64f429349 Fix VCR scrubber rubber-band: hold dragPct during async fetch
Root cause traced: mouseup sets VCR.dragging=false and starts async
fetch. Between fetch start and response (~50-200ms), the 30s interval
fires updateTimelinePlayhead() which found no matching branch for
REPLAY+old playhead, defaulting to x=cw (right edge snap).

Fix: dragPct now takes priority over buffer-based position during
REPLAY/PAUSED modes. Cleared only when fetch completes and replay
actually starts with real buffer data.
2026-03-19 07:07:26 +00:00
you be21b9ea1b Fix Recent Activity on nodes page: remove extra closing div
An extra </div> was closing the node-detail wrapper before the
Recent Activity section rendered, causing content to fall outside
the styled container.
2026-03-19 07:06:01 +00:00
you 27ed57308f Fix VCR scrubber: limit replay to 50 packets from scrub point
Root cause: scrub replay was playing through the ENTIRE buffer
from scrub point to end (thousands of packets), racing the playhead
forward to now. Now caps replay at 50 packets from scrub point,
then pauses. Hit LIVE to resume real-time.
2026-03-19 07:02:42 +00:00
you 4286dffa2f Fix VCR scrubber: pause after replay ends, hold playhead position
Two root causes fixed:
1. startReplay() was calling vcrResumeLive() when buffer exhausted,
   snapping back to LIVE mode. Now pauses instead.
2. updateTimelinePlayhead() recalculated position from timestamps
   relative to now (which shifts). Now holds at dragPct position
   when paused after a scrub.
2026-03-19 07:01:01 +00:00
you c6af2b6ff8 Fix VCR scrubber: pure visual drag + DB fetch on release
Root cause: scrubbing moved playhead to closest buffer entry (recent
WS packets only), then replay tick() recalculated position relative
to current time, snapping it back. Fixed by splitting into two phases:
1. scrubVisual: only moves the DOM playhead element during drag
2. scrubCommit: on release, fetches packets from DB around target
   timestamp, merges into buffer, seeks to closest entry, starts replay.
No more rubber-banding.
2026-03-19 06:58:42 +00:00
you 1ebc05b1c1 Fix VCR scrubber rubber-band, compact replay button, fix channel links
VCR: playhead now stays where you drag it — updateTimelinePlayhead()
skips during drag (VCR.dragging flag). Always update playhead visually
via direct DOM during scrub instead of relying on buffer position calc.

Packets: replay button compact, inline next to View Route button.
Analytics: channel links now navigate to specific channel hash.
2026-03-19 06:49:11 +00:00
you cdd3293957 Fix single packet replay: pause VCR to suppress live packets 2026-03-19 06:40:25 +00:00
you aefdfd500f Move replay button next to View Route in packet detail 2026-03-19 06:38:54 +00:00
you 4faf5463f4 Single packet replay: skip replayRecent when navigating from packets page
Only animates the selected packet instead of loading 8 recent ones.
2026-03-19 06:36:57 +00:00
you 8a13fa8cea 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 a9b0d23199 Fix timeline scrubbing: handle empty buffer, fetch from DB for historical times
Click/drag on timeline now works even when buffer is empty.
Dragging to a point before the buffer's start triggers DB fetch
on release. Removed redundant click handler (drag handles clicks).
Visual playhead feedback during drag even without buffer data.
2026-03-19 06:32:31 +00:00
you 12f67758fe Fix Discord embed: serve OG image from GitHub (bypass geo-block) 2026-03-19 06:25:03 +00:00
you 04703c407e Add drag scrubbing to VCR timeline
Mouse drag and touch drag support on the timeline sparkline.
Scrubs playhead in real-time as you drag. Touch support for mobile.
Grab cursor on hover, grabbing while dragging.
2026-03-19 06:24:11 +00:00
you f93c377483 Fix node claiming: grid not updating after first claim
myNodesGrid element was only rendered when hasNodes was true on
initial page load. Claiming first node called loadMyNodes() but
the grid container didn't exist. Now always render the grid div.
Also dynamically update hero text and hide onboarding prompt.
2026-03-19 06:22:42 +00:00
you ad1a50c1ed Fix timeline scrubber: fetch historical timestamps from DB
Timeline sparkline was only showing packets from the current browser
session (WS buffer). Now fetches timestamps from DB via lightweight
/api/packets/timestamps endpoint, so 6h/12h/24h scopes actually
show historical activity density.
2026-03-19 06:19:35 +00:00
you 75fa8ba82b Fix OG image: crop to 1200x630 banner ratio 2026-03-19 06:03:18 +00:00
you cf91d0a3b0 Add OG meta tags and embed image for Discord/social sharing 2026-03-19 05:56:09 +00:00
you 0a046815ac Fix channel chat not showing new messages
Two bugs:
1. refreshMessages() compared array length to detect changes — at the
   200 message limit, new messages don't change the count. Now compares
   last message timestamp instead.
2. WS handler only triggered on type 'message' — observer-decoded
   GRP_TXT packets broadcast as type 'packet' were missed. Now also
   triggers refresh on packet events with GRP_TXT payload type.
2026-03-19 04:04:50 +00:00
you cf166ba945 Improve Route Patterns layout — less squished
- Detail sidebar starts collapsed, expands on click (420px, max 50vw)
- Route column allows word wrap instead of forced nowrap
- Tables use auto layout for breathing room
- List panel has min-width:0 to prevent flex overflow
- Smoother transitions on sidebar open
2026-03-19 03:00:22 +00:00
you 766d8225bc Add jump nav buttons for chain lengths in Route Patterns 2026-03-19 02:56:40 +00:00
you 14d29d6338 Add toggle to hide prefix collision self-loops in route patterns
Checkbox persists to localStorage. Hides rows with self-loops
(same node repeated consecutively) which are likely 1-byte collisions.
2026-03-19 02:55:58 +00:00
you f6a9187cf0 Make hop names clickable in packet byte breakdown panel
Hop labels in the field table now link to the node detail page.
2026-03-19 02:55:10 +00:00
you 61f18e6d07 Relabel signal quality as 'Observer Receive Signal' with caveat 2026-03-19 02:54:08 +00:00
you 16a73b69e5 Add subpath detail sidebar with minimap and analytics
Click any route in Route Patterns to open detail sidebar showing:
- Minimap with nodes and route line (green=origin, red=dest, amber=hops)
- Signal quality (avg SNR/RSSI)
- Activity by hour (UTC) bar chart
- First/last seen timestamps
- Observers that captured this route
- Full parent paths containing this subpath

Split layout with scrollable list + fixed sidebar, responsive on mobile.
2026-03-19 01:27:03 +00:00
you 6134bc9fc9 Show prefix subpath on separate line below friendly names 2026-03-19 01:22:39 +00:00
you aaf7024e3f Show raw hop prefixes alongside friendly names in route patterns
Each hop now displays as 'NodeName [ab]' with the hex prefix visible.
Makes prefix collisions obvious — e.g. same prefix resolving to same
name confirms it's a collision, different prefixes confirm real route.
2026-03-19 01:21:36 +00:00
you e9ec3bb16a Fix escapeHtml → esc, flag self-loop subpaths with 🔄
Self-loops (likely prefix collisions) shown at 60% opacity with amber
frequency bar and 🔄 icon with tooltip explaining the collision.
2026-03-19 01:20:23 +00:00
you 66859842c8 Add Route Patterns subpage to analytics
New 'Route Patterns' analytics tab showing most common subpaths in the
mesh, broken down by length (pairs, triples, quads, long chains).
Reveals backbone routes, bottlenecks, and preferred relay chains.
Each subpath shows occurrence count, % of all paths, and frequency bar.
2026-03-19 01:18:20 +00:00
you 253fcc533e Geographic hop disambiguation for 1-byte path prefixes
When multiple nodes match a 1-byte hop prefix, use geographic context
(observer's typical nodes + other resolved hops) to pick the closest
match. Shows ⚠ indicator on ambiguous hops with tooltip listing all
candidates. Hover to see which nodes collide on that prefix.
2026-03-18 23:41:26 +00:00
you f506b9caaf Disable caching for JS/CSS/HTML files — force fresh loads 2026-03-18 23:36:02 +00:00
you a9b47a462a Fix channels showing oldest messages instead of latest
Messages were sliced from the start (oldest first). Now returns the
last N messages so the chat view shows the most recent conversation.
2026-03-18 23:30:13 +00:00
you a0de75659c Add 'View packet' link in channel chat messages
Include packetId in channel message API response, render as link
in message metadata row that navigates to #/packets/id/<id>.
2026-03-18 23:19:37 +00:00
you 4ecb50cd8f Filter packet list by hash when navigating to specific packet
When arriving via #/packets/id/<id>, fetch the packet first, set the
hash filter, reload the list, then show the detail sidebar. List now
shows only related packets instead of the full unfiltered view.
2026-03-18 23:13:10 +00:00