233 lines
7.1 KiB
Dart
233 lines
7.1 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:kmobile/data/repositories/auth_repository.dart';
|
|
import 'package:kmobile/features/profile/change_password/change_password_screen.dart';
|
|
import 'package:kmobile/features/profile/logout_dialog.dart';
|
|
import 'package:kmobile/security/secure_storage.dart';
|
|
import 'package:local_auth/local_auth.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import '../../di/injection.dart';
|
|
import '../../l10n/app_localizations.dart';
|
|
import 'package:kmobile/features/profile/preferences/preference_screen.dart';
|
|
|
|
class ProfileScreen extends StatefulWidget {
|
|
final String mobileNumber;
|
|
const ProfileScreen({super.key, required this.mobileNumber});
|
|
|
|
@override
|
|
State<ProfileScreen> createState() => _ProfileScreenState();
|
|
}
|
|
|
|
class _ProfileScreenState extends State<ProfileScreen> {
|
|
bool _isBiometricEnabled = false;
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadBiometricStatus();
|
|
}
|
|
|
|
Future<void> _loadBiometricStatus() async {
|
|
final storage = getIt<SecureStorage>();
|
|
final isEnabled = await storage.read('biometric_enabled');
|
|
setState(() {
|
|
_isBiometricEnabled = isEnabled == 'true';
|
|
});
|
|
}
|
|
|
|
Future<void> _handleLogout(BuildContext context) async {
|
|
final auth = getIt<AuthRepository>();
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.clear(); // clear saved session/token
|
|
await auth.clearAuthTokens();
|
|
// Navigate to login and remove all previous routes
|
|
Navigator.pushNamedAndRemoveUntil(context, '/login', (route) => false);
|
|
}
|
|
|
|
|
|
Future<void> _handleBiometricToggle(bool enable) async {
|
|
final localAuth = LocalAuthentication();
|
|
final storage = getIt<SecureStorage>();
|
|
final canCheck = await localAuth.canCheckBiometrics;
|
|
|
|
if (!canCheck) {
|
|
// Optional: Show a snackbar or dialog if biometrics are not available
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text(AppLocalizations.of(context).biometricsNotAvailable)),
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (enable) {
|
|
// Show "Enable" dialog
|
|
final optIn = await showDialog<bool>(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (ctx) => AlertDialog(
|
|
title: Text(AppLocalizations.of(context).enableFingerprintLogin),
|
|
content: Text(AppLocalizations.of(context).enableFingerprintMessage),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(ctx).pop(false),
|
|
child: Text(AppLocalizations.of(context).no),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.of(ctx).pop(true),
|
|
child: Text(AppLocalizations.of(context).yes),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (optIn == true) {
|
|
try {
|
|
final didAuth = await localAuth.authenticate(
|
|
localizedReason: AppLocalizations.of(context).authenticateToEnable,
|
|
options: const AuthenticationOptions(
|
|
stickyAuth: true,
|
|
biometricOnly: true,
|
|
),
|
|
);
|
|
if (didAuth) {
|
|
await storage.write('biometric_enabled', 'true');
|
|
setState(() {
|
|
_isBiometricEnabled = true;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
// Handle authentication errors
|
|
}
|
|
}
|
|
} else {
|
|
// Show "Disable" dialog
|
|
final optOut = await showDialog<bool>(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (ctx) => AlertDialog(
|
|
title: Text(AppLocalizations.of(context).disableFingerprintLogin),
|
|
content: Text(AppLocalizations.of(context).disableFingerprintMessage),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(ctx).pop(false),
|
|
child: Text(AppLocalizations.of(context).no),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.of(ctx).pop(true),
|
|
child: Text(AppLocalizations.of(context).yes),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (optOut == true) {
|
|
await storage.write('biometric_enabled', 'false');
|
|
setState(() {
|
|
_isBiometricEnabled = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final loc = AppLocalizations.of(context);
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(loc.profile), // Localized "Profile"
|
|
),
|
|
body: ListView(
|
|
children: [
|
|
ListTile(
|
|
leading: const Icon(Icons.settings),
|
|
title: Text(loc.preferences),
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => const PreferenceScreen()),
|
|
);
|
|
},
|
|
),
|
|
SwitchListTile(
|
|
title: Text(AppLocalizations.of(context).enableFingerprintLogin),
|
|
value: _isBiometricEnabled,
|
|
onChanged: (bool value) {
|
|
_handleBiometricToggle(value);
|
|
},
|
|
secondary: const Icon(Icons.fingerprint),
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.password),
|
|
title: Text(loc.changeLoginPassword),
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => ChangePasswordScreen(
|
|
mobileNumber: widget.mobileNumber,
|
|
)),
|
|
);
|
|
},
|
|
),
|
|
// ListTile(
|
|
// leading: const Icon(Icons.password),
|
|
// title: const Text("Manage TPIN"),
|
|
// onTap: () async {
|
|
// },
|
|
// ),
|
|
// ListTile(
|
|
// leading: const Icon(Icons.password),
|
|
// title: const Text("Change Login MPIN"),
|
|
// onTap: () async {
|
|
// },
|
|
// ),
|
|
ListTile(
|
|
leading: const Icon(Icons.exit_to_app),
|
|
title: Text(AppLocalizations.of(context).logout),
|
|
onTap: () async {
|
|
final shouldExit = await showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(AppLocalizations.of(context).logout),
|
|
content: Text(AppLocalizations.of(context).logoutCheck),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(false),
|
|
child: Text(AppLocalizations.of(context).no),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(true),
|
|
child: Text(AppLocalizations.of(context).yes),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (shouldExit == true) {
|
|
if (Platform.isAndroid) {
|
|
SystemNavigator.pop();
|
|
}
|
|
exit(0);
|
|
}
|
|
},
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.logout),
|
|
title: Text(AppLocalizations.of(context).deregister),
|
|
onTap: () async {
|
|
final shouldLogout = await showDialog<bool>(
|
|
context: context,
|
|
builder: (_) => const LogoutDialog(),
|
|
);
|
|
|
|
if (shouldLogout == true) {
|
|
await _handleLogout(context);
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|