fixes macos touch id lock

This commit is contained in:
eYdr1en
2025-08-08 17:22:12 +02:00
parent d9e860466c
commit be506bdad1
4 changed files with 42 additions and 9 deletions

View File

@@ -321,7 +321,8 @@ class _HomePageState extends State<HomePage> {
final bool shouldShowLockScreen =
await LockScreenSettings.instance.shouldShowLockScreen();
if (shouldShowLockScreen) {
await AppLock.of(context)!.showLockScreen();
// Manual lock: do not auto-prompt Touch ID; wait for user tap
await AppLock.of(context)!.showManualLockScreen();
} else {
await showDialogWidget(
context: context,

View File

@@ -127,14 +127,19 @@ class _AppLockState extends State<AppLock> with WidgetsBindingObserver {
case '/lock-screen':
return PageRouteBuilder(
pageBuilder: (_, __, ___) => this._lockScreen,
settings: settings,
);
case '/unlocked':
return PageRouteBuilder(
pageBuilder: (_, __, ___) =>
this.widget.builder(settings.arguments),
settings: settings,
);
}
return PageRouteBuilder(pageBuilder: (_, __, ___) => this._lockScreen);
return PageRouteBuilder(
pageBuilder: (_, __, ___) => this._lockScreen,
settings: settings,
);
},
);
}
@@ -190,10 +195,18 @@ class _AppLockState extends State<AppLock> with WidgetsBindingObserver {
});
}
/// Manually show the [lockScreen].
/// Show the [lockScreen] for automatic locking (app launch, background resume).
Future<void> showLockScreen() {
this._isLocked = true;
return _navigatorKey.currentState!.pushNamed('/lock-screen');
return _navigatorKey.currentState!
.pushNamed('/lock-screen', arguments: {"manual": false});
}
/// Show the [lockScreen] for user-initiated manual lock (no auto-auth on first frame).
Future<void> showManualLockScreen() {
this._isLocked = true;
return _navigatorKey.currentState!
.pushNamed('/lock-screen', arguments: {"manual": true});
}
void _didUnlockOnAppLaunch(Object? args) {

View File

@@ -34,6 +34,9 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
final _lockscreenSetting = LockScreenSettings.instance;
late Brightness _platformBrightness;
final bool isLoggedIn = Configuration.instance.isLoggedIn();
bool _isManualPresentation = false;
// Suppress auto-auth only for the initial manual presentation.
bool _suppressAutoPrompt = false;
@override
void initState() {
@@ -42,7 +45,16 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
invalidAttemptCount = _lockscreenSetting.getInvalidAttemptCount();
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_showLockScreen(source: "postFrameInit");
final Object? args = ModalRoute.of(context)?.settings.arguments;
if (args is Map && args['manual'] is bool) {
_isManualPresentation = args['manual'] as bool;
} else {
_isManualPresentation = false;
}
_suppressAutoPrompt = _isManualPresentation;
if (!_isManualPresentation) {
_showLockScreen(source: "postFrameInit");
}
});
_platformBrightness =
SchedulerBinding.instance.platformDispatcher.platformBrightness;
@@ -67,7 +79,8 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
),
body: GestureDetector(
onTap: () {
isTimerRunning ? null : _showLockScreen(source: "tap");
if (isTimerRunning) return;
_showLockScreen(source: "tap");
},
child: Container(
decoration: BoxDecoration(
@@ -215,8 +228,7 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
DateTime.now().millisecondsSinceEpoch - lastAuthenticatingTime! <
5000;
if (!_hasAuthenticationFailed && !didAuthInLast5Seconds) {
// Show the lock screen again only if the app is resuming from the
// background, and not when the lock screen was explicitly dismissed
// If there is a cooldown timer (after multiple failures), respect it
if (_lockscreenSetting.getlastInvalidAttemptTime() >
DateTime.now().millisecondsSinceEpoch &&
!_isShowingLockScreen) {
@@ -227,6 +239,9 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
startLockTimer(time);
_showLockScreen(source: "lifeCycle");
});
} else if (!_suppressAutoPrompt) {
// No cooldown: auto-prompt when app becomes active again
_showLockScreen(source: "lifeCycle");
}
} else {
_hasAuthenticationFailed = false; // Reset failure state
@@ -238,6 +253,9 @@ class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
if (!_isShowingLockScreen) {
_hasPlacedAppInBackground = true;
_hasAuthenticationFailed = false; // reset failure state
// If we suppressed the initial auto-prompt due to manual lock,
// enable auto-prompt for the next resume after focus loss.
_suppressAutoPrompt = false;
}
}
}

View File

@@ -30,7 +30,8 @@ Future<bool> requestAuthentication(
isAuthenticatingForInAppChange: isAuthenticatingForInAppChange,
);
}
if (Platform.isMacOS || Platform.isLinux) {
if (Platform.isLinux) {
// Linux uses flutter_local_authentication
return await FlutterLocalAuthentication().authenticate();
} else {
await LocalAuthentication().stopAuthentication();