diff --git a/frontend/src/components/PathModal.tsx b/frontend/src/components/PathModal.tsx index 9ff0916..63aa326 100644 --- a/frontend/src/components/PathModal.tsx +++ b/frontend/src/components/PathModal.tsx @@ -51,7 +51,7 @@ export function PathModal({ onAnalyzePacket, }: PathModalProps) { const { distanceUnit } = useDistanceUnit(); - const [expandedMaps, setExpandedMaps] = useState>(new Set()); + const [mapModalIndex, setMapModalIndex] = useState(null); const hasResendActions = isOutgoingChan && messageId !== undefined && onResend; const hasPaths = paths.length > 0; const showAnalyzePacket = hasPaths && packetId != null && onAnalyzePacket; @@ -141,59 +141,65 @@ export function PathModal({ )} - {resolvedPaths.map((pathData, index) => { - const mapExpanded = expandedMaps.has(index); - const toggleMap = () => - setExpandedMaps((prev) => { - const next = new Set(prev); - if (next.has(index)) next.delete(index); - else next.add(index); - return next; - }); - - return ( -
-
- {!hasSinglePath ? ( -
- Path {index + 1}{' '} - - — received {formatTime(pathData.received_at)} - -
- ) : ( -
- )} - -
- {mapExpanded && ( -
- - } - > - - + {resolvedPaths.map((pathData, index) => ( +
+
+ {!hasSinglePath ? ( +
+ Path {index + 1}{' '} + + — received {formatTime(pathData.received_at)} +
+ ) : ( +
)} - +
- ); - })} + +
+ ))} + + {/* Map modal — opens when a "Map route" button is clicked */} + !open && setMapModalIndex(null)}> + + + + {mapModalIndex !== null && !hasSinglePath + ? `Path ${mapModalIndex + 1} Route Map` + : 'Route Map'} + + + Map of known node locations along this message route. + + + {mapModalIndex !== null && ( + + } + > + + + )} + +
)} diff --git a/frontend/src/components/PathRouteMap.tsx b/frontend/src/components/PathRouteMap.tsx index 331665b..98388d7 100644 --- a/frontend/src/components/PathRouteMap.tsx +++ b/frontend/src/components/PathRouteMap.tsx @@ -8,6 +8,7 @@ import type { ResolvedPath, SenderInfo } from '../utils/pathUtils'; interface PathRouteMapProps { resolved: ResolvedPath; senderInfo: SenderInfo; + height?: number; } // Colors for hop markers (indexed by hop number - 1) @@ -82,7 +83,7 @@ function RouteMapBounds({ points }: { points: [number, number][] }) { return null; } -export function PathRouteMap({ resolved, senderInfo }: PathRouteMapProps) { +export function PathRouteMap({ resolved, senderInfo, height = 220 }: PathRouteMapProps) { const points = collectPoints(resolved); const hasAnyGps = points.length > 0; @@ -117,7 +118,7 @@ export function PathRouteMap({ resolved, senderInfo }: PathRouteMapProps) { className="rounded border border-border overflow-hidden" role="img" aria-label="Map showing message route between nodes" - style={{ height: 220 }} + style={{ height }} > + {resolved.sender.prefix} + {' · '} {senderInfo.name || 'Sender'} @@ -154,6 +157,8 @@ export function PathRouteMap({ resolved, senderInfo }: PathRouteMapProps) { icon={makeIcon(String(hopIdx + 1), getHopColor(hopIdx))} > + {hop.prefix} + {' · '} {m.name || m.public_key.slice(0, 12)} @@ -167,6 +172,8 @@ export function PathRouteMap({ resolved, senderInfo }: PathRouteMapProps) { icon={makeIcon('R', RECEIVER_COLOR)} > + {resolved.receiver.prefix} + {' · '} {resolved.receiver.name || 'Receiver'}