payfrit-beacon-ios/PayfritBeacon/App/AppState.swift
Schwifty cfa78679be feat: complete rebuild of PayfritBeacon iOS from scratch
100% fresh codebase — no legacy code carried over. Built against
the Android beacon app as the behavioral spec.

Architecture:
- App: SwiftUI @main, AppState-driven navigation, Keychain storage
- Views: LoginView (OTP + biometric), BusinessListView, ScanView (provisioning hub)
- Models: Business, ServicePoint, BeaconConfig, BeaconType, DiscoveredBeacon
- Services: APIClient (actor, async/await), BLEManager (CoreBluetooth scanner)
- Provisioners: KBeacon, DXSmart (2-step auth + flashing), BlueCharm
- Utils: UUIDFormatting, BeaconBanList, BeaconShardPool (64 shards)

Matches Android feature parity:
- 4-screen flow: Login → Business Select → Scan/Provision
- 3 beacon types with correct GATT protocols and timeouts
- Namespace allocation via beacon-sharding API
- Smart service point naming (Table N auto-increment)
- DXSmart special flow (connect → flash → user confirms → write)
- Biometric auth, dev/prod build configs, DEV banner overlay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:13:36 +00:00

48 lines
1.2 KiB
Swift

import SwiftUI
/// Central app state drives navigation between Login Business Select Scan
@MainActor
final class AppState: ObservableObject {
enum Screen {
case login
case businessList
case scan(business: Business)
}
@Published var currentScreen: Screen = .login
@Published var token: String?
@Published var userId: String?
init() {
// Restore saved session
if let saved = SecureStorage.loadSession() {
self.token = saved.token
self.userId = saved.userId
self.currentScreen = .businessList
}
}
func didLogin(token: String, userId: String) {
self.token = token
self.userId = userId
SecureStorage.saveSession(token: token, userId: userId)
currentScreen = .businessList
}
func selectBusiness(_ business: Business) {
AppPrefs.lastBusinessId = business.id
currentScreen = .scan(business: business)
}
func backToBusinessList() {
currentScreen = .businessList
}
func logout() {
token = nil
userId = nil
SecureStorage.clearSession()
currentScreen = .login
}
}