@@ -12,11 +12,16 @@ enum ScreenCaptureOCR {
1212 }
1313 }
1414 /// Launch interactive screen capture, OCR the captured image, and return recognized text.
15- @MainActor static func captureAndRecognize( ) async throws -> String {
16- // Run screencapture -i -c (interactive selection → clipboard)
15+ static func captureAndRecognize( ) async throws -> String {
16+ // Generate a unique temp file path to avoid concurrency conflicts
17+ let tmpURL = URL ( fileURLWithPath: NSTemporaryDirectory ( ) )
18+ . appendingPathComponent ( " moepeek_ocr_ \( UUID ( ) . uuidString) .png " )
19+ defer { try ? FileManager . default. removeItem ( at: tmpURL) }
20+
21+ // Run screencapture -i <tmpPath> (interactive selection → temp file, clipboard untouched)
1722 let process = Process ( )
1823 process. executableURL = URL ( fileURLWithPath: " /usr/sbin/screencapture " )
19- process. arguments = [ " -i " , " -c " ]
24+ process. arguments = [ " -i " , tmpURL . path ]
2025
2126 let status = try await withTaskCancellationHandler {
2227 try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Int32 , Error > ) in
@@ -42,14 +47,13 @@ enum ScreenCaptureOCR {
4247 throw OCRError . captureCancelled
4348 }
4449
45- // Read image from clipboard and perform OCR inside autoreleasepool
50+ // Read image from temp file and perform OCR inside autoreleasepool
4651 // to ensure large screenshot images are freed promptly.
4752 let cgImage : CGImage = try autoreleasepool {
48- let pasteboard = NSPasteboard . general
49- guard let image = NSImage ( pasteboard: pasteboard) ,
53+ guard let image = NSImage ( contentsOf: tmpURL) ,
5054 let cg = image. cgImage ( forProposedRect: nil , context: nil , hints: nil )
5155 else {
52- throw OCRError . noImageInClipboard
56+ throw OCRError . captureReadFailed
5357 }
5458 return cg
5559 }
@@ -99,14 +103,14 @@ enum ScreenCaptureOCR {
99103
100104enum OCRError : LocalizedError {
101105 case captureCancelled
102- case noImageInClipboard
106+ case captureReadFailed
103107 case noTextRecognized
104108
105109 var errorDescription : String ? {
106110 switch self {
107- case . captureCancelled: String ( localized: " Screen capture was cancelled " )
108- case . noImageInClipboard : String ( localized: " No image found in clipboard after capture " )
109- case . noTextRecognized: String ( localized: " No text was recognized in the captured image " )
111+ case . captureCancelled: String ( localized: " Screen capture was cancelled " )
112+ case . captureReadFailed : String ( localized: " Failed to read the captured image " )
113+ case . noTextRecognized: String ( localized: " No text was recognized in the captured image " )
110114 }
111115 }
112116}
0 commit comments