Files
ux/ios/Classes/ClipboardPlugin.swift
agra fb00e98681 clipboard: add UxClipboard.readImage native bridge
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".
2026-05-09 07:29:14 +03:00

53 lines
1.9 KiB
Swift

import Flutter
import MobileCoreServices
import UIKit
import UniformTypeIdentifiers
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 = UIPasteboard.general
// Prefer raw PNG / JPEG bytes already on the clipboard so we don't
// round-trip through UIImage when we don't have to.
if #available(iOS 14.0, *) {
if let png = pb.data(forPasteboardType: UTType.png.identifier) {
return result(FlutterStandardTypedData(bytes: png))
}
if let jpg = pb.data(forPasteboardType: UTType.jpeg.identifier) {
return result(FlutterStandardTypedData(bytes: jpg))
}
} else {
if let png = pb.data(forPasteboardType: kUTTypePNG as String) {
return result(FlutterStandardTypedData(bytes: png))
}
if let jpg = pb.data(forPasteboardType: kUTTypeJPEG as String) {
return result(FlutterStandardTypedData(bytes: jpg))
}
}
// Fallback: re-encode whatever UIImage resolves to as PNG.
if let img = pb.image, let png = img.pngData() {
return result(FlutterStandardTypedData(bytes: png))
}
result(nil)
}
}