[2026-07-resubmission] Add guest browsing flow with App Attest session for App Review resubmission
Adds a pre-login public store locator (guest session via DeviceCheck/App Attest, keychain-backed token storage) so the app no longer forces sign-in before showing any content, plus updated support URL metadata.
This commit is contained in:
@@ -2,7 +2,7 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@State var root: RootFlow = DefaultTokenStore().jwt == nil ? .auth : .main
|
||||
@State var root: RootFlow = .main
|
||||
@State var selectedTab: MainTab = .home
|
||||
private let tokenStore: TokenStore = DefaultTokenStore()
|
||||
@State var appState = AppState()
|
||||
@@ -167,20 +167,35 @@ struct ContentView: View {
|
||||
appState.cart = cachedCart
|
||||
}
|
||||
|
||||
// Anonymous session: the account address cache above doesn't apply —
|
||||
// restore the "ENTREGAR EM" label from the state/city picked via the
|
||||
// public locator (GuestLocationStore persists this in Keychain across
|
||||
// launches on its own; this just resyncs the display label with it).
|
||||
if appState.session.isAuthenticated == false,
|
||||
let guestState = GuestLocationStore.shared.selectedState,
|
||||
let guestCity = GuestLocationStore.shared.selectedCity {
|
||||
appState.address.display = "\(guestCity), \(guestState)"
|
||||
dismissAddressPickerIfAddressExists()
|
||||
}
|
||||
|
||||
// Always refresh profile when authenticated.
|
||||
// This keeps profile/address/cart scope consistent after relogin
|
||||
// and avoids stale local state during checkout payload generation.
|
||||
do {
|
||||
let response = try await ApiService().profile()
|
||||
if response.error == false, let customer = response.result {
|
||||
hydrateAppState(with: customer)
|
||||
// Anonymous browsing has no session to refresh, so skip the call
|
||||
// entirely rather than let it 401 and force-logout a guest.
|
||||
if appState.session.isAuthenticated {
|
||||
do {
|
||||
let response = try await ApiService().profile()
|
||||
if response.error == false, let customer = response.result {
|
||||
hydrateAppState(with: customer)
|
||||
}
|
||||
} catch let error as ApiServiceError {
|
||||
if case .sessionExpired = error {
|
||||
forceLogoutToStart()
|
||||
}
|
||||
} catch {
|
||||
// Keep local state when backend refresh fails transiently
|
||||
}
|
||||
} catch let error as ApiServiceError {
|
||||
if case .sessionExpired = error {
|
||||
forceLogoutToStart()
|
||||
}
|
||||
} catch {
|
||||
// Keep local state when backend refresh fails transiently
|
||||
}
|
||||
|
||||
await refreshFeatureFlags(forceRefresh: false)
|
||||
@@ -418,13 +433,17 @@ struct AddressPickerModalView: View {
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
AddressesView(
|
||||
message: appState.address.onboardingMessage,
|
||||
appState: $appState,
|
||||
selectionMode: true
|
||||
)
|
||||
.onAppear {
|
||||
appState.address.onboardingMessage = nil
|
||||
if appState.session.isAuthenticated {
|
||||
AddressesView(
|
||||
message: appState.address.onboardingMessage,
|
||||
appState: $appState,
|
||||
selectionMode: true
|
||||
)
|
||||
.onAppear {
|
||||
appState.address.onboardingMessage = nil
|
||||
}
|
||||
} else {
|
||||
PublicLocationPickerView(appState: $appState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user