diff --git a/lib/app.dart b/lib/app.dart index 9272d47..d0e1bf6 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -20,6 +20,7 @@ import 'features/dashboard/screens/dashboard_screen.dart'; import 'features/auth/screens/mpin_screen.dart'; import 'package:local_auth/local_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'dart:async'; class KMobile extends StatefulWidget { const KMobile({super.key}); @@ -34,13 +35,15 @@ class KMobile extends StatefulWidget { } } -class _KMobileState extends State { +class _KMobileState extends State with WidgetsBindingObserver { + Timer? _backgroundTimer; bool showSplash = true; Locale? _locale; @override void initState() { super.initState(); + WidgetsBinding.instance.addObserver(this); loadPreferences(); Future.delayed(const Duration(seconds: 3), () { setState(() { @@ -49,10 +52,32 @@ class _KMobileState extends State { }); } + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + _backgroundTimer?.cancel(); + super.dispose(); + } + +@override +void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + switch (state) { + case AppLifecycleState.resumed: + _backgroundTimer?.cancel(); + break; + case AppLifecycleState.paused: + _backgroundTimer = Timer(const Duration(minutes: 2), () { + SystemNavigator.pop(); + }); + break; + default: + break; + } +} + Future loadPreferences() async { final prefs = await SharedPreferences.getInstance(); - - // Load Locale final String? langCode = prefs.getString('locale'); if (langCode != null) { setState(() { @@ -117,7 +142,6 @@ class _KMobileState extends State { class AuthGate extends StatefulWidget { const AuthGate({super.key}); - @override State createState() => _AuthGateState(); } @@ -180,7 +204,6 @@ class _AuthGateState extends State { if (_checking) { return const SplashScreen(); } - if (_isLoggedIn) { if (_hasMPin) { if (_biometricEnabled) { @@ -190,11 +213,9 @@ class _AuthGateState extends State { if (snapshot.connectionState == ConnectionState.waiting) { return const SplashScreen(); } - if (snapshot.data == true) { - return const NavigationScaffold(); // Authenticated + return const NavigationScaffold(); } - return MPinScreen( mode: MPinMode.enter, onCompleted: (_) { @@ -225,7 +246,6 @@ class _AuthGateState extends State { onCompleted: (_) async { final storage = getIt(); final localAuth = LocalAuthentication(); - final optIn = await showDialog( context: context, barrierDismissible: false, @@ -246,7 +266,6 @@ class _AuthGateState extends State { ], ), ); - if (optIn == true) { final canCheck = await localAuth.canCheckBiometrics; bool didAuth = false; @@ -254,7 +273,6 @@ class _AuthGateState extends State { if (context.mounted) { authEnable = AppLocalizations.of(context).authenticateToEnable; } - if (canCheck) { didAuth = await localAuth.authenticate( localizedReason: authEnable, @@ -269,7 +287,6 @@ class _AuthGateState extends State { await storage.write('biometric_enabled', 'false'); } } - if (context.mounted) { Navigator.of(context).pushReplacement( MaterialPageRoute( @@ -287,7 +304,6 @@ class _AuthGateState extends State { class NavigationScaffold extends StatefulWidget { const NavigationScaffold({super.key}); - @override State createState() => _NavigationScaffoldState(); } @@ -295,7 +311,6 @@ class NavigationScaffold extends StatefulWidget { class _NavigationScaffoldState extends State { final PageController _pageController = PageController(); int _selectedIndex = 0; - final List _pages = [ const DashboardScreen(), const CardManagementScreen(), @@ -372,11 +387,9 @@ class _NavigationScaffoldState extends State { } } -// Add this widget at the end of the file class BiometricPromptScreen extends StatelessWidget { final VoidCallback onCompleted; const BiometricPromptScreen({super.key, required this.onCompleted}); - Future _handleBiometric(BuildContext context) async { final localAuth = LocalAuthentication(); final canCheck = await localAuth.canCheckBiometrics; @@ -444,4 +457,4 @@ class BiometricPromptScreen extends StatelessWidget { onCompleted(); } } -} +} \ No newline at end of file diff --git a/lib/features/profile/logout_dialog.dart b/lib/features/profile/logout_dialog.dart index 4b930d3..101ccd6 100644 --- a/lib/features/profile/logout_dialog.dart +++ b/lib/features/profile/logout_dialog.dart @@ -8,8 +8,8 @@ class LogoutDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(AppLocalizations.of(context).logout), - content: Text(AppLocalizations.of(context).logoutCheck), + title: Text(AppLocalizations.of(context).deregister), + content: Text(AppLocalizations.of(context).deregistercheck), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), // dismiss diff --git a/lib/features/profile/profile_screen.dart b/lib/features/profile/profile_screen.dart index 2ad29a6..edb7705 100644 --- a/lib/features/profile/profile_screen.dart +++ b/lib/features/profile/profile_screen.dart @@ -1,4 +1,6 @@ +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'; @@ -70,9 +72,39 @@ class _ProfileScreenState extends State { // onTap: () async { // }, // ), + ListTile( + leading: const Icon(Icons.exit_to_app), + title: Text(AppLocalizations.of(context).logout), + onTap: () async { + final shouldExit = await showDialog( + 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).logout), + title: Text(AppLocalizations.of(context).deregister), onTap: () async { final shouldLogout = await showDialog( context: context, diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 59bb816..65bb936 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -326,5 +326,7 @@ "editLimit": "Edit Limit", "removeLimit": "Remove Limit", "limitAmount": "Limit Amount", - "save": "Save" + "save": "Save", + "deregister": "De-Register", + "deregistercheck": "Are you sure you want to De-Register?" } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index 559f0d1..0b2d861 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -327,5 +327,7 @@ "editLimit": "सीमा संपादित करें", "removeLimit": "सीमा हटाएँ", "limitAmount": "सीमा राशि", - "save": "जमा करें" + "save": "जमा करें", + "deregister": "अपंजीकृत", + "deregistercheck": "क्या आप वाकई पंजीकरण रद्द करना चाहते हैं??" }