pi-remote-ios/Sources/App/AppState.swift

55 lines
1.6 KiB
Swift

// 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() {
// Test-only overrides
let args = ProcessInfo.processInfo.arguments
if args.contains("--reset-state") {
Keychain.shared.delete(key: "piremote.credential")
UserDefaults.standard.removeObject(forKey: "faceid.enabled")
}
if args.contains("--enable-faceid") {
UserDefaults.standard.set(true, forKey: "faceid.enabled")
}
if args.contains("--force-lock") {
isLocked = true
}
// 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
}
}