diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index 5a2c7f51..de0a62a8 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -1,4 +1,5 @@ import SwiftUI +import AVFoundation import Timeline import Network import KeychainSwift @@ -10,7 +11,7 @@ import RevenueCat @main struct IceCubesApp: App { public static let defaultServer = "mastodon.social" - + @UIApplicationDelegateAdaptor private var appDelegate: AppDelegate @Environment(\.scenePhase) private var scenePhase @@ -72,9 +73,7 @@ struct IceCubesApp: App { private func badgeFor(tab: Tab) -> Int { if tab == .notifications && selectedTab != tab { - return watcher.unreadNotificationsCount - } else if tab == .messages && selectedTab != tab { - return watcher.unreadMessagesCount + return watcher.unreadNotificationsCount + userPreferences.pushNotificationsCount } return 0 } @@ -131,6 +130,7 @@ struct IceCubesApp: App { watcher.stopWatching() case .active: watcher.watch(streams: [.user, .direct]) + UIApplication.shared.applicationIconBadgeNumber = 0 case .inactive: break default: @@ -151,6 +151,7 @@ struct IceCubesApp: App { class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + try? AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers) return true } diff --git a/IceCubesApp/App/Tabs/MessagesTab.swift b/IceCubesApp/App/Tabs/MessagesTab.swift index a51a3e03..8aca203f 100644 --- a/IceCubesApp/App/Tabs/MessagesTab.swift +++ b/IceCubesApp/App/Tabs/MessagesTab.swift @@ -36,7 +36,6 @@ struct MessagesTab: View { } .onAppear { routeurPath.client = client - watcher.unreadMessagesCount = 0 } .withSafariRouteur() .environmentObject(routeurPath) diff --git a/IceCubesApp/App/Tabs/NotificationTab.swift b/IceCubesApp/App/Tabs/NotificationTab.swift index 50eebd56..6c85bbc7 100644 --- a/IceCubesApp/App/Tabs/NotificationTab.swift +++ b/IceCubesApp/App/Tabs/NotificationTab.swift @@ -8,6 +8,7 @@ struct NotificationsTab: View { @EnvironmentObject private var client: Client @EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var currentAccount: CurrentAccount + @EnvironmentObject private var userPreferences: UserPreferences @StateObject private var routeurPath = RouterPath() @Binding var popToRootTab: Tab @@ -27,6 +28,7 @@ struct NotificationsTab: View { .onAppear { routeurPath.client = client watcher.unreadNotificationsCount = 0 + userPreferences.pushNotificationsCount = 0 } .withSafariRouteur() .environmentObject(routeurPath) diff --git a/IceCubesApp/App/Tabs/Settings/PushNotificationsView.swift b/IceCubesApp/App/Tabs/Settings/PushNotificationsView.swift index d18c07f6..56a6e243 100644 --- a/IceCubesApp/App/Tabs/Settings/PushNotificationsView.swift +++ b/IceCubesApp/App/Tabs/Settings/PushNotificationsView.swift @@ -17,7 +17,7 @@ struct PushNotificationsView: View { Form { Section { Toggle(isOn: $pushNotifications.isPushEnabled) { - Text("Push notification") + Text("Push notifications") } } footer: { Text("Receive push notifications on new activities") diff --git a/IceCubesApp/IceCubesApp.entitlements b/IceCubesApp/IceCubesApp.entitlements index a18821af..85188eba 100644 --- a/IceCubesApp/IceCubesApp.entitlements +++ b/IceCubesApp/IceCubesApp.entitlements @@ -6,6 +6,10 @@ development com.apple.security.app-sandbox + com.apple.security.application-groups + + group.icecubesapps + com.apple.security.files.user-selected.read-only keychain-access-groups diff --git a/IceCubesNotifications/IceCubesNotifications.entitlements b/IceCubesNotifications/IceCubesNotifications.entitlements index e04b3fac..8ffdc6f3 100644 --- a/IceCubesNotifications/IceCubesNotifications.entitlements +++ b/IceCubesNotifications/IceCubesNotifications.entitlements @@ -2,6 +2,10 @@ + com.apple.security.application-groups + + group.icecubesapps + keychain-access-groups $(AppIdentifierPrefix)com.thomasricouard.IceCubesApp diff --git a/IceCubesNotifications/NotificationService.swift b/IceCubesNotifications/NotificationService.swift index a926c971..36cbef40 100644 --- a/IceCubesNotifications/NotificationService.swift +++ b/IceCubesNotifications/NotificationService.swift @@ -54,6 +54,11 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.userInfo["plaintext"] = plaintextData bestAttemptContent.sound = UNNotificationSound.init(named: UNNotificationSoundName(rawValue: "glass.wav")) + let preferences = UserPreferences() + preferences.pushNotificationsCount += 1 + + bestAttemptContent.badge = .init(integerLiteral: preferences.pushNotificationsCount) + if let urlString = notification.icon, let url = URL(string: urlString) { let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("notification-attachments") diff --git a/Packages/DesignSystem/Sources/DesignSystem/DesignSystem.swift b/Packages/DesignSystem/Sources/DesignSystem/DesignSystem.swift index e73c0595..9bc9eeee 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/DesignSystem.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/DesignSystem.swift @@ -2,7 +2,7 @@ import Foundation extension CGFloat { public static let layoutPadding: CGFloat = 20 - public static let dividerPadding: CGFloat = 4 + public static let dividerPadding: CGFloat = 2 public static let statusColumnsSpacing: CGFloat = 8 public static let maxColumnWidth: CGFloat = 650 } diff --git a/Packages/Env/Sources/Env/PushNotificationsService.swift b/Packages/Env/Sources/Env/PushNotificationsService.swift index 7b220012..77b1c41e 100644 --- a/Packages/Env/Sources/Env/PushNotificationsService.swift +++ b/Packages/Env/Sources/Env/PushNotificationsService.swift @@ -48,12 +48,14 @@ public class PushNotificationsService: ObservableObject { private var keychain: KeychainSwift { let keychain = KeychainSwift() - keychain.accessGroup = Constants.keychainGroup + #if !DEBUG + keychain.accessGroup = Constants.keychainGroup + #endif return keychain } public func requestPushNotifications() { - UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { (_, _) in + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (_, _) in DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } diff --git a/Packages/Env/Sources/Env/StreamWatcher.swift b/Packages/Env/Sources/Env/StreamWatcher.swift index 8dfcb1e5..359e2c6c 100644 --- a/Packages/Env/Sources/Env/StreamWatcher.swift +++ b/Packages/Env/Sources/Env/StreamWatcher.swift @@ -19,7 +19,6 @@ public class StreamWatcher: ObservableObject { @Published public var events: [any StreamEvent] = [] @Published public var unreadNotificationsCount: Int = 0 - @Published public var unreadMessagesCount: Int = 0 @Published public var latestEvent: (any StreamEvent)? public init() { @@ -81,8 +80,6 @@ public class StreamWatcher: ObservableObject { self.latestEvent = event if let event = event as? StreamEventNotification, event.notification.status?.visibility != .direct { self.unreadNotificationsCount += 1 - } else if event is StreamEventConversation { - self.unreadMessagesCount += 1 } } } diff --git a/Packages/Env/Sources/Env/UserPreferences.swift b/Packages/Env/Sources/Env/UserPreferences.swift index 502db807..8e58cbac 100644 --- a/Packages/Env/Sources/Env/UserPreferences.swift +++ b/Packages/Env/Sources/Env/UserPreferences.swift @@ -2,8 +2,18 @@ import SwiftUI import Foundation public class UserPreferences: ObservableObject { + private static let sharedDefault = UserDefaults.init(suiteName: "group.icecubesapps") + @AppStorage("remote_local_timeline") public var remoteLocalTimelines: [String] = [] @AppStorage("preferred_browser") public var preferredBrowser: PreferredBrowser = .inAppSafari + public var pushNotificationsCount: Int { + get { + Self.sharedDefault?.integer(forKey: "push_notifications_count") ?? 0 + } + set { + Self.sharedDefault?.set(newValue, forKey: "push_notifications_count") + } + } public init() { } }