Reworks the tray window per feedback and fills it in.
- Starts hidden in the tray (no window on launch); the window opens from the
menu. On macOS the app now uses the Accessory activation policy, so it lives
in the menu bar with no Dock icon (via a winit event-loop hook, pinned to
eframe's winit). Fixed, non-resizable 360x600 window; the layout targets it.
- Tidied layout: top bar (title + refresh), a bottom panel with the join form
and the action banner, and a scrolling list of network tiles between them.
Labels and values sit on two-column grids so they align; the join name and
secret inputs are the same fixed width.
- A ⟳ button beside the secret generates a fresh random secret
(NetworkSecret::generate), for creating a network.
- Each network tile shows id, range, this device's address, peers
(connected/known), the active and broadcast switches, a Leave button, and a
collapsing "peers (N)" section with a formatted per-peer table (short key,
address, handshake age, tx/rx packets, rate).
- Traffic: a new sampler turns the agent's cumulative packet counters into a
packets-per-second rate per network and per peer, from the deltas between
snapshots (the snapshot now carries a generation and timestamp so each
refresh is sampled once). The network tile shows the current rate and a small
hand-drawn sparkline of recent rates (no extra dependency).
Note: rates are packets/s — the report has no byte counters yet; bytes would
need an agent change. Builds and is clippy-clean (-D warnings) on macOS; the UI
has not been run in this headless session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>