处理系统的未读消息数逻辑

This commit is contained in:
anlicheng 2025-07-11 15:29:28 +08:00
parent fbd362f84e
commit 34a48116d2
3 changed files with 98 additions and 5 deletions

View File

@ -120,6 +120,31 @@ struct API {
return await doRequest(request: request, as: T.self) return await doRequest(request: request, as: T.self)
} }
//
static func getUserUnreadNum<T: Codable>(userId: String, as: T.Type) async -> APIResponse<T> {
let request = URLRequest(url: URL(string: baseUrl + "/api/get_unread_num?user_id=\(userId)")!)
return await doRequest(request: request, as: T.self)
}
static func updateUserUnreadNum<T: Codable>(userId: String, dramaId: Int, as: T.Type) async -> APIResponse<T> {
let request = URLRequest(url: URL(string: baseUrl + "/api/update_unread_num?user_id=\(userId)&drama_id=\(dramaId)")!)
return await doRequest(request: request, as: T.self)
}
static func resetUserUnreadNum<T: Codable>(userId: String, dramaIds: [Int], as: T.Type) async -> APIResponse<T> {
let jsonData = try! JSONSerialization.data(withJSONObject: ["drama_ids": dramaIds], options: [])
let url = URL(string: baseUrl + "/api/reset_unread_num?user_id=\(userId)")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
return await doRequest(request: request, as: T.self)
}
// http // http
private static func doRequest<T: Codable>(request: URLRequest, as: T.Type) async -> APIResponse<T> { private static func doRequest<T: Codable>(request: URLRequest, as: T.Type) async -> APIResponse<T> {
do { do {

View File

@ -150,6 +150,8 @@ struct IndexMainView: View {
} }
.task { .task {
await self.indexModel.loadData(userId: self.userId) await self.indexModel.loadData(userId: self.userId)
} }
} }

View File

@ -14,6 +14,8 @@ struct dimensionhubApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject var appNav = AppNavigation.shared @StateObject var appNav = AppNavigation.shared
private var userId: String
var sharedModelContainer: ModelContainer = { var sharedModelContainer: ModelContainer = {
let schema = Schema([ let schema = Schema([
Item.self, Item.self,
@ -33,11 +35,11 @@ struct dimensionhubApp: App {
}() }()
init() { init() {
self.userId = KeychainHelper.getPersistentUserId()
// //
UNUserNotificationCenter.current().delegate = appDelegate UNUserNotificationCenter.current().delegate = appDelegate
print("user_id is: \(self.userId)")
let userId = KeychainHelper.getPersistentUserId()
print("user_id is: \(userId)")
} }
var body: some Scene { var body: some Scene {
@ -60,6 +62,11 @@ struct dimensionhubApp: App {
withAnimation { withAnimation {
appNav.append(dest: .detail(id: dramaId)) appNav.append(dest: .detail(id: dramaId))
} }
Task {
await self.updateUserUnreadNum(userId: self.userId, dramaId: dramaId)
}
appNav.targetDetailId = 0 appNav.targetDetailId = 0
} }
} }
@ -67,13 +74,25 @@ struct dimensionhubApp: App {
} }
.navigationViewStyle(.stack) .navigationViewStyle(.stack)
.tint(.black) .tint(.black)
.environment(\.userId, KeychainHelper.getPersistentUserId()) .environment(\.userId, self.userId)
.environmentObject(appNav) .environmentObject(appNav)
.preferredColorScheme(.light) .preferredColorScheme(.light)
} }
.modelContainer(sharedModelContainer) .modelContainer(sharedModelContainer)
} }
private func updateUserUnreadNum(userId: String, dramaId: Int) async {
let response = await API.updateUserUnreadNum(userId: userId, dramaId: dramaId, as: Int.self)
switch response {
case .result(let newUnreadNum):
NSLog("updateUserUnreadNum success, new unread_num:\(newUnreadNum)")
Task {@MainActor in
try? await UNUserNotificationCenter.current().setBadgeCount(newUnreadNum)
}
case .error(let errorCode, let error):
NSLog("updateUserUnreadNum error: \(error), error_code: \(errorCode)")
}
}
} }
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
@ -81,6 +100,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
Task.detached { Task.detached {
await self.registerForPushNotifications() await self.registerForPushNotifications()
//
let unreadDramaIds = await self.getSystemUnreadDramaIds()
let userId = KeychainHelper.getPersistentUserId()
let response = await API.resetUserUnreadNum(userId: userId, dramaIds: unreadDramaIds, as: String.self)
switch response {
case .result(let result):
NSLog("reset user unread num result is: \(result)")
case .error(let errorCode, let message):
NSLog("reset user unread error_code: \(errorCode), message: \(message)")
}
Task {@MainActor in
do {
try await UNUserNotificationCenter.current().setBadgeCount(unreadDramaIds.count)
NSLog("UNUserNotificationCenter setBadgeCount num: \(unreadDramaIds.count)")
} catch let err {
NSLog("UNUserNotificationCenter setBadgeCount get error: \(err)")
}
}
} }
return true return true
} }
@ -109,6 +148,34 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
} }
} }
//
private func fetchUserUnreadCount() async -> Int? {
let userId = KeychainHelper.getPersistentUserId()
let response = await API.getUserUnreadNum(userId: userId, as: Int.self)
switch response {
case .result(let unreadNum):
return unreadNum
case .error(let errorCode, let error):
NSLog("fetchUserUnreadCount get error: \(error), code: \(errorCode)")
return nil
}
}
//
private func getSystemUnreadDramaIds() async -> [Int] {
let notifications = await UNUserNotificationCenter.current().deliveredNotifications()
let unreadDramaIds = notifications.flatMap { n -> [Int] in
let userInfo = n.request.content.userInfo
guard let customData = userInfo["custom_data"] as? [String: AnyObject],
let params = customData["params"] as? [String : AnyObject],
let dramaId = params["drama_id"] as? Int else {
return []
}
return [dramaId]
}
return unreadDramaIds
}
// deviceToken // deviceToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) } let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
@ -136,7 +203,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// App // App
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData) completionHandler(.newData)
} }