Fix screen capture crash by isolating services
This commit is contained in:
parent
7a7dbaecab
commit
14d52a9c08
@ -8,6 +8,7 @@ enum EnhancementPrompt {
|
|||||||
case aiAssistant
|
case aiAssistant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
class AIEnhancementService: ObservableObject {
|
class AIEnhancementService: ObservableObject {
|
||||||
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "AIEnhancementService")
|
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "AIEnhancementService")
|
||||||
|
|
||||||
|
|||||||
@ -106,7 +106,7 @@ class AudioTranscriptionService: ObservableObject {
|
|||||||
var promptDetectionResult: PromptDetectionService.PromptDetectionResult? = nil
|
var promptDetectionResult: PromptDetectionService.PromptDetectionResult? = nil
|
||||||
|
|
||||||
if let enhancementService = enhancementService, enhancementService.isConfigured {
|
if let enhancementService = enhancementService, enhancementService.isConfigured {
|
||||||
let detectionResult = promptDetectionService.analyzeText(text, with: enhancementService)
|
let detectionResult = await promptDetectionService.analyzeText(text, with: enhancementService)
|
||||||
promptDetectionResult = detectionResult
|
promptDetectionResult = detectionResult
|
||||||
await promptDetectionService.applyDetectionResult(detectionResult, to: enhancementService)
|
await promptDetectionService.applyDetectionResult(detectionResult, to: enhancementService)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ class PromptDetectionService {
|
|||||||
let originalPromptId: UUID?
|
let originalPromptId: UUID?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
func analyzeText(_ text: String, with enhancementService: AIEnhancementService) -> PromptDetectionResult {
|
func analyzeText(_ text: String, with enhancementService: AIEnhancementService) -> PromptDetectionResult {
|
||||||
let originalEnhancementState = enhancementService.isEnhancementEnabled
|
let originalEnhancementState = enhancementService.isEnhancementEnabled
|
||||||
let originalPromptId = enhancementService.selectedPromptId
|
let originalPromptId = enhancementService.selectedPromptId
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import Vision
|
|||||||
import os
|
import os
|
||||||
import ScreenCaptureKit
|
import ScreenCaptureKit
|
||||||
|
|
||||||
|
@MainActor
|
||||||
class ScreenCaptureService: ObservableObject {
|
class ScreenCaptureService: ObservableObject {
|
||||||
@Published var isCapturing = false
|
@Published var isCapturing = false
|
||||||
@Published var lastCapturedText: String?
|
@Published var lastCapturedText: String?
|
||||||
@ -60,41 +61,41 @@ class ScreenCaptureService: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractText(from image: NSImage, completion: @escaping (String?) -> Void) {
|
private func extractText(from image: NSImage) async -> String? {
|
||||||
guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
|
guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
|
||||||
completion(nil)
|
return nil
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
|
let result: Result<String?, Error> = await Task.detached(priority: .userInitiated) {
|
||||||
let request = VNRecognizeTextRequest { request, error in
|
let request = VNRecognizeTextRequest()
|
||||||
if let error = error {
|
request.recognitionLevel = .accurate
|
||||||
self.logger.notice("📸 Text recognition failed: \(error.localizedDescription, privacy: .public)")
|
request.usesLanguageCorrection = true
|
||||||
completion(nil)
|
request.automaticallyDetectsLanguage = true
|
||||||
return
|
|
||||||
|
let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
|
||||||
|
|
||||||
|
do {
|
||||||
|
try requestHandler.perform([request])
|
||||||
|
guard let observations = request.results as? [VNRecognizedTextObservation] else {
|
||||||
|
return .success(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = observations
|
||||||
|
.compactMap { $0.topCandidates(1).first?.string }
|
||||||
|
.joined(separator: "\n")
|
||||||
|
|
||||||
|
return .success(text.isEmpty ? nil : text)
|
||||||
|
} catch {
|
||||||
|
return .failure(error)
|
||||||
}
|
}
|
||||||
|
}.value
|
||||||
|
|
||||||
guard let observations = request.results as? [VNRecognizedTextObservation] else {
|
switch result {
|
||||||
completion(nil)
|
case .success(let text):
|
||||||
return
|
return text
|
||||||
}
|
case .failure(let error):
|
||||||
|
|
||||||
let text = observations.compactMap { observation in
|
|
||||||
observation.topCandidates(1).first?.string
|
|
||||||
}.joined(separator: "\n")
|
|
||||||
|
|
||||||
completion(text.isEmpty ? nil : text)
|
|
||||||
}
|
|
||||||
|
|
||||||
request.recognitionLevel = VNRequestTextRecognitionLevel.accurate
|
|
||||||
request.usesLanguageCorrection = true
|
|
||||||
request.automaticallyDetectsLanguage = true
|
|
||||||
|
|
||||||
do {
|
|
||||||
try requestHandler.perform([request])
|
|
||||||
} catch {
|
|
||||||
logger.notice("📸 Text recognition failed: \(error.localizedDescription, privacy: .public)")
|
logger.notice("📸 Text recognition failed: \(error.localizedDescription, privacy: .public)")
|
||||||
completion(nil)
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +125,7 @@ class ScreenCaptureService: ObservableObject {
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if let capturedImage = await captureActiveWindow() {
|
if let capturedImage = await captureActiveWindow() {
|
||||||
let extractedText = await withCheckedContinuation({ continuation in
|
let extractedText = await extractText(from: capturedImage)
|
||||||
extractText(from: capturedImage) { text in
|
|
||||||
continuation.resume(returning: text)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if let extractedText = extractedText, !extractedText.isEmpty {
|
if let extractedText = extractedText, !extractedText.isEmpty {
|
||||||
contextText += "Window Content:\n\(extractedText)"
|
contextText += "Window Content:\n\(extractedText)"
|
||||||
|
|||||||
@ -327,7 +327,7 @@ class WhisperState: NSObject, ObservableObject {
|
|||||||
finalPastedText = text
|
finalPastedText = text
|
||||||
|
|
||||||
if let enhancementService = enhancementService, enhancementService.isConfigured {
|
if let enhancementService = enhancementService, enhancementService.isConfigured {
|
||||||
let detectionResult = promptDetectionService.analyzeText(text, with: enhancementService)
|
let detectionResult = await promptDetectionService.analyzeText(text, with: enhancementService)
|
||||||
promptDetectionResult = detectionResult
|
promptDetectionResult = detectionResult
|
||||||
await promptDetectionService.applyDetectionResult(detectionResult, to: enhancementService)
|
await promptDetectionService.applyDetectionResult(detectionResult, to: enhancementService)
|
||||||
}
|
}
|
||||||
@ -429,4 +429,3 @@ class WhisperState: NSObject, ObservableObject {
|
|||||||
await dismissMiniRecorder()
|
await dismissMiniRecorder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user