From fb2dbd1865b27e77cdc12357db2ecb4ed3d12688 Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:14:46 +0630 Subject: [PATCH] login --- .../auth/presentation/pages/login_page.dart | 21 +++++++ .../settings_local_data_source.dart | 8 +++ .../settings_repository_impl.dart | 5 ++ .../domain/entities/settings_content.dart | 2 + .../repositories/settings_repository.dart | 1 + .../domain/use_cases/set_finger_enabled.dart | 9 +++ .../manager/settings_ui_state.dart | 4 ++ .../manager/settings_view_model.dart | 11 ++++ .../presentation/pages/settings_page.dart | 10 ++++ pubspec.lock | 58 ++++++++++++++++++- pubspec.yaml | 1 + 11 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 lib/features/settings/domain/use_cases/set_finger_enabled.dart diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index 1c21534..7f73b8f 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -1,5 +1,6 @@ import 'package:cb_prestige_qr/core/utils/MainShell.dart'; import 'package:flutter/material.dart'; +import 'package:local_auth/local_auth.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @@ -8,12 +9,32 @@ class LoginPage extends StatefulWidget { State createState() => _LoginPageState(); } +enum _SupportState { unknown, supported, unsupported } + class _LoginPageState extends State { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); + final LocalAuthentication auth = LocalAuthentication(); + bool? _canCheckBiometric; + List? _availableBiometrics; + String _authorized = "Not Authorized"; + bool _isAuthenticating = false; + _SupportState _supportState = _SupportState.unknown; var _obscurePassword = true; + + @override + void initState(){ + super.initState(); + auth.isDeviceSupported().then( + (bool isSupported) => setState( + () => _supportState = isSupported + ? _SupportState.supported + : _SupportState.unsupported, + ), + ); + } @override void dispose() { diff --git a/lib/features/settings/data/data_sources/settings_local_data_source.dart b/lib/features/settings/data/data_sources/settings_local_data_source.dart index af896ea..fbc35fd 100644 --- a/lib/features/settings/data/data_sources/settings_local_data_source.dart +++ b/lib/features/settings/data/data_sources/settings_local_data_source.dart @@ -4,6 +4,7 @@ abstract class SettingsLocalDataSource { SettingsContent getSettings(); void setNotificationsEnabled(bool value); void setHapticsEnabled(bool value); + void setFingerEnabled(bool value); } class SettingsLocalDataSourceImpl implements SettingsLocalDataSource { @@ -11,12 +12,14 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource { bool _notificationsEnabled = true; bool _hapticsEnabled = true; + bool _fingerEnabled = true; @override SettingsContent getSettings() { return SettingsContent( notificationsEnabled: _notificationsEnabled, hapticsEnabled: _hapticsEnabled, + fingerEnabled: _fingerEnabled, appVersionLabel: 'v1.0.0', ); } @@ -30,4 +33,9 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource { void setHapticsEnabled(bool value) { _hapticsEnabled = value; } + + @override + void setFingerEnabled(bool value) { + _fingerEnabled = value; + } } diff --git a/lib/features/settings/data/repositories/settings_repository_impl.dart b/lib/features/settings/data/repositories/settings_repository_impl.dart index 7b8053c..77242d1 100644 --- a/lib/features/settings/data/repositories/settings_repository_impl.dart +++ b/lib/features/settings/data/repositories/settings_repository_impl.dart @@ -19,4 +19,9 @@ class SettingsRepositoryImpl implements SettingsRepository { Future setHapticsEnabled(bool value) async { _localDataSource.setHapticsEnabled(value); } + + @override + Future setFingerEnabled(bool value) async { + _localDataSource.setFingerEnabled(value); + } } diff --git a/lib/features/settings/domain/entities/settings_content.dart b/lib/features/settings/domain/entities/settings_content.dart index 3633e12..1c20146 100644 --- a/lib/features/settings/domain/entities/settings_content.dart +++ b/lib/features/settings/domain/entities/settings_content.dart @@ -2,10 +2,12 @@ class SettingsContent { const SettingsContent({ required this.notificationsEnabled, required this.hapticsEnabled, + required this.fingerEnabled, required this.appVersionLabel, }); final bool notificationsEnabled; final bool hapticsEnabled; + final bool fingerEnabled; final String appVersionLabel; } diff --git a/lib/features/settings/domain/repositories/settings_repository.dart b/lib/features/settings/domain/repositories/settings_repository.dart index e08579e..99173c8 100644 --- a/lib/features/settings/domain/repositories/settings_repository.dart +++ b/lib/features/settings/domain/repositories/settings_repository.dart @@ -4,4 +4,5 @@ abstract class SettingsRepository { Future getSettings(); Future setNotificationsEnabled(bool value); Future setHapticsEnabled(bool value); + Future setFingerEnabled(bool value); } diff --git a/lib/features/settings/domain/use_cases/set_finger_enabled.dart b/lib/features/settings/domain/use_cases/set_finger_enabled.dart new file mode 100644 index 0000000..cf64fbf --- /dev/null +++ b/lib/features/settings/domain/use_cases/set_finger_enabled.dart @@ -0,0 +1,9 @@ +import '../repositories/settings_repository.dart'; + +class SetFingerEnabled { + const SetFingerEnabled(this._repository); + + final SettingsRepository _repository; + + Future call(bool value) => _repository.setFingerEnabled(value); +} diff --git a/lib/features/settings/presentation/manager/settings_ui_state.dart b/lib/features/settings/presentation/manager/settings_ui_state.dart index c72dde4..2fa4a7f 100644 --- a/lib/features/settings/presentation/manager/settings_ui_state.dart +++ b/lib/features/settings/presentation/manager/settings_ui_state.dart @@ -5,21 +5,25 @@ class SettingsUiState { const SettingsUiState({ required this.notificationsEnabled, required this.hapticsEnabled, + required this.fingerEnabled, required this.appVersionLabel, }); final bool notificationsEnabled; final bool hapticsEnabled; + final bool fingerEnabled; final String appVersionLabel; SettingsUiState copyWith({ bool? notificationsEnabled, bool? hapticsEnabled, + bool? fingerEnabled, String? appVersionLabel, }) { return SettingsUiState( notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled, hapticsEnabled: hapticsEnabled ?? this.hapticsEnabled, + fingerEnabled: fingerEnabled ?? this.fingerEnabled, appVersionLabel: appVersionLabel ?? this.appVersionLabel, ); } diff --git a/lib/features/settings/presentation/manager/settings_view_model.dart b/lib/features/settings/presentation/manager/settings_view_model.dart index cadedbd..7a2e309 100644 --- a/lib/features/settings/presentation/manager/settings_view_model.dart +++ b/lib/features/settings/presentation/manager/settings_view_model.dart @@ -5,6 +5,7 @@ import '../../data/repositories/settings_repository_impl.dart'; import '../../domain/entities/settings_content.dart'; import '../../domain/repositories/settings_repository.dart'; import '../../domain/use_cases/get_settings.dart'; +import '../../domain/use_cases/set_finger_enabled.dart'; import '../../domain/use_cases/set_haptics_enabled.dart'; import '../../domain/use_cases/set_notifications_enabled.dart'; import 'settings_ui_state.dart'; @@ -29,6 +30,10 @@ final _setHapticsEnabledProvider = Provider( (ref) => SetHapticsEnabled(ref.watch(_settingsRepositoryProvider)), ); +final _setFingerEnabledProvider = Provider( + (ref) => SetFingerEnabled(ref.watch(_settingsRepositoryProvider)), +); + final settingsViewModelProvider = AsyncNotifierProvider( SettingsViewModel.new, @@ -45,6 +50,7 @@ class SettingsViewModel extends AsyncNotifier { return SettingsUiState( notificationsEnabled: content.notificationsEnabled, hapticsEnabled: content.hapticsEnabled, + fingerEnabled: content.fingerEnabled, appVersionLabel: content.appVersionLabel, ); } @@ -58,4 +64,9 @@ class SettingsViewModel extends AsyncNotifier { await ref.watch(_setHapticsEnabledProvider)(value); state = state.whenData((s) => s.copyWith(hapticsEnabled: value)); } + + Future toggleFinger(bool value) async { + await ref.watch(_setFingerEnabledProvider)(value); + state = state.whenData((s) => s.copyWith(fingerEnabled: value)); + } } diff --git a/lib/features/settings/presentation/pages/settings_page.dart b/lib/features/settings/presentation/pages/settings_page.dart index f0c333a..8001a51 100644 --- a/lib/features/settings/presentation/pages/settings_page.dart +++ b/lib/features/settings/presentation/pages/settings_page.dart @@ -27,6 +27,7 @@ class SettingsPage extends ConsumerWidget { state: state, onNotificationsChanged: viewModel.toggleNotifications, onHapticsChanged: viewModel.toggleHaptics, + onFingerChanged: viewModel.toggleFinger, ), loading: () => const Center(child: CircularProgressIndicator()), error: (error, stackTrace) => Center( @@ -45,11 +46,13 @@ class _SettingsBody extends StatelessWidget { required this.state, required this.onNotificationsChanged, required this.onHapticsChanged, + required this.onFingerChanged, }); final SettingsUiState state; final ValueChanged onNotificationsChanged; final ValueChanged onHapticsChanged; + final ValueChanged onFingerChanged; @override Widget build(BuildContext context) { @@ -72,6 +75,13 @@ class _SettingsBody extends StatelessWidget { title: const Text('Haptics'), subtitle: const Text('Vibration feedback'), ), + const Divider(height: 1), + SwitchListTile.adaptive( + value: state.fingerEnabled, + onChanged: onFingerChanged, + title: const Text('Fingerprint'), + subtitle: const Text('Enable fingerprint authentication'), + ), ], ), const SizedBox(height: 12), diff --git a/pubspec.lock b/pubspec.lock index e3bb824..2e0de45 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -278,6 +278,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.7" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" + url: "https://pub.dev" + source: hosted + version: "2.0.34" flutter_riverpod: dependency: transitive description: @@ -384,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.0" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" io: dependency: transitive description: @@ -432,6 +448,46 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.0" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: ae6f382f638108c6becd134318d7c3f0a93875383a54010f61d7c97ac05d5137 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: b41970749c2d43791790724b76917eeee1e90de76e6b0eec3edca03a329bf44c + url: "https://pub.dev" + source: hosted + version: "2.0.7" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: a8c3d4e17454111f7fd31ff72a31222359f6059f7fe956c2dcfe0f88f49826d4 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 + url: "https://pub.dev" + source: hosted + version: "1.1.0" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: be12c5b8ba5e64896983123655c5f67d2484ecfcc95e367952ad6e3bff94cb16 + url: "https://pub.dev" + source: hosted + version: "2.0.1" logging: dependency: transitive description: @@ -855,4 +911,4 @@ packages: version: "3.1.3" sdks: dart: ">=3.11.3 <4.0.0" - flutter: ">=3.35.0" + flutter: ">=3.38.0" diff --git a/pubspec.yaml b/pubspec.yaml index 054846f..446dce9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: riverpod_annotation: ^4.0.2 carousel_slider: ^5.1.2 mobile_scanner: ^7.2.0 + local_auth: ^3.0.1 dev_dependencies: flutter_test: