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
+2
View File
@@ -336,6 +336,8 @@ struct TrashLaneView: View {
marquee: marquee,
drops: drops
)
// The value gate, `LaneView`'s rule on the trash side (`CardFaceView.==`).
.equatable()
case let .entry(.lane(lane)):
// The opaque unit's row its own view, because "no styling accents" and
// "never expandable" are exactly what a card face is not