Back out the render-at-release drop presentation
The settle rule 3f4125e introduced — at release the shadow swaps for the
dropped card(s) drawn in place immediately — is withdrawn on review. The
board returns to the presentation the committed-overlay hold has always
had: the shadows keep standing at their landing slot and the originals
keep their lift until the echo reload lands, whatever the operation was,
and the real faces arrive with the snapshot that carries the write.
Gone with it: the DropLanding/DroppedItem seam and the three landing
accessors, the hold's landing/operation payload and the removesOriginals
and keepsIdentity halves it decided, the pickup-captured titles a
cross-board arrival's face needed, LaneSlot.dropped with DroppedFace and
DroppedCardFace, the strip's dropped-lane run, and the trash column's
settled tombstone rows — the same presentation at the delete gesture's
end, which goes for the same reason while the drop-to-delete write and
its shadow row stay exactly as they were.
Kept: the hold itself, which predates the commit, along with the 1500 ms
failed-write timeout, its injectable duration and its extracted expire,
and the guard that keeps a settled release past retargeting. The tests
pinning those stay; the ones asserting what the landing slot drew are
gone, and the suite now pins the hold's own claim — the arrangement does
not move at the release.
The pause between the release and the echo is therefore an open design
question again, filed on the Redesign board.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -374,11 +374,8 @@ struct BoardView: View {
|
||||
/// off the tidy snapped layout regardless of the live overflow.
|
||||
///
|
||||
/// A lane being **dragged** is simply absent from the strip: it is lifted out of the resting
|
||||
/// layout at pickup and stays out for as long as the drag is in flight, whatever the effective
|
||||
/// operation is (DRAG-REORDER.md § Resting-layout zones), while the system drag session carries
|
||||
/// its replica. At release it comes straight back — at its *landing* slot, drawn by this very
|
||||
/// function, because a settled reorder renders the lanes rather than their outlines
|
||||
/// (`stripSlots`, `runSlots`).
|
||||
/// layout at pickup and stays out until release, whatever the effective operation is
|
||||
/// (DRAG-REORDER.md § Resting-layout zones), while the system drag session carries its replica.
|
||||
@ViewBuilder
|
||||
private func laneSlot(_ lane: Lane, standard: CGFloat) -> some View {
|
||||
let resizing = resize.isResizing(lane.id)
|
||||
@@ -567,39 +564,18 @@ struct BoardView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// What the strip lays out: the resting lanes — the dragged run lifted out while the drag is in
|
||||
/// flight — with the run opened at the proposal.
|
||||
/// What the strip lays out: the resting lanes — the dragged run lifted out, whatever the
|
||||
/// effective operation is — with the shadows opened at the proposal.
|
||||
private var stripSlots: [StripSlot] {
|
||||
let session = appModel.dragSession
|
||||
let hidden = session.hiddenMembers(onBoardRooted: store.rootURL)
|
||||
var slots = liveLanes.filter { !hidden.contains($0.id) }.map(StripSlot.lane)
|
||||
guard let landing = session.laneLanding(onBoardRooted: store.rootURL) else { return slots }
|
||||
slots.insert(contentsOf: runSlots(landing, session: session), at: min(max(0, landing.index), slots.count))
|
||||
guard let index = stripProposal else { return slots }
|
||||
let shadows = session.laneUnits.enumerated().map { StripSlot.shadow(index: $0.offset, units: $0.element) }
|
||||
slots.insert(contentsOf: shadows, at: min(max(0, index), slots.count))
|
||||
return slots
|
||||
}
|
||||
|
||||
/// What the strip's run is made of — shadows while the drag is in flight, and **the dropped lanes
|
||||
/// themselves** the instant a within-board reorder settles (03-board-ui.md § Motion: "rendering
|
||||
/// the arrangement means rendering the card").
|
||||
///
|
||||
/// A within-board reorder is the easy half and the whole of what the strip owes: the lanes are
|
||||
/// still in this snapshot, so the run draws the real `LaneView`s at their landing slot — keyed by
|
||||
/// lane identity, so the echo reload is a content swap inside one element and the lane never
|
||||
/// loses its scroll position or its masonry to the settle.
|
||||
///
|
||||
/// **A cross-board lane arrival keeps its shadow**, deliberately: the destination has no lane to
|
||||
/// draw yet, and a lane's face is a whole column of cards rather than a title and an icon — the
|
||||
/// card level's payload-title fallback (`DroppedCardFace`) has no honest equivalent here. The
|
||||
/// shadow stands until the echo, which for an arriving column is the same round trip a create
|
||||
/// already takes.
|
||||
private func runSlots(_ landing: DropLanding, session: DragSession) -> [StripSlot] {
|
||||
if case let .dropped(drop) = landing.run, drop.isLocal {
|
||||
let lanes = drop.items.compactMap { item in liveLanes.first { $0.id == item.id } }
|
||||
if lanes.count == drop.items.count { return lanes.map(StripSlot.lane) }
|
||||
}
|
||||
return session.laneUnits.enumerated().map { StripSlot.shadow(index: $0.offset, units: $0.element) }
|
||||
}
|
||||
|
||||
// MARK: - Grammar keys
|
||||
|
||||
/// **Return**, narrowly (04-interactions.md ▸ Grammar): a sole selected live card begins an
|
||||
|
||||
Reference in New Issue
Block a user