diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..94b8c49 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d863196 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..3982ff5 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..bc16a80 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..77e2f54 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..c79c58a --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..1995a59 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..3c3a099 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..d795954 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..520dd50 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..0529196 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..27e960c --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #0F0F14 + \ No newline at end of file diff --git a/assets/icon/icon.png b/assets/icon/icon.png new file mode 100644 index 0000000..0efb9de Binary files /dev/null and b/assets/icon/icon.png differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 6706bf3..1c6fdbf 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -431,7 +431,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -488,7 +488,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fa..d0d98aa 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index dc9ada4..590df09 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 7353c41..7fa2fa1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 797d452..750aa5a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 6ed2d93..b1fb1ed 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cd7b00..0e17707 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index fe73094..4dc1735 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 321773c..84b7a8c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 797d452..750aa5a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 502f463..2aa70e1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 0ec3034..3718aec 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000..7b07d2a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000..2c980c1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000..efefe58 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000..cd8eb85 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 0ec3034..3718aec 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index e9f5fea..35cacd9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000..1995a59 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000..520dd50 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 84ac32a..e37cece 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 8953cba..c5ba2da 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 0467bf1..00d36c1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/app/app.dart b/lib/app/app.dart index 0c7e46c..45d5d89 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -11,7 +11,6 @@ class App extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final themeMode = ref.watch(themeProvider); - // Trigger exchange rate fetch on app start ref.watch(ratesInitProvider); return MaterialApp.router( diff --git a/lib/app/theme.dart b/lib/app/theme.dart index 6d3e7f3..c786ca6 100644 --- a/lib/app/theme.dart +++ b/lib/app/theme.dart @@ -211,5 +211,4 @@ class AppTheme { } } -// Keep for backward compatibility ThemeData buildAppTheme() => AppTheme.darkTheme; diff --git a/lib/core/constants.dart b/lib/core/constants.dart index c90a8a4..dc4d021 100644 --- a/lib/core/constants.dart +++ b/lib/core/constants.dart @@ -12,7 +12,6 @@ class AppColors { static const divider = Color(0xFF2A2A38); static const warning = Color(0xFFFFB74D); - // Light theme colors static const lightBackground = Color(0xFFF5F5F7); static const lightSurface = Color(0xFFFFFFFF); static const lightTextPrimary = Color(0xFF1A1A24); @@ -96,7 +95,6 @@ extension AmountFormatExt on AmountFormat { String format(double amount) { switch (this) { case AmountFormat.commasDot: - // groups of 3 with commas, dot decimal final parts = amount.toStringAsFixed(2).split('.'); final intPart = parts[0].replaceAllMapped( RegExp(r'(\d)(?=(\d{3})+$)'), (m) => '${m[1]},'); diff --git a/lib/features/add_transaction/provider.dart b/lib/features/add_transaction/provider.dart index df9bcab..6497d44 100644 --- a/lib/features/add_transaction/provider.dart +++ b/lib/features/add_transaction/provider.dart @@ -79,7 +79,6 @@ class AddTransactionNotifier extends StateNotifier { void setCategory(String v) => state = state.copyWith(category: v); void setType(TransactionType v) { - // Reset category to first item of new type final newCategory = AppCategories.forType(v).first; state = state.copyWith(type: v, category: newCategory); } @@ -102,7 +101,6 @@ final addTransactionProvider = StateNotifierProvider.autoDispose (ref, initial) => AddTransactionNotifier(initial), ); -// Reactive categories based on selected type final availableCategoriesProvider = Provider.autoDispose.family, Transaction?>((ref, initial) { final type = ref.watch(addTransactionProvider(initial).select((s) => s.type)); diff --git a/lib/features/add_transaction/screen.dart b/lib/features/add_transaction/screen.dart index 0bdb5fe..ac0347a 100644 --- a/lib/features/add_transaction/screen.dart +++ b/lib/features/add_transaction/screen.dart @@ -40,7 +40,6 @@ class _AddTransactionScreenState extends ConsumerState { _amountController.text = widget.initial!.amount.toString(); _noteController.text = widget.initial!.note ?? ''; } else { - // Set default currency from global provider after first frame WidgetsBinding.instance.addPostFrameCallback((_) { final curr = ref.read(currencyProvider); ref.read(addTransactionProvider(null).notifier).setCurrency(curr.symbol, curr.code); @@ -161,7 +160,6 @@ class _AddTransactionScreenState extends ConsumerState { child: ListView( padding: const EdgeInsets.all(20), children: [ - // Type toggle _TypeToggle( selected: state.type, onChanged: (t) => @@ -169,7 +167,6 @@ class _AddTransactionScreenState extends ConsumerState { ), const SizedBox(height: 24), - // Amount _SectionLabel('Amount'), const SizedBox(height: 8), Container( @@ -231,7 +228,6 @@ class _AddTransactionScreenState extends ConsumerState { ), const SizedBox(height: 20), - // Currency Text( 'Currency', style: TextStyle( @@ -247,7 +243,6 @@ class _AddTransactionScreenState extends ConsumerState { ), const SizedBox(height: 20), - // Category _SectionLabel('Category'), const SizedBox(height: 8), _CategoryPicker( @@ -258,7 +253,6 @@ class _AddTransactionScreenState extends ConsumerState { ), const SizedBox(height: 20), - // Date _SectionLabel('Date'), const SizedBox(height: 8), InkWell( @@ -288,7 +282,6 @@ class _AddTransactionScreenState extends ConsumerState { ), const SizedBox(height: 20), - // Note _SectionLabel('Note (optional)'), const SizedBox(height: 8), TextFormField( diff --git a/lib/features/categories/provider.dart b/lib/features/categories/provider.dart index aa386f4..90fb1fd 100644 --- a/lib/features/categories/provider.dart +++ b/lib/features/categories/provider.dart @@ -13,7 +13,6 @@ final categoryExpenseProvider = Provider>((ref) { return map; }); -// Monthly breakdown for last 6 months final monthlyBreakdownProvider = Provider>((ref) { final txs = ref.watch(transactionsProvider) .where((t) => t.type == TransactionType.expense); diff --git a/lib/features/categories/screen.dart b/lib/features/categories/screen.dart index e798235..8f54bd9 100644 --- a/lib/features/categories/screen.dart +++ b/lib/features/categories/screen.dart @@ -29,7 +29,6 @@ class _CategoriesScreenState extends ConsumerState { final total = data.values.fold(0.0, (a, b) => a + b); final currencyInfo = ref.watch(currencyProvider); - // Sort categories by amount descending final sortedEntries = data.entries.toList() ..sort((a, b) => b.value.compareTo(a.value)); diff --git a/lib/features/dashboard/provider.dart b/lib/features/dashboard/provider.dart index 5fcfa79..02a1816 100644 --- a/lib/features/dashboard/provider.dart +++ b/lib/features/dashboard/provider.dart @@ -45,12 +45,10 @@ class TransactionsNotifier extends StateNotifier> { void clearAll() { state = []; - // also clear from SharedPreferences: SharedPreferences.getInstance().then((prefs) => prefs.remove('transactions')); } } -// Search and filter state final searchQueryProvider = StateProvider((ref) => ''); enum TransactionFilter { all, income, expense } @@ -58,7 +56,6 @@ enum TransactionFilter { all, income, expense } final transactionFilterProvider = StateProvider((ref) => TransactionFilter.all); -// Converted balance providers (convert all transactions to selected currency) final totalBalanceProvider = Provider((ref) { final txs = ref.watch(transactionsProvider); final exchangeService = ref.watch(exchangeRateServiceProvider); @@ -111,14 +108,12 @@ final filteredTransactionsProvider = Provider>((ref) { var filtered = txs; - // Apply type filter if (filter == TransactionFilter.income) { filtered = filtered.where((t) => t.type == TransactionType.income).toList(); } else if (filter == TransactionFilter.expense) { filtered = filtered.where((t) => t.type == TransactionType.expense).toList(); } - // Apply search query if (query.isNotEmpty) { filtered = filtered.where((t) { final matchesCategory = t.category.toLowerCase().contains(query); @@ -127,7 +122,6 @@ final filteredTransactionsProvider = Provider>((ref) { }).toList(); } - // Sort by date descending filtered.sort((a, b) => b.date.compareTo(a.date)); return filtered; }); diff --git a/lib/features/dashboard/screen.dart b/lib/features/dashboard/screen.dart index e1750e8..c831a3b 100644 --- a/lib/features/dashboard/screen.dart +++ b/lib/features/dashboard/screen.dart @@ -12,7 +12,6 @@ import '../../shared/providers/amount_format_provider.dart'; import '../settings/provider.dart'; import 'provider.dart'; -// Helper for balance card only - hides .00 decimals String _smartBalance(double amount, AmountFormat fmt, String symbol) { const spaceAfter = {'Br'}; final sep = spaceAfter.contains(symbol) ? ' ' : ''; @@ -20,7 +19,6 @@ String _smartBalance(double amount, AmountFormat fmt, String symbol) { String formatted; if (isWhole) { - // format the integer, then manually remove .00 formatted = fmt.format(amount); if (formatted.endsWith('.00')) { formatted = formatted.substring(0, formatted.length - 3); diff --git a/lib/features/settings/provider.dart b/lib/features/settings/provider.dart index ccf857f..f7f82eb 100644 --- a/lib/features/settings/provider.dart +++ b/lib/features/settings/provider.dart @@ -32,7 +32,6 @@ class BudgetNotifier extends StateNotifier { } } -// Currency info: symbol and code class CurrencyInfo { final String symbol; final String code; @@ -95,7 +94,6 @@ final themeProvider = StateNotifierProvider( (ref) => ThemeModeNotifier(), ); -// Exchange rate service final exchangeRateServiceProvider = Provider((ref) { final prefs = ref.watch(sharedPreferencesProvider); return ExchangeRateService(prefs); @@ -119,11 +117,9 @@ class ExportService { final currency = _ref.read(currencyProvider); final fmt = _ref.read(amountFormatProvider); - // CSV header final buffer = StringBuffer(); buffer.writeln('Date,Type,Category,Amount,Currency,Note'); - // CSV rows for (final tx in transactions) { final date = DateFormat('yyyy-MM-dd').format(tx.date); final type = tx.type.name; @@ -133,7 +129,6 @@ class ExportService { buffer.writeln('$date,$type,$category,$amount,${tx.currencyCode},$note'); } - // Save to Downloads final directory = await getApplicationDocumentsDirectory(); final timestamp = DateFormat('yyyyMMdd_HHmmss').format(DateTime.now()); final file = File('${directory.path}/transactions_$timestamp.csv'); diff --git a/lib/features/settings/screen.dart b/lib/features/settings/screen.dart index 0f6047c..37d201f 100644 --- a/lib/features/settings/screen.dart +++ b/lib/features/settings/screen.dart @@ -52,7 +52,6 @@ class _SettingsScreenState extends ConsumerState { } void _confirmClearData(BuildContext context, WidgetRef ref) { - // First confirmation showDialog( context: context, builder: (ctx) => AlertDialog( @@ -66,7 +65,6 @@ class _SettingsScreenState extends ConsumerState { TextButton( onPressed: () { Navigator.pop(ctx); - // Second confirmation showDialog( context: context, builder: (ctx2) => AlertDialog( @@ -109,7 +107,6 @@ class _SettingsScreenState extends ConsumerState { final fmt = ref.watch(amountFormatProvider); final isDark = Theme.of(context).brightness == Brightness.dark; - // Update currency format when it changes _currencyFmt = NumberFormat.currency(symbol: currencyInfo.symbol, decimalDigits: 2); return Scaffold( @@ -139,7 +136,6 @@ class _SettingsScreenState extends ConsumerState { padding: const EdgeInsets.fromLTRB(20, 16, 20, 20), children: [ - // Theme Toggle Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( @@ -194,7 +190,6 @@ class _SettingsScreenState extends ConsumerState { ), const SizedBox(height: 16), - // Budget Setting Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( @@ -310,7 +305,6 @@ class _SettingsScreenState extends ConsumerState { ), const SizedBox(height: 16), - // Amount Format Selector Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( @@ -393,7 +387,6 @@ class _SettingsScreenState extends ConsumerState { ), const SizedBox(height: 16), - // Currency Selector Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( @@ -486,7 +479,6 @@ class _SettingsScreenState extends ConsumerState { ), const SizedBox(height: 24), - // Danger Zone Text( 'Danger Zone', style: TextStyle( diff --git a/lib/shared/services/exchange_rate_service.dart b/lib/shared/services/exchange_rate_service.dart index 477dbf9..b7158f4 100644 --- a/lib/shared/services/exchange_rate_service.dart +++ b/lib/shared/services/exchange_rate_service.dart @@ -40,7 +40,6 @@ class ExchangeRateService { Future fetchRates() async { try { - // Try primary URL final response = await http .get(Uri.parse(_primaryUrl)) .timeout(const Duration(seconds: 10)); @@ -60,11 +59,9 @@ class ExchangeRateService { } } } catch (e) { - // Primary failed, try fallback } try { - // Try fallback URL final response = await http .get(Uri.parse(_fallbackUrl)) .timeout(const Duration(seconds: 10)); @@ -84,10 +81,8 @@ class ExchangeRateService { } } } catch (e) { - // Both failed, use cached or fallback } - // If both failed and no cache, use fallback if (_rates.isEmpty) { _rates = Map.from(_fallbackRates); } @@ -104,7 +99,6 @@ class ExchangeRateService { final fromRate = currentRates[from] ?? 1.0; final toRate = currentRates[to] ?? 1.0; - // Convert to USD first, then to target currency final amountInUsd = amount / fromRate; return amountInUsd * toRate; } diff --git a/lib/shared/services/storage_service.dart b/lib/shared/services/storage_service.dart index ae869be..21a8d0b 100644 --- a/lib/shared/services/storage_service.dart +++ b/lib/shared/services/storage_service.dart @@ -70,14 +70,13 @@ class StorageService { } bool loadThemeMode() { - return _prefs.getBool(_themeKey) ?? true; // default dark + return _prefs.getBool(_themeKey) ?? true; } Future saveThemeMode(bool isDark) async { await _prefs.setBool(_themeKey, isDark); } - // Process recurring transactions Future processRecurringTransactions() async { final transactions = loadTransactions(); final now = DateTime.now(); @@ -115,7 +114,6 @@ class StorageService { } if (shouldCreate) { - // Create new occurrence final newTx = Transaction( id: _uuid.v4(), amount: tx.amount, @@ -128,7 +126,6 @@ class StorageService { ); transactions.add(newTx); - // Update original transaction's lastOccurrence final index = transactions.indexWhere((t) => t.id == tx.id); if (index != -1) { transactions[index] = tx.copyWith(lastOccurrence: today); diff --git a/lib/shared/utils/currency_utils.dart b/lib/shared/utils/currency_utils.dart index a51e6ed..1c767cb 100644 --- a/lib/shared/utils/currency_utils.dart +++ b/lib/shared/utils/currency_utils.dart @@ -1,7 +1,6 @@ import '../../core/constants.dart'; String formatAmount(String symbol, double amount, AmountFormat fmt) { - // Symbols that need a space after them (prefix symbols like Br, ₽ etc.) const spaceAfter = {'Br'}; final formatted = fmt.format(amount); final sep = spaceAfter.contains(symbol) ? ' ' : ''; diff --git a/pubspec.lock b/pubspec.lock index 46b460e..f3b2c51 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff + url: "https://pub.dev" + source: hosted + version: "4.0.9" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -25,6 +41,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -118,6 +150,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" + url: "https://pub.dev" + source: hosted + version: "0.14.4" flutter_lints: dependency: "direct dev" description: @@ -192,6 +232,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image: + dependency: transitive + description: + name: image + sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce + url: "https://pub.dev" + source: hosted + version: "4.8.0" intl: dependency: "direct main" description: @@ -200,6 +248,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" + source: hosted + version: "4.11.0" leak_tracker: dependency: transitive description: @@ -336,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" platform: dependency: transitive description: @@ -352,6 +416,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" + url: "https://pub.dev" + source: hosted + version: "6.5.0" pub_semver: dependency: transitive description: @@ -549,6 +621,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 74bfb92..d2f7308 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,10 +21,22 @@ dependencies: http: ^1.2.0 sensors_plus: ^6.1.0 +flutter_launcher_icons: + android: true + ios: true + image_path: "assets/icon/icon.png" + min_sdk_android: 21 + web: + generate: true + image_path: "assets/icon/icon.png" + adaptive_icon_background: "#0F0F14" + adaptive_icon_foreground: "assets/icon/icon.png" + dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^6.0.0 + flutter_launcher_icons: ^0.14.1 flutter: uses-material-design: true diff --git a/web/favicon.png b/web/favicon.png index 8aaa46a..9e27669 100644 Binary files a/web/favicon.png and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png index b749bfe..0529196 100644 Binary files a/web/icons/Icon-192.png and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png index 88cfd48..45ba864 100644 Binary files a/web/icons/Icon-512.png and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png index eb9b4d7..0529196 100644 Binary files a/web/icons/Icon-maskable-192.png and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png index d69c566..45ba864 100644 Binary files a/web/icons/Icon-maskable-512.png and b/web/icons/Icon-maskable-512.png differ diff --git a/web/manifest.json b/web/manifest.json index 1b4d837..648cc20 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -32,4 +32,4 @@ "purpose": "maskable" } ] -} +} \ No newline at end of file