mirror of
https://github.com/we-promise/sure.git
synced 2026-05-08 13:14:58 +00:00
* Feature: Biometric lock for app resume User enables "Biometric Lock" in Settings → prompted to verify fingerprint/face first. User backgrounds the app → _isLocked = true. User returns → lock screen appears, auto-triggers biometric prompt. Success → app unlocks, state preserved underneath. Can retry or log out as fallback. Add USE_BIOMETRIC permission to AndroidManifest. * Fix: Remove duplicate local_auth entry in pubspec.lock and add NSFaceIDUsageDescription to iOS Info.plist * fix(mobile) : Remove duplicate local auth files first * fix(mobile): keep MainNavigationScreen in the Stack, let the lock screen float above, no unmounting * Updtae: Swap out Flutter Activity for FlutterFragmentActivity that extends the lock scan feature * fix(mobile): address biometric lock PR review feedback * fix(mobile): only require biometric auth when enabling lock, not disabling Prevents users from getting locked out if biometrics start failing — they can now disable the lock without needing to pass biometric auth. * fix(mobile): add missing closing brace in setBiometricEnabled --------- Signed-off-by: Tristan Katana <50181095+felixmuinde@users.noreply.github.com>
48 lines
1.4 KiB
Dart
48 lines
1.4 KiB
Dart
import 'package:local_auth/local_auth.dart';
|
|
import 'log_service.dart';
|
|
|
|
class BiometricService {
|
|
static final BiometricService instance = BiometricService._();
|
|
BiometricService._();
|
|
|
|
final LocalAuthentication _auth = LocalAuthentication();
|
|
|
|
/// Returns true when the platform supports biometrics AND at least one
|
|
/// biometric is enrolled on the device.
|
|
Future<bool> isDeviceSupported() async {
|
|
try {
|
|
final isSupported = await _auth.isDeviceSupported();
|
|
if (!isSupported) return false;
|
|
final enrolled = await _auth.getAvailableBiometrics();
|
|
return enrolled.isNotEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Returns the list of enrolled biometric types (fingerprint, face, etc.).
|
|
Future<List<BiometricType>> getAvailableBiometrics() async {
|
|
try {
|
|
return await _auth.getAvailableBiometrics();
|
|
} catch (_) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// Triggers the OS biometric prompt. Returns true if authentication succeeds.
|
|
Future<bool> authenticate({String reason = 'Unlock Sure to continue'}) async {
|
|
try {
|
|
return await _auth.authenticate(
|
|
localizedReason: reason,
|
|
options: const AuthenticationOptions(
|
|
stickyAuth: true,
|
|
biometricOnly: false,
|
|
),
|
|
);
|
|
} catch (e, stack) {
|
|
LogService.instance.error('BiometricService', 'authenticate() failed: $e\n$stack');
|
|
return false;
|
|
}
|
|
}
|
|
}
|