[push/opt-in-prompts] Implement push notifications client integration
Build the full client half of docs/api/push-notifications-integration-guide.md: OS permission + APNs device-token registration and pipeline wiring, profile notifications/biometric-login toggles on the Ver Perfil screen reflecting server truth, order-tracking opt-in fallback prompt, profile-cache refresh on every mutation, a Notification Service Extension for rich/image push, the Push Notifications capability, targeting-attributes sync, campaign open tracking, and tap-to-order deep linking with foreground notification display.
This commit is contained in:
@@ -15,6 +15,7 @@ struct ContentView: View {
|
||||
@State private var sessionExpiredObserver: NSObjectProtocol?
|
||||
@State var cartResetObserver: Any?
|
||||
@State var appResumeObserver: Any?
|
||||
@State var pushOrderTapObserver: Any?
|
||||
@StateObject var snackbarCenter = SnackbarCenter.shared
|
||||
|
||||
var body: some View {
|
||||
@@ -90,11 +91,13 @@ struct ContentView: View {
|
||||
attachCartResetObserverIfNeeded()
|
||||
attachAppResumeObserverIfNeeded()
|
||||
attachSessionExpiredObserverIfNeeded()
|
||||
attachPushOrderTapObserverIfNeeded()
|
||||
}
|
||||
.onDisappear {
|
||||
detachCartResetObserver()
|
||||
detachAppResumeObserver()
|
||||
detachSessionExpiredObserver()
|
||||
detachPushOrderTapObserver()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,6 +244,38 @@ struct ContentView: View {
|
||||
self.appResumeObserver = nil
|
||||
}
|
||||
|
||||
/// §6 of the push notifications guide — an `order_status` push tap
|
||||
/// (reported by `PushNotificationCoordinator`) routes here to the
|
||||
/// Profile tab's Orders list, pre-targeted at that order.
|
||||
private func attachPushOrderTapObserverIfNeeded() {
|
||||
guard pushOrderTapObserver == nil else { return }
|
||||
pushOrderTapObserver = NotificationCenter.default.addObserver(
|
||||
forName: .pushTappedOrderStatus,
|
||||
object: nil,
|
||||
queue: nil
|
||||
) { notification in
|
||||
let orderId = notification.userInfo?["orderId"] as? String
|
||||
let shortId = notification.userInfo?["shortId"] as? String
|
||||
Task { @MainActor in
|
||||
guard root == .main, let orderId else { return }
|
||||
appState.pendingOrderDeepLink = OrderRouteContext(
|
||||
orderId: orderId,
|
||||
shortId: shortId,
|
||||
paymentMethod: nil,
|
||||
total: nil,
|
||||
intent: .auto
|
||||
)
|
||||
selectedTab = .profile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func detachPushOrderTapObserver() {
|
||||
guard let pushOrderTapObserver else { return }
|
||||
NotificationCenter.default.removeObserver(pushOrderTapObserver)
|
||||
self.pushOrderTapObserver = nil
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func hydrateAppState(with customer: CustomerProfile) {
|
||||
appState.profile.id = customer.id
|
||||
|
||||
Reference in New Issue
Block a user