diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index c30e7eaf..0d33e41d 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -103,7 +103,7 @@ struct IceCubesApp: App { if tab == .notifications, selectedTab != tab, let token = appAccountsManager.currentAccount.oauthToken { - return watcher.unreadNotificationsCount + userPreferences.getNotificationsCount(for: token) + return watcher.unreadNotificationsCount + (userPreferences.notificationsCount[token] ?? 0) } return 0 } @@ -176,7 +176,7 @@ struct IceCubesApp: App { if selectedTab == .notifications, let token = appAccountsManager.currentAccount.oauthToken { - userPreferences.setNotification(count: 0, token: token) + userPreferences.notificationsCount[token] = 0 watcher.unreadNotificationsCount = 0 } } @@ -217,6 +217,7 @@ struct IceCubesApp: App { case .active: watcher.watch(streams: [.user, .direct]) UNUserNotificationCenter.current().setBadgeCount(0) + userPreferences.reloadNotificationsCount(tokens: appAccountsManager.availableAccounts.compactMap{ $0.oauthToken }) Task { await userPreferences.refreshServerPreferences() } @@ -285,6 +286,12 @@ class AppDelegate: NSObject, UIApplicationDelegate { } func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {} + + func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) async -> UIBackgroundFetchResult { + + UserPreferences.shared.reloadNotificationsCount(tokens: AppAccountsManager.shared.availableAccounts.compactMap{ $0.oauthToken }) + return .noData + } func application(_: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options _: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role) diff --git a/IceCubesApp/App/SideBarView.swift b/IceCubesApp/App/SideBarView.swift index 6036e910..5bb1cf1f 100644 --- a/IceCubesApp/App/SideBarView.swift +++ b/IceCubesApp/App/SideBarView.swift @@ -22,7 +22,7 @@ struct SideBarView: View { if tab == .notifications, selectedTab != tab, let token = appAccounts.currentAccount.oauthToken { - return watcher.unreadNotificationsCount + userPreferences.getNotificationsCount(for: token) + return watcher.unreadNotificationsCount + (userPreferences.notificationsCount[token] ?? 0) } return 0 } @@ -82,9 +82,10 @@ struct SideBarView: View { AppAccountView(viewModel: .init(appAccount: account, isCompact: true)) if showBadge, let token = account.oauthToken, - userPreferences.getNotificationsCount(for: token) > 0 + let notificationsCount = userPreferences.notificationsCount[token], + notificationsCount > 0 { - makeBadgeView(count: userPreferences.getNotificationsCount(for: token)) + makeBadgeView(count: notificationsCount) } } } @@ -110,7 +111,7 @@ struct SideBarView: View { SoundEffectManager.shared.playSound(of: .tabSelection) if tab == .notifications { if let token = appAccounts.currentAccount.oauthToken { - userPreferences.setNotification(count: 0, token: token) + userPreferences.notificationsCount[token] = 0 } watcher.unreadNotificationsCount = 0 } diff --git a/IceCubesApp/App/Tabs/NotificationTab.swift b/IceCubesApp/App/Tabs/NotificationTab.swift index 5e76fb0c..2e953aee 100644 --- a/IceCubesApp/App/Tabs/NotificationTab.swift +++ b/IceCubesApp/App/Tabs/NotificationTab.swift @@ -90,7 +90,7 @@ struct NotificationsTab: View { private func clearNotifications() { if isSecondaryColumn { if let token = appAccount.currentAccount.oauthToken { - userPreferences.setNotification(count: 0, token: token) + userPreferences.notificationsCount[token] = 0 } watcher.unreadNotificationsCount = 0 } diff --git a/IceCubesNotifications/NotificationService.swift b/IceCubesNotifications/NotificationService.swift index bd2c149a..41c79f5b 100644 --- a/IceCubesNotifications/NotificationService.swift +++ b/IceCubesNotifications/NotificationService.swift @@ -64,14 +64,16 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "glass.caf")) let preferences = UserPreferences.shared + let tokens = AppAccountsManager.shared.pushAccounts.map(\.token) + preferences.reloadNotificationsCount(tokens: tokens) + if let token = AppAccountsManager.shared.availableAccounts.first(where: { $0.oauthToken?.accessToken == notification.accessToken })?.oauthToken { - var currentCount = preferences.getNotificationsCount(for: token) + var currentCount = preferences.notificationsCount[token] ?? 0 currentCount += 1 - preferences.setNotification(count: currentCount, token: token) + preferences.notificationsCount[token] = currentCount } - let tokens = AppAccountsManager.shared.pushAccounts.map(\.token) - bestAttemptContent.badge = .init(integerLiteral: preferences.getNotificationsTotalCount(for: tokens)) + bestAttemptContent.badge = .init(integerLiteral: preferences.totalNotificationsCount) if let urlString = notification.icon, let url = URL(string: urlString) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift index 09729768..733f2e50 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift @@ -67,9 +67,9 @@ public struct AppAccountView: View { .offset(x: 5, y: -5) } else if viewModel.showBadge, let token = viewModel.appAccount.oauthToken, - preferences.getNotificationsCount(for: token) > 0 + let notificationsCount = preferences.notificationsCount[token], + notificationsCount > 0 { - let notificationsCount = preferences.getNotificationsCount(for: token) ZStack { Circle() .fill(.red) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index 785f5085..192dd429 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -20,7 +20,7 @@ public struct AppAccountsSelectorView: View { accountsViewModel .filter { $0.account?.id != currentAccount.account?.id } .compactMap(\.appAccount.oauthToken) - .map { preferences.getNotificationsCount(for: $0) } + .map { preferences.notificationsCount[$0] ?? 0 } .reduce(0, +) > 0 } diff --git a/Packages/Env/Sources/Env/UserPreferences.swift b/Packages/Env/Sources/Env/UserPreferences.swift index 19e5776e..15252c55 100644 --- a/Packages/Env/Sources/Env/UserPreferences.swift +++ b/Packages/Env/Sources/Env/UserPreferences.swift @@ -133,23 +133,25 @@ public class UserPreferences: ObservableObject { } } - public func setNotification(count: Int, token: OauthToken) { - Self.sharedDefault?.set(count, forKey: "push_notifications_count_\(token.createdAt)") - objectWillChange.send() - } - - public func getNotificationsCount(for token: OauthToken) -> Int { - Self.sharedDefault?.integer(forKey: "push_notifications_count_\(token.createdAt)") ?? 0 - } - - public func getNotificationsTotalCount(for tokens: [OauthToken]) -> Int { - var count = 0 - for token in tokens { - count += getNotificationsCount(for: token) + @Published public var notificationsCount: [OauthToken: Int] = [:] { + didSet { + for (key, value) in notificationsCount { + Self.sharedDefault?.set(value, forKey: "push_notifications_count_\(key.createdAt)") + } } - return count } - + + public var totalNotificationsCount: Int { + notificationsCount.compactMap{ $0.value }.reduce(0, +) + } + + public func reloadNotificationsCount(tokens: [OauthToken]) { + notificationsCount = [:] + for token in tokens { + notificationsCount[token] = Self.sharedDefault?.integer(forKey: "push_notifications_count_\(token.createdAt)") ?? 0 + } + } + @Published public var serverPreferences: ServerPreferences? private init() {}