Skip to content

Commit da0c0ba

Browse files
committed
minor error handling improvements
1 parent 1e436bc commit da0c0ba

11 files changed

+104
-17
lines changed

.swiftlint.yml

+5
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ custom_rules:
6363
message: "Use `SFSafeSymbols` via `systemSymbol` parameters for type safety."
6464
regex: "(Image\\(systemName:)|(NSImage\\(symbolName:)|(Label[^,]+?,\\s*systemImage:)|(UIApplicationShortcutIcon\\(systemImageName:)"
6565
severity: warning
66+
no_print_statements:
67+
name: "No print statements"
68+
message: "Use the `Logging` package instead."
69+
regex: "(print\\(.*\\))|(debugPrint\\(.*\\))"
70+
severity: warning

TimeMachineStatus.xcodeproj/project.pbxproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@
190190
28FAD5A62AFE3DBF00F642E7 /* CardViewModifier.swift */,
191191
28FAD5AC2AFF0D7200F642E7 /* ExpandableSection.swift */,
192192
28FAD5AE2AFF0D9600F642E7 /* UserfacingErrorView.swift */,
193+
281C819D2CBC887D00CDFED6 /* HiddenViewModifier+.swift */,
193194
);
194195
path = Components;
195196
sourceTree = "<group>";
@@ -281,7 +282,6 @@
281282
281822662AFD86AC0067E564 /* Color+RawRepresentable.swift */,
282283
2888D17B2C99B3E80081FBBB /* KeyedDecodingContainer+.swift */,
283284
28710D2E2CAF16AF00033855 /* Timer+Sendable.swift */,
284-
281C819D2CBC887D00CDFED6 /* HiddenViewModifier+.swift */,
285285
);
286286
path = Extensions;
287287
sourceTree = "<group>";

TimeMachineStatus/Components/CustomLabeledContentStyle.swift

+6
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ struct CustomLabeledContentStyle: LabeledContentStyle {
2828
}
2929
}
3030
}
31+
32+
extension LabeledContentStyle where Self == CustomLabeledContentStyle {
33+
static var custom: CustomLabeledContentStyle {
34+
CustomLabeledContentStyle()
35+
}
36+
}

TimeMachineStatus/Components/ExpandableSection.swift

+12
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,15 @@ struct ExpandableSection<C: View, H: View>: View {
5151
}
5252
}
5353
}
54+
55+
#Preview {
56+
List {
57+
ExpandableSection {
58+
Text("Item 1")
59+
Text("Item 2")
60+
Text("Item 3")
61+
} header: {
62+
Text("Header")
63+
}
64+
}
65+
}

TimeMachineStatus/Localizable.xcstrings

+55-4
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,20 @@
426426
}
427427
},
428428
"D" : {
429+
"extractionState" : "manual",
429430
"localizations" : {
430431
"de" : {
431432
"stringUnit" : {
432433
"state" : "translated",
433434
"value" : "D"
434435
}
435436
},
437+
"en" : {
438+
"stringUnit" : {
439+
"state" : "translated",
440+
"value" : "D"
441+
}
442+
},
436443
"it" : {
437444
"stringUnit" : {
438445
"state" : "translated",
@@ -464,6 +471,28 @@
464471
}
465472
}
466473
},
474+
"dest_info_error" : {
475+
"localizations" : {
476+
"de" : {
477+
"stringUnit" : {
478+
"state" : "translated",
479+
"value" : "Fehler Code"
480+
}
481+
},
482+
"en" : {
483+
"stringUnit" : {
484+
"state" : "translated",
485+
"value" : "Error Code"
486+
}
487+
},
488+
"it" : {
489+
"stringUnit" : {
490+
"state" : "translated",
491+
"value" : "Codice errore"
492+
}
493+
}
494+
}
495+
},
467496
"dest_info_filesystem" : {
468497
"extractionState" : "manual",
469498
"localizations" : {
@@ -579,6 +608,28 @@
579608
}
580609
}
581610
},
611+
"dest_info_number_of_backups" : {
612+
"localizations" : {
613+
"de" : {
614+
"stringUnit" : {
615+
"state" : "translated",
616+
"value" : "Anzahl an Sicherungen"
617+
}
618+
},
619+
"en" : {
620+
"stringUnit" : {
621+
"state" : "translated",
622+
"value" : "Number of backups"
623+
}
624+
},
625+
"it" : {
626+
"stringUnit" : {
627+
"state" : "translated",
628+
"value" : "Numero di backup"
629+
}
630+
}
631+
}
632+
},
582633
"dest_info_quota" : {
583634
"extractionState" : "manual",
584635
"localizations" : {
@@ -671,25 +722,25 @@
671722
}
672723
}
673724
},
674-
"dest_label_last_backup_failed" : {
725+
"dest_label_last_backup_failed_%lld" : {
675726
"extractionState" : "manual",
676727
"localizations" : {
677728
"de" : {
678729
"stringUnit" : {
679730
"state" : "translated",
680-
"value" : "Letztes Backup fehlgeschlagen. TimeMachine Einstellungen öffnen um mehr zu erfahren."
731+
"value" : "Letztes Backup fehlgeschlagen (%lld). TimeMachine Einstellungen öffnen um mehr zu erfahren."
681732
}
682733
},
683734
"en" : {
684735
"stringUnit" : {
685736
"state" : "translated",
686-
"value" : "Last Backup Failed. Open TimeMachine Settings for more information."
737+
"value" : "Last Backup Failed (%lld). Open TimeMachine Settings for more information."
687738
}
688739
},
689740
"it" : {
690741
"stringUnit" : {
691742
"state" : "translated",
692-
"value" : "Ultimo backup non riuscito. Apri le Impostazioni di TimeMachine per ulteriori informazioni."
743+
"value" : "Ultimo backup non riuscito (%lld). Apri le Impostazioni di TimeMachine per ulteriori informazioni."
693744
}
694745
}
695746
}

TimeMachineStatus/Model/BackupState/BackupState.swift

+4-7
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ enum BackupState {
2828
if let state = try? _decodePlist(data, raw: result) {
2929
return state
3030
}
31+
3132
#if DEBUG
3233
log.error("Unknown state: \(result)")
33-
fatalError("Unknown state: \(result)")
34-
#else
35-
throw BackupStateError.invalidState(raw: result)
3634
#endif
35+
36+
throw BackupStateError.invalidState(raw: result)
3737
}
3838
}
3939

@@ -72,11 +72,8 @@ extension BackupState {
7272
case ._thinning:
7373
return try decoder.decode(BackupState.Thinning.self, from: data)
7474
case ._unknown(let state):
75-
#if DEBUG
76-
throw BackupStateError.invalidState(raw: raw)
77-
#else
75+
log.warning("Unknown state: \(state), raw: \(raw)")
7876
return BackupState.Unknown(title: state, raw: raw)
79-
#endif
8077
}
8178
}
8279
}

