krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.5.0: 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? = nil,
38 defaults: UserDefaults? = sharedDefaults()
39 ) -> SystemStatusWidgetSnapshot? {
40 guard let defaults,
41 let data = defaults.data(forKey: scopedKey(for: resolvedAccountID(accountID, defaults: defaults))) 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? = nil,
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: resolvedAccountID(accountID, defaults: defaults)))
57 reloadWidgetTimelines()
58 }
59
60 static func clear(
61 accountID: String? = nil,
62 defaults: UserDefaults? = sharedDefaults()
63 ) {
64 guard let defaults else { return }
65 defaults.removeObject(forKey: scopedKey(for: resolvedAccountID(accountID, defaults: defaults)))
66 reloadWidgetTimelines()
67 }
68
69 private static func sharedDefaults() -> UserDefaults? {
70 UserDefaults(suiteName: HutchAppGroup.identifier)
71 }
72
73 private static func scopedKey(for accountID: String?) -> String {
74 guard let accountID, !accountID.isEmpty else { return snapshotKey }
75 return "\(snapshotKey).\(accountID)"
76 }
77
78 private static func resolvedAccountID(_ accountID: String?, defaults: UserDefaults) -> String? {
79 accountID ?? ActiveAccountContextStore.load(defaults: defaults)
80 }
81
82 private static func reloadWidgetTimelines() {
83 #if canImport(WidgetKit)
84 WidgetCenter.shared.reloadTimelines(ofKind: SystemStatusWidgetConfiguration.kind)
85 #endif
86 }
87}