fix app lock hanging on macOS and blocking the photo picker
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s

- Lock only when the scene really backgrounds: transient inactive
  states (system photo picker, app switcher) no longer swap in the
  lock screen and break gallery selection on iOS.
- Cache biometric availability once per session off the main thread
  instead of calling LAContext.canEvaluatePolicy in view bodies,
  which froze the macOS lock screen, and auto-prompt biometrics on
  iOS only.
- Keep UI tests as an opt-in target and guard both fixes in
  verify.sh.
This commit is contained in:
wt committed 2026-08-30 01:14:23 +07:00
1 parent 8b86e33186
commit 6ed5cb3ce9
9 files changed
+86 -78

No files matched your search

+23
View File
@@ -60,6 +60,11 @@ final class AppModel: ObservableObject {
@Published private(set) var isAppLocked = false
@Published private(set) var appLockIsEnabled = false
@Published private(set) var appLockBiometricIsEnabled = false
/// Cached once per session: LAContext.canEvaluatePolicy performs IPC with
/// the security daemon and must never run in a view body (it froze the
/// macOS lock screen).
@Published private(set) var biometricUnlockAvailable = false
@Published private(set) var biometricUnlockName = ""
@Published private(set) var mediaViewerItem: MediaViewerItem?
@Published private(set) var mediaPreviewURLs: [String: URL] = [:]
@Published private(set) var mediaThumbnailData: [String: Data] = [:]
@@ -140,6 +145,7 @@ final class AppModel: ObservableObject {
appLockIsEnabled = appLock.isEnabled
appLockBiometricIsEnabled = appLock.biometricUnlockEnabled
isAppLocked = appLock.isEnabled && !RuntimeEnvironment.isRunningTests
refreshBiometricAvailability()
xmpp.eventHandler = { [weak self] event in
self?.consume(event)
@@ -535,6 +541,23 @@ final class AppModel: ObservableObject {
return true
}
func refreshBiometricAvailability() {
guard !RuntimeEnvironment.isRunningTests else { return }
Task.detached(priority: .utility) {
let context = LAContext()
var error: NSError?
let available = context.canEvaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
error: &error
)
let name = context.biometryType == .faceID ? "Face ID" : "Touch ID"
await MainActor.run { [weak self] in
self?.biometricUnlockAvailable = available
self?.biometricUnlockName = name
}
}
}
func unlockWithBiometrics() async -> Bool {
guard appLockIsEnabled, appLockBiometricIsEnabled else { return false }
let context = LAContext()