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:
@@ -215,6 +215,15 @@ public protocol ClipboardPasteboard: AnyObject {
|
||||
/// specific one, added for the image branch (which knows its type only at runtime, off the
|
||||
/// classification above).
|
||||
func data(forType type: String) -> Data?
|
||||
|
||||
/// Every file URL the pasteboard's items carry, in item order — the file-URL branch's own read
|
||||
/// (04-interactions.md ▸ Clipboard, ruled 2026-08-09; `ClipboardStore.pasteFiles`).
|
||||
///
|
||||
/// A method of its own rather than another `data(forType:)` call, because `availableTypes()`'s
|
||||
/// first-item carve-out is wrong here: "is a file being offered at all" only needs the first
|
||||
/// item, but "which files" does not — a Finder copy of several files is several pasteboard
|
||||
/// items, each carrying `public.file-url` on its own, and this reads across all of them.
|
||||
func fileURLs() -> [URL]
|
||||
}
|
||||
|
||||
/// The real pasteboard.
|
||||
@@ -253,6 +262,16 @@ public final class SystemPasteboard: ClipboardPasteboard {
|
||||
pasteboard.data(forType: NSPasteboard.PasteboardType(type))
|
||||
}
|
||||
|
||||
/// `readObjects(forClasses:options:)` rather than a per-item `data(forType:)` walk: it is the
|
||||
/// framework's own multi-item reconstruction of `public.file-url`, `.urlReadingFileURLsOnly`
|
||||
/// keeping a web URL (`public.url`, which does not conform) from ever surfacing here.
|
||||
public func fileURLs() -> [URL] {
|
||||
(pasteboard.readObjects(
|
||||
forClasses: [NSURL.self],
|
||||
options: [.urlReadingFileURLsOnly: true]
|
||||
) as? [URL]) ?? []
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func write(manifest: Data, text: String) -> Int {
|
||||
pasteboard.clearContents()
|
||||
|
||||
Reference in New Issue
Block a user