From d67d8cb89ce0c2b1f1b49e132c10a780e7812de0 Mon Sep 17 00:00:00 2001 From: kolo Date: Sun, 22 Mar 2026 17:25:22 +0300 Subject: [PATCH] stableee --- lib/app/theme.dart | 1 - lib/core/services/card_color_service.dart | 7 +- lib/features/dashboard/provider.dart | 161 +++++++++++++++++----- 3 files changed, 135 insertions(+), 34 deletions(-) diff --git a/lib/app/theme.dart b/lib/app/theme.dart index 9bdba93..6c39ca7 100644 --- a/lib/app/theme.dart +++ b/lib/app/theme.dart @@ -5,7 +5,6 @@ import '../core/constants.dart'; TextStyle? _f(TextStyle? s) { final result = s?.copyWith(fontFamilyFallback: ['NunitoCyrillic']); - debugPrint('fallback: ${result?.fontFamilyFallback}'); // проверь в логах return result; } diff --git a/lib/core/services/card_color_service.dart b/lib/core/services/card_color_service.dart index 94dffd5..a695d53 100644 --- a/lib/core/services/card_color_service.dart +++ b/lib/core/services/card_color_service.dart @@ -16,7 +16,6 @@ class CardColorService { static const defaultGradient = GradientType.sweep; - static Future<(Color, Color, GradientType)> load() async { final prefs = await SharedPreferences.getInstance(); final c1 = prefs.getInt(_key1); @@ -29,7 +28,11 @@ class CardColorService { ); } - static Future save(Color primary, Color secondary, GradientType gradient) async { + static Future save( + Color primary, + Color secondary, + GradientType gradient, + ) async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt(_key1, primary.value); await prefs.setInt(_key2, secondary.value); diff --git a/lib/features/dashboard/provider.dart b/lib/features/dashboard/provider.dart index 261ae31..c26db0f 100644 --- a/lib/features/dashboard/provider.dart +++ b/lib/features/dashboard/provider.dart @@ -16,9 +16,9 @@ final storageServiceProvider = Provider((ref) { final transactionsProvider = StateNotifierProvider>((ref) { - final storage = ref.watch(storageServiceProvider); - return TransactionsNotifier(storage); -}); + final storage = ref.watch(storageServiceProvider); + return TransactionsNotifier(storage); + }); class TransactionsNotifier extends StateNotifier> { final StorageService _storage; @@ -47,7 +47,9 @@ class TransactionsNotifier extends StateNotifier> { void clearAll() { state = []; - SharedPreferences.getInstance().then((prefs) => prefs.remove('transactions')); + SharedPreferences.getInstance().then( + (prefs) => prefs.remove('transactions'), + ); } } @@ -57,10 +59,13 @@ enum TransactionFilter { all, income, expense } enum TimeFilter { allTime, lastMonth } -final transactionFilterProvider = - StateProvider((ref) => TransactionFilter.all); +final transactionFilterProvider = StateProvider( + (ref) => TransactionFilter.all, +); -final timeFilterProvider = StateProvider((ref) => TimeFilter.lastMonth); +final timeFilterProvider = StateProvider( + (ref) => TimeFilter.lastMonth, +); final totalBalanceProvider = Provider((ref) { final txs = ref.watch(transactionsProvider); @@ -68,42 +73,57 @@ final totalBalanceProvider = Provider((ref) { final targetCurrency = ref.watch(currencyProvider).code; return txs.fold(0.0, (sum, t) { - final converted = exchangeService.convert(t.amount, t.currencyCode, targetCurrency); + final converted = exchangeService.convert( + t.amount, + t.currencyCode, + targetCurrency, + ); return t.type == TransactionType.income ? sum + converted : sum - converted; }); }); final totalIncomeProvider = Provider((ref) { - final txs = ref.watch(transactionsProvider).where((t) => t.type == TransactionType.income); + final txs = ref + .watch(transactionsProvider) + .where((t) => t.type == TransactionType.income); final exchangeService = ref.watch(exchangeRateServiceProvider); final targetCurrency = ref.watch(currencyProvider).code; return txs.fold(0.0, (sum, t) { - return sum + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); + return sum + + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); }); }); final totalExpenseProvider = Provider((ref) { - final txs = ref.watch(transactionsProvider).where((t) => t.type == TransactionType.expense); + final txs = ref + .watch(transactionsProvider) + .where((t) => t.type == TransactionType.expense); final exchangeService = ref.watch(exchangeRateServiceProvider); final targetCurrency = ref.watch(currencyProvider).code; return txs.fold(0.0, (sum, t) { - return sum + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); + return sum + + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); }); }); final currentMonthExpenseProvider = Provider((ref) { final now = DateTime.now(); - final txs = ref.watch(transactionsProvider).where((t) => - t.type == TransactionType.expense && - t.date.year == now.year && - t.date.month == now.month); + final txs = ref + .watch(transactionsProvider) + .where( + (t) => + t.type == TransactionType.expense && + t.date.year == now.year && + t.date.month == now.month, + ); final exchangeService = ref.watch(exchangeRateServiceProvider); final targetCurrency = ref.watch(currencyProvider).code; return txs.fold(0.0, (sum, t) { - return sum + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); + return sum + + exchangeService.convert(t.amount, t.currencyCode, targetCurrency); }); }); @@ -119,16 +139,21 @@ final filteredTransactionsProvider = Provider>((ref) { final now = DateTime.now(); final start = DateTime(now.year, now.month, 1); final end = DateTime(now.year, now.month + 1, 1); - filtered = filtered.where((t) => - t.date.isAfter(start.subtract(const Duration(seconds: 1))) && - t.date.isBefore(end) - ).toList(); + filtered = filtered + .where( + (t) => + t.date.isAfter(start.subtract(const Duration(seconds: 1))) && + t.date.isBefore(end), + ) + .toList(); } if (typeFilter == TransactionFilter.income) { filtered = filtered.where((t) => t.type == TransactionType.income).toList(); } else if (typeFilter == TransactionFilter.expense) { - filtered = filtered.where((t) => t.type == TransactionType.expense).toList(); + filtered = filtered + .where((t) => t.type == TransactionType.expense) + .toList(); } if (query.isNotEmpty) { @@ -155,34 +180,108 @@ class CardColors { const CardColors(this.primary, this.secondary, this.gradientType); } -final cardColorsProvider = StateNotifierProvider((ref) { - return CardColorsNotifier(); -}); +final cardColorsProvider = + StateNotifierProvider((ref) { + final notifier = CardColorsNotifier(); + notifier.setupThemeListener(ref); + return notifier; + }); class CardColorsNotifier extends StateNotifier { CardColorsNotifier() - : super(const CardColors( + : super( + const CardColors( CardColorService.defaultPrimary, CardColorService.defaultSecondary, CardColorService.defaultGradient, - )) { + ), + ) { _load(); } + void setupThemeListener(Ref ref) { + ref.listen(themeProvider, (previous, next) { + if (previous != null) { + _onThemeChanged(previous, next); + } + }); + } + Future _load() async { final (c1, c2, g) = await CardColorService.load(); state = CardColors(c1, c2, g); } - Future save(Color primary, Color secondary, GradientType gradient) async { + Future save( + Color primary, + Color secondary, + GradientType gradient, + ) async { state = CardColors(primary, secondary, gradient); await CardColorService.save(primary, secondary, gradient); } Future reset(bool isDark) async { - final primary = isDark ? CardColorService.defaultPrimary : CardColorService.defaultPrimaryLight; - final secondary = isDark ? CardColorService.defaultSecondary : CardColorService.defaultSecondaryLight; + final primary = isDark + ? CardColorService.defaultPrimary + : CardColorService.defaultPrimaryLight; + final secondary = isDark + ? CardColorService.defaultSecondary + : CardColorService.defaultSecondaryLight; state = CardColors(primary, secondary, CardColorService.defaultGradient); - await CardColorService.save(primary, secondary, CardColorService.defaultGradient); + await CardColorService.save( + primary, + secondary, + CardColorService.defaultGradient, + ); + } + + void _onThemeChanged(ThemeMode previous, ThemeMode next) { + final previousBrightness = _resolve(previous); + final nextBrightness = _resolve(next); + + // No change in actual brightness + if (previousBrightness == nextBrightness) return; + + final oldDefaults = _defaultsFor(previousBrightness); + final newDefaults = _defaultsFor(nextBrightness); + + // Check if current colors match old theme defaults + final isUsingOldDefaults = + state.primary == oldDefaults.primary && + state.secondary == oldDefaults.secondary && + state.gradientType == oldDefaults.gradient; + + // Only auto-switch if using default colors + if (isUsingOldDefaults) { + state = CardColors( + newDefaults.primary, + newDefaults.secondary, + newDefaults.gradient, + ); + } + } + + Brightness _resolve(ThemeMode mode) { + if (mode == ThemeMode.system) { + return WidgetsBinding.instance.platformDispatcher.platformBrightness; + } + return mode == ThemeMode.dark ? Brightness.dark : Brightness.light; + } + + ({Color primary, Color secondary, GradientType gradient}) _defaultsFor( + Brightness brightness, + ) { + return brightness == Brightness.dark + ? ( + primary: CardColorService.defaultPrimary, + secondary: CardColorService.defaultSecondary, + gradient: CardColorService.defaultGradient, + ) + : ( + primary: CardColorService.defaultPrimaryLight, + secondary: CardColorService.defaultSecondaryLight, + gradient: CardColorService.defaultGradient, + ); } }