16 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-260729-fw7 | 01 | execute | 1 |
|
true |
|
|
User feedback (verbatim): "please make the hop graphic and animation on mesh messages much better balanced, the desktop one is very small and it doesn't work on mobile where it should be vertical, and make it much more archipelago style and branded, make it beautiful."
Purpose: The current hop viz (inline in Mesh.vue lines ~2627-2678, styles in mesh-styles.css lines ~597-637) is a cramped horizontal flex row inside a 420px modal — tiny emoji endpoints, a dashed border with blinking • dots, no mobile handling. It reads as an afterthought, not an Archipelago feature.
Output: New HopVizModal.vue component wired into Mesh.vue, old inline markup and .mesh-hopviz-* CSS removed, rebuilt bundle in web/dist/neode-ui/ verified to contain the new strings.
Current implementation (read all of these first):
neode-ui/src/views/Mesh.vuelines ~1291-1310 (hopVizMsg / hopVizPeer / hopVizHops state), lines ~2340-2350 (transport pill + ⋯ button that sethopVizMsg), lines ~2627-2678 (the inline Teleported modal to replace). AlsotransportLabel()andsignalQualityLabel()helpers used by the modal — grep for them in Mesh.vue.neode-ui/src/views/mesh/mesh-styles.csslines ~160-175 (transport pill accent colors +.mesh-chat-e2e), ~572-584 (.mesh-transport-modal-backdrop,.mesh-transport-modal, title/sub/cancel — SHARED with the send-transport and image-quality modals, do not break them), ~597-637 (.mesh-hopviz-*rules to delete/migrate).neode-ui/src/components/ScreensaverRing.vue— the brand EQ-segment motif: thin 4px rounded bars, white gradient fill, staggeredscaleYpulse keyframes. Echo this visual language for relay-node markers.neode-ui/tailwind.config.js— glass tokens (glass-dark/glass-border/shadow-glass), fonts:Montserrat=font-archipelagoheader font; app is dark-only.- Global focus glow + accent used app-wide: orange
rgba(251,146,60,…)(#fb923c).
Transport accent map (must match pill colors): meshtastic #3eb489, meshcore #fb923c, reticulum #60a5fa, lora #f59e0b, fips #a78bfa, tor #818cf8.
Data realities: For LoRa transports only a hop COUNT is known (peer.hops, 0 or 0xff/null = direct), not per-relay identities — render count relays as anonymous branded markers. Tor = fixed "3 anonymous relays" shape. FIPS = direct P2P. null transport = not recorded. SNR/RSSI are current link readings (keep the existing disclaimer note).
Project rules that apply:
- Modals MUST
<Teleport to="body">with full-screen backdrop (already true — preserve it). - Frontend build can silently no-op: after
npm run build, grep the built bundle inweb/dist/neode-ui/for new strings before claiming done. - Commit the code changes when they work; push via
git push gitea-ai main. Stage explicitly by path (git add <paths>), nevergit add -A— other agents may share the tree. - Do not deploy to any node; this rides the normal dev-pair → OTA pipeline later.
Component contract:
- Props:
msg: MeshMessage(import type from../../types/apior wherever Mesh.vue imports it),peer: MeshPeer | null, plus the two label strings Mesh.vue already computes (transportLabelresult andsignalQualityLabelresult) OR import/reuse those helpers if they are importable; if they are local functions in Mesh.vue, pass computed strings as props — do NOT duplicate logic. - Emits:
close. - Template:
<Teleport to="body">wrapping a full-screen backdrop (reuse.mesh-transport-modal-backdropclass so backdrop behavior stays consistent) with@click.self="emit('close')", containing aglass-cardpanel.
Visual redesign (all styles SCOPED in the component; delete the old .mesh-hopviz-* rules from mesh-styles.css lines ~597-637 — but leave .mesh-transport-modal-backdrop, .mesh-transport-modal, .mesh-transport-title/sub/cancel untouched since the send-transport and image-quality modals still use them; the new panel should use its own width class, wider than 420px — target min(560px, 94vw) on desktop):
-
Header: transport-colored title using the Montserrat brand font (
font-family: 'Montserrat', sans-serifor thefont-archipelagoutility), e.g. "MeshCore route", with the existing You → peer subtitle. Derive an--hop-accentCSS custom property on the panel root frommsg.transportusing the exact pill color map (meshtastic #3eb489, meshcore #fb923c, reticulum #60a5fa, lora #f59e0b, fips #a78bfa, tor #818cf8, fallback rgba(251,146,60) orange). All accents below usevar(--hop-accent). -
Endpoint nodes (You / peer): substantial circular medallions (~64-72px) instead of bare emoji — island glyph 🏝️ centered inside a ring of 12-16 EQ-style segments (thin rounded bars radiating like a compact ScreensaverRing — reuse its technique: absolutely-positioned bars,
transform: rotate(deg) translateY(-radius), staggeredscaleYpulse animation, white-to-transparent gradient tinted with the accent). Soft accent glow behind each medallion (box-shadow: 0 0 24px color-mix(...)or an rgba shadow). Node name below in white 600-weight, ellipsized. -
Path between endpoints: replace the dashed-border + blinking
•row with a proper track: a horizontal line/gradient in the accent color connecting the medallions, with:- Relay markers for each hop (LoRa transports:
Math.min(hops, 6)markers; Tor: exactly 3 with a 🧅/anonymous treatment; FIPS: no relays, a single direct link) rendered as small EQ-segment clusters or glowing accent dots (~10-14px) sitting ON the track, each with its own subtle pulse, staggered. - An animated packet: a small bright dot/comet (accent color, blurred glow trail) traveling from sender to recipient along the track on an infinite ~2s loop. Use a CSS keyframe translating along the track container (like the existing
mesh-hopviz-travelsweep but as a discrete glowing packet, not a background sheen). - Label under/over the track: "direct radio link" / "N hops" / "3 anonymous relays" / "direct peer-to-peer" / "transport wasn't recorded" — preserve the existing per-transport template branches and copy.
- Staggered entrance: sender medallion, then track+relays, then recipient fade/slide in (keep the existing appear pattern, ~0.05/0.35/0.65s delays).
- Relay markers for each hop (LoRa transports:
-
Metadata footer: keep the SNR/RSSI signal row (LoRa only, with the existing "current link readings" disclaimer note) and the E2E / delivered ✓✓ / timestamp row, restyled as small glass chips consistent with
.mesh-transport-metasizing. Keep the Close button (.mesh-transport-cancelclass is fine). -
Reduced motion: wrap ALL looping animations (packet, segment pulses, relay pulses) and entrance animations in the component's own
@media (prefers-reduced-motion: reduce)block that disables them — the old CSS did this; the new component must too.
Wire-up in Mesh.vue: import HopVizModal, replace the inline <Teleport> block at lines ~2627-2678 with <HopVizModal v-if="hopVizMsg" :msg="hopVizMsg" :peer="hopVizPeer" ... @close="hopVizMsg = null" />. Keep hopVizMsg/hopVizPeer/hopVizHops state in Mesh.vue (or move hopVizHops into the component — it only needs peer.hops; prefer moving it in to shrink Mesh.vue). Do not touch the transport pill / ⋯ button triggers.
cd /home/archipelago/Projects/archy/neode-ui && npx vue-tsc --noEmit 2>/dev/null || npm run build
HopVizModal.vue exists with the medallion + track + packet design, Mesh.vue renders it in place of the inline modal, old .mesh-hopviz-* rules removed from mesh-styles.css, other transport modals' shared classes untouched, type-check/build passes.
<success_criteria>
- Desktop hop modal is visually balanced: ~560px panel, prominent glowing endpoint medallions with EQ-segment rings, accent-colored track with animated traveling packet and staggered relay markers.
- Mobile (< 560px) renders the chain vertically top-to-bottom with the packet traveling downward; nothing overflows.
- Per-transport accent colors match the existing transport pill colors exactly.
- Reduced-motion users get a static layout.
- Built bundle verified to contain the new strings; code committed and pushed via gitea-ai. </success_criteria>