@@ -14,13 +14,14 @@ struct AppDataScreen: View {
14
14
@State private var showDeleteDataConfirmation = false
15
15
@State private var isCreatingBackup = false
16
16
@State private var isRestoringFromBackup = false
17
- @State private var showResult = false
18
17
@State private var operationResult : OperationResult ?
19
18
20
19
var body : some View {
21
20
VStack ( spacing: 16 ) {
22
21
Group {
23
- backupDataButton
22
+ if !items. isEmpty {
23
+ backupDataButton
24
+ }
24
25
restoreDataButton
25
26
if !items. isEmpty {
26
27
removeAllDataButton
@@ -32,7 +33,7 @@ struct AppDataScreen: View {
32
33
. animation ( . default, value: items. isEmpty)
33
34
. alert (
34
35
operationResult? . title ?? " " ,
35
- isPresented: $showResult ,
36
+ isPresented: $operationResult . mappedToBool ( ) ,
36
37
presenting: operationResult,
37
38
actions: { _ in
38
39
Button ( " Ok " ) { }
@@ -51,7 +52,7 @@ struct AppDataScreen: View {
51
52
. accessibilityIdentifier ( " backupDataButton " )
52
53
. fileExporter (
53
54
isPresented: $isCreatingBackup,
54
- document: BackupFileDocument ( items: items. map ( BackupFileDocument . makeBackupItem ) ) ,
55
+ document: BackupFileDocument ( items: items. map ( BackupFileDocument . toBackupItem ) ) ,
55
56
contentType: . json,
56
57
defaultFilename: " Days backup "
57
58
) { result in
@@ -61,7 +62,6 @@ struct AppDataScreen: View {
61
62
case let . failure( error) :
62
63
operationResult = . error( error. localizedDescription)
63
64
}
64
- showResult = true
65
65
}
66
66
}
67
67
@@ -77,21 +77,25 @@ struct AppDataScreen: View {
77
77
) { result in
78
78
switch result {
79
79
case let . success( urls) :
80
- if let url = urls. first,
81
- url. startAccessingSecurityScopedResource ( ) ,
82
- let data = try ? Data ( contentsOf: url) ,
83
- let importedItems = try ? JSONDecoder ( ) . decode ( [ BackupFileDocument . BackupItem ] . self, from: data) {
80
+ guard let url = urls. first, url. startAccessingSecurityScopedResource ( ) else {
81
+ operationResult = . failedToRestore
82
+ return
83
+ }
84
+ do {
84
85
defer { url. stopAccessingSecurityScopedResource ( ) }
85
- let mappedRealItems = importedItems. map ( \. realItem)
86
- mappedRealItems. forEach { modelContext. insert ( $0) }
86
+ let data = try Data ( contentsOf: url)
87
+ let importedItems = try JSONDecoder ( ) . decode ( [ BackupFileDocument . BackupItem ] . self, from: data)
88
+ let currentItems = items. map ( \. backupItem)
89
+ let newItemsFromBackup = importedItems. filter { !currentItems. contains ( $0) }
90
+ newItemsFromBackup. forEach { modelContext. insert ( $0. realItem) }
91
+ try modelContext. save ( )
87
92
operationResult = . restoreSuccess
88
- } else {
93
+ } catch {
89
94
operationResult = . failedToRestore
90
95
}
91
96
case let . failure( error) :
92
97
operationResult = . error( error. localizedDescription)
93
98
}
94
- showResult = true
95
99
}
96
100
}
97
101
@@ -109,10 +113,11 @@ struct AppDataScreen: View {
109
113
Button ( " Delete " , role: . destructive) {
110
114
do {
111
115
try modelContext. delete ( model: Item . self)
116
+ try modelContext. save ( )
117
+ operationResult = . deletionSuccess
112
118
} catch {
113
119
assertionFailure ( error. localizedDescription)
114
120
operationResult = . error( error. localizedDescription)
115
- showResult = true
116
121
}
117
122
}
118
123
. accessibilityIdentifier ( " confirmRemoveAllDataButton " )
@@ -124,12 +129,13 @@ extension AppDataScreen {
124
129
private enum OperationResult : Equatable {
125
130
case backupSuccess
126
131
case restoreSuccess
132
+ case deletionSuccess
127
133
case failedToRestore
128
134
case error( String )
129
135
130
136
var title : LocalizedStringKey {
131
137
switch self {
132
- case . backupSuccess, . restoreSuccess: " Done "
138
+ case . backupSuccess, . restoreSuccess, . deletionSuccess : " Done "
133
139
case . failedToRestore, . error: " Error "
134
140
}
135
141
}
@@ -138,6 +144,7 @@ extension AppDataScreen {
138
144
switch self {
139
145
case . backupSuccess: " Backup data saved "
140
146
case . restoreSuccess: " Data restored from backup "
147
+ case . deletionSuccess: " All data deleted "
141
148
case . failedToRestore: " Unable to recover data from the selected file "
142
149
case let . error( message) : . init( message)
143
150
}
0 commit comments