From 9a6314f2d9fe68141be9e9a937a35f705f0b68c8 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sun, 24 Mar 2024 18:49:39 -0700 Subject: [PATCH] Fix numerous warnings. --- Account/Sources/Account/Account.swift | 11 ++++ Shared/Extensions/RSImage-Extensions.swift | 18 +++++-- Shared/Images/AuthorAvatarDownloader.swift | 5 +- Shared/Images/FeedIconDownloader.swift | 6 ++- Shared/SmartFeeds/SearchFeedDelegate.swift | 5 +- .../SearchTimelineFeedDelegate.swift | 5 +- Shared/SmartFeeds/SmartFeed.swift | 53 +++++++++---------- Shared/SmartFeeds/SmartFeedDelegate.swift | 3 +- Shared/SmartFeeds/StarredFeedDelegate.swift | 5 ++ Shared/SmartFeeds/TodayFeedDelegate.swift | 5 +- 10 files changed, 74 insertions(+), 42 deletions(-) diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index b77d931a3..25fa7f6e3 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -747,10 +747,21 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, return try await unreadArticles(feeds: feeds) } + public func unreadCountForToday() async throws -> Int { + + try await database.unreadCountForToday(feedIDs: allFeedIDs()) ?? 0 + } + public func fetchUnreadCountForToday(_ completion: @escaping SingleUnreadCountCompletionBlock) { + database.fetchUnreadCountForToday(for: flattenedFeeds().feedIDs(), completion: completion) } + public func unreadCountForStarredArticles() async throws -> Int { + + try await database.starredAndUnreadCount(feedIDs: allFeedIDs()) ?? 0 + } + public func fetchUnreadCountForStarredArticles(_ completion: @escaping SingleUnreadCountCompletionBlock) { database.fetchStarredAndUnreadCount(for: flattenedFeeds().feedIDs(), completion: completion) } diff --git a/Shared/Extensions/RSImage-Extensions.swift b/Shared/Extensions/RSImage-Extensions.swift index 5d6c6ac29..1737de3f5 100644 --- a/Shared/Extensions/RSImage-Extensions.swift +++ b/Shared/Extensions/RSImage-Extensions.swift @@ -27,9 +27,9 @@ extension RSImage { return maxIconSize * maxScreenScale }() + static func scaledForIcon(_ data: Data) async -> RSImage? { - static func scaledForIcon(_ data: Data, imageResultBlock: @escaping ImageResultBlock) { - IconScalerQueue.shared.scaledForIcon(data, imageResultBlock) + await IconScalerQueue.shared.scaledForIcon(data) } static func scaledForIcon(_ data: Data) -> RSImage? { @@ -60,11 +60,19 @@ private final class IconScalerQueue: @unchecked Sendable { return q }() - func scaledForIcon(_ data: Data, _ imageResultBlock: @escaping ImageResultBlock) { + private func scaledForIcon(_ data: Data, _ imageResultBlock: @escaping ImageResultBlock) { queue.async { let image = RSImage.scaledForIcon(data) - DispatchQueue.main.async { - imageResultBlock(image) + imageResultBlock(image) + } + } + + func scaledForIcon(_ data: Data) async -> RSImage? { + + await withCheckedContinuation { continuation in + + self.scaledForIcon(data) { image in + continuation.resume(returning: image) } } } diff --git a/Shared/Images/AuthorAvatarDownloader.swift b/Shared/Images/AuthorAvatarDownloader.swift index 82efc8471..21210528b 100644 --- a/Shared/Images/AuthorAvatarDownloader.swift +++ b/Shared/Images/AuthorAvatarDownloader.swift @@ -68,8 +68,9 @@ final class AuthorAvatarDownloader { private extension AuthorAvatarDownloader { func scaleAndCacheImageData(_ imageData: Data, _ avatarURL: String) { - RSImage.scaledForIcon(imageData) { (image) in - if let image = image { + + Task { @MainActor in + if let image = await RSImage.scaledForIcon(imageData) { self.handleImageDidBecomeAvailable(avatarURL, image) } } diff --git a/Shared/Images/FeedIconDownloader.swift b/Shared/Images/FeedIconDownloader.swift index 874c497ce..2ea3ff69a 100644 --- a/Shared/Images/FeedIconDownloader.swift +++ b/Shared/Images/FeedIconDownloader.swift @@ -180,7 +180,11 @@ private extension FeedIconDownloader { imageResultBlock(nil) return } - RSImage.scaledForIcon(imageData, imageResultBlock: imageResultBlock) + + Task { + let image = await RSImage.scaledForIcon(imageData) + imageResultBlock(image) + } } func postFeedIconDidBecomeAvailableNotification(_ feed: Feed) { diff --git a/Shared/SmartFeeds/SearchFeedDelegate.swift b/Shared/SmartFeeds/SearchFeedDelegate.swift index 5c6aa685a..923200d35 100644 --- a/Shared/SmartFeeds/SearchFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchFeedDelegate.swift @@ -31,8 +31,9 @@ struct SearchFeedDelegate: SmartFeedDelegate { self.fetchType = .search(searchString) } - func fetchUnreadCount(for: Account, completion: @escaping SingleUnreadCountCompletionBlock) { - // TODO: after 5.0 + func unreadCount(account: Account) async -> Int { + + return 0 } } diff --git a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift index 2c4a5965f..e420001f0 100644 --- a/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift +++ b/Shared/SmartFeeds/SearchTimelineFeedDelegate.swift @@ -31,7 +31,8 @@ struct SearchTimelineFeedDelegate: SmartFeedDelegate { self.fetchType = .searchWithArticleIDs(searchString, articleIDs) } - func fetchUnreadCount(for: Account, completion: @escaping SingleUnreadCountCompletionBlock) { - // TODO: after 5.0 + func unreadCount(account: Account) async -> Int { + + return 0 } } diff --git a/Shared/SmartFeeds/SmartFeed.swift b/Shared/SmartFeeds/SmartFeed.swift index e617152af..a80b1efc3 100644 --- a/Shared/SmartFeeds/SmartFeed.swift +++ b/Shared/SmartFeeds/SmartFeed.swift @@ -50,21 +50,22 @@ final class SmartFeed: PseudoFeed { private let delegate: SmartFeedDelegate private var unreadCounts = [String: Int]() - init(delegate: SmartFeedDelegate) { + @MainActor init(delegate: SmartFeedDelegate) { self.delegate = delegate NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) queueFetchUnreadCounts() // Fetch unread count at startup } - @objc func unreadCountDidChange(_ note: Notification) { + @MainActor @objc func unreadCountDidChange(_ note: Notification) { if note.object is AppDelegate { queueFetchUnreadCounts() } } - @objc @MainActor func fetchUnreadCounts() { + @MainActor @objc func fetchUnreadCounts() { + let activeAccounts = AccountManager.shared.activeAccounts - + // Remove any accounts that are no longer active or have been deleted let activeAccountIDs = activeAccounts.map { $0.accountID } unreadCounts.keys.forEach { accountID in @@ -72,14 +73,18 @@ final class SmartFeed: PseudoFeed { unreadCounts.removeValue(forKey: accountID) } } - + if activeAccounts.isEmpty { updateUnreadCount() - } else { - activeAccounts.forEach { self.fetchUnreadCount(for: $0) } + return + } + + Task { @MainActor in + for account in activeAccounts { + await fetchUnreadCount(for: account) + } } } - } extension SmartFeed: ArticleFetcher { @@ -107,31 +112,25 @@ extension SmartFeed: ArticleFetcher { private extension SmartFeed { - func queueFetchUnreadCounts() { - Task { @MainActor in - CoalescingQueue.standard.add(self, #selector(fetchUnreadCounts)) - } + @MainActor func queueFetchUnreadCounts() { + CoalescingQueue.standard.add(self, #selector(fetchUnreadCounts)) } - func fetchUnreadCount(for account: Account) { - delegate.fetchUnreadCount(for: account) { singleUnreadCountResult in + @MainActor func fetchUnreadCount(for account: Account) async { - MainActor.assumeIsolated { - guard let accountUnreadCount = try? singleUnreadCountResult.get() else { - return - } - self.unreadCounts[account.accountID] = accountUnreadCount - self.updateUnreadCount() - } - } + let unreadCount = await delegate.unreadCount(account: account) + unreadCounts[account.accountID] = unreadCount + + updateUnreadCount() } @MainActor func updateUnreadCount() { - unreadCount = AccountManager.shared.activeAccounts.reduce(0) { (result, account) -> Int in - if let oneUnreadCount = unreadCounts[account.accountID] { - return result + oneUnreadCount - } - return result + + var unread = 0 + for account in AccountManager.shared.activeAccounts { + unread = unread + (unreadCounts[account.accountID] ?? 0) } + + unreadCount = unread } } diff --git a/Shared/SmartFeeds/SmartFeedDelegate.swift b/Shared/SmartFeeds/SmartFeedDelegate.swift index 87736efd6..a039b4856 100644 --- a/Shared/SmartFeeds/SmartFeedDelegate.swift +++ b/Shared/SmartFeeds/SmartFeedDelegate.swift @@ -17,7 +17,8 @@ protocol SmartFeedDelegate: SidebarItemIdentifiable, DisplayNameProvider, Articl var fetchType: FetchType { get } - func fetchUnreadCount(for: Account, completion: @escaping SingleUnreadCountCompletionBlock) + func unreadCount(account: Account) async -> Int +// func fetchUnreadCount(for: Account, completion: @escaping SingleUnreadCountCompletionBlock) } extension SmartFeedDelegate { diff --git a/Shared/SmartFeeds/StarredFeedDelegate.swift b/Shared/SmartFeeds/StarredFeedDelegate.swift index bd0db9544..b471fc1e9 100644 --- a/Shared/SmartFeeds/StarredFeedDelegate.swift +++ b/Shared/SmartFeeds/StarredFeedDelegate.swift @@ -25,6 +25,11 @@ struct StarredFeedDelegate: SmartFeedDelegate { return AppAssets.starredFeedImage } + func unreadCount(account: Account) async -> Int { + + (try? await account.unreadCountForStarredArticles()) ?? 0 + } + func fetchUnreadCount(for account: Account, completion: @escaping SingleUnreadCountCompletionBlock) { account.fetchUnreadCountForStarredArticles(completion) } diff --git a/Shared/SmartFeeds/TodayFeedDelegate.swift b/Shared/SmartFeeds/TodayFeedDelegate.swift index ad510b0e0..f09f7f078 100644 --- a/Shared/SmartFeeds/TodayFeedDelegate.swift +++ b/Shared/SmartFeeds/TodayFeedDelegate.swift @@ -23,8 +23,9 @@ struct TodayFeedDelegate: SmartFeedDelegate { return AppAssets.todayFeedImage } - func fetchUnreadCount(for account: Account, completion: @escaping SingleUnreadCountCompletionBlock) { - account.fetchUnreadCountForToday(completion) + func unreadCount(account: Account) async -> Int { + + (try? await account.unreadCountForToday()) ?? 0 } }