Convert createFeed to async await.

This commit is contained in:
Brent Simmons 2024-04-02 20:46:28 -07:00
parent 323d0404f2
commit 8fa2d9bda4
15 changed files with 161 additions and 107 deletions

View File

@ -612,8 +612,9 @@ public enum FetchType {
try await delegate.addFeed(for: self, with: feed, to: container)
}
public func createFeed(url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
delegate.createFeed(for: self, url: url, name: name, container: container, validateFeed: validateFeed, completion: completion)
public func createFeed(url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await delegate.createFeed(for: self, url: url, name: name, container: container, validateFeed: validateFeed)
}
func createFeed(with name: String?, url: String, feedID: String, homePageURL: String?) -> Feed {

View File

@ -36,7 +36,7 @@ import Secrets
func renameFolder(for account: Account, with folder: Folder, to name: String) async throws
func removeFolder(for account: Account, with folder: Folder) async throws
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void)
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed
func renameFeed(for account: Account, with feed: Feed, to name: String) async throws
func addFeed(for account: Account, with: Feed, to container: Container) async throws
func removeFeed(for account: Account, with feed: Feed, from container: Container) async throws

View File

@ -243,7 +243,21 @@ enum CloudKitAccountDelegateError: LocalizedError {
}
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await withCheckedThrowingContinuation { continuation in
self.createFeed(for: account, url: url, name: name, container: container, validateFeed: validateFeed) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
private func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(LocalAccountDelegateError.invalidParameter))
return

View File

@ -467,7 +467,21 @@ final class FeedbinAccountDelegate: AccountDelegate {
}
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await withCheckedThrowingContinuation { continuation in
self.createFeed(for: account, url: url, name: name, container: container, validateFeed: validateFeed) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
private func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
refreshProgress.addToNumberOfTasksAndRemaining(1)
caller.createSubscription(url: url) { result in

View File

@ -419,7 +419,21 @@ final class FeedlyAccountDelegate: AccountDelegate {
}
}
@MainActor func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await withCheckedThrowingContinuation { continuation in
self.createFeed(for: account, url: url, name: name, container: container, validateFeed: validateFeed) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
private func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
do {
guard let credentials = credentials else {

View File

@ -82,6 +82,24 @@ final class LocalAccountDelegate: AccountDelegate {
}
}
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
guard let url = URL(string: urlString) else {
throw LocalAccountDelegateError.invalidParameter
}
return try await withCheckedThrowingContinuation { continuation in
self.createRSSFeed(for: account, url: url, editedName: name, container: container) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(LocalAccountDelegateError.invalidParameter))

View File

@ -515,7 +515,21 @@ final class NewsBlurAccountDelegate: AccountDelegate {
}
}
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> ()) {
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await withCheckedThrowingContinuation { continuation in
self.createFeed(for: account, url: url, name: name, container: container, validateFeed: validateFeed) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
private func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> ()) {
refreshProgress.addToNumberOfTasksAndRemaining(1)
let folderName = (container as? Folder)?.name

View File

@ -469,7 +469,21 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
}
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool) async throws -> Feed {
try await withCheckedThrowingContinuation { continuation in
self.createFeed(for: account, url: url, name: name, container: container, validateFeed: validateFeed) { result in
switch result {
case .success(let feed):
continuation.resume(returning: feed)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
private func createFeed(for account: Account, url: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
guard let url = URL(string: url) else {
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
return

View File

@ -62,31 +62,25 @@ import RSParser
return
}
account.createFeed(url: url.absoluteString, name: title, container: container, validateFeed: true) { result in
DispatchQueue.main.async {
self.endShowingProgress()
}
switch result {
case .success(let feed):
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed])
case .failure(let error):
switch error {
case AccountError.createErrorAlreadySubscribed:
self.showAlreadySubscribedError(url.absoluteString)
case AccountError.createErrorNotFound:
self.showNoFeedsErrorMessage()
default:
DispatchQueue.main.async {
NSApplication.shared.presentError(error)
}
}
}
}
beginShowingProgress()
Task { @MainActor in
do {
let feed = try await account.createFeed(url: url.absoluteString, name: title, container: container, validateFeed: true)
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed])
} catch AccountError.createErrorAlreadySubscribed {
self.showAlreadySubscribedError(url.absoluteString)
} catch AccountError.createErrorNotFound {
self.showNoFeedsErrorMessage()
} catch {
NSApplication.shared.presentError(error)
}
self.endShowingProgress()
}
}
func addFeedWindowControllerUserDidCancel(_: AddFeedWindowController) {

View File

@ -14,8 +14,8 @@ import Account
protocol AddFeedWindowControllerDelegate: AnyObject {
// userEnteredURL will have already been validated and normalized.
func addFeedWindowController(_: AddFeedWindowController, userEnteredURL: URL, userEnteredTitle: String?, container: Container)
func addFeedWindowControllerUserDidCancel(_: AddFeedWindowController)
@MainActor func addFeedWindowController(_: AddFeedWindowController, userEnteredURL: URL, userEnteredTitle: String?, container: Container)
@MainActor func addFeedWindowControllerUserDidCancel(_: AddFeedWindowController)
}
class AddFeedWindowController : NSWindowController {

View File

@ -346,11 +346,11 @@ private extension SidebarOutlineDataSource {
func copyFeedBetweenAccounts(node: Node, to parentNode: Node) {
guard let feed = node.representedObject as? Feed,
let destinationAccount = nodeAccount(parentNode),
let destinationContainer = parentNode.representedObject as? Container else {
let destinationAccount = nodeAccount(parentNode),
let destinationContainer = parentNode.representedObject as? Container else {
return
}
if let existingFeed = destinationAccount.existingFeed(withURL: feed.url) {
Task { @MainActor in
@ -361,11 +361,10 @@ private extension SidebarOutlineDataSource {
}
}
} else {
destinationAccount.createFeed(url: feed.url, name: feed.nameForDisplay, container: destinationContainer, validateFeed: false) { result in
switch result {
case .success:
break
case .failure(let error):
Task { @MainActor in
do {
try await destinationAccount.createFeed(url: feed.url, name: feed.nameForDisplay, container: destinationContainer, validateFeed: false)
} catch {
NSApplication.shared.presentError(error)
}
}
@ -425,10 +424,10 @@ private extension SidebarOutlineDataSource {
}
func copyFolderBetweenAccounts(node: Node, to parentNode: Node) {
guard let folder = node.representedObject as? Folder,
let destinationAccount = nodeAccount(parentNode) else {
return
let destinationAccount = nodeAccount(parentNode) else {
return
}
Task { @MainActor in
@ -440,17 +439,9 @@ private extension SidebarOutlineDataSource {
if let existingFeed = destinationAccount.existingFeed(withURL: feed.url) {
try await destinationAccount.addFeed(existingFeed, to: destinationFolder)
} else {
destinationAccount.createFeed(url: feed.url, name: feed.nameForDisplay, container: destinationFolder, validateFeed: false) { result in
switch result {
case .success:
break
case .failure(let error):
NSApplication.shared.presentError(error)
}
}
try await destinationAccount.createFeed(url: feed.url, name: feed.nameForDisplay, container: destinationFolder, validateFeed: false)
}
}
} catch {
NSApplication.shared.presentError(error)
}

View File

@ -102,19 +102,19 @@ import Articles
// suspendExecution(). When we get the callback, we supply the event result and call resumeExecution().
command.suspendExecution()
account.createFeed(url: url, name: titleFromArgs, container: container, validateFeed: true) { result in
switch result {
case .success(let feed):
Task { @MainActor in
do {
let feed = try await account.createFeed(url: url, name: titleFromArgs, container: container, validateFeed: true)
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed])
let scriptableFeed = self.scriptableFeed(feed, account:account, folder:folder)
command.resumeExecution(withResult:scriptableFeed.objectSpecifier)
case .failure:
} catch {
command.resumeExecution(withResult:nil)
}
}
return nil
return nil
}
// MARK: --- Scriptable properties ---

View File

@ -156,7 +156,8 @@ private extension ExtensionFeedAddRequestFile {
guard let container = destinationContainer else { return }
account.createFeed(url: request.feedURL.absoluteString, name: request.name, container: container, validateFeed: true) { _ in }
}
Task { @MainActor in
try? await account.createFeed(url: request.feedURL.absoluteString, name: request.name, container: container, validateFeed: true)
}
}
}

View File

@ -117,23 +117,21 @@ class AddFeedViewController: UITableViewController {
BatchUpdate.shared.start()
account!.createFeed(url: url.absoluteString, name: feedName, container: container, validateFeed: true) { result in
BatchUpdate.shared.end()
switch result {
case .success(let feed):
Task { @MainActor in
do {
let feed = try await account!.createFeed(url: url.absoluteString, name: feedName, container: container, validateFeed: true)
self.dismiss(animated: true)
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed])
case .failure(let error):
} catch {
self.addButton.isEnabled = true
self.activityIndicator.isHidden = true
self.activityIndicator.stopAnimating()
self.presentError(error)
}
BatchUpdate.shared.end()
}
}
@objc func textDidChange(_ note: Notification) {

View File

@ -109,55 +109,36 @@ extension SidebarViewController: UITableViewDropDelegate {
do {
try await sourceContainer.account?.moveFeed(feed, from: sourceContainer, to: destinationContainer)
BatchUpdate.shared.end()
} catch {
BatchUpdate.shared.end()
self.presentError(error)
}
BatchUpdate.shared.end()
}
}
func moveFeedBetweenAccounts(feed: Feed, sourceContainer: Container, destinationContainer: Container) {
if let existingFeed = destinationContainer.account?.existingFeed(withURL: feed.url) {
let existingFeed = destinationContainer.account?.existingFeed(withURL: feed.url)
BatchUpdate.shared.start()
BatchUpdate.shared.start()
Task { @MainActor in
Task { @MainActor in
do {
do {
if let existingFeed {
try await destinationContainer.account?.addFeed(existingFeed, to: destinationContainer)
try await sourceContainer.account?.removeFeed(feed, from: sourceContainer)
BatchUpdate.shared.end()
} catch {
BatchUpdate.shared.end()
self.presentError(error)
}
}
} else {
BatchUpdate.shared.start()
destinationContainer.account?.createFeed(url: feed.url, name: feed.editedName, container: destinationContainer, validateFeed: false) { result in
switch result {
case .success:
Task { @MainActor in
do {
try await sourceContainer.account?.removeFeed(feed, from: sourceContainer)
BatchUpdate.shared.end()
} catch {
BatchUpdate.shared.end()
self.presentError(error)
}
}
case .failure(let error):
BatchUpdate.shared.end()
self.presentError(error)
}
} else {
_ = try await destinationContainer.account?.createFeed(url: feed.url, name: feed.editedName, container: destinationContainer, validateFeed: false)
}
try await sourceContainer.account?.removeFeed(feed, from: sourceContainer)
} catch {
self.presentError(error)
}
BatchUpdate.shared.end()
}
}
}