migration
This commit is contained in:
49
PediFoods/Coordinators/DeepLinkDestination.swift
Normal file
49
PediFoods/Coordinators/DeepLinkDestination.swift
Normal file
@@ -0,0 +1,49 @@
|
||||
import Foundation
|
||||
|
||||
/// Single decode target for anything that can deep-link into the app — push
|
||||
/// notification taps today (docs/api/push-notifications-integration-guide.md
|
||||
/// §6), in-app promo/discount banner taps tomorrow (same shape: a string-keyed
|
||||
/// dictionary naming a screen + its params). Adding a new destination means
|
||||
/// adding one case here + one branch in `ContentView.route(to:)` — never a new
|
||||
/// `NotificationCenter` name, `AppState` field, or observer pair.
|
||||
enum DeepLinkDestination: Equatable {
|
||||
/// `type: "order_status"` — the only push type Atomenta fixes today
|
||||
/// (§6), so it gets its own case instead of routing through `targetScreen`.
|
||||
case orderTracking(orderId: String, shortId: String?)
|
||||
|
||||
/// Everything else, keyed by `targetScreen` — our own convention (§6
|
||||
/// leaves this to us). Once a real screen exists for a given name (e.g.
|
||||
/// future promo/coupon "list of participating stores/products"), give it
|
||||
/// its own case; until then this carries the raw params so nothing is
|
||||
/// silently dropped.
|
||||
case screen(name: String, params: [String: String])
|
||||
}
|
||||
|
||||
/// Resolves the *navigation* half of a tapped push's payload. Pure and
|
||||
/// side-effect-free on purpose: easy to unit test, and reusable as-is for
|
||||
/// in-app banner taps once those exist. Campaign-open reporting (§6a) is a
|
||||
/// separate side effect, not a navigation target, and is not decided here —
|
||||
/// see `PushNotificationCoordinator.handleTap`.
|
||||
struct PushDeepLinkParser {
|
||||
static func parse(_ userInfo: [AnyHashable: Any]) -> DeepLinkDestination? {
|
||||
if let type = userInfo["type"] as? String, type == "order_status" {
|
||||
// Atomenta's real order-status push (PushNotificationService.
|
||||
// notifyOrderStatusUpdate) sends only `shortId`, never `orderId` —
|
||||
// `GET /api/public/orders/:orderId` accepts either as the lookup
|
||||
// key server-side, so `shortId` doubles as the id here too.
|
||||
let shortId = userInfo["shortId"] as? String
|
||||
guard let orderId = (userInfo["orderId"] as? String) ?? shortId else { return nil }
|
||||
return .orderTracking(orderId: orderId, shortId: shortId)
|
||||
}
|
||||
|
||||
guard let targetScreen = userInfo["targetScreen"] as? String else { return nil }
|
||||
var params: [String: String] = [:]
|
||||
for (key, value) in userInfo {
|
||||
guard let key = key as? String, key != "type", key != "targetScreen" else { continue }
|
||||
if let stringValue = value as? String {
|
||||
params[key] = stringValue
|
||||
}
|
||||
}
|
||||
return .screen(name: targetScreen, params: params)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user