TimeMachineStatus/Model/Preferences/Preferences.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ struct Destination: Decodable {
105105
case referenceLocalSnapshotDate = "ReferenceLocalSnapshotDate"
106106
case snapshotDates = "SnapshotDates"
107107
case attemptDates = "AttemptDates"
108+
case result = "RESULT"
108109
}
109110

110111
let lastKnownVolumeName: String?
@@ -119,6 +120,7 @@ struct Destination: Decodable {
119120
let referenceLocalSnapshotDate: Date?
120121
let snapshotDates: [Date]?
121122
let attemptDates: [Date]?
123+
let result: Int?
122124

123125
var lastBackupFailed: Bool {
124126
guard let snapshotDates,
@@ -129,6 +131,10 @@ struct Destination: Decodable {
129131

130132
return lastAttempt > last
131133
}
134+
135+
var numberOfBackups: Int {
136+
snapshotDates?.count ?? 0
137+
}
132138
}
133139

134140
extension Preferences {
@@ -160,7 +166,8 @@ extension Destination {
160166
consistencyScanDate: .distantPast,
161167
referenceLocalSnapshotDate: .now,
162168
snapshotDates: [.distantPast, .now.addingTimeInterval(.random(in: -100_000...0))],
163-
attemptDates: [.distantPast, .now.addingTimeInterval(.random(in: -100_000...0))]
169+
attemptDates: [.distantPast, .now.addingTimeInterval(.random(in: -100_000...0))],
170+
result: 0
164171
)
165172
}
166173
}

TimeMachineStatus/Views/DestinationCell.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ struct DestinationCell: View {
6161
.contentShape(.rect)
6262
.contextMenu { contextMenuActions }
6363
.card(.background.secondary)
64+
.onTapGesture {
65+
showInfo.toggle()
66+
}
6467
.onHover { hovering in
6568
withAnimation(.snappy) {
6669
self.hovering = hovering
@@ -141,7 +144,7 @@ struct DestinationCell: View {
141144
}
142145
.buttonStyle(.plain)
143146
.focusable(false)
144-
.help("dest_label_last_backup_failed")
147+
.help("dest_label_last_backup_failed_\(dest.result ?? -1)")
145148
}
146149
}
147150

TimeMachineStatus/Views/DestinationInfoView.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct DestinationInfoView: View {
2222
if let lastKnownEncryptionState = dest.lastKnownEncryptionState {
2323
LabeledContent("dest_info_encrypted", value: lastKnownEncryptionState)
2424
}
25-
if let networkURL = dest.networkURL {
25+
if let networkURL = dest.networkURL?.removingPercentEncoding {
2626
LabeledContent("dest_info_url", value: networkURL)
2727
}
2828
}
@@ -41,16 +41,22 @@ struct DestinationInfoView: View {
4141
}
4242
}
4343
Section {
44+
LabeledContent("dest_info_number_of_backups", value: "\(dest.numberOfBackups)")
4445
if let last = dest.snapshotDates?.max() {
4546
LabeledContent("dest_info_lastbackup", value: last.formatted(.relativeDate))
4647
}
4748
if let last = dest.attemptDates?.max() {
4849
LabeledContent("dest_info_lastattempt", value: last.formatted(.relativeDate))
4950
}
5051
}
52+
Section {
53+
if let errorCode = dest.result, errorCode != 0 {
54+
LabeledContent("dest_info_error", value: "\(errorCode)")
55+
}
56+
}
5157
}
5258
.formStyle(.grouped)
53-
.labeledContentStyle(CustomLabeledContentStyle())
59+
.labeledContentStyle(.custom)
5460
.frame(width: 500)
5561
}
5662
}

TimeMachineStatus/Views/MenuView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ struct MenuView: View {
118118
} header: {
119119
Text("section_general_info")
120120
}
121-
.labeledContentStyle(CustomLabeledContentStyle())
121+
.labeledContentStyle(.custom)
122122
}
123123
}
124124

0 commit comments

Comments
 (0)