try: fix repeated auth (#294)

This commit is contained in:
lollipopkit
2024-03-21 01:24:07 -06:00
parent 32da0c8283
commit 7feebb8c1f
3 changed files with 57 additions and 39 deletions

View File

@@ -2,14 +2,22 @@ import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.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:toolbox/core/utils/platform/base.dart';
import 'package:local_auth/error_codes.dart' as errs; import 'package:local_auth/error_codes.dart' as errs;
import 'package:toolbox/data/res/store.dart';
abstract final class BioAuth { abstract final class BioAuth {
static final _auth = LocalAuthentication(); static final _auth = LocalAuthentication();
static bool get isPlatformSupported => isAndroid || isIOS || isWindows; static bool get isPlatformSupported => isAndroid || isIOS || isWindows;
static bool _isAuthing = false;
static Future<bool> get isAvail async { static Future<bool> get isAvail async {
if (!isPlatformSupported) return false; if (!isPlatformSupported) return false;
if (!await _auth.canCheckBiometrics) { if (!await _auth.canCheckBiometrics) {
@@ -24,16 +32,55 @@ abstract final class BioAuth {
biometrics.contains(BiometricType.fingerprint); biometrics.contains(BiometricType.fingerprint);
} }
static Future<AuthResult> 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<AuthResult> authWithResult() async {
if (!await isAvail) return AuthResult.notAvail; if (!await isAvail) return AuthResult.notAvail;
try { try {
await _auth.stopAuthentication();
final reuslt = await _auth.authenticate( final reuslt = await _auth.authenticate(
localizedReason: msg ?? 'Auth required', localizedReason: l10n.authRequired,
options: const AuthenticationOptions( options: const AuthenticationOptions(
stickyAuth: true, biometricOnly: true,
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) { if (reuslt) {
return AuthResult.success; return AuthResult.success;
} }

View File

@@ -47,7 +47,6 @@ class _HomePageState extends State<HomePage>
final _selectIndex = ValueNotifier(0); final _selectIndex = ValueNotifier(0);
bool _switchingPage = false; bool _switchingPage = false;
bool _isAuthing = false;
@override @override
void initState() { void initState() {
@@ -83,7 +82,7 @@ class _HomePageState extends State<HomePage>
switch (state) { switch (state) {
case AppLifecycleState.resumed: case AppLifecycleState.resumed:
_auth(); BioAuth.auth();
if (!Pros.server.isAutoRefreshOn) { if (!Pros.server.isAutoRefreshOn) {
Pros.server.startAutoRefresh(); Pros.server.startAutoRefresh();
} }
@@ -316,7 +315,7 @@ ${GithubIds.participants.map((e) => '[$e](${e.url})').join(' ')}
@override @override
Future<void> afterFirstLayout(BuildContext context) async { Future<void> afterFirstLayout(BuildContext context) async {
// Auth required for first launch // Auth required for first launch
_auth(); BioAuth.auth();
if (Stores.setting.autoCheckAppUpdate.fetch()) { if (Stores.setting.autoCheckAppUpdate.fetch()) {
doUpdate(context); doUpdate(context);
@@ -357,32 +356,4 @@ ${GithubIds.participants.map((e) => '[$e](${e.url})').join(' ')}
Loggers.app.warning('Update json settings failed', e, trace); 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;
}
},
);
}
}
}
} }

View File

@@ -36,7 +36,7 @@ abstract final class PlatformPublicSettings {
return; return;
} }
// Only auth when turn off (val == false) // 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 failed, turn on again
if (result != AuthResult.success) { if (result != AuthResult.success) {
Stores.setting.useBioAuth.put(true); Stores.setting.useBioAuth.put(true);