A file copied in Finder becomes a card's attachment — ⌘V's reserved clause finally answers
The image branch's precedence ladder always had a second clause: a file URL on the pasteboard suppresses it, "a different gesture with a different answer" that the code deliberately declined rather than guessed at. This fills it in: one or more file URLs paste through the same `importAttachments` a Finder drop takes — one collision ladder, one folder refusal (`FinderDrop.partition`), one set of banners — outranking raw image data riding beside it (a Finder-copied image file carries both; the actual file lands, not a re-encoded copy of its bytes) while still deferring to the app's own clipboard type. Both ⌘V surfaces read the same `ClipboardStore.fileURLPayload`, so the board's fallback and the card window's own branch stay in step by construction rather than by two hand-kept-in-sync checks. Fixed a real leak in the body editor's paste yield along the way: `public.file-url` conforms to `public.url`, which `NSTextView` legitimately reads for a pasted hyperlink, and `NSPasteboard.availableType(from:)` matches by conformance rather than exact type — so a Finder copy carrying a generic URL representation beside its file URL would have been silently swallowed as text and never reached the window's attachment branch at all. The yield now declines outright on any file-URL pasteboard before the generic capability check runs. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -775,7 +775,7 @@ struct PasteBoardBackgroundTests {
|
||||
// MARK: - The body editor's paste yield
|
||||
|
||||
/// The responder behind the editor in these tests — stands where the card window's
|
||||
/// `cardWindowImagePaste` bridge stands in the app, and only counts.
|
||||
/// `cardWindowPaste` bridge stands in the app, and only counts.
|
||||
@MainActor
|
||||
private final class PasteCatcher: NSView {
|
||||
var pastes = 0
|
||||
@@ -820,6 +820,26 @@ struct PasteYieldTests {
|
||||
#expect(catcher.pastes == 1)
|
||||
}
|
||||
|
||||
/// **The file-URL branch's own yield** — a Finder copy reaches the window's attachment branch
|
||||
/// exactly as a screenshot does, `readablePasteboardTypes`'s explicit exclusion of `.fileURL`
|
||||
/// (`CardBodyTextView`'s override) proven rather than assumed: `importsGraphics` being `false` is
|
||||
/// an AppKit default this pins down as a contract.
|
||||
@Test("A file-URL-only pasteboard validates through the editor and forwards to the responder behind")
|
||||
func fileURLOnlyYields() throws {
|
||||
let catcher = PasteCatcher(frame: .zero)
|
||||
let (editor, pasteboard) = makeEditor(behind: catcher)
|
||||
defer { pasteboard.releaseGlobally() }
|
||||
let fileURL = FileManager.default.temporaryDirectory
|
||||
.appendingPathComponent("paste-yield-\(UUID().uuidString).png")
|
||||
try Data([0x01]).write(to: fileURL)
|
||||
defer { try? FileManager.default.removeItem(at: fileURL) }
|
||||
pasteboard.writeObjects([fileURL as NSURL])
|
||||
|
||||
#expect(editor.validateUserInterfaceItem(pasteItem))
|
||||
editor.paste(nil)
|
||||
#expect(catcher.pastes == 1)
|
||||
}
|
||||
|
||||
/// No expectation on `validateUserInterfaceItem` here: a readable pasteboard routes validation
|
||||
/// to `super`, and `NSTextView`'s own answer reads the *machine's* general pasteboard — asserting
|
||||
/// it would tie the test to whatever the host's clipboard happens to hold. The claim under test
|
||||
|
||||
Reference in New Issue
Block a user