summaryrefslogtreecommitdiff
path: root/Hutch/App/HutchIntents.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-12 00:55:42 -0500
committerChristian Cleberg <[email protected]>2026-04-12 00:55:42 -0500
commit9050405b4f33b2b9b70458fcf3e43b80c940eef7 (patch)
tree983c3a07a560258059cfe421beb3ffcf3c18baf4 /Hutch/App/HutchIntents.swift
parent5f6d545eb3455a9e4da5a3cb4460811e3a48d939 (diff)
downloadhutch-2.15.0.tar.gz
hutch-2.15.0.tar.bz2
hutch-2.15.0.zip
add shortcuts widgets and power-user workflowsv2.15.0
Diffstat (limited to 'Hutch/App/HutchIntents.swift')
-rw-r--r--Hutch/App/HutchIntents.swift154
1 files changed, 154 insertions, 0 deletions
diff --git a/Hutch/App/HutchIntents.swift b/Hutch/App/HutchIntents.swift
new file mode 100644
index 0000000..652c07b
--- /dev/null
+++ b/Hutch/App/HutchIntents.swift
@@ -0,0 +1,154 @@
+import AppIntents
+import Foundation
+
+// MARK: - Open Hutch Intent
+
+enum HutchDestination: String, AppEnum {
+ case home
+ case inbox
+ case builds
+ case repositories
+ case trackers
+ case systemStatus
+ case lookup
+
+ static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Hutch Section")
+
+ static var caseDisplayRepresentations: [HutchDestination: DisplayRepresentation] = [
+ .home: "Home",
+ .inbox: "Inbox",
+ .builds: "Builds",
+ .repositories: "Repositories",
+ .trackers: "Trackers",
+ .systemStatus: "System Status",
+ .lookup: "Look Up"
+ ]
+}
+
+struct OpenHutchIntent: AppIntent {
+ static var title: LocalizedStringResource = "Open Hutch"
+ static var description = IntentDescription("Opens Hutch to a specific section.")
+ static var openAppWhenRun = true
+
+ @Parameter(title: "Section", default: .home)
+ var destination: HutchDestination
+
+ @MainActor
+ func perform() async throws -> some IntentResult {
+ HutchIntentNavigator.shared.pendingDestination = destination
+ return .result()
+ }
+}
+
+// MARK: - Check System Status Intent
+
+struct CheckSystemStatusIntent: AppIntent {
+ static var title: LocalizedStringResource = "Check SourceHut Status"
+ static var description = IntentDescription("Returns the current SourceHut system status.")
+
+ @MainActor
+ func perform() async throws -> some IntentResult & ReturnsValue<String> {
+ guard let snapshot = SystemStatusWidgetSnapshotStore.load() else {
+ return .result(value: "System status is unavailable. Open Hutch to refresh.")
+ }
+
+ if snapshot.hasDisruption {
+ let disrupted = snapshot.services
+ .filter { $0.requiresAttention }
+ .map { "\($0.name): \($0.status)" }
+ .joined(separator: ", ")
+ return .result(value: "SourceHut disruption detected: \(disrupted)")
+ }
+
+ return .result(value: "All SourceHut services operational.")
+ }
+}
+
+// MARK: - Check Builds Intent
+
+struct CheckBuildsIntent: AppIntent {
+ static var title: LocalizedStringResource = "Check Hutch Builds"
+ static var description = IntentDescription("Returns a summary of your recent build status.")
+
+ @MainActor
+ func perform() async throws -> some IntentResult & ReturnsValue<String> {
+ guard let snapshot = NeedsAttentionSnapshotStore.load() else {
+ return .result(value: "Build status unavailable. Open Hutch to refresh.")
+ }
+
+ var parts: [String] = []
+
+ if let failed = snapshot.failedBuilds {
+ if failed > 0 {
+ parts.append("\(failed) failed build\(failed == 1 ? "" : "s")")
+ } else {
+ parts.append("No failed builds")
+ }
+ }
+
+ if let unread = snapshot.unreadInboxThreads, unread > 0 {
+ parts.append("\(unread) unread thread\(unread == 1 ? "" : "s")")
+ }
+
+ if let assigned = snapshot.assignedOpenTickets, assigned > 0 {
+ parts.append("\(assigned) assigned ticket\(assigned == 1 ? "" : "s")")
+ }
+
+ if parts.isEmpty {
+ return .result(value: "No recent data. Open Hutch to refresh.")
+ }
+
+ return .result(value: parts.joined(separator: ". ") + ".")
+ }
+}
+
+// MARK: - Shortcuts Provider
+
+struct HutchShortcuts: AppShortcutsProvider {
+ static var appShortcuts: [AppShortcut] {
+ AppShortcut(
+ intent: OpenHutchIntent(),
+ phrases: [
+ "Open \(.applicationName)",
+ "Open \(.applicationName) \(\.$destination)",
+ "Show my \(.applicationName) \(\.$destination)",
+ "Go to \(\.$destination) in \(.applicationName)"
+ ],
+ shortTitle: "Open Hutch",
+ systemImageName: "house"
+ )
+
+ AppShortcut(
+ intent: CheckSystemStatusIntent(),
+ phrases: [
+ "Check \(.applicationName) status",
+ "Is SourceHut up in \(.applicationName)",
+ "SourceHut status in \(.applicationName)"
+ ],
+ shortTitle: "Check SourceHut Status",
+ systemImageName: "server.rack"
+ )
+
+ AppShortcut(
+ intent: CheckBuildsIntent(),
+ phrases: [
+ "Check my \(.applicationName) builds",
+ "How are my builds in \(.applicationName)",
+ "Build status in \(.applicationName)"
+ ],
+ shortTitle: "Check Builds",
+ systemImageName: "hammer"
+ )
+ }
+}
+
+// MARK: - Intent Navigator
+
+@MainActor
+@Observable
+final class HutchIntentNavigator {
+ static let shared = HutchIntentNavigator()
+ var pendingDestination: HutchDestination?
+
+ private init() {}
+}