diff --git a/Modules/Capabilities/Shortcuts/Resources/en.lproj/Localizable.strings b/Modules/Capabilities/Shortcuts/Resources/en.lproj/Localizable.strings index f8e2ba30..36527a7e 100644 --- a/Modules/Capabilities/Shortcuts/Resources/en.lproj/Localizable.strings +++ b/Modules/Capabilities/Shortcuts/Resources/en.lproj/Localizable.strings @@ -47,6 +47,11 @@ "OutputFormat.heic" = "HEIC"; "OutputFormat.png" = "PNG"; +"RecognizeTextIntent.combineResults.title" = "Combine Results"; +"RecognizeTextIntent.description" = "Recognizes all text in an image."; +"RecognizeTextIntent.parameterSummary${sourceFile}" = "Recognize text in ${sourceFile}"; +"RecognizeTextIntent.title" = "Recognize Text"; + "RedactDetectionsIntent.color" = "Color"; "RedactDetectionsIntent.description" = "Redacts detected items in an image."; "RedactDetectionsIntent.detectionKind.title" = "Items to Detect"; diff --git a/Modules/Capabilities/Shortcuts/Sources/Intents/RecognizeTextIntent.swift b/Modules/Capabilities/Shortcuts/Sources/Intents/RecognizeTextIntent.swift new file mode 100644 index 00000000..2fd73200 --- /dev/null +++ b/Modules/Capabilities/Shortcuts/Sources/Intents/RecognizeTextIntent.swift @@ -0,0 +1,55 @@ +// Created by Geoff Pado on 9/4/25. +// Copyright © 2025 Cocoatype, LLC. All rights reserved. + +import AppIntents +import UIKit + +import FactoryKit + +import Defaults +import Detections +import Logging + +@available(iOS 16.0, *) +struct RecognizeTextIntent: AppIntent { + static let title: LocalizedStringResource = "RecognizeTextIntent.title" + static let description: IntentDescription = "RecognizeTextIntent.description" + + @Parameter( + title: "RecognizeTextIntent.image.title" + ) + var sourceFile: IntentFile + + @Parameter( + title: "RecognizeTextIntent.combineResults.title", + default: true + ) + var combineResults: Bool + + static var parameterSummary: some ParameterSummary { + Summary("RecognizeTextIntent.parameterSummary\(\.$sourceFile)") { + \.$combineResults + } + } + + @MainActor func perform() async throws -> some IntentResult & ReturnsValue<[String]> { + guard let image = UIImage(data: sourceFile.data) else { + throw Error.noImage + } + + let detector = TextDetector() + let observations = try await detector.recognizeText(in: image) + let observedStrings = observations.map(\.string) + + if combineResults { + let combinedString = observedStrings.joined(separator: " ") + return .result(value: [combinedString]) + } else { + return .result(value: observedStrings) + } + } + + enum Error: Swift.Error { + case noImage + } +}