diff --git a/docs/architecture.md b/docs/architecture.md index bce1868..5b5a2e2 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -113,6 +113,8 @@ The `/path-analyzer` panel (standalone iframe page, `path-analyzer.js`) is a rea - **All filtering/stats/map/routes logic is client-side** over the bulk payload (hundreds of KB for 7 days — fine on a LAN): filters operate on per-hop tokens split with each echo's own `hash_size` (mixed 1/2/3-byte networks are real), so SQL-side token filtering was rejected. Every view always reflects the active filters for free - **Four views** share the one payload: Messages (hop-by-hop echo detail), Repeaters (per-hash relay/SNR stats), Routes (consecutive hop-segment n-grams — user-selectable length 2–4, counted anywhere in a path), and Map (Leaflet path drawing). The repeater filter accepts a `>`-chained sequence (each element a hash prefix or contact name) matched as consecutive hops; Routes rows write such a sequence into that filter on click - **Deep link** — `GET /path-analyzer?hash=&path=` opens straight on the Map view with that message selected and that exact echo drawn. Used by the chat path popup (`app.js` → `openPathInAnalyzer` stashes `{hash, path}` in `window.paDeepLink`; the modal's `show.bs.modal` handler builds the iframe URL). On load the analyzer resolves the message by `packet_hash`, widening the time range once to 7 days if it isn't in the current window, and matches the echo by raw path hex (fallback: shortest routed echo) +- **Map layers** — three `L.layerGroup`s added in draw order (base repeater markers → alternative echoes → selected path), both extras gated by opt-in checkboxes in a `topright` `L.Control` (the shared filter bar is wrong for view-specific state). Alternative echoes are coloured by their index in `echoView`, so a hue survives changing which echo is primary; segments are deduplicated against a `Set` of endpoint-pair keys that the primary path fills first, so alternatives render only where they diverge instead of underneath the primary line. Toggling calls `paRenderMapView(false)` — a full re-render (the sidebar swatches must follow) with `fitBounds` suppressed, so overlay changes never discard the user's viewport +- **Filter persistence** — toolbar controls plus the Routes segment length are mirrored into `localStorage` under `mc-webui-pa-filters` (browser-local working set, deliberately not device state in SQLite). Only user-driven handlers write, via `paApplyAndSaveFilters()`, so programmatic changes — notably the deep link forcing 7 days — never overwrite the stored set; restore is skipped entirely when `paDeepLink` is present, and stored `