From d8211ab7c5855377d8760e12107f3dbea00c36a7 Mon Sep 17 00:00:00 2001 From: Endri Bezati Date: Fri, 6 Nov 2026 10:10:44 +0100 Subject: [PATCH] fix: what the review of the drag routes and the trace turned up A dropped node's edges: once the server's route reaches the ports it is drawn at once, inside the drag's 650ms settling window too; before, the live router kept drawing its own route until the window closed and the edge jumped onto the server's. The reveal fallback grows with the number of hidden edges (25ms each, 6s at most), since libavoid's time does. A node with no edges is walked once per drag, not once per pointer move. The selection trace reads a wire by where its two nodes stand rather than by their ports, so two nodes overlapping across the page (one under the other, or moved by hand) do not turn it round. A slid route must leave its port on a stub of 8px or more; a node moved up to its own bend had kept a 1px stub, a vertical exit to the eye. The unpadded node boxes come from the padded obstacles instead of a second walk of the model. libavoid's unkink works on the end it is given, source first and target last as libavoid lists them, instead of guessing the end by x-distance, which picked the wrong one on a U-shaped route. Claude-Session: https://claude.ai/code/session_01EToj6RJRMSSHQiqGNMU9wv --- CHANGELOG.md | 20 ++++++++++++------- .../src/elk-live-drag-router.ts | 15 +++++++++++--- .../diagram-client/src/selection-trace.ts | 7 +++++++ packages/diagram-client/src/views.ts | 8 ++++++-- .../test/edges-hidden-while-dragged.test.ts | 13 ++++++++++++ .../test/selection-trace.test.ts | 9 +++++++++ .../reroute-edges-avoid-overlaps-handler.ts | 13 ++++++++---- .../src/routing/libavoid-router.ts | 8 ++++---- .../reroute-keeps-the-layouts-trunk.test.ts | 15 ++++++++++++++ 9 files changed, 88 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c118833..cc1a29a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,11 @@ platform API version. piece of a cut edge drawn. The walk reads the diagram left to right: a wire drawn back to the left, a handshake's `ready` or a loop's feedback, is walked against its arrow, so a netlist's ready wires do not make a cycle of - every two neighbours and the trace follows the data as far as it goes. On a - cycle that remains, the trace is cut to the node's direct neighbours, since - reachability would light the whole diagram. A selected + every two neighbours and the trace follows the data as far as it goes. A + wire is read by where its two nodes stand, not their ports, so two nodes + that overlap across the page do not turn it. On a cycle that remains, the + trace is cut to the node's direct neighbours, since reachability would + light the whole diagram. A selected edge draws all its pieces and its two ends; a selected container, what feeds it and what it feeds, leaving its members as they are. Drawn as GLSP feedback, so it survives a relayout or an edit. @@ -43,8 +45,12 @@ platform API version. node held still mid-drag keeps its edges hidden: a drag with no move for 5s is taken as one that never finishes. A bounds pass mid-drag, which draws the server's model in the hidden layer with the node still at its old - place, no longer draws the edges again for the rest of the drag. If no - route arrives within 1.5s of the drop the edges are drawn as they were. + place, no longer draws the edges again for the rest of the drag. A route + that reaches the ports is drawn the moment it arrives, inside the drag's + settling window too, instead of a client route that is swapped out + later. If no route arrives the edges are drawn as they were: after 1.5s, + plus 25ms an edge hidden and 6s at most, since a dense node's routes take + the router longer. - The server logs one `[dialogram perf] reroute` line per reroute it persists: edges kept, edges routed, the router and the time taken. @@ -85,8 +91,8 @@ platform API version. move). Now an edge keeps its route and only its ends follow the ports, at any distance, not just under 5px as before; the router runs only for an edge whose kept route would not do: a straight edge with no bend to - carry, a stub that would turn back through its node, a segment that - would run through a node. An edge is rerouted for a node that moved onto + carry, a stub that would turn back through its node or shrink under 8px, + a segment that would run through a node. An edge is rerouted for a node that moved onto it only when the node covers it, not when it came within the router's padding, and only the node that moved counts, not the one at the far end of its edges. diff --git a/packages/diagram-client/src/elk-live-drag-router.ts b/packages/diagram-client/src/elk-live-drag-router.ts index 37cf005..ab13db5 100644 --- a/packages/diagram-client/src/elk-live-drag-router.ts +++ b/packages/diagram-client/src/elk-live-drag-router.ts @@ -147,7 +147,7 @@ function anchorOfPort(port: any): { x: number; y: number } | undefined { } /** Whether the edge's stored route starts and ends where its ports are now. */ -function routeReachesPorts(root: Readonly, edge: Readonly): boolean { +export function routeReachesPorts(root: Readonly, edge: Readonly): boolean { const route = (edge as any).routingPoints as Array<{ x: number; y: number }> | undefined; if (!Array.isArray(route) || route.length < 2) { return false; @@ -165,6 +165,9 @@ function routeReachesPorts(root: Readonly, edge: Readonly