Flutter's Clipboard API only exposes text shapes. Banlu's chat composer needs image bytes from the system clipboard for desktop paste, so add a UxClipboard facade backed by per-platform native plugins: * iOS: prefer raw PNG/JPEG bytes off the pasteboard, fall back to re-encoding `UIPasteboard.image` as PNG. * macOS: prefer NSPasteboard `.png`, fall back to TIFF transcoded through NSBitmapImageRep so screenshots / Preview hand-offs still work. * Android: read primary ClipData's first item URI and stream the bytes through ContentResolver — don't trust the clip description's MIME, copy whatever the resolver returns. Returns null (never throws) when the clipboard has no image — callers treat null as "fall through to text paste".
40 lines
1.3 KiB
Swift
40 lines
1.3 KiB
Swift
import AppKit
|
|
import FlutterMacOS
|
|
|
|
public class ClipboardPlugin: NSObject, NativePlugin {
|
|
private var channel: FlutterMethodChannel?
|
|
|
|
public func register(with registrar: FlutterPluginRegistrar) {
|
|
let c = FlutterMethodChannel(name: "ux/clipboard", binaryMessenger: registrar.messenger)
|
|
c.setMethodCallHandler { [weak self] call, result in
|
|
self?.handle(call, result: result)
|
|
}
|
|
channel = c
|
|
}
|
|
|
|
private func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
switch call.method {
|
|
case "readImage": handleReadImage(result: result)
|
|
default: result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
|
|
private func handleReadImage(result: @escaping FlutterResult) {
|
|
let pb = NSPasteboard.general
|
|
|
|
if let png = pb.data(forType: .png) {
|
|
return result(FlutterStandardTypedData(bytes: png))
|
|
}
|
|
|
|
// macOS Screenshot.app and Preview hand off TIFF; transcode so
|
|
// the Dart side always gets PNG bytes regardless of producer.
|
|
if let tiff = pb.data(forType: .tiff),
|
|
let rep = NSBitmapImageRep(data: tiff),
|
|
let png = rep.representation(using: .png, properties: [:]) {
|
|
return result(FlutterStandardTypedData(bytes: png))
|
|
}
|
|
|
|
result(nil)
|
|
}
|
|
}
|