feat: 接入消息未读数、全部已读与首页红点角标同步。
固定消息中心为首页入口,并在推送到达、已读后刷新桌面角标。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -1,6 +1,32 @@
|
||||
import UIKit
|
||||
import UserNotifications
|
||||
|
||||
/// App 桌面图标角标设置能力,便于业务同步未读消息数量并进行测试替换。
|
||||
@MainActor
|
||||
protocol ApplicationIconBadgeSetting: AnyObject {
|
||||
/// 将桌面图标角标更新为指定非负数量。
|
||||
func setBadgeCount(_ count: Int) async
|
||||
}
|
||||
|
||||
/// 使用 UserNotifications 更新 App 桌面图标角标的系统实现。
|
||||
@MainActor
|
||||
final class SystemApplicationIconBadgeSetter: ApplicationIconBadgeSetting {
|
||||
/// 全局角标设置器。
|
||||
static let shared = SystemApplicationIconBadgeSetter()
|
||||
|
||||
private init() {}
|
||||
|
||||
func setBadgeCount(_ count: Int) async {
|
||||
do {
|
||||
try await UNUserNotificationCenter.current().setBadgeCount(max(count, 0))
|
||||
} catch {
|
||||
#if DEBUG
|
||||
print("Update application icon badge failed: \(error.localizedDescription)")
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 极光 SDK 的最小能力边界,便于推送生命周期逻辑使用测试替身。
|
||||
@MainActor
|
||||
protocol PushSDKProviding: AnyObject {
|
||||
@ -85,6 +111,7 @@ final class PushNotificationManager: NSObject {
|
||||
private let appStore: AppStore
|
||||
private let defaults: UserDefaults
|
||||
private let router: any PushRouting
|
||||
private let applicationIconBadgeSetter: any ApplicationIconBadgeSetting
|
||||
|
||||
private var isInitialized = false
|
||||
private var didRequestAuthorization = false
|
||||
@ -99,13 +126,15 @@ final class PushNotificationManager: NSObject {
|
||||
api: (any PushRegistrationServing)? = nil,
|
||||
appStore: AppStore = .shared,
|
||||
defaults: UserDefaults = .standard,
|
||||
router: (any PushRouting)? = nil
|
||||
router: (any PushRouting)? = nil,
|
||||
applicationIconBadgeSetter: (any ApplicationIconBadgeSetting)? = nil
|
||||
) {
|
||||
self.sdk = sdk ?? JPushSDKAdapter()
|
||||
self.api = api ?? NetworkServices.shared.pushAPI
|
||||
self.appStore = appStore
|
||||
self.defaults = defaults
|
||||
self.router = router ?? PushRouteCoordinator.shared
|
||||
self.applicationIconBadgeSetter = applicationIconBadgeSetter ?? SystemApplicationIconBadgeSetter.shared
|
||||
super.init()
|
||||
}
|
||||
|
||||
@ -152,6 +181,12 @@ final class PushNotificationManager: NSObject {
|
||||
uploadTask = nil
|
||||
queuedForcedUpload = false
|
||||
router.resetPendingRoute()
|
||||
Task { await updateApplicationIconBadgeCount(0) }
|
||||
}
|
||||
|
||||
/// 将桌面 App Icon 角标更新为最新未读消息数量。
|
||||
func updateApplicationIconBadgeCount(_ count: Int) async {
|
||||
await applicationIconBadgeSetter.setBadgeCount(max(count, 0))
|
||||
}
|
||||
|
||||
/// App 回到前台时补偿失败或尚未完成的 Registration ID 上报。
|
||||
@ -204,6 +239,7 @@ final class PushNotificationManager: NSObject {
|
||||
/// 处理后台静默通知并向极光上报到达,不触发页面跳转。
|
||||
func handleRemoteNotification(_ userInfo: [AnyHashable: Any]) {
|
||||
JPUSHService.handleRemoteNotification(userInfo)
|
||||
NotificationCenter.default.post(name: NotificationName.unreadMessageCountDidChange, object: nil)
|
||||
}
|
||||
|
||||
private func observeJPushNetworkLogin() {
|
||||
@ -317,6 +353,9 @@ extension PushNotificationManager: JPUSHRegisterDelegate {
|
||||
withCompletionHandler completionHandler: @escaping (Int) -> Void
|
||||
) {
|
||||
JPUSHService.handleRemoteNotification(notification.request.content.userInfo)
|
||||
Task { @MainActor in
|
||||
NotificationCenter.default.post(name: NotificationName.unreadMessageCountDidChange, object: nil)
|
||||
}
|
||||
let options: UNNotificationPresentationOptions = [.banner, .list, .sound, .badge]
|
||||
completionHandler(Int(options.rawValue))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user