From b23a2e170e2c194fccc341cdfb2dbd284be3467e Mon Sep 17 00:00:00 2001 From: kolo Date: Sat, 21 Mar 2026 23:19:31 +0300 Subject: [PATCH] update --- lib/app/router.dart | 1 + lib/features/settings/screen.dart | 222 +++++++++--------------------- 2 files changed, 66 insertions(+), 157 deletions(-) diff --git a/lib/app/router.dart b/lib/app/router.dart index 4dfe0fb..5f2d353 100644 --- a/lib/app/router.dart +++ b/lib/app/router.dart @@ -68,6 +68,7 @@ class AppShell extends ConsumerWidget { final s = ref.watch(stringsProvider); final idx = _locationToIndex(context); return Scaffold( + extendBody: true, body: child, bottomNavigationBar: NavigationBar( selectedIndex: idx, diff --git a/lib/features/settings/screen.dart b/lib/features/settings/screen.dart index 97743b0..19b95a7 100644 --- a/lib/features/settings/screen.dart +++ b/lib/features/settings/screen.dart @@ -18,67 +18,49 @@ class SettingsScreen extends ConsumerWidget { void _confirmClearData(BuildContext context, WidgetRef ref) { final s = ref.read(stringsProvider); - showDialog( context: context, - builder: (ctx) => AlertDialog( title: Text(s.clearDataConfirm), - content: Text(s.clearDataWarning), - actions: [ TextButton( onPressed: () => Navigator.pop(ctx), - child: Text(s.cancel), ), - TextButton( onPressed: () { Navigator.pop(ctx); - showDialog( context: context, - builder: (ctx2) => AlertDialog( title: Text(s.areYouSure), - content: Text(s.allTransactionsWillBeDeleted), - actions: [ TextButton( onPressed: () => Navigator.pop(ctx2), - child: Text(s.noKeepThem), ), - TextButton( onPressed: () { ref.read(transactionsProvider.notifier).clearAll(); - Navigator.pop(ctx2); - ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(s.allTransactionsDeleted)), ); }, - style: TextButton.styleFrom( foregroundColor: const Color(0xFFE05C6B), ), - child: Text(s.yesDeleteEverything), ), ], ), ); }, - style: TextButton.styleFrom( foregroundColor: const Color(0xFFE05C6B), ), - child: Text(s.delete), ), ], @@ -92,25 +74,19 @@ class SettingsScreen extends ConsumerWidget { return Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, - appBar: AppBar( title: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ Text( s.settings, - style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onSurface, ), ), - Text( s.managePreferences, - style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), ), @@ -118,86 +94,56 @@ class SettingsScreen extends ConsumerWidget { ], ), ), - body: ListView( physics: const ClampingScrollPhysics(), - - padding: const EdgeInsets.fromLTRB(20, 16, 20, 40), - + padding: const EdgeInsets.fromLTRB(20, 16, 20, 100), children: [ const ThemeSection(), - const SizedBox(height: 16), - const HapticSection(), - const SizedBox(height: 16), - const _BiometricSection(), - const LanguageSection(), - const SizedBox(height: 16), - const CurrencySection(), - const SizedBox(height: 16), - const AmountFormatSection(), - const SizedBox(height: 16), - const BudgetSection(), - const SizedBox(height: 24), - Text( s.dangerZone, - style: TextStyle( fontSize: 12, - letterSpacing: 1.2, - color: const Color(0xFFE05C6B).withOpacity(0.8), - fontWeight: FontWeight.w600, ), ), - const SizedBox(height: 8), - SizedBox( width: double.infinity, - child: OutlinedButton.icon( onPressed: () => _confirmClearData(context, ref), - icon: const Icon(Icons.delete_forever, color: Color(0xFFE05C6B)), - label: Text( s.clearAllTransactions, - style: const TextStyle(color: Color(0xFFE05C6B)), ), - style: OutlinedButton.styleFrom( side: BorderSide( color: const Color(0xFFE05C6B).withOpacity(0.5), ), - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), - const SizedBox(height: 32), - const _FooterWidget(), + const SizedBox(height: 8), ], ), ); @@ -210,11 +156,9 @@ class _FooterWidget extends StatelessWidget { @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; - final baseColor = isDark ? Colors.white.withOpacity(0.25) : Colors.black.withOpacity(0.25); - final emphasisColor = isDark ? Colors.white.withOpacity(0.35) : Colors.black.withOpacity(0.35); @@ -222,33 +166,24 @@ class _FooterWidget extends StatelessWidget { return Center( child: RichText( textAlign: TextAlign.center, - text: TextSpan( style: TextStyle(fontSize: 13, color: baseColor), - children: [ TextSpan( text: 'casha', - style: TextStyle( fontWeight: FontWeight.bold, - color: emphasisColor, ), ), - const TextSpan( - text: ' powered with ❤️ by ', - + text: ' powered with ❤️ by ', style: TextStyle(fontStyle: FontStyle.italic), ), - TextSpan( text: 'kolo', - style: TextStyle( fontWeight: FontWeight.bold, - color: emphasisColor, ), ), @@ -268,134 +203,107 @@ class _BiometricSection extends ConsumerStatefulWidget { class _BiometricSectionState extends ConsumerState<_BiometricSection> { bool _available = false; - bool _enabled = false; - bool _loading = true; @override void initState() { super.initState(); - _load(); } - Future _load() async { + Future _load() async { final available = await BiometricService.isAvailable(); - final enabled = await BiometricService.isEnabled(); - if (mounted) { setState(() { _available = available; - _enabled = enabled; - _loading = false; }); } } - Future _onToggle(bool val) async { + Future _onToggle(bool val) async { if (val) { final ok = await BiometricService.authenticate(); - if (!ok) return; - HapticService.light(); } - await BiometricService.setEnabled(val); - if (mounted) setState(() => _enabled = val); } @override Widget build(BuildContext context) { - if (_loading || !_available) return const SizedBox.shrink(); - final s = ref.watch(stringsProvider); - final isDark = Theme.of(context).brightness == Brightness.dark; - return Column( - children: [ - Container( - padding: const EdgeInsets.all(20), - - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - - borderRadius: BorderRadius.circular(16), - - border: isDark - ? null - : Border.all(color: const Color(0xFFDDDDEE), width: 1), - ), - - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(10), - - decoration: BoxDecoration( - color: AppColors.accent.withOpacity(0.15), - - borderRadius: BorderRadius.circular(12), + return Visibility( + visible: !_loading && _available, + maintainSize: true, + maintainAnimation: true, + maintainState: true, + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(16), + border: isDark + ? null + : Border.all(color: const Color(0xFFDDDDEE), width: 1), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: AppColors.accent.withOpacity(0.15), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.fingerprint, + color: AppColors.accent, + size: 20, + ), ), - - child: const Icon( - Icons.fingerprint, - - color: AppColors.accent, - - size: 20, - ), - ), - - const SizedBox(width: 12), - - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - - children: [ - Text( - s.biometricLock, - - style: Theme.of(context).textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w600, - - color: Theme.of(context).colorScheme.onSurface, + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + s.biometricLock, + style: Theme.of(context).textTheme.titleMedium + ?.copyWith( + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.onSurface, + ), ), - ), - - Text( - s.requireFingerprint, - - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Theme.of( - context, - ).colorScheme.onSurface.withOpacity(0.6), + Text( + s.requireFingerprint, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Theme.of( + context, + ).colorScheme.onSurface.withOpacity(0.6), + ), ), - ), - ], + ], + ), ), - ), - - Switch( - value: _enabled, - - onChanged: _onToggle, - - activeThumbColor: const Color(0xFF7C6DED), - ), - ], + Switch( + value: _enabled, + onChanged: _onToggle, + activeThumbColor: const Color(0xFF7C6DED), + ), + ], + ), ), - ), - - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ); } }