Realign the width and lane-move commands — three fresh settlements
DESIGN edits landing from the parallel session, honored: - Caret chords yield to any focused text control (04 ▸ Grammar): Move Left/Right ⌘←/⌘→ and the width pair ⌥⌘←/⌥⌘→ now disable while the board popover is open — its fields are the one non-inline text surface a board window has today; the search field and card-window fields extend the rule with their own cards. - The width pair batches over a multi-lane selection (03 ▸ Lane, the styling precedent): each selected lane steps one unit through one bracket (stepLaneWidths); floor members hold on a decrease; the context-menu stepper stays single-lane by nature. - A width write landing on 1 removes the width key (03 ▸ Lane, the remove-at-default family), every mechanism alike — writeLaneWidths is the one commit point; a hand-written width: 1 is preserved by the unchanged guard until the app itself next edits width. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -678,19 +678,54 @@ public final class BoardStore {
|
||||
/// second thing to do about it. The lane stays at its old width, which is the truth — nothing was
|
||||
/// written.
|
||||
public func setLaneWidth(_ id: ItemID, units: Int) {
|
||||
let clamped = max(1, units)
|
||||
guard let lane = snapshot.lanes.first(where: { $0.id == id }),
|
||||
LaneLayoutMath.displayUnits(of: lane) != clamped
|
||||
else { return }
|
||||
writeLaneWidths([(id, max(1, units))])
|
||||
}
|
||||
|
||||
/// Steps every lane in `ids` one unit — the Increase/Decrease Lane Width menu items' batch
|
||||
/// (03-board-ui.md § Lane, settled: "they batch over a multi-lane selection — each selected
|
||||
/// lane steps one unit, one gesture, one commit"; the context-menu stepper stays single-lane
|
||||
/// by nature and keeps calling `setLaneWidth`).
|
||||
///
|
||||
/// Lanes already at the one-unit floor simply hold there on a decrease — the batch is not
|
||||
/// refused because one member has nowhere to go, matching the style batch's silent-skip shape.
|
||||
public func stepLaneWidths(_ ids: Set<ItemID>, by delta: Int) {
|
||||
let changes: [(ItemID, Int)] = snapshot.lanes
|
||||
.filter { ids.contains($0.id) && !$0.isDeleted }
|
||||
.map { ($0.id, max(1, LaneLayoutMath.displayUnits(of: $0) + delta)) }
|
||||
writeLaneWidths(changes)
|
||||
}
|
||||
|
||||
/// The one commit point every width mechanism shares — the edge drag, the context-menu stepper,
|
||||
/// and the menu items' batch. One `performWrite` bracket whatever the count: one gesture, one
|
||||
/// app-mediated reload, one commit on git boards (the style batch's rule).
|
||||
///
|
||||
/// **A width landing on 1 removes the `width` key** (03-board-ui.md § Lane, settled — the
|
||||
/// remove-at-default family beside the empty rename's `title` and the None well's
|
||||
/// `background`): a default lane's frontmatter stays clean whichever mechanism wrote it. A
|
||||
/// hand-written `width: 1` is legal and preserved until the app itself next edits width — the
|
||||
/// unchanged-units guard below skips it, so only a real change reaches the remove.
|
||||
private func writeLaneWidths(_ changes: [(id: ItemID, units: Int)]) {
|
||||
let writes: [(folder: URL, units: Int)] = changes.compactMap { change in
|
||||
guard let lane = snapshot.lanes.first(where: { $0.id == change.id }),
|
||||
LaneLayoutMath.displayUnits(of: lane) != change.units
|
||||
else { return nil }
|
||||
return (rootURL.appendingPathComponent(change.id.rawValue), change.units)
|
||||
}
|
||||
guard !writes.isEmpty else { return }
|
||||
|
||||
let folder = rootURL.appendingPathComponent(id.rawValue)
|
||||
// The closure's signature is spelled out because of `try?`: with the error discarded at the
|
||||
// call site Swift stops inferring the typed `throws(BoardWriteError)` and widens it to `any
|
||||
// Error`, which `performWrite` will not take. Same wart as the value-returning call sites
|
||||
// `performWrite`'s doc comment records, arriving from the other direction.
|
||||
try? performWrite { () throws(BoardWriteError) -> Void in
|
||||
try BoardWriter.updateIndex(inItemFolder: folder, operation: .resize(title: nil)) { document in
|
||||
document.set(FrontmatterKeys.width, to: .int(clamped))
|
||||
for write in writes {
|
||||
try BoardWriter.updateIndex(inItemFolder: write.folder, operation: .resize(title: nil)) { document in
|
||||
if write.units == 1 {
|
||||
document.remove(FrontmatterKeys.width)
|
||||
} else {
|
||||
document.set(FrontmatterKeys.width, to: .int(write.units))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user