From d22aea7cf51dd51dddbaac3a2b808d0aeb2bf507 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 10 May 2020 16:59:23 -0500 Subject: [PATCH] Enhance remove folder to also remove webfeeds and articles from the cloud --- .../CloudKit/CloudKitAccountDelegate.swift | 48 ++++++++++++++++--- .../CloudKit/CloudKitAccountZone.swift | 26 ++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift index 8d7aea637..3e84be7f5 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountDelegate.swift @@ -27,7 +27,6 @@ enum CloudKitAccountDelegateError: LocalizedError { } } - final class CloudKitAccountDelegate: AccountDelegate { private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit") @@ -320,18 +319,55 @@ final class CloudKitAccountDelegate: AccountDelegate { } func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) { - refreshProgress.addToNumberOfTasksAndRemaining(1) - accountZone.removeFolder(folder) { result in + + refreshProgress.addToNumberOfTasksAndRemaining(2) + accountZone.findWebFeedExternalIDs(for: folder) { result in self.refreshProgress.completeTask() switch result { - case .success: - account.removeFolder(folder) - completion(.success(())) + case .success(let webFeedExternalIDs): + + let webFeeds = webFeedExternalIDs.compactMap { account.existingWebFeed(withExternalID: $0) } + let group = DispatchGroup() + var errorOccurred = false + + for webFeed in webFeeds { + group.enter() + self.removeWebFeed(for: account, with: webFeed, from: folder) { result in + group.leave() + if case .failure(let error) = result { + os_log(.error, log: self.log, "Remove folder, remove webfeed error: %@.", error.localizedDescription) + errorOccurred = true + } + } + } + + group.notify(queue: DispatchQueue.global(qos: .background)) { + guard !errorOccurred else { + self.refreshProgress.completeTask() + completion(.failure(CloudKitAccountDelegateError.unknown)) + return + } + + self.accountZone.removeFolder(folder) { result in + self.refreshProgress.completeTask() + switch result { + case .success: + account.removeFolder(folder) + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } + } + case .failure(let error): + self.refreshProgress.completeTask() + self.refreshProgress.completeTask() self.processAccountError(account, error) completion(.failure(error)) } } + } func restoreFolder(for account: Account, folder: Folder, completion: @escaping (Result) -> Void) { diff --git a/Frameworks/Account/CloudKit/CloudKitAccountZone.swift b/Frameworks/Account/CloudKit/CloudKitAccountZone.swift index b65bb6d0b..eac0f70ab 100644 --- a/Frameworks/Account/CloudKit/CloudKitAccountZone.swift +++ b/Frameworks/Account/CloudKit/CloudKitAccountZone.swift @@ -12,6 +12,12 @@ import RSWeb import RSParser import CloudKit +enum CloudKitAccountZoneError: LocalizedError { + case unknown + var errorDescription: String? { + return NSLocalizedString("An unexpected CloudKit error occurred.", comment: "An unexpected CloudKit error occurred.") + } +} final class CloudKitAccountZone: CloudKitZone { static var zoneID: CKRecordZone.ID { @@ -221,6 +227,26 @@ final class CloudKitAccountZone: CloudKitZone { } } + func findWebFeedExternalIDs(for folder: Folder, completion: @escaping (Result<[String], Error>) -> Void) { + guard let folderExternalID = folder.externalID else { + completion(.failure(CloudKitAccountZoneError.unknown)) + return + } + + let predicate = NSPredicate(format: "containerExternalIDs CONTAINS %@", folderExternalID) + let ckQuery = CKQuery(recordType: CloudKitWebFeed.recordType, predicate: predicate) + + query(ckQuery) { result in + switch result { + case .success(let records): + let webFeedExternalIds = records.map { $0.externalID } + completion(.success(webFeedExternalIds)) + case .failure(let error): + completion(.failure(error)) + } + } + } + func findOrCreateAccount(completion: @escaping (Result) -> Void) { let predicate = NSPredicate(format: "isAccount = \"1\"") let ckQuery = CKQuery(recordType: CloudKitContainer.recordType, predicate: predicate)