Sources/OrgstarMobile/CaptureIntent.swift
48 lines · 1992 bytes
1#if os(iOS)
2import AppIntents
3import OrgApp
4import OrgCore
5
6/// Shortcuts' "Capture to Orgstar": files text with a capture template without the capture
7/// sheet. Prompts in the template take their defaults, and `%c` is empty: reading the
8/// pasteboard would ask for permission on every run.
9struct CaptureIntent: AppIntent {
10 static let title: LocalizedStringResource = "Capture to Orgstar"
11 static let description = IntentDescription("Files text with one of your capture templates.")
12
13 @Parameter(title: "Text")
14 var text: String
15
16 @Parameter(title: "Template Key", description: "A template's key in capture.toml; the first template when empty.")
17 var template: String?
18
19 struct Failure: Error, CustomLocalizedStringResourceConvertible {
20 let message: String
21 var localizedStringResource: LocalizedStringResource { "\(message)" }
22 }
23
24 @MainActor
25 func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog {
26 let model = MobileModel.shared
27 guard let workspace = model.workspace else { throw Failure(message: model.failure ?? "Orgstar isn't ready") }
28 let placed = model.session.capture(
29 text, templateKey: template, templates: CaptureTemplates.load().templates, workspace: workspace, clock: model.clock,
30 clipboard: "", userName: ""
31 )
32 switch placed {
33 case .failure(let error):
34 throw Failure(message: error.message)
35 case .success(let chosen):
36 for path in model.session.dirtyPaths { _ = model.session.save(path) }
37 let message = "Captured with \(chosen.name)"
38 return .result(value: message, dialog: "\(message)")
39 }
40 }
41}
42
43struct OrgstarShortcuts: AppShortcutsProvider {
44 static var appShortcuts: [AppShortcut] {
45 AppShortcut(intent: CaptureIntent(), phrases: ["Capture to \(.applicationName)"], shortTitle: "Capture", systemImageName: "tray.and.arrow.down")
46 }
47}
48#endif