This commit is contained in:
2026-03-25 14:45:58 +03:00
parent b617e3acf6
commit d2278523bd
7 changed files with 148 additions and 3 deletions
+5
View File
@@ -184,5 +184,10 @@ class AppStrings {
String get accountsInfoLimit => String get accountsInfoLimit =>
_ru ? 'Максимум 5 счетов.' : 'Maximum 5 accounts.'; _ru ? 'Максимум 5 счетов.' : 'Maximum 5 accounts.';
String get currencyConversions =>
_ru ? 'Конвертация валют' : 'Currency conversions';
String get showConversionsOnCard =>
_ru ? 'Показывать на карточке' : 'Show on balance card';
String get dateLocale => _ru ? 'ru_RU' : 'en_US'; String get dateLocale => _ru ? 'ru_RU' : 'en_US';
} }
@@ -368,6 +368,16 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(widget.context).colorScheme.surface, color: Theme.of(widget.context).colorScheme.surface,
shape: BoxShape.circle, shape: BoxShape.circle,
border:
Theme.of(widget.context).brightness ==
Brightness.dark
? Border.all(
color: Theme.of(
widget.context,
).colorScheme.onSurface.withOpacity(0.3),
width: 1,
)
: null,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.red.withOpacity(0.2), color: Colors.red.withOpacity(0.2),
@@ -393,6 +403,16 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(widget.context).colorScheme.surface, color: Theme.of(widget.context).colorScheme.surface,
shape: BoxShape.circle, shape: BoxShape.circle,
border:
Theme.of(widget.context).brightness ==
Brightness.dark
? Border.all(
color: Theme.of(
widget.context,
).colorScheme.onSurface.withOpacity(0.3),
width: 1,
)
: null,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.3), color: Colors.black.withOpacity(0.3),
@@ -34,7 +34,20 @@ class AccountDeleteDialog extends ConsumerWidget {
'Are you sure you want to delete this account? All associated transactions will also be permanently deleted.', 'Are you sure you want to delete this account? All associated transactions will also be permanently deleted.',
), ),
actions: [ actions: [
TextButton(onPressed: onCancel, child: const Text('Cancel')), TextButton(
onPressed: onCancel,
style: Theme.of(context).brightness == Brightness.dark
? TextButton.styleFrom(
side: BorderSide(
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.3),
width: 1,
),
)
: null,
child: const Text('Cancel'),
),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
if (editingAccount == null) return; if (editingAccount == null) return;
@@ -57,6 +70,16 @@ class AccountDeleteDialog extends ConsumerWidget {
HapticService.medium(); HapticService.medium();
} }
}, },
style: Theme.of(context).brightness == Brightness.dark
? TextButton.styleFrom(
side: BorderSide(
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.3),
width: 1,
),
)
: null,
child: const Text( child: const Text(
'Delete', 'Delete',
style: TextStyle(color: Colors.red), style: TextStyle(color: Colors.red),
@@ -130,8 +130,8 @@ class BalanceCardState extends ConsumerState<BalanceCard>
final s = ref.watch(stringsProvider); final s = ref.watch(stringsProvider);
final rates = ref.read(exchangeRateServiceProvider); final rates = ref.read(exchangeRateServiceProvider);
final fmt = ref.watch(amountFormatProvider); final fmt = ref.watch(amountFormatProvider);
final showConversions = ref.watch(showCurrencyConversionsProvider);
// Use account-specific colors if provided, otherwise use global colors
final globalColors = ref.watch(cardColorsProvider); final globalColors = ref.watch(cardColorsProvider);
final savedColors = widget.accountColors ?? globalColors; final savedColors = widget.accountColors ?? globalColors;
final primary = widget.previewPrimary ?? savedColors.primary; final primary = widget.previewPrimary ?? savedColors.primary;
@@ -259,7 +259,7 @@ class BalanceCardState extends ConsumerState<BalanceCard>
], ],
), ),
), ),
if (widget.balance != 0) ...[ if (widget.balance != 0 && showConversions) ...[
const SizedBox(width: 16), const SizedBox(width: 16),
Container( Container(
width: 1, width: 1,
+22
View File
@@ -165,6 +165,28 @@ class HapticNotifier extends StateNotifier<bool> {
} }
} }
final showCurrencyConversionsProvider =
StateNotifierProvider<ShowCurrencyConversionsNotifier, bool>((ref) {
return ShowCurrencyConversionsNotifier();
});
class ShowCurrencyConversionsNotifier extends StateNotifier<bool> {
ShowCurrencyConversionsNotifier() : super(true) {
_load();
}
Future<void> _load() async {
final prefs = await SharedPreferences.getInstance();
state = prefs.getBool('show_currency_conversions') ?? true;
}
Future<void> toggle(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('show_currency_conversions', value);
state = value;
}
}
final exportProvider = Provider<ExportService>((ref) { final exportProvider = Provider<ExportService>((ref) {
return ExportService(ref); return ExportService(ref);
}); });
+3
View File
@@ -9,6 +9,7 @@ import 'provider.dart';
import 'widgets/theme_section.dart'; import 'widgets/theme_section.dart';
import 'widgets/card_text_color_section.dart'; import 'widgets/card_text_color_section.dart';
import 'widgets/haptic_section.dart'; import 'widgets/haptic_section.dart';
import 'widgets/currency_conversions_section.dart';
import 'widgets/language_section.dart'; import 'widgets/language_section.dart';
import 'widgets/currency_section.dart'; import 'widgets/currency_section.dart';
import 'widgets/amount_format_section.dart'; import 'widgets/amount_format_section.dart';
@@ -129,6 +130,8 @@ class SettingsScreen extends ConsumerWidget {
const SizedBox(height: 16), const SizedBox(height: 16),
const HapticSection(), const HapticSection(),
const SizedBox(height: 16), const SizedBox(height: 16),
const CurrencyConversionsSection(),
const SizedBox(height: 16),
const _BiometricSection(), const _BiometricSection(),
const LanguageSection(), const LanguageSection(),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/constants.dart';
import '../../../core/l10n/locale_provider.dart';
import '../provider.dart';
class CurrencyConversionsSection extends ConsumerWidget {
const CurrencyConversionsSection({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final s = ref.watch(stringsProvider);
final enabled = ref.watch(showCurrencyConversionsProvider);
final isDark = Theme.of(context).brightness == Brightness.dark;
return 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.currency_exchange_rounded,
color: AppColors.accent,
size: 20,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.currencyConversions,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
),
Text(
s.showConversionsOnCard,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.6),
),
),
],
),
),
Switch(
value: enabled,
onChanged: (val) =>
ref.read(showCurrencyConversionsProvider.notifier).toggle(val),
activeThumbColor: const Color(0xFF7C6DED),
),
],
),
);
}
}