Proposal changes stop rebuilding the whole board — lanes and card faces gate on their values

LaneView and CardFaceView become Equatable and are instantiated through
.equatable(): the strip's body re-runs on every drop-proposal change, and
without the gates that rebuilt every lane and every card face on every
cursor move of a drag. The == compares value inputs and window-lived
collaborator identities; the closures BoardView rebuilds each pass are
deliberately excluded (BoardDropContext.isEquivalent / MarqueeControl.
isEquivalent / CardFaceRole.isEquivalent own that judgment). Observation
reads inside the bodies still self-invalidate — the lane under the drag
keeps re-running; the other lanes stop.

Ports the pathfinder's CardView/ColumnView gating pattern (drag-perf
suspect #2, card cbb6e476).

Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
2026-08-01 18:28:33 -04:00
parent ef423bb9d2
commit 84f909a720
7 changed files with 497 additions and 2 deletions
+4
View File
@@ -461,6 +461,10 @@ struct BoardView: View {
marquee: marqueeControl,
openCard: openCard
)
// **The value gate** (`LaneView.==`): this body re-runs on every drop-proposal change,
// and without this every lane on the board and every card face in it rebuilds on
// every cursor move of every drag.
.equatable()
.frame(width: resizing ? resize.liveWidth : slotWidth, alignment: .leading)
}
.frame(width: slotWidth, alignment: .topLeading)