feat: 接入消息未读数、全部已读与首页红点角标同步。

固定消息中心为首页入口,并在推送到达、已读后刷新桌面角标。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-21 18:02:43 +08:00
parent e7f1d777dd
commit caeeb9a1cf
18 changed files with 748 additions and 37 deletions

View File

@ -158,6 +158,28 @@ final class PushNotificationTests: XCTestCase {
XCTAssertEqual(router.destinations, [.task])
}
func testRemoteNotificationNotifiesUnreadMessageStateChange() async {
let manager = makeManager()
let unreadChanged = expectation(
forNotification: NotificationName.unreadMessageCountDidChange,
object: nil
)
manager.handleRemoteNotification(["route": "message_center"])
await fulfillment(of: [unreadChanged], timeout: 1)
}
func testApplicationIconBadgeUsesLatestNonnegativeCount() async {
let badgeSetter = ApplicationIconBadgeSetterMock()
let manager = makeManager(badgeSetter: badgeSetter)
await manager.updateApplicationIconBadgeCount(12)
await manager.updateApplicationIconBadgeCount(-2)
XCTAssertEqual(badgeSetter.counts, [12, 0])
}
func testRouteCoordinatorWaitsForLoginAndDeduplicatesColdStartResponse() {
let coordinator = PushRouteCoordinator(appStore: appStore)
let window = UIWindow(frame: UIScreen.main.bounds)
@ -189,7 +211,8 @@ final class PushNotificationTests: XCTestCase {
private func makeManager(
sdk: PushSDKMock? = nil,
api: PushRegistrationAPIMock? = nil,
router: PushRouterMock? = nil
router: PushRouterMock? = nil,
badgeSetter: ApplicationIconBadgeSetterMock? = nil
) -> PushNotificationManager {
let resolvedSDK: PushSDKMock
if let sdk {
@ -217,7 +240,8 @@ final class PushNotificationTests: XCTestCase {
api: resolvedAPI,
appStore: appStore,
defaults: defaults,
router: resolvedRouter
router: resolvedRouter,
applicationIconBadgeSetter: badgeSetter ?? ApplicationIconBadgeSetterMock()
)
}
@ -233,6 +257,16 @@ final class PushNotificationTests: XCTestCase {
}
}
/// App
@MainActor
private final class ApplicationIconBadgeSetterMock: ApplicationIconBadgeSetting {
private(set) var counts: [Int] = []
func setBadgeCount(_ count: Int) async {
counts.append(count)
}
}
/// SDK
@MainActor
private final class PushSDKMock: PushSDKProviding {