新增 APNs 推送注册与 Payload 路由

引入 AppDelegate、显式 Info.plist 与 entitlements,并将 PushNotificationManager 接入登录生命周期,用于 device token 上报与通知处理。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 09:18:49 +08:00
parent a04168cf30
commit 0314033a7f
10 changed files with 561 additions and 26 deletions

View File

@ -28,6 +28,7 @@ struct RootView: View {
@State private var statisticsAPI: StatisticsAPI
@State private var paymentAPI: PaymentAPI
@State private var walletAPI: WalletAPI
@State private var pushAPI: PushAPI
@State private var scenicPermissionAPI: ScenicPermissionAPI
@State private var scenicSettlementAPI: ScenicSettlementAPI
@State private var messageCenterAPI: MessageCenterAPI
@ -63,6 +64,7 @@ struct RootView: View {
_statisticsAPI = State(initialValue: StatisticsAPI(client: apiClient))
_paymentAPI = State(initialValue: PaymentAPI(client: apiClient))
_walletAPI = State(initialValue: WalletAPI(client: apiClient))
_pushAPI = State(initialValue: PushAPI(client: apiClient))
_scenicPermissionAPI = State(initialValue: ScenicPermissionAPI(client: apiClient))
_scenicSettlementAPI = State(initialValue: ScenicSettlementAPI(client: apiClient))
_messageCenterAPI = State(initialValue: MessageCenterAPI(client: apiClient))
@ -114,6 +116,7 @@ struct RootView: View {
.environment(statisticsAPI)
.environment(paymentAPI)
.environment(walletAPI)
.environment(pushAPI)
.environment(scenicPermissionAPI)
.environment(scenicSettlementAPI)
.environment(messageCenterAPI)
@ -132,6 +135,7 @@ struct RootView: View {
.environment(authSessionCoordinator)
.task {
apiClient.bindAuthTokenProvider { appSession.token }
PushNotificationManager.shared.configure(api: pushAPI, session: appSession, router: appRouter)
await globalLoading.withLoading {
await sessionBootstrapper.restore(
appSession: appSession,
@ -142,6 +146,9 @@ struct RootView: View {
toastCenter: toastCenter
)
}
if appSession.isLoggedIn {
PushNotificationManager.shared.requestAuthorizationAndRegister()
}
}
.task(id: scenicSpotTaskID) {
guard appSession.isLoggedIn else {
@ -176,12 +183,18 @@ struct RootView: View {
}
}
.onChange(of: appSession.phase) { _, phase in
guard phase == .loggedOut else { return }
accountContext.reset()
permissionContext.reset()
scenicSpotContext.reset()
appRouter.reset()
toastCenter.dismiss()
switch phase {
case .loggedIn:
PushNotificationManager.shared.requestAuthorizationAndRegister()
case .loggedOut:
accountContext.reset()
permissionContext.reset()
scenicSpotContext.reset()
appRouter.reset()
toastCenter.dismiss()
case .restoring:
break
}
}
}