// AppState.swift — global app state, credential lifecycle import SwiftUI @MainActor final class AppState: ObservableObject { static let shared = AppState() @Published var credential: SidecarCredential? = nil @Published var isLocked = false @Published var lastForegroundedAt: Date = Date() private init() { // Try loading persisted credential on launch credential = try? Keychain.shared.load(key: "piremote.credential") } func didPair(credential: SidecarCredential) { self.credential = credential try? Keychain.shared.save(credential, key: "piremote.credential") } func unpair() { credential = nil Keychain.shared.delete(key: "piremote.credential") } // MARK: - Face ID gate func appDidBackground() { lastForegroundedAt = Date() } func appWillForeground() async { let elapsed = Date().timeIntervalSince(lastForegroundedAt) guard elapsed > 60 else { return } // within 60s → no re-auth isLocked = true let ok = await FaceIDGate.authenticate() isLocked = !ok } }