diff --git a/Account/Sources/Account/AccountDelegate.swift b/Account/Sources/Account/AccountDelegate.swift index 849b7c217..3d7eb27e9 100644 --- a/Account/Sources/Account/AccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegate.swift @@ -28,7 +28,7 @@ import Secrets func refreshAll(for account: Account) async throws func syncArticleStatus(for account: Account) async throws func sendArticleStatus(for account: Account) async throws - func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) + func refreshArticleStatus(for account: Account) async throws func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result) -> Void) diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index 538643919..d7b9ad1ab 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -142,7 +142,20 @@ enum CloudKitAccountDelegateError: LocalizedError { sendArticleStatus(for: account, showProgress: false, completion: completion) } - func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { + func refreshArticleStatus(for account: Account) async throws { + try await withCheckedThrowingContinuation { continuation in + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + private func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { let op = CloudKitReceiveStatusOperation(articlesZone: articlesZone) op.completionBlock = { mainThreadOperation in Task { @MainActor in diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index c3fff7168..ea1e7071c 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -218,7 +218,21 @@ final class FeedbinAccountDelegate: AccountDelegate { } } - func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { + func refreshArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + private func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { os_log(.debug, log: log, "Refreshing article statuses...") diff --git a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift index 3ce26ed42..0fe2ece64 100644 --- a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift @@ -207,13 +207,27 @@ final class FeedlyAccountDelegate: AccountDelegate { operationQueue.add(send) } + func refreshArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + /// Attempts to ensure local articles have the same status as they do remotely. /// So if the user is using another client roughly simultaneously with this app, /// this app does its part to ensure the articles have a consistent status between both. /// /// - Parameter account: The account whose articles have a remote status. /// - Parameter completion: Call on the main queue. - @MainActor func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { + private func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { guard let credentials = credentials else { return completion(.success(())) } diff --git a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift index 25f63ef75..937ed7cbe 100644 --- a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift @@ -65,8 +65,7 @@ final class LocalAccountDelegate: AccountDelegate { func sendArticleStatus(for account: Account) async throws { } - func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { - completion(.success(())) + func refreshArticleStatus(for account: Account) async throws { } func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift index cc8839eda..de5b24a25 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift +++ b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift @@ -505,9 +505,10 @@ extension NewsBlurAccountDelegate { // Download the initial articles downloadFeed(account: account, feed: feed, page: 1) { result in - self.refreshArticleStatus(for: account) { result in - switch result { - case .success: + + Task { @MainActor in + do { + try await self.refreshArticleStatus(for: account) self.refreshMissingStories(for: account) { result in switch result { case .success: @@ -521,8 +522,7 @@ extension NewsBlurAccountDelegate { completion(.failure(error)) } } - - case .failure(let error): + } catch { completion(.failure(error)) } } diff --git a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift index ee327efa6..3ddf00ce5 100644 --- a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift @@ -238,7 +238,21 @@ final class NewsBlurAccountDelegate: AccountDelegate { } } - func refreshArticleStatus(for account: Account, completion: @escaping (Result) -> ()) { + func refreshArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + private func refreshArticleStatus(for account: Account, completion: @escaping (Result) -> ()) { os_log(.debug, log: log, "Refreshing story statuses...") let group = DispatchGroup() diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index e3fdc85b6..acd251cff 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -279,7 +279,21 @@ final class ReaderAPIAccountDelegate: AccountDelegate { } } - func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { + func refreshArticleStatus(for account: Account) async throws { + + try await withCheckedThrowingContinuation { continuation in + self.refreshArticleStatus(for: account) { result in + switch result { + case .success: + continuation.resume() + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + private func refreshArticleStatus(for account: Account, completion: @escaping ((Result) -> Void)) { os_log(.debug, log: log, "Refreshing article statuses...") let group = DispatchGroup()