payfrit-works-ios/PayfritWorks/Views/RootView.swift
2026-02-01 23:38:34 -08:00

86 lines
2.6 KiB
Swift

import SwiftUI
import LocalAuthentication
struct RootView: View {
@EnvironmentObject var appState: AppState
@State private var isCheckingAuth = true
@State private var isDev = false
var body: some View {
Group {
if isCheckingAuth {
loadingView
} else if appState.isAuthenticated {
BusinessSelectionScreen()
} else {
LoginScreen()
}
}
.animation(.easeInOut(duration: 0.3), value: appState.isAuthenticated)
.overlay(alignment: .bottomLeading) {
if isDev {
Text("DEV")
.font(.caption.bold())
.foregroundColor(.white)
.frame(width: 80, height: 20)
.background(Color.orange)
.rotationEffect(.degrees(45))
.offset(x: -20, y: -6)
.allowsHitTesting(false)
}
}
.task {
isDev = await APIService.shared.isDev
await checkAuthWithBiometrics()
isCheckingAuth = false
}
}
private var loadingView: some View {
ZStack {
Color.white.ignoresSafeArea()
VStack(spacing: 16) {
Image("PayfritLogoLight")
.resizable()
.scaledToFit()
.frame(width: 200)
ProgressView()
.tint(.payfritGreen)
}
}
}
private func checkAuthWithBiometrics() async {
let creds = await AuthStorage.shared.loadAuth()
guard creds != nil else { return }
let context = LAContext()
context.localizedCancelTitle = "Use Password"
var error: NSError?
let canUseBiometrics = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
#if targetEnvironment(simulator)
// Skip biometrics on simulator test on real device
await appState.loadSavedAuth()
return
#endif
guard canUseBiometrics else {
await appState.loadSavedAuth()
return
}
do {
let success = try await context.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Sign in to Payfrit Works"
)
if success {
await appState.loadSavedAuth()
}
} catch {
// User tapped "Use Password" or biometrics failed show login screen
NSLog("PAYFRIT [biometrics] cancelled/failed: \(error.localizedDescription)")
}
}
}