fix(chat): detach NSOpenPanel image read off MainActor

`presentImagePicker()` ran `Data(contentsOf: url)` synchronously on
MainActor inside the URL loop before the detached `encode()`. A 24 MP
HEIC at 8-15 MB stalled the chat composer per file. The drag/drop and
paste paths already read off-main via `loadObject`/`loadDataRepresentation`
callbacks; this brings the open-panel branch in line by capturing the
URLs into a `Task.detached` and reading bytes there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-01 13:20:50 +02:00
parent 3d85b91392
commit 11bb2bd0c3
@@ -486,12 +486,14 @@ struct RichChatInputBar: View {
panel.prompt = "Attach" panel.prompt = "Attach"
let response = panel.runModal() let response = panel.runModal()
guard response == .OK else { return } guard response == .OK else { return }
let urls = panel.urls let urls = Array(panel.urls.prefix(Self.maxAttachments - attachments.count))
let remainingSlots = Self.maxAttachments - attachments.count guard !urls.isEmpty else { return }
for url in urls.prefix(remainingSlots) { isEncodingAttachment = true
guard let data = try? Data(contentsOf: url) else { continue } Task.detached(priority: .userInitiated) {
isEncodingAttachment = true for url in urls {
encode(data: data, filename: url.lastPathComponent) guard let data = try? Data(contentsOf: url) else { continue }
encode(data: data, filename: url.lastPathComponent)
}
} }
#endif #endif
} }