Every board root keys once at its store — the hover path stops walking the filesystem
`DragLocality.isSameBoard` resolved symlinks on both URLs, which stats every path component. It ran five-plus times per `dropUpdated` and again per lane per body evaluation through `renderedCards` → `hiddenMembers` — order of 50–100 stat calls per mouse-move, and worse on iCloud-backed paths. A pickup stall sample had it on ~47 of 943 stacks. `BoardRootKey` mints that canonical spelling once, where the root is, and every locality comparison downstream is an `==` on two strings. The drag carriers hold keys rather than URLs, so re-deriving under the cursor is no longer expressible. `rootURL` keeps the user's spelling — the folder name is the display-name fallback, and canonicalizing there would visibly rename a board opened through a pin. The key follows the folder through `relocate(to:)`: a key frozen at open would collide with a new board opened at the vacated path, and two boards comparing as one is a cross-board drag silently behaving as a move. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -170,7 +170,7 @@ struct BoardView: View {
|
||||
// discards itself the moment a snapshot lands — because holding a moment longer would draw
|
||||
// the arrangement twice.
|
||||
.onChange(of: store.snapshotGeneration) { _, generation in
|
||||
appModel.dragSession.handOff(root: store.rootURL, generation: generation)
|
||||
appModel.dragSession.handOff(root: store.rootKey, generation: generation)
|
||||
}
|
||||
.trashPurgeAlert(store: store, confirmations: confirmations)
|
||||
// The board's own anchor for the Style… popover — the surface a board-targeted session hangs
|
||||
@@ -602,9 +602,9 @@ struct BoardView: View {
|
||||
private var arrivingLaneUnits: Int {
|
||||
let session = appModel.dragSession
|
||||
guard session.isDraggingLanes,
|
||||
session.stripProposal(onBoardRooted: store.rootURL) != nil,
|
||||
session.stripProposal(onBoardRooted: store.rootKey) != nil,
|
||||
let source = session.sourceRoot,
|
||||
!DragLocality.isSameBoard(source, store.rootURL)
|
||||
source != store.rootKey
|
||||
else { return 0 }
|
||||
return session.laneUnits.reduce(0, +)
|
||||
}
|
||||
@@ -612,7 +612,7 @@ struct BoardView: View {
|
||||
/// The strip's current lane-drop proposal — the reflow's narrow animation key, and where the
|
||||
/// shadow run opens.
|
||||
private var stripProposal: Int? {
|
||||
appModel.dragSession.stripProposal(onBoardRooted: store.rootURL)
|
||||
appModel.dragSession.stripProposal(onBoardRooted: store.rootKey)
|
||||
}
|
||||
|
||||
/// One position in the strip: a lane, or one of the drag's N contiguous shadows.
|
||||
@@ -635,7 +635,7 @@ struct BoardView: View {
|
||||
/// the shadows opened at the proposal.
|
||||
private var stripSlots: [StripSlot] {
|
||||
let session = appModel.dragSession
|
||||
let hidden = session.hiddenMembers(onBoardRooted: store.rootURL)
|
||||
let hidden = session.hiddenMembers(onBoardRooted: store.rootKey)
|
||||
var slots = boardLanes.filter { !hidden.contains($0.id) }.map(StripSlot.lane)
|
||||
guard let index = stripProposal else { return slots }
|
||||
let shadows = session.laneUnits.enumerated().map { StripSlot.shadow(index: $0.offset, units: $0.element) }
|
||||
|
||||
Reference in New Issue
Block a user