diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index 31abe646..da5b1e75 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -99,8 +99,9 @@ struct IceCubesApp: App { } private func badgeFor(tab: Tab) -> Int { - if tab == .notifications && selectedTab != tab { - return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount + if tab == .notifications && selectedTab != tab, + let token = appAccountsManager.currentAccount.oauthToken { + return watcher.unreadNotificationsCount + userPreferences.getNotificationsCount(for: token) } return 0 } @@ -167,6 +168,11 @@ struct IceCubesApp: App { } } selectedTab = newTab + if selectedTab == .notifications, + let token = appAccountsManager.currentAccount.oauthToken { + userPreferences.setNotification(count: 0, token: token) + watcher.unreadNotificationsCount = 0 + } } HapticManager.shared.fireHaptic(of: .tabSelection) })) { diff --git a/IceCubesApp/App/SideBarView.swift b/IceCubesApp/App/SideBarView.swift index 428dea0d..769047ed 100644 --- a/IceCubesApp/App/SideBarView.swift +++ b/IceCubesApp/App/SideBarView.swift @@ -19,43 +19,36 @@ struct SideBarView: View { @ViewBuilder var content: () -> Content private func badgeFor(tab: Tab) -> Int { - if tab == .notifications && selectedTab != tab { - return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount + if tab == .notifications && selectedTab != tab, + let token = appAccounts.currentAccount.oauthToken { + return watcher.unreadNotificationsCount + userPreferences.getNotificationsCount(for: token) } return 0 } - - private var profileView: some View { - Button { - selectedTab = .profile - } label: { - AppAccountsSelectorView(routerPath: RouterPath(), - accountCreationEnabled: false, - avatarSize: .status) - } - .frame(width: .sidebarWidth, height: 60) - .background(selectedTab == .profile ? theme.secondaryBackgroundColor : .clear) - } - + private func makeIconForTab(tab: Tab) -> some View { ZStack(alignment: .topTrailing) { SideBarIcon(systemIconName: tab.iconName, isSelected: tab == selectedTab) if let badge = badgeFor(tab: tab), badge > 0 { - ZStack { - Circle() - .fill(.red) - Text(String(badge)) - .foregroundColor(.white) - .font(.caption2) - } - .frame(width: 20, height: 20) - .offset(x: 10, y: -10) + makeBadgeView(count: badge) } } .contentShape(Rectangle()) .frame(width: .sidebarWidth, height: 50) } + + private func makeBadgeView(count: Int) -> some View { + ZStack { + Circle() + .fill(.red) + Text(String(count)) + .foregroundColor(.white) + .font(.caption2) + } + .frame(width: 20, height: 20) + .offset(x: 10, y: -10) + } private var postButton: some View { Button { @@ -70,7 +63,7 @@ struct SideBarView: View { .keyboardShortcut("n", modifiers: .command) } - private func makeAccountButton(account: AppAccount) -> some View { + private func makeAccountButton(account: AppAccount, showBadge: Bool) -> some View { Button { if account.id == appAccounts.currentAccount.id { selectedTab = .profile @@ -82,7 +75,14 @@ struct SideBarView: View { } } } label: { - AppAccountView(viewModel: .init(appAccount: account, isCompact: true)) + ZStack(alignment: .topTrailing) { + AppAccountView(viewModel: .init(appAccount: account, isCompact: true)) + if showBadge, + let token = account.oauthToken, + userPreferences.getNotificationsCount(for: token) > 0 { + makeBadgeView(count: userPreferences.getNotificationsCount(for: token)) + } + } } .frame(width: .sidebarWidth, height: 50) .padding(.vertical, 8) @@ -101,8 +101,10 @@ struct SideBarView: View { } selectedTab = tab if tab == .notifications { + if let token = appAccounts.currentAccount.oauthToken { + userPreferences.setNotification(count: 0, token: token) + } watcher.unreadNotificationsCount = 0 - userPreferences.pushNotificationsCount = 0 } } label: { makeIconForTab(tab: tab) @@ -119,7 +121,8 @@ struct SideBarView: View { tabsView } else { ForEach(appAccounts.availableAccounts) { account in - makeAccountButton(account: account) + makeAccountButton(account: account, + showBadge: account.id != appAccounts.currentAccount.id) if account.id == appAccounts.currentAccount.id { tabsView } diff --git a/IceCubesApp/App/Tabs/NotificationTab.swift b/IceCubesApp/App/Tabs/NotificationTab.swift index ae1cd881..e232455a 100644 --- a/IceCubesApp/App/Tabs/NotificationTab.swift +++ b/IceCubesApp/App/Tabs/NotificationTab.swift @@ -44,8 +44,6 @@ struct NotificationsTab: View { } .onAppear { routerPath.client = client - watcher.unreadNotificationsCount = 0 - userPreferences.pushNotificationsCount = 0 } .withSafariRouter() .environmentObject(routerPath) @@ -72,8 +70,10 @@ struct NotificationsTab: View { switch scenePhase { case .active: if isSecondaryColumn { + if let token = appAccount.currentAccount.oauthToken { + userPreferences.setNotification(count: 0, token: token) + } watcher.unreadNotificationsCount = 0 - userPreferences.pushNotificationsCount = 0 } default: break diff --git a/IceCubesNotifications/NotificationService.swift b/IceCubesNotifications/NotificationService.swift index 700357eb..269ce1b1 100644 --- a/IceCubesNotifications/NotificationService.swift +++ b/IceCubesNotifications/NotificationService.swift @@ -64,9 +64,14 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "glass.caf")) let preferences = UserPreferences.shared - preferences.pushNotificationsCount += 1 + if let token = AppAccountsManager.shared.availableAccounts.first(where: { $0.oauthToken?.accessToken == notification.accessToken})?.oauthToken { + var currentCount = preferences.getNotificationsCount(for: token) + currentCount += 1 + preferences.setNotification(count: currentCount, token: token) + } - bestAttemptContent.badge = .init(integerLiteral: preferences.pushNotificationsCount) + let tokens = AppAccountsManager.shared.pushAccounts.map { $0.token } + bestAttemptContent.badge = .init(integerLiteral: preferences.getNotificationsTotalCount(for: tokens)) if let urlString = notification.icon, let url = URL(string: urlString) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index fd5a94b9..91809a7d 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -3,6 +3,7 @@ import Env import SwiftUI public struct AppAccountsSelectorView: View { + @EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var appAccounts: AppAccountsManager @@ -90,7 +91,12 @@ public struct AppAccountsSelectorView: View { if let image = viewModel.roundedAvatar { Image(uiImage: image) } - Text("\(viewModel.account?.displayName ?? "")") + if let token = viewModel.appAccount.oauthToken, + preferences.getNotificationsCount(for: token) > 0 { + Text("\(viewModel.account?.displayName ?? "") (\(preferences.getNotificationsCount(for: token)))") + } else { + Text("\(viewModel.account?.displayName ?? "")") + } } } } diff --git a/Packages/Env/Sources/Env/UserPreferences.swift b/Packages/Env/Sources/Env/UserPreferences.swift index e5247819..02e7680a 100644 --- a/Packages/Env/Sources/Env/UserPreferences.swift +++ b/Packages/Env/Sources/Env/UserPreferences.swift @@ -97,13 +97,20 @@ public class UserPreferences: ObservableObject { } } - public var pushNotificationsCount: Int { - get { - Self.sharedDefault?.integer(forKey: "push_notifications_count") ?? 0 - } - set { - Self.sharedDefault?.set(newValue, forKey: "push_notifications_count") + public func setNotification(count: Int, token: OauthToken) { + Self.sharedDefault?.set(count, forKey: "push_notifications_count_\(token.createdAt)") + } + + 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: Int = 0 + for token in tokens { + count += getNotificationsCount(for: token) } + return count } public var chosenFont: UIFont? {