diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index 65ee8c749..296ba32d6 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -642,8 +642,8 @@ public enum FetchType { delegate.removeFolder(for: self, with: folder, completion: completion) } - public func renameFolder(_ folder: Folder, to name: String, completion: @escaping (Result) -> Void) { - delegate.renameFolder(for: self, with: folder, to: name, completion: completion) + public func renameFolder(_ folder: Folder, to name: String) async throws { + try await delegate.renameFolder(for: self, with: folder, to: name) } public func restoreFolder(_ folder: Folder, completion: @escaping (Result) -> Void) { @@ -895,7 +895,7 @@ public enum FetchType { Task { @MainActor in do { - let statusesDictionary = try await database.createStatusesIfNeeded(articleIDs: articleIDs) + _ = try await database.createStatusesIfNeeded(articleIDs: articleIDs) completion?(nil) } catch { completion?(error as? DatabaseError) diff --git a/Account/Sources/Account/AccountDelegate.swift b/Account/Sources/Account/AccountDelegate.swift index 1c13e3d5f..43f43ec92 100644 --- a/Account/Sources/Account/AccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegate.swift @@ -33,7 +33,7 @@ import Secrets func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result) -> Void) func createFolder(for account: Account, name: String) async throws -> Folder - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result) -> Void) diff --git a/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift index 12d89ccba..3a8dc3e99 100644 --- a/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/FeedbinAccountDelegate.swift @@ -292,7 +292,7 @@ public enum FeedbinAccountDelegateError: String, Error { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) { + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { guard folder.hasAtLeastOneFeed() else { folder.name = name @@ -300,23 +300,25 @@ public enum FeedbinAccountDelegateError: String, Error { } refreshProgress.addToNumberOfTasksAndRemaining(1) - caller.renameTag(oldName: folder.name ?? "", newName: name) { result in - self.refreshProgress.completeTask() - switch result { - case .success: - DispatchQueue.main.async { - self.renameFolderRelationship(for: account, fromName: folder.name ?? "", toName: name) - folder.name = name - completion(.success(())) - } - case .failure(let error): - DispatchQueue.main.async { - let wrappedError = WrappedAccountError(accountID: account.accountID, accountNameForDisplay: account.nameForDisplay, underlyingError: error) - completion(.failure(wrappedError)) + + try await withCheckedThrowingContinuation { continuation in + caller.renameTag(oldName: folder.name ?? "", newName: name) { result in + self.refreshProgress.completeTask() + switch result { + case .success: + Task { @MainActor in + self.renameFolderRelationship(for: account, fromName: folder.name ?? "", toName: name) + folder.name = name + continuation.resume() + } + case .failure(let error): + Task { @MainActor in + let wrappedError = WrappedAccountError(accountID: account.accountID, accountNameForDisplay: account.nameForDisplay, underlyingError: error) + continuation.resume(throwing: wrappedError) + } } } } - } func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift index d75cbf090..7a55d994d 100644 --- a/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/LocalAccountDelegate.swift @@ -173,9 +173,8 @@ final class LocalAccountDelegate: AccountDelegate, Logging { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) { + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { folder.name = name - completion(.success(())) } func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift index c35b9dfa7..50329afbe 100644 --- a/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/NewsBlurAccountDelegate.swift @@ -373,29 +373,29 @@ final class NewsBlurAccountDelegate: AccountDelegate, Logging { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> ()) { + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { guard let folderToRename = folder.name else { - completion(.failure(NewsBlurError.invalidParameter)) - return + throw NewsBlurError.invalidParameter } refreshProgress.addToNumberOfTasksAndRemaining(1) let nameBefore = folder.name + folder.name = name - caller.renameFolder(with: folderToRename, to: name) { result in - self.refreshProgress.completeTask() + try await withCheckedThrowingContinuation { continuation in + caller.renameFolder(with: folderToRename, to: name) { result in + self.refreshProgress.completeTask() - switch result { - case .success: - completion(.success(())) - case .failure(let error): - folder.name = nameBefore - completion(.failure(error)) + switch result { + case .success: + continuation.resume() + case .failure(let error): + folder.name = nameBefore + continuation.resume(throwing: error) + } } } - - folder.name = name } func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> ()) { diff --git a/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift index 6d3723def..229694dc1 100644 --- a/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/AccountDelegates/ReaderAPIAccountDelegate.swift @@ -300,26 +300,24 @@ public enum ReaderAPIAccountDelegateError: LocalizedError { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) { - + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { + refreshProgress.addToNumberOfTasksAndRemaining(1) - caller.renameTag(oldName: folder.name ?? "", newName: name) { result in - self.refreshProgress.completeTask() - switch result { - case .success: - DispatchQueue.main.async { + + try await withCheckedThrowingContinuation { continuation in + caller.renameTag(oldName: folder.name ?? "", newName: name) { @MainActor result in + self.refreshProgress.completeTask() + switch result { + case .success: folder.externalID = "user/-/label/\(name)" folder.name = name - completion(.success(())) - } - case .failure(let error): - DispatchQueue.main.async { + continuation.resume() + case .failure(let error): let wrappedError = WrappedAccountError(accountID: account.accountID, accountNameForDisplay: account.nameForDisplay, underlyingError: error) - completion(.failure(wrappedError)) + continuation.resume(throwing: wrappedError) } } } - } func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index 6899e2b8f..bc8338a32 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -310,17 +310,20 @@ final class CloudKitAccountDelegate: AccountDelegate, Logging { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) { + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { refreshProgress.addToNumberOfTasksAndRemaining(1) - accountZone.renameFolder(folder, to: name) { result in - self.refreshProgress.completeTask() - switch result { - case .success: - folder.name = name - completion(.success(())) - case .failure(let error): - self.processAccountError(account, error) - completion(.failure(error)) + + try await withCheckedThrowingContinuation { continuation in + accountZone.renameFolder(folder, to: name) { result in + self.refreshProgress.completeTask() + switch result { + case .success: + folder.name = name + continuation.resume() + case .failure(let error): + self.processAccountError(account, error) + continuation.resume(throwing: error) + } } } } diff --git a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift index f35191b0c..ce4c38feb 100644 --- a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift @@ -269,29 +269,29 @@ final class FeedlyAccountDelegate: AccountDelegate, Logging { } } - func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result) -> Void) { + func renameFolder(for account: Account, with folder: Folder, to name: String) async throws { guard let id = folder.externalID else { - return DispatchQueue.main.async { - completion(.failure(FeedlyAccountDelegateError.unableToRenameFolder(folder.nameForDisplay, name))) - } + throw FeedlyAccountDelegateError.unableToRenameFolder(folder.nameForDisplay, name) } - + let nameBefore = folder.name - - caller.renameCollection(with: id, to: name) { result in - switch result { - case .success(let collection): - folder.name = collection.label - completion(.success(())) - case .failure(let error): - folder.name = nameBefore - completion(.failure(error)) + + try await withCheckedThrowingContinuation { continuation in + caller.renameCollection(with: id, to: name) { result in + switch result { + case .success(let collection): + folder.name = collection.label + continuation.resume() + case .failure(let error): + folder.name = nameBefore + continuation.resume(throwing: error) + } } + + folder.name = name } - - folder.name = name } - + func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result) -> Void) { guard let id = folder.externalID else { return DispatchQueue.main.async { diff --git a/Account/Sources/Account/Folder.swift b/Account/Sources/Account/Folder.swift index c92216b8c..4fade0d40 100644 --- a/Account/Sources/Account/Folder.swift +++ b/Account/Sources/Account/Folder.swift @@ -66,9 +66,9 @@ public final class Folder: FeedProtocol, Container, Hashable { // MARK: - Renamable - @MainActor public func rename(to name: String, completion: @escaping (Result) -> Void) { + @MainActor public func rename(to name: String) async throws { guard let account = account else { return } - account.renameFolder(self, to: name, completion: completion) + try await account.renameFolder(self, to: name) } // MARK: - Init diff --git a/Mac/Inspector/FolderInspectorViewController.swift b/Mac/Inspector/FolderInspectorViewController.swift index 8fa655396..b26e54b87 100644 --- a/Mac/Inspector/FolderInspectorViewController.swift +++ b/Mac/Inspector/FolderInspectorViewController.swift @@ -108,18 +108,18 @@ private extension FolderInspectorViewController { func renameFolderIfNecessary() { guard let folder = folder, let account = folder.account, - let nameTextField = nameTextField, - folder.nameForDisplay != nameTextField.stringValue else { + let newName = nameTextField?.stringValue, + folder.nameForDisplay != newName else { return } - - account.renameFolder(folder, to: nameTextField.stringValue) { [weak self] result in - if case .failure(let error) = result { - self?.presentError(error) - } else { - self?.windowTitle = folder.nameForDisplay + + Task { @MainActor in + do { + try await account.renameFolder(folder, to: newName) + self.windowTitle = folder.nameForDisplay + } catch { + self.presentError(error) } } } - } diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index 9089ff609..c58a86240 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -228,22 +228,17 @@ extension SidebarViewController: RenameWindowControllerDelegate { func renameWindowController(_ windowController: RenameWindowController, didRenameObject object: Any, withNewName name: String) { - if let feed = object as? Feed { - Task { @MainActor in - do { + Task { @MainActor in + + do { + if let feed = object as? Feed { try await feed.rename(to: name) - } catch let error { - NSApplication.shared.presentError(error) } - } - } else if let folder = object as? Folder { - folder.rename(to: name) { result in - switch result { - case .success: - break - case .failure(let error): - NSApplication.shared.presentError(error) + else if let folder = object as? Folder { + try await folder.rename(to: name) } + } catch { + NSApplication.shared.presentError(error) } } }