From f0be57b77c7661068f980e39baa634fcb1572c84 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Tue, 16 Apr 2024 23:10:55 -0700 Subject: [PATCH] Convert FeedIconDownloader to async await. --- .../Sources/Images/FeedIconDownloader.swift | 79 +++++++++---------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/Images/Sources/Images/FeedIconDownloader.swift b/Images/Sources/Images/FeedIconDownloader.swift index 7d49bb26f..80bd62ca6 100644 --- a/Images/Sources/Images/FeedIconDownloader.swift +++ b/Images/Sources/Images/FeedIconDownloader.swift @@ -18,7 +18,7 @@ public extension Notification.Name { static let FeedIconDidBecomeAvailable = Notification.Name("FeedIconDidBecomeAvailableNotification") // UserInfoKey.feed } -public protocol FeedIconDownloaderDelegate { +public protocol FeedIconDownloaderDelegate: Sendable { var appIconImage: IconImage? { get } @@ -96,42 +96,40 @@ public protocol FeedIconDownloaderDelegate { guard let homePageURL = feed.homePageURL else { return } - icon(forHomePageURL: homePageURL, feed: feed) { (image) in - Task { @MainActor in - if let image { - self.postFeedIconDidBecomeAvailableNotification(feed) - self.cache[feed] = IconImage(image) - } + + Task { @MainActor in + if let image = await icon(forHomePageURL: homePageURL, feed: feed) { + postFeedIconDidBecomeAvailableNotification(feed) + cache[feed] = IconImage(image) } } } func checkFeedIconURL() { - if let iconURL = feed.iconURL { - icon(forURL: iconURL, feed: feed) { (image) in - Task { @MainActor in - if let image { - self.postFeedIconDidBecomeAvailableNotification(feed) - self.cache[feed] = IconImage(image) - } else { - checkHomePageURL() - } - } - } - } else { + guard let iconURL = feed.iconURL else { checkHomePageURL() + return + } + + Task { @MainActor in + if let image = await icon(forURL: iconURL, feed: feed) { + postFeedIconDidBecomeAvailableNotification(feed) + cache[feed] = IconImage(image) + } else { + checkHomePageURL() + } } } - + if let feedProviderURL = feedURLToIconURLCache[feed.url] { - self.icon(forURL: feedProviderURL, feed: feed) { (image) in - Task { @MainActor in - if let image = image { - self.postFeedIconDidBecomeAvailableNotification(feed) - self.cache[feed] = IconImage(image) - } + + Task { @MainActor in + if let image = await icon(forURL: feedProviderURL, feed: feed) { + postFeedIconDidBecomeAvailableNotification(feed) + cache[feed] = IconImage(image) } } + return nil } @@ -170,32 +168,29 @@ public protocol FeedIconDownloaderDelegate { private extension FeedIconDownloader { - func icon(forHomePageURL homePageURL: String, feed: Feed, _ imageResultBlock: @Sendable @escaping (RSImage?) -> Void) { + func icon(forHomePageURL homePageURL: String, feed: Feed) async -> RSImage? { if homePagesWithNoIconURLCache.contains(homePageURL) || homePagesWithUglyIcons.contains(homePageURL) { - imageResultBlock(nil) - return + return nil } if let iconURL = cachedIconURL(for: homePageURL) { - icon(forURL: iconURL, feed: feed, imageResultBlock) - return + return await icon(forURL: iconURL, feed: feed) } findIconURLForHomePageURL(homePageURL, feed: feed, downloadMetadata: delegate!.downloadMetadata(_:)) + + return nil } - func icon(forURL url: String, feed: Feed, _ imageResultBlock: @Sendable @escaping (RSImage?) -> Void) { - waitingForFeedURLs[url] = feed - guard let imageData = imageDownloader.image(for: url) else { - imageResultBlock(nil) - return - } + func icon(forURL url: String, feed: Feed) async -> RSImage? { - Task { - let image = await RSImage.scaledForIcon(imageData) - imageResultBlock(image) + waitingForFeedURLs[url] = feed + + guard let imageData = imageDownloader.image(for: url) else { + return nil } + return await RSImage.scaledForIcon(imageData) } func postFeedIconDidBecomeAvailableNotification(_ feed: Feed) { @@ -241,7 +236,8 @@ private extension FeedIconDownloader { if let url = metadata.bestWebsiteIconURL() { cacheIconURL(for: homePageURL, url) - icon(forURL: url, feed: feed) { (image) in + Task { @MainActor in + await icon(forURL: url, feed: feed) } return } @@ -331,5 +327,4 @@ private extension FeedIconDownloader { assertionFailure(error.localizedDescription) } } - }