krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.1.11: Shared/SystemStatusWidgetSnapshot.swift · raw
1import Foundation
2#if canImport(WidgetKit)
3import WidgetKit
4#endif
5
6enum SystemStatusWidgetConfiguration {
7 static let kind = "SystemStatusWidget"
8}
9
10struct SystemStatusWidgetSnapshot: Codable, Sendable {
11 let services: [ServiceEntry]
12 let hasDisruption: Bool
13 let overallStatusText: String
14 let bannerSummary: String
15 let updatedAt: Date
16
17 struct ServiceEntry: Codable, Sendable, Identifiable {
18 let id: String
19 let name: String
20 let status: String
21 let requiresAttention: Bool
22 }
23
24 static let unavailable = SystemStatusWidgetSnapshot(
25 services: [],
26 hasDisruption: false,
27 overallStatusText: "Unavailable",
28 bannerSummary: "",
29 updatedAt: .now
30 )
31}
32
33enum SystemStatusWidgetSnapshotStore {
34 private static let snapshotKey = "systemStatus.widgetSnapshot"
35
36 static func load(
37 accountID: String? = ActiveAccountContextStore.load(),
38 defaults: UserDefaults? = sharedDefaults()
39 ) -> SystemStatusWidgetSnapshot? {
40 guard let defaults,
41 let data = defaults.data(forKey: scopedKey(for: accountID)) else {
42 return nil
43 }
44 return try? JSONDecoder().decode(SystemStatusWidgetSnapshot.self, from: data)
45 }
46
47 static func save(
48 _ snapshot: SystemStatusWidgetSnapshot,
49 accountID: String? = ActiveAccountContextStore.load(),
50 defaults: UserDefaults? = sharedDefaults()
51 ) {
52 guard let defaults,
53 let data = try? JSONEncoder().encode(snapshot) else {
54 return
55 }
56 defaults.set(data, forKey: scopedKey(for: accountID))
57 reloadWidgetTimelines()
58 }
59
60 static func clear(
61 accountID: String? = ActiveAccountContextStore.load(),
62 defaults: UserDefaults? = sharedDefaults()
63 ) {
64 defaults?.removeObject(forKey: scopedKey(for: accountID))
65 reloadWidgetTimelines()
66 }
67
68 private static func sharedDefaults() -> UserDefaults? {
69 UserDefaults(suiteName: HutchAppGroup.identifier)
70 }
71
72 private static func scopedKey(for accountID: String?) -> String {
73 guard let accountID, !accountID.isEmpty else { return snapshotKey }
74 return "\(snapshotKey).\(accountID)"
75 }
76
77 private static func reloadWidgetTimelines() {
78 #if canImport(WidgetKit)
79 WidgetCenter.shared.reloadTimelines(ofKind: SystemStatusWidgetConfiguration.kind)
80 #endif
81 }
82}