Skip to content

Commit 80650a8

Browse files
committed
Address GUI PR feedback
1 parent fabd699 commit 80650a8

23 files changed

Lines changed: 789 additions & 290 deletions

macos/TimeCapsuleSMB/Sources/TimeCapsuleSMBApp/ActivityStore.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class ActivityStore: ObservableObject {
2020
@Published private(set) var snapshot = ActivitySnapshot(
2121
isRunning: false,
2222
scope: .unknown,
23-
operationTitle: "No active operation",
23+
operationTitle: L10n.string("activity.no_active_operation"),
2424
latestMessage: nil,
2525
timeline: []
2626
)
@@ -86,7 +86,8 @@ final class ActivityStore: ObservableObject {
8686
snapshot = ActivitySnapshot(
8787
isRunning: coordinator.backend.isRunning,
8888
scope: scope,
89-
operationTitle: operation.map(OperationTimelineBuilder.operationTitle) ?? (timeline.isEmpty ? "No active operation" : "Last operation"),
89+
operationTitle: operation.map(OperationTimelineBuilder.operationTitle)
90+
?? (timeline.isEmpty ? L10n.string("activity.no_active_operation") : L10n.string("activity.last_operation")),
9091
latestMessage: latestMessage,
9192
timeline: timeline
9293
)

macos/TimeCapsuleSMB/Sources/TimeCapsuleSMBApp/AppReadinessStore.swift

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ enum AppReadinessStateKind: String, CaseIterable, Equatable {
99
case ready
1010
case degraded
1111
case blocked
12+
13+
var title: String {
14+
switch self {
15+
case .idle:
16+
return L10n.string("app_readiness.state.idle")
17+
case .resolvingBundle:
18+
return L10n.string("app_readiness.state.resolving_bundle")
19+
case .checkingCapabilities:
20+
return L10n.string("app_readiness.state.checking_capabilities")
21+
case .validatingInstall:
22+
return L10n.string("app_readiness.state.validating_install")
23+
case .ready:
24+
return L10n.string("app_readiness.state.ready")
25+
case .degraded:
26+
return L10n.string("app_readiness.state.degraded")
27+
case .blocked:
28+
return L10n.string("app_readiness.state.blocked")
29+
}
30+
}
1231
}
1332

1433
struct AppReadinessSummary: Equatable {
@@ -134,7 +153,7 @@ final class AppReadinessStore: ObservableObject {
134153
code: .helperMissing,
135154
severity: .error,
136155
message: error.localizedDescription,
137-
recovery: "Reinstall TimeCapsuleSMB or choose a valid helper in Diagnostics."
156+
recovery: L10n.string("app_readiness.recovery.helper_missing")
138157
))
139158
return
140159
}
@@ -205,7 +224,7 @@ final class AppReadinessStore: ObservableObject {
205224
code: .operationFailed,
206225
severity: .error,
207226
message: payload.summary,
208-
recovery: "Open Diagnostics and retry app readiness."
227+
recovery: L10n.string("app_readiness.recovery.retry_diagnostics")
209228
))
210229
return
211230
}
@@ -225,7 +244,7 @@ final class AppReadinessStore: ObservableObject {
225244
code: .installValidationFailed,
226245
severity: .error,
227246
message: payload.summary,
228-
recovery: "Reinstall TimeCapsuleSMB or open Diagnostics for the failed checks."
247+
recovery: L10n.string("app_readiness.recovery.install_validation_failed")
229248
))
230249
return
231250
}
@@ -272,16 +291,16 @@ final class AppReadinessStore: ObservableObject {
272291
code: code,
273292
severity: .error,
274293
message: event.message ?? event.summary,
275-
recovery: BackendErrorViewModel(event: event).recovery?.message ?? "Open Diagnostics and retry app readiness."
294+
recovery: BackendErrorViewModel(event: event).recovery?.message ?? L10n.string("app_readiness.recovery.retry_diagnostics")
276295
)
277296
}
278297

279298
private func contractIssue(operation: String, error: Error) -> BundleRuntimeIssue {
280299
BundleRuntimeIssue(
281300
code: .contractDecodeFailed,
282301
severity: .error,
283-
message: "\(operation) returned an unexpected payload: \(error.localizedDescription)",
284-
recovery: "Update or reinstall TimeCapsuleSMB so the app and helper use the same API contract."
302+
message: L10n.format("app_readiness.error.unexpected_payload", operation, error.localizedDescription),
303+
recovery: L10n.string("app_readiness.recovery.contract_mismatch")
285304
)
286305
}
287306

macos/TimeCapsuleSMB/Sources/TimeCapsuleSMBApp/BackendClient.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ final class BackendClient: ObservableObject {
2424
self.helperPath = helperPath
2525
}
2626

27+
deinit {
28+
runTask?.cancel()
29+
}
30+
2731
func clear() {
2832
guard !isRunning else {
2933
return

macos/TimeCapsuleSMB/Sources/TimeCapsuleSMBApp/BackendPayloads.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ struct BackendRecoveryPayload: Decodable, Equatable {
672672
let title: String
673673
let message: String?
674674
let actions: [String]
675+
let actionIDs: [String]
675676
let retryable: Bool
676677
let suggestedOperation: String?
677678
let docsAnchor: String?
@@ -680,8 +681,20 @@ struct BackendRecoveryPayload: Decodable, Equatable {
680681
case title
681682
case message
682683
case actions
684+
case actionIDs = "action_ids"
683685
case retryable
684686
case suggestedOperation = "suggested_operation"
685687
case docsAnchor = "docs_anchor"
686688
}
689+
690+
init(from decoder: Decoder) throws {
691+
let container = try decoder.container(keyedBy: CodingKeys.self)
692+
self.title = try container.decode(String.self, forKey: .title)
693+
self.message = try container.decodeIfPresent(String.self, forKey: .message)
694+
self.actions = try container.decodeIfPresent([String].self, forKey: .actions) ?? []
695+
self.actionIDs = try container.decodeIfPresent([String].self, forKey: .actionIDs) ?? []
696+
self.retryable = try container.decode(Bool.self, forKey: .retryable)
697+
self.suggestedOperation = try container.decodeIfPresent(String.self, forKey: .suggestedOperation)
698+
self.docsAnchor = try container.decodeIfPresent(String.self, forKey: .docsAnchor)
699+
}
687700
}

0 commit comments

Comments
 (0)