diff --git a/lib/core/utils/platform/auth.dart b/lib/core/utils/platform/auth.dart index daba72c5..083be6ea 100644 --- a/lib/core/utils/platform/auth.dart +++ b/lib/core/utils/platform/auth.dart @@ -2,14 +2,22 @@ import 'dart:io'; import 'package:flutter/services.dart'; import 'package:local_auth/local_auth.dart'; +// ignore: depend_on_referenced_packages +import 'package:local_auth_android/local_auth_android.dart'; +// ignore: depend_on_referenced_packages +import 'package:local_auth_ios/types/auth_messages_ios.dart'; +import 'package:toolbox/core/extension/context/locale.dart'; import 'package:toolbox/core/utils/platform/base.dart'; import 'package:local_auth/error_codes.dart' as errs; +import 'package:toolbox/data/res/store.dart'; abstract final class BioAuth { static final _auth = LocalAuthentication(); static bool get isPlatformSupported => isAndroid || isIOS || isWindows; + static bool _isAuthing = false; + static Future get isAvail async { if (!isPlatformSupported) return false; if (!await _auth.canCheckBiometrics) { @@ -24,16 +32,55 @@ abstract final class BioAuth { biometrics.contains(BiometricType.fingerprint); } - static Future auth([String? msg]) async { + static void auth([int count = 0]) async { + if (Stores.setting.useBioAuth.fetch()) { + if (!_isAuthing) { + _isAuthing = true; + final val = await authWithResult(); + switch (val) { + case AuthResult.success: + // wait for animation + Future.delayed( + count >= 3 ? const Duration(milliseconds: 500) : const Duration(seconds: 1), + () => _isAuthing = false, + ); + break; + case AuthResult.fail: + case AuthResult.cancel: + _isAuthing = false; + auth(count + 1); + break; + case AuthResult.notAvail: + _isAuthing = false; + Stores.setting.useBioAuth.put(false); + break; + } + } + } + } + + static Future authWithResult() async { if (!await isAvail) return AuthResult.notAvail; try { + await _auth.stopAuthentication(); final reuslt = await _auth.authenticate( - localizedReason: msg ?? 'Auth required', - options: const AuthenticationOptions( - stickyAuth: true, - biometricOnly: true, - ), - ); + localizedReason: l10n.authRequired, + options: const AuthenticationOptions( + biometricOnly: true, + ), + authMessages: [ + AndroidAuthMessages( + biometricHint: l10n.bioAuth, + biometricNotRecognized: l10n.failed, + biometricRequiredTitle: l10n.authRequired, + biometricSuccess: l10n.success, + cancelButton: l10n.cancel, + ), + IOSAuthMessages( + lockOut: l10n.authRequired, + cancelButton: l10n.ok, + ), + ]); if (reuslt) { return AuthResult.success; } diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index 9e043a5d..da342a01 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -47,7 +47,6 @@ class _HomePageState extends State final _selectIndex = ValueNotifier(0); bool _switchingPage = false; - bool _isAuthing = false; @override void initState() { @@ -83,7 +82,7 @@ class _HomePageState extends State switch (state) { case AppLifecycleState.resumed: - _auth(); + BioAuth.auth(); if (!Pros.server.isAutoRefreshOn) { Pros.server.startAutoRefresh(); } @@ -316,7 +315,7 @@ ${GithubIds.participants.map((e) => '[$e](${e.url})').join(' ')} @override Future afterFirstLayout(BuildContext context) async { // Auth required for first launch - _auth(); + BioAuth.auth(); if (Stores.setting.autoCheckAppUpdate.fetch()) { doUpdate(context); @@ -357,32 +356,4 @@ ${GithubIds.participants.map((e) => '[$e](${e.url})').join(' ')} Loggers.app.warning('Update json settings failed', e, trace); } } - - void _auth() { - if (Stores.setting.useBioAuth.fetch()) { - if (!_isAuthing) { - _isAuthing = true; - BioAuth.auth(l10n.authRequired).then( - (val) { - switch (val) { - case AuthResult.success: - // wait for animation - Future.delayed( - const Duration(seconds: 1), () => _isAuthing = false); - break; - case AuthResult.fail: - case AuthResult.cancel: - _isAuthing = false; - _auth(); - break; - case AuthResult.notAvail: - _isAuthing = false; - Stores.setting.useBioAuth.put(false); - break; - } - }, - ); - } - } - } } diff --git a/lib/view/page/setting/platform/platform_pub.dart b/lib/view/page/setting/platform/platform_pub.dart index 302ee297..047ac28f 100644 --- a/lib/view/page/setting/platform/platform_pub.dart +++ b/lib/view/page/setting/platform/platform_pub.dart @@ -36,7 +36,7 @@ abstract final class PlatformPublicSettings { return; } // Only auth when turn off (val == false) - final result = await BioAuth.auth(l10n.authRequired); + final result = await BioAuth.authWithResult(); // If failed, turn on again if (result != AuthResult.success) { Stores.setting.useBioAuth.put(true);