krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.0.0: Hutch/App/HutchIntents.swift · raw
1import AppIntents
2import Foundation
3
4// MARK: - Open Hutch Intent
5
6enum HutchDestination: String, AppEnum {
7 case home
8 case work
9 case builds
10 case repositories
11 case trackers
12 case systemStatus
13 case lookup
14
15 static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Hutch Section")
16
17 static var caseDisplayRepresentations: [HutchDestination: DisplayRepresentation] = [
18 .home: "Home",
19 .work: "Work",
20 .builds: "Builds",
21 .repositories: "Repositories",
22 .trackers: "Trackers",
23 .systemStatus: "System Status",
24 .lookup: "Look Up"
25 ]
26}
27
28struct OpenHutchIntent: AppIntent {
29 static var title: LocalizedStringResource = "Open Hutch"
30 static var description = IntentDescription("Opens Hutch to a specific section.")
31 static var openAppWhenRun = true
32
33 @Parameter(title: "Section", default: .home)
34 var destination: HutchDestination
35
36 @MainActor
37 func perform() async throws -> some IntentResult {
38 HutchIntentNavigator.shared.pendingDestination = destination
39 return .result()
40 }
41}
42
43// MARK: - Check System Status Intent
44
45struct CheckSystemStatusIntent: AppIntent {
46 static var title: LocalizedStringResource = "Check SourceHut Status"
47 static var description = IntentDescription("Returns the current SourceHut system status.")
48
49 @MainActor
50 func perform() async throws -> some IntentResult & ReturnsValue<String> {
51 guard let snapshot = SystemStatusWidgetSnapshotStore.load() else {
52 return .result(value: "System status is unavailable. Open Hutch to refresh.")
53 }
54
55 if snapshot.hasDisruption {
56 let disrupted = snapshot.services
57 .filter { $0.requiresAttention }
58 .map { "\($0.name): \($0.status)" }
59 .joined(separator: ", ")
60 return .result(value: "SourceHut disruption detected: \(disrupted)")
61 }
62
63 return .result(value: "All SourceHut services operational.")
64 }
65}
66
67// MARK: - Check Builds Intent
68
69struct CheckBuildsIntent: AppIntent {
70 static var title: LocalizedStringResource = "Check Hutch Builds"
71 static var description = IntentDescription("Returns a summary of your recent build status.")
72
73 @MainActor
74 func perform() async throws -> some IntentResult & ReturnsValue<String> {
75 guard let snapshot = NeedsAttentionSnapshotStore.load() else {
76 return .result(value: "Build status unavailable. Open Hutch to refresh.")
77 }
78
79 var parts: [String] = []
80
81 if let failed = snapshot.failedBuilds {
82 if failed > 0 {
83 parts.append("\(failed) failed build\(failed == 1 ? "" : "s")")
84 } else {
85 parts.append("No failed builds")
86 }
87 }
88
89 if let unread = snapshot.unreadInboxThreads, unread > 0 {
90 parts.append("\(unread) unread thread\(unread == 1 ? "" : "s")")
91 }
92
93 if let assigned = snapshot.assignedOpenTickets, assigned > 0 {
94 parts.append("\(assigned) assigned ticket\(assigned == 1 ? "" : "s")")
95 }
96
97 if parts.isEmpty {
98 return .result(value: "No recent data. Open Hutch to refresh.")
99 }
100
101 return .result(value: parts.joined(separator: ". ") + ".")
102 }
103}
104
105// MARK: - Shortcuts Provider
106
107struct HutchShortcuts: AppShortcutsProvider {
108 static var appShortcuts: [AppShortcut] {
109 AppShortcut(
110 intent: OpenHutchIntent(),
111 phrases: [
112 "Open \(.applicationName)",
113 "Open \(.applicationName) \(\.$destination)",
114 "Show my \(.applicationName) \(\.$destination)",
115 "Go to \(\.$destination) in \(.applicationName)"
116 ],
117 shortTitle: "Open Hutch",
118 systemImageName: "house"
119 )
120
121 AppShortcut(
122 intent: CheckSystemStatusIntent(),
123 phrases: [
124 "Check \(.applicationName) status",
125 "Is SourceHut up in \(.applicationName)",
126 "SourceHut status in \(.applicationName)"
127 ],
128 shortTitle: "Check SourceHut Status",
129 systemImageName: "server.rack"
130 )
131
132 AppShortcut(
133 intent: CheckBuildsIntent(),
134 phrases: [
135 "Check my \(.applicationName) builds",
136 "How are my builds in \(.applicationName)",
137 "Build status in \(.applicationName)"
138 ],
139 shortTitle: "Check Builds",
140 systemImageName: "hammer"
141 )
142 }
143}
144
145// MARK: - Intent Navigator
146
147@MainActor
148@Observable
149final class HutchIntentNavigator {
150 static let shared = HutchIntentNavigator()
151 var pendingDestination: HutchDestination?
152
153 private init() {}
154}