login
This commit is contained in:
parent
1bf4c99843
commit
fb2dbd1865
@ -1,5 +1,6 @@
|
|||||||
import 'package:cb_prestige_qr/core/utils/MainShell.dart';
|
import 'package:cb_prestige_qr/core/utils/MainShell.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:local_auth/local_auth.dart';
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget {
|
class LoginPage extends StatefulWidget {
|
||||||
const LoginPage({super.key});
|
const LoginPage({super.key});
|
||||||
@ -8,12 +9,32 @@ class LoginPage extends StatefulWidget {
|
|||||||
State<LoginPage> createState() => _LoginPageState();
|
State<LoginPage> createState() => _LoginPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum _SupportState { unknown, supported, unsupported }
|
||||||
|
|
||||||
class _LoginPageState extends State<LoginPage> {
|
class _LoginPageState extends State<LoginPage> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final _usernameController = TextEditingController();
|
final _usernameController = TextEditingController();
|
||||||
final _passwordController = TextEditingController();
|
final _passwordController = TextEditingController();
|
||||||
|
final LocalAuthentication auth = LocalAuthentication();
|
||||||
|
bool? _canCheckBiometric;
|
||||||
|
List<BiometricType>? _availableBiometrics;
|
||||||
|
String _authorized = "Not Authorized";
|
||||||
|
bool _isAuthenticating = false;
|
||||||
|
_SupportState _supportState = _SupportState.unknown;
|
||||||
|
|
||||||
var _obscurePassword = true;
|
var _obscurePassword = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState(){
|
||||||
|
super.initState();
|
||||||
|
auth.isDeviceSupported().then(
|
||||||
|
(bool isSupported) => setState(
|
||||||
|
() => _supportState = isSupported
|
||||||
|
? _SupportState.supported
|
||||||
|
: _SupportState.unsupported,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ abstract class SettingsLocalDataSource {
|
|||||||
SettingsContent getSettings();
|
SettingsContent getSettings();
|
||||||
void setNotificationsEnabled(bool value);
|
void setNotificationsEnabled(bool value);
|
||||||
void setHapticsEnabled(bool value);
|
void setHapticsEnabled(bool value);
|
||||||
|
void setFingerEnabled(bool value);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
|
class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
|
||||||
@ -11,12 +12,14 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
|
|||||||
|
|
||||||
bool _notificationsEnabled = true;
|
bool _notificationsEnabled = true;
|
||||||
bool _hapticsEnabled = true;
|
bool _hapticsEnabled = true;
|
||||||
|
bool _fingerEnabled = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SettingsContent getSettings() {
|
SettingsContent getSettings() {
|
||||||
return SettingsContent(
|
return SettingsContent(
|
||||||
notificationsEnabled: _notificationsEnabled,
|
notificationsEnabled: _notificationsEnabled,
|
||||||
hapticsEnabled: _hapticsEnabled,
|
hapticsEnabled: _hapticsEnabled,
|
||||||
|
fingerEnabled: _fingerEnabled,
|
||||||
appVersionLabel: 'v1.0.0',
|
appVersionLabel: 'v1.0.0',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -30,4 +33,9 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
|
|||||||
void setHapticsEnabled(bool value) {
|
void setHapticsEnabled(bool value) {
|
||||||
_hapticsEnabled = value;
|
_hapticsEnabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setFingerEnabled(bool value) {
|
||||||
|
_fingerEnabled = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,4 +19,9 @@ class SettingsRepositoryImpl implements SettingsRepository {
|
|||||||
Future<void> setHapticsEnabled(bool value) async {
|
Future<void> setHapticsEnabled(bool value) async {
|
||||||
_localDataSource.setHapticsEnabled(value);
|
_localDataSource.setHapticsEnabled(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> setFingerEnabled(bool value) async {
|
||||||
|
_localDataSource.setFingerEnabled(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,12 @@ class SettingsContent {
|
|||||||
const SettingsContent({
|
const SettingsContent({
|
||||||
required this.notificationsEnabled,
|
required this.notificationsEnabled,
|
||||||
required this.hapticsEnabled,
|
required this.hapticsEnabled,
|
||||||
|
required this.fingerEnabled,
|
||||||
required this.appVersionLabel,
|
required this.appVersionLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool notificationsEnabled;
|
final bool notificationsEnabled;
|
||||||
final bool hapticsEnabled;
|
final bool hapticsEnabled;
|
||||||
|
final bool fingerEnabled;
|
||||||
final String appVersionLabel;
|
final String appVersionLabel;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,4 +4,5 @@ abstract class SettingsRepository {
|
|||||||
Future<SettingsContent> getSettings();
|
Future<SettingsContent> getSettings();
|
||||||
Future<void> setNotificationsEnabled(bool value);
|
Future<void> setNotificationsEnabled(bool value);
|
||||||
Future<void> setHapticsEnabled(bool value);
|
Future<void> setHapticsEnabled(bool value);
|
||||||
|
Future<void> setFingerEnabled(bool value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
import '../repositories/settings_repository.dart';
|
||||||
|
|
||||||
|
class SetFingerEnabled {
|
||||||
|
const SetFingerEnabled(this._repository);
|
||||||
|
|
||||||
|
final SettingsRepository _repository;
|
||||||
|
|
||||||
|
Future<void> call(bool value) => _repository.setFingerEnabled(value);
|
||||||
|
}
|
||||||
@ -5,21 +5,25 @@ class SettingsUiState {
|
|||||||
const SettingsUiState({
|
const SettingsUiState({
|
||||||
required this.notificationsEnabled,
|
required this.notificationsEnabled,
|
||||||
required this.hapticsEnabled,
|
required this.hapticsEnabled,
|
||||||
|
required this.fingerEnabled,
|
||||||
required this.appVersionLabel,
|
required this.appVersionLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool notificationsEnabled;
|
final bool notificationsEnabled;
|
||||||
final bool hapticsEnabled;
|
final bool hapticsEnabled;
|
||||||
|
final bool fingerEnabled;
|
||||||
final String appVersionLabel;
|
final String appVersionLabel;
|
||||||
|
|
||||||
SettingsUiState copyWith({
|
SettingsUiState copyWith({
|
||||||
bool? notificationsEnabled,
|
bool? notificationsEnabled,
|
||||||
bool? hapticsEnabled,
|
bool? hapticsEnabled,
|
||||||
|
bool? fingerEnabled,
|
||||||
String? appVersionLabel,
|
String? appVersionLabel,
|
||||||
}) {
|
}) {
|
||||||
return SettingsUiState(
|
return SettingsUiState(
|
||||||
notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled,
|
notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled,
|
||||||
hapticsEnabled: hapticsEnabled ?? this.hapticsEnabled,
|
hapticsEnabled: hapticsEnabled ?? this.hapticsEnabled,
|
||||||
|
fingerEnabled: fingerEnabled ?? this.fingerEnabled,
|
||||||
appVersionLabel: appVersionLabel ?? this.appVersionLabel,
|
appVersionLabel: appVersionLabel ?? this.appVersionLabel,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import '../../data/repositories/settings_repository_impl.dart';
|
|||||||
import '../../domain/entities/settings_content.dart';
|
import '../../domain/entities/settings_content.dart';
|
||||||
import '../../domain/repositories/settings_repository.dart';
|
import '../../domain/repositories/settings_repository.dart';
|
||||||
import '../../domain/use_cases/get_settings.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_haptics_enabled.dart';
|
||||||
import '../../domain/use_cases/set_notifications_enabled.dart';
|
import '../../domain/use_cases/set_notifications_enabled.dart';
|
||||||
import 'settings_ui_state.dart';
|
import 'settings_ui_state.dart';
|
||||||
@ -29,6 +30,10 @@ final _setHapticsEnabledProvider = Provider<SetHapticsEnabled>(
|
|||||||
(ref) => SetHapticsEnabled(ref.watch(_settingsRepositoryProvider)),
|
(ref) => SetHapticsEnabled(ref.watch(_settingsRepositoryProvider)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final _setFingerEnabledProvider = Provider<SetFingerEnabled>(
|
||||||
|
(ref) => SetFingerEnabled(ref.watch(_settingsRepositoryProvider)),
|
||||||
|
);
|
||||||
|
|
||||||
final settingsViewModelProvider =
|
final settingsViewModelProvider =
|
||||||
AsyncNotifierProvider<SettingsViewModel, SettingsUiState>(
|
AsyncNotifierProvider<SettingsViewModel, SettingsUiState>(
|
||||||
SettingsViewModel.new,
|
SettingsViewModel.new,
|
||||||
@ -45,6 +50,7 @@ class SettingsViewModel extends AsyncNotifier<SettingsUiState> {
|
|||||||
return SettingsUiState(
|
return SettingsUiState(
|
||||||
notificationsEnabled: content.notificationsEnabled,
|
notificationsEnabled: content.notificationsEnabled,
|
||||||
hapticsEnabled: content.hapticsEnabled,
|
hapticsEnabled: content.hapticsEnabled,
|
||||||
|
fingerEnabled: content.fingerEnabled,
|
||||||
appVersionLabel: content.appVersionLabel,
|
appVersionLabel: content.appVersionLabel,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -58,4 +64,9 @@ class SettingsViewModel extends AsyncNotifier<SettingsUiState> {
|
|||||||
await ref.watch(_setHapticsEnabledProvider)(value);
|
await ref.watch(_setHapticsEnabledProvider)(value);
|
||||||
state = state.whenData((s) => s.copyWith(hapticsEnabled: value));
|
state = state.whenData((s) => s.copyWith(hapticsEnabled: value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> toggleFinger(bool value) async {
|
||||||
|
await ref.watch(_setFingerEnabledProvider)(value);
|
||||||
|
state = state.whenData((s) => s.copyWith(fingerEnabled: value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
state: state,
|
state: state,
|
||||||
onNotificationsChanged: viewModel.toggleNotifications,
|
onNotificationsChanged: viewModel.toggleNotifications,
|
||||||
onHapticsChanged: viewModel.toggleHaptics,
|
onHapticsChanged: viewModel.toggleHaptics,
|
||||||
|
onFingerChanged: viewModel.toggleFinger,
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, stackTrace) => Center(
|
error: (error, stackTrace) => Center(
|
||||||
@ -45,11 +46,13 @@ class _SettingsBody extends StatelessWidget {
|
|||||||
required this.state,
|
required this.state,
|
||||||
required this.onNotificationsChanged,
|
required this.onNotificationsChanged,
|
||||||
required this.onHapticsChanged,
|
required this.onHapticsChanged,
|
||||||
|
required this.onFingerChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
final SettingsUiState state;
|
final SettingsUiState state;
|
||||||
final ValueChanged<bool> onNotificationsChanged;
|
final ValueChanged<bool> onNotificationsChanged;
|
||||||
final ValueChanged<bool> onHapticsChanged;
|
final ValueChanged<bool> onHapticsChanged;
|
||||||
|
final ValueChanged<bool> onFingerChanged;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -72,6 +75,13 @@ class _SettingsBody extends StatelessWidget {
|
|||||||
title: const Text('Haptics'),
|
title: const Text('Haptics'),
|
||||||
subtitle: const Text('Vibration feedback'),
|
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),
|
const SizedBox(height: 12),
|
||||||
|
|||||||
58
pubspec.lock
58
pubspec.lock
@ -278,6 +278,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.7"
|
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:
|
flutter_riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -384,6 +392,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.0"
|
version: "4.8.0"
|
||||||
|
intl:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: intl
|
||||||
|
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.20.2"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -432,6 +448,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.0"
|
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:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -855,4 +911,4 @@ packages:
|
|||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.11.3 <4.0.0"
|
dart: ">=3.11.3 <4.0.0"
|
||||||
flutter: ">=3.35.0"
|
flutter: ">=3.38.0"
|
||||||
|
|||||||
@ -40,6 +40,7 @@ dependencies:
|
|||||||
riverpod_annotation: ^4.0.2
|
riverpod_annotation: ^4.0.2
|
||||||
carousel_slider: ^5.1.2
|
carousel_slider: ^5.1.2
|
||||||
mobile_scanner: ^7.2.0
|
mobile_scanner: ^7.2.0
|
||||||
|
local_auth: ^3.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user