Implemented feed and folder restore so that undo works.

This commit is contained in:
Maurice Parker 2020-03-31 11:07:54 -05:00
parent 218df326f4
commit 1be5dc8a54
2 changed files with 67 additions and 17 deletions

View File

@ -180,7 +180,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
case .failure(let error):
self.refreshProgress.completeTask()
completion(.failure(error)) // TODO: need to handle userDeletedZone
completion(.failure(error))
}
}
@ -244,7 +244,16 @@ final class CloudKitAccountDelegate: AccountDelegate {
}
func restoreWebFeed(for account: Account, feed: WebFeed, container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
addWebFeed(for: account, with: feed, to: container, completion: completion)
accountZone.createWebFeed(url: feed.url, editedName: feed.editedName, container: container) { result in
switch result {
case .success(let externalID):
feed.externalID = externalID
container.addWebFeed(feed)
completion(.success(()))
case .failure(let error):
completion(.failure(error))
}
}
}
func createFolder(for account: Account, name: String, completion: @escaping (Result<Folder, Error>) -> Void) {
@ -298,6 +307,30 @@ final class CloudKitAccountDelegate: AccountDelegate {
case .success(let externalID):
folder.externalID = externalID
account.addFolder(folder)
let group = DispatchGroup()
for feed in folder.topLevelWebFeeds {
folder.topLevelWebFeeds.remove(feed)
group.enter()
self.restoreWebFeed(for: account, feed: feed, container: folder) { result in
group.leave()
switch result {
case .success:
break
case .failure(let error):
os_log(.error, log: self.log, "Restore folder feed error: %@.", error.localizedDescription)
}
}
}
group.notify(queue: DispatchQueue.main) {
account.addFolder(folder)
completion(.success(()))
}
case .failure(let error):
completion(.failure(error))
}

View File

@ -102,23 +102,31 @@ extension CloudKitZone {
return
}
database.perform(query, inZoneWith: Self.zoneID) { records, error in
refreshProgress?.addToNumberOfTasksAndRemaining(1)
database.perform(query, inZoneWith: Self.zoneID) { [weak self] records, error in
switch CloudKitZoneResult.resolve(error) {
case .success:
DispatchQueue.main.async {
self?.refreshProgress?.completeTask()
if let records = records {
completion(.success(records))
} else {
completion(.failure(CloudKitZoneError.unknown))
}
}
case .retry(let timeToWait):
self.retryIfPossible(after: timeToWait) {
self.query(query, completion: completion)
self?.retryIfPossible(after: timeToWait) {
self?.query(query, completion: completion)
}
default:
DispatchQueue.main.async {
self?.refreshProgress?.completeTask()
completion(.failure(error!))
}
}
}
}
func fetch(externalID: String?, completion: @escaping (Result<CKRecord, Error>) -> Void) {
guard let externalID = externalID else {
@ -128,10 +136,12 @@ extension CloudKitZone {
let recordID = CKRecord.ID(recordName: externalID, zoneID: Self.zoneID)
database?.fetch(withRecordID: recordID) { record, error in
refreshProgress?.addToNumberOfTasksAndRemaining(1)
database?.fetch(withRecordID: recordID) { [weak self] record, error in
switch CloudKitZoneResult.resolve(error) {
case .success:
DispatchQueue.main.async {
self?.refreshProgress?.completeTask()
if let record = record {
completion(.success(record))
} else {
@ -139,11 +149,12 @@ extension CloudKitZone {
}
}
case .retry(let timeToWait):
self.retryIfPossible(after: timeToWait) {
self.fetch(externalID: externalID, completion: completion)
self?.retryIfPossible(after: timeToWait) {
self?.fetch(externalID: externalID, completion: completion)
}
default:
DispatchQueue.main.async {
self?.refreshProgress?.completeTask()
completion(.failure(error!))
}
}
@ -187,6 +198,7 @@ extension CloudKitZone {
switch CloudKitZoneResult.resolve(error) {
case .success:
DispatchQueue.main.async {
self.refreshProgress?.completeTask()
completion(.success(()))
}
case .zoneNotFound:
@ -195,11 +207,15 @@ extension CloudKitZone {
case .success:
self.modify(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete, completion: completion)
case .failure(let error):
DispatchQueue.main.async {
self.refreshProgress?.completeTask()
completion(.failure(error))
}
}
}
case .userDeletedZone:
DispatchQueue.main.async {
self.refreshProgress?.completeTask()
completion(.failure(CloudKitZoneError.userDeletedZone))
}
case .retry(let timeToWait):
@ -213,18 +229,18 @@ extension CloudKitZone {
}
default:
DispatchQueue.main.async {
self.refreshProgress?.completeTask()
completion(.failure(error!))
}
}
}
refreshProgress?.addToNumberOfTasksAndRemaining(1)
database?.add(op)
}
func fetchChangesInZone(completion: @escaping (Result<Void, Error>) -> Void) {
refreshProgress?.addToNumberOfTasksAndRemaining(1)
let zoneConfig = CKFetchRecordZoneChangesOperation.ZoneConfiguration()
zoneConfig.previousServerChangeToken = changeToken
let op = CKFetchRecordZoneChangesOperation(recordZoneIDs: [Self.zoneID], configurationsByRecordZoneID: [Self.zoneID: zoneConfig])
@ -279,6 +295,7 @@ extension CloudKitZone {
}
}
refreshProgress?.addToNumberOfTasksAndRemaining(1)
database?.add(op)
}