Realign search, clipboard, and lane-hover code with the second batch
Creation now clears the search by mechanism, not gesture: one seam (noteUserCreation) states 04's rule once, called from the placeholder funnel, paste — cards and lanes, after the staleness guard so a stale paste clears nothing — and Finder file-drop creation; the attach path deliberately doesn't clear, and cross-board arrivals and New Lane stay outside the seam (a transfer isn't creation; a lane can't be born invisible). An open inline rename now survives the filter hiding its card: the model already kept the editor, but the field renders in the card's slot, so renderedCards keeps the renaming card's slot exactly as long as the editor is open — the query stands throughout, and commit or Escape lets the predicate apply in the same pass. Verified conformant and newly pinned: query-emptied lanes keep their slot with a 0 badge, pasteboard staleness (takeover before paste and mid-staging both no-op), out-transition reachability and the strip pre-divide hold by construction with comments citing their rulings. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -142,6 +142,24 @@ struct ImportAttachmentsToCardTests {
|
||||
#expect(store.banners.oneShots.isEmpty)
|
||||
}
|
||||
|
||||
/// **Attaching is not creating, so the query stands** (04-interactions.md § Search): the
|
||||
/// carve-out is for an item that would otherwise be born invisible, and a drop on a card mints
|
||||
/// nothing. Its twin — the *create* half clearing — is `creatingFromFilesClearsTheSearch` below.
|
||||
@Test("A drop that only attaches leaves the search exactly where it was")
|
||||
func attachingLeavesTheSearch() throws {
|
||||
let fixture = try makeBoard()
|
||||
defer { fixture.tearDown() }
|
||||
let sources = try DropSources()
|
||||
defer { sources.tearDown() }
|
||||
let store = try BoardStore(rootURL: fixture.root)
|
||||
let shot = try sources.file("shot.png")
|
||||
|
||||
store.searchQuery = "first"
|
||||
store.importAttachments([shot], toCard: card1)
|
||||
|
||||
#expect(store.searchQuery == "first")
|
||||
}
|
||||
|
||||
@Test("A name already taken is renamed Finder-style rather than overwritten")
|
||||
func collisionsRename() throws {
|
||||
let fixture = try makeBoard()
|
||||
@@ -415,6 +433,43 @@ struct CreateCardsFromFilesTests {
|
||||
#expect(store.banners.oneShots.count == 1)
|
||||
#expect(store.banners.oneShots.first?.error.operation == .importAttachment(filename: "gone.png"))
|
||||
}
|
||||
|
||||
/// **The create half is a user-initiated creation, so it clears the query** (04-interactions.md
|
||||
/// § Search, stated by mechanism: "⌘N, Return-creation, the header button, empty-space
|
||||
/// double-click, paste, and Finder file drops alike"). The card is titled `shot`, which the
|
||||
/// standing query would hide — the whole point of the carve-out.
|
||||
@Test("A file drop that creates cards clears the search — the same rule ⌘N obeys")
|
||||
func creatingFromFilesClearsTheSearch() throws {
|
||||
let fixture = try makeBoard()
|
||||
defer { fixture.tearDown() }
|
||||
let sources = try DropSources()
|
||||
defer { sources.tearDown() }
|
||||
let store = try BoardStore(rootURL: fixture.root)
|
||||
let shot = try sources.file("shot.png")
|
||||
|
||||
store.searchQuery = "first"
|
||||
store.createCards(fromFiles: [shot], inLane: lane1, at: 1)
|
||||
|
||||
#expect(store.searchQuery.isEmpty)
|
||||
}
|
||||
|
||||
/// The other side of the same rule: a drop that creates nothing clears nothing. A destination the
|
||||
/// reload took away is not a creation either — nothing was minted, so nothing could be born
|
||||
/// invisible.
|
||||
@Test("A drop with no destination creates nothing and leaves the query standing")
|
||||
func aRefusedCreateLeavesTheSearch() throws {
|
||||
let fixture = try makeBoard()
|
||||
defer { fixture.tearDown() }
|
||||
let sources = try DropSources()
|
||||
defer { sources.tearDown() }
|
||||
let store = try BoardStore(rootURL: fixture.root)
|
||||
let shot = try sources.file("shot.png")
|
||||
|
||||
store.searchQuery = "first"
|
||||
store.createCards(fromFiles: [shot], inLane: ItemID(rawValue: "no-such-lane"), at: 0)
|
||||
|
||||
#expect(store.searchQuery == "first")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Folders, refused
|
||||
|
||||
Reference in New Issue
Block a user