diff --git a/assets/openVault.png b/assets/openVault.png new file mode 100644 index 00000000..bc3c39a0 Binary files /dev/null and b/assets/openVault.png differ diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e105..7c569640 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile b/ios/Podfile index fdcc671e..d97f17e2 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f6aa5be5..7a7e5f5b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,10 +1,17 @@ PODS: - Flutter (1.0.0) + - flutter_local_notifications (0.0.1): + - Flutter - flutter_native_splash (0.0.1): - Flutter - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) + - permission_handler_apple (9.3.0): + - Flutter + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS - sqflite (0.0.3): - Flutter - FMDB (>= 2.7.5) @@ -25,13 +32,19 @@ PODS: - sqlite3/rtree - url_launcher_ios (0.0.1): - Flutter + - workmanager (0.0.1): + - Flutter DEPENDENCIES: - Flutter (from `Flutter`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite (from `.symlinks/plugins/sqflite/ios`) - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - workmanager (from `.symlinks/plugins/workmanager/ios`) SPEC REPOS: trunk: @@ -41,24 +54,36 @@ SPEC REPOS: EXTERNAL SOURCES: Flutter: :path: Flutter + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" flutter_native_splash: :path: ".symlinks/plugins/flutter_native_splash/ios" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" sqflite: :path: ".symlinks/plugins/sqflite/ios" sqlite3_flutter_libs: :path: ".symlinks/plugins/sqlite3_flutter_libs/ios" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" + workmanager: + :path: ".symlinks/plugins/workmanager/ios" SPEC CHECKSUMS: - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a sqlite3: 6e2d4a4879854d0ec86b476bf3c3e30870bac273 sqlite3_flutter_libs: eb769059df0356dc52ddda040f09cacc9391a7cf url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 + workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 -PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189 +PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0a53136a..80823f5c 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -199,6 +199,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 211392328957DBA96447070D /* [CP] Embed Pods Frameworks */, + 6090A52EFEF53161A56AE5DE /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -216,7 +217,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { @@ -303,6 +304,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 6090A52EFEF53161A56AE5DE /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -453,7 +471,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -580,7 +598,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -629,7 +647,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 87131a09..8e3ca5df 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ runApp(const ProviderScope(child: Launcher()))); } @@ -35,7 +44,7 @@ class Launcher extends ConsumerWidget { themeMode: appThemeState.isDarkModeEnabled ? ThemeMode.dark : ThemeMode.light, onGenerateRoute: makeRoute, - initialRoute: '/', + initialRoute: _isFirstLogin == null || _isFirstLogin! ? '/onboarding' : '/', ); } } diff --git a/lib/model/bank_account.dart b/lib/model/bank_account.dart index 89458faa..fd6f7e4c 100644 --- a/lib/model/bank_account.dart +++ b/lib/model/bank_account.dart @@ -141,7 +141,7 @@ class BankAccountMethods extends SossoldiDatabase { if (maps.isNotEmpty) { return BankAccount.fromJson(maps.first); } else { - throw Exception('Main Account not found'); + return null; } } diff --git a/lib/model/currency.dart b/lib/model/currency.dart index 6a49af93..8f3a7a86 100644 --- a/lib/model/currency.dart +++ b/lib/model/currency.dart @@ -93,6 +93,13 @@ class CurrencyMethods extends SossoldiDatabase { return item.copy(id: id); } + Future insertAll(List list) async { + final db = await database; + for(Currency currency in list){ + await db.insert(currencyTable, currency.toJson()); + } + } + Future selectById(int id) async { final db = await database; diff --git a/lib/pages/add_page/widgets/amount_section.dart b/lib/pages/add_page/widgets/amount_section.dart index 2c743fef..273d4b33 100644 --- a/lib/pages/add_page/widgets/amount_section.dart +++ b/lib/pages/add_page/widgets/amount_section.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import "package:flutter_riverpod/flutter_riverpod.dart"; import '../../../constants/functions.dart'; @@ -162,7 +163,7 @@ class _AmountSectionState extends ConsumerState with Functions { ), const Spacer(), Text( - ref.watch(bankAccountProvider)!.name, + ref.watch(bankAccountProvider)?.name ?? "", style: Theme.of(context).textTheme.bodySmall!.copyWith( color: grey1, ), @@ -282,7 +283,10 @@ class _AmountSectionState extends ConsumerState with Functions { .headlineMedium! .copyWith(color: typeToColor(selectedType)), ), - keyboardType: const TextInputType.numberWithOptions(decimal: true), + keyboardType: const TextInputType.numberWithOptions(decimal: true, signed: true), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}')), + ], // inputFormatters: [DecimalTextInputFormatter(decimalDigits: 2)], autofocus: false, textAlign: TextAlign.center, @@ -292,6 +296,12 @@ class _AmountSectionState extends ConsumerState with Functions { fontSize: 58, fontWeight: FontWeight.bold, ), + onTapOutside: (_){ + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, ), ), ], diff --git a/lib/pages/add_page/widgets/category_selector.dart b/lib/pages/add_page/widgets/category_selector.dart index 45b0527b..65e16b52 100644 --- a/lib/pages/add_page/widgets/category_selector.dart +++ b/lib/pages/add_page/widgets/category_selector.dart @@ -60,7 +60,7 @@ class _CategorySelectorState extends ConsumerState with Functi width: double.infinity, child: categoriesList.when( data: (categories) => ListView.builder( - itemCount: 4, + itemCount: categories.length, // to prevent range error scrollDirection: Axis.horizontal, shrinkWrap: true, itemBuilder: (context, i) { diff --git a/lib/pages/categories/add_category.dart b/lib/pages/categories/add_category.dart index c74bcb97..ac8d4bdb 100644 --- a/lib/pages/categories/add_category.dart +++ b/lib/pages/categories/add_category.dart @@ -275,10 +275,10 @@ class _AddCategoryState extends ConsumerState with Functions { ], ), ), - Container( + Align( alignment: Alignment.bottomCenter, child: Container( - width: double.infinity, + width: MediaQuery.sizeOf(context).width, decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, boxShadow: [ @@ -289,7 +289,7 @@ class _AddCategoryState extends ConsumerState with Functions { ) ], ), - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + padding: const EdgeInsets.only(left:24 ,right: 24, top: 16, bottom: 30), child: Container( decoration: BoxDecoration( boxShadow: [defaultShadow], @@ -297,16 +297,18 @@ class _AddCategoryState extends ConsumerState with Functions { ), child: TextButton( onPressed: () async { - if (selectedCategory != null) { - ref - .read(categoriesProvider.notifier) - .updateCategory(nameController.text) - .whenComplete(() => Navigator.of(context).pop()); - } else { - ref - .read(categoriesProvider.notifier) - .addCategory(nameController.text) - .whenComplete(() => Navigator.of(context).pop()); + if(nameController.text.isNotEmpty) { + if (selectedCategory != null) { + ref + .read(categoriesProvider.notifier) + .updateCategory(nameController.text) + .whenComplete(() => Navigator.of(context).pop()); + } else { + ref + .read(categoriesProvider.notifier) + .addCategory(nameController.text) + .whenComplete(() => Navigator.of(context).pop()); + } } }, style: TextButton.styleFrom( diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 5a0418cb..3dda2ece 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -264,10 +264,11 @@ class _HomePageState extends ConsumerState with Functions { ), ), ); - } else { + } else if(accounts.isNotEmpty) { BankAccount account = accounts[i]; return AccountsSum(account: account); } + }, ), loading: () => const SizedBox(), diff --git a/lib/pages/onboarding_page/onboarding_page.dart b/lib/pages/onboarding_page/onboarding_page.dart new file mode 100644 index 00000000..9e9be360 --- /dev/null +++ b/lib/pages/onboarding_page/onboarding_page.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import '/pages/onboarding_page/widgets/budget_setup.dart'; +import '/constants/style.dart'; + +class Onboarding extends StatefulWidget { + const Onboarding({Key? key}) : super(key: key); + + @override + State createState() => _OnboardingState(); +} + +class _OnboardingState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: blue7, + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.sizeOf(context).height/9, + ), + Text( + 'Set up the app', + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox( + height: 80, + ), + Image.asset( + 'assets/openVault.png', + height: MediaQuery.sizeOf(context).height/3.7, + ), + const SizedBox( + height: 74, + ), + Text( + 'In a few steps you\'ll be ready to start keeping\ntrack of your personal finances (almost) like\nMr. Rip', + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + + ], + + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), + child: SizedBox( + width: MediaQuery.sizeOf(context).width, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const BudgetSetup(), + ), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + 'START THE SET UP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: white), + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/account_setup.dart b/lib/pages/onboarding_page/widgets/account_setup.dart new file mode 100644 index 00000000..4c56b8fc --- /dev/null +++ b/lib/pages/onboarding_page/widgets/account_setup.dart @@ -0,0 +1,356 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/material.dart'; +import '../../../constants/constants.dart'; +import '../../../providers/accounts_provider.dart'; +import '../../../providers/currency_provider.dart'; +import '/constants/style.dart'; + +final showAccountIconsProvider = StateProvider.autoDispose((ref) => false); + +class AccountSetup extends ConsumerStatefulWidget { + const AccountSetup({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _AccountSetupState(); +} + +class _AccountSetupState extends ConsumerState { + TextEditingController accountNameController = TextEditingController(); + TextEditingController amountController = TextEditingController(); + + + bool _validName = false; + bool _validAmount = false; + + // Function to validate amount + void validateAmount(String value) { + setState(() { + _validAmount = RegExp(r'^\d*\.?\d{0,2}$').hasMatch(value); + }); + } + +// Function to validate name + void validateName(String value) { + setState(() { + _validName = RegExp(r'^[a-zA-Z\s]{3,}$').hasMatch(value); + }); + } + + + @override + void dispose() { + accountNameController.dispose(); + amountController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final accountIcon = ref.watch(accountIconProvider); + final accountColor = ref.watch(accountColorProvider); + + return Scaffold( + backgroundColor: blue7, + resizeToAvoidBottomInset: false, + body: SafeArea( + child: Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Text("STEP 2 OF 2", style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set the liquidity in your main\naccount", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 20), + Text( + "It will be used as a baseline to which you can add\nincome, expenses and calculate your wealth.\n\nYou’ll be able to add more accounts within the app.", + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.bodySmall?.copyWith(color: blue1), + ), + const SizedBox(height: 10), + Container( + margin: const EdgeInsets.only(left: 25.0, right: 25.0), + padding: const EdgeInsets.only(left: 20.0, right: 20.0,top: 15, bottom: 15), + decoration: BoxDecoration( + color: white, + shape: BoxShape.rectangle, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 20, + offset: const Offset(2, 2), + ), + ], + borderRadius: const BorderRadius.all(Radius.circular(20))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("ACCOUNT NAME ", + style: Theme.of(context).textTheme.labelSmall?.copyWith(color: grey1)), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + textAlign: TextAlign.center, + controller: accountNameController, + onChanged: validateName, + autofocus: true, + inputFormatters: [ + FilteringTextInputFormatter.deny(RegExp(r'^[a-zA-Z]{10,}$')), + ], + decoration: InputDecoration( + hintText: "Main Account", + errorStyle: Theme.of(context).textTheme.bodyLarge?.copyWith(fontSize: 10, color: red), + hintStyle: Theme.of(context).textTheme.bodySmall, + border: const UnderlineInputBorder( + borderSide: BorderSide(color: grey2, width: 0.2), + ), + ), + onTapOutside: (_){ + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("SET AMOUNT ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: grey1)), + const Icon(Icons.edit, size: 10) + ], + ), + TextField( + textAlign: TextAlign.center, + controller: amountController, + keyboardType: const TextInputType.numberWithOptions(decimal: true, signed: true), + onChanged: validateAmount, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}')), + ], + decoration: InputDecoration( + hintText: "e.g 1300 €", + suffixText: "€", + errorStyle: Theme.of(context).textTheme.bodyLarge?.copyWith(fontSize: 10, color: red), + hintStyle: Theme.of(context).textTheme.bodySmall, + border: const UnderlineInputBorder( + borderSide:BorderSide(color: grey2, width: 0.2), + ), + ), + onTapOutside: (_){ + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } + }, + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("EDIT ICON AND COLOR ", + style: Theme.of(context) + .textTheme + .labelSmall + ?.copyWith(color: grey1)), + const Icon(Icons.edit, size: 10) + ], + ), + const SizedBox(height: 6), + Material( + color: Colors.transparent, + child: InkWell( + borderRadius: const BorderRadius.all(Radius.circular(90)), + onTap: () => ref.read(showAccountIconsProvider.notifier).state = true, + child: Ink( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: accountColorList[accountColor], + ), + padding: const EdgeInsets.all(16), + child: Icon( + accountIconList[accountIcon], + size: 36, + color: Theme.of(context).colorScheme.background, + ), + ), + ), + ), + const SizedBox(height: 10), + SizedBox( + height: 38, + child: ListView.separated( + scrollDirection: Axis.horizontal, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 16), + separatorBuilder: (context, index) => const SizedBox(width: 16), + itemBuilder: (context, index) { + Color color = accountColorList[index]; + return GestureDetector( + onTap: () => ref.read(accountColorProvider.notifier).state = index, + child: Container( + height: accountColorList[accountColor] == color ? 38 : 32, + width: accountColorList[accountColor] == color ? 38 : 32, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color, + border: accountColorList[accountColor] == color + ? Border.all( + color: Theme.of(context).colorScheme.primary, + width: 3, + ) + : null, + ), + ), + ); + }, + itemCount: accountColorList.length, + ), + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 8.0), + child: Divider(height: 1, color: grey2), + ), + SizedBox( + height: 38, + child: ListView.separated( + scrollDirection: Axis.horizontal, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 16), + separatorBuilder: (context, index) => const SizedBox(width: 16), + itemBuilder: (context, index) { + IconData accountIconData = + accountIconList.values.elementAt(index); + String accountIconName = accountIconList.keys.elementAt(index); + return GestureDetector( + onTap: () => ref.read(accountIconProvider.notifier).state = + accountIconName, + child: Container( + width: 38, + height: 38, + margin: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: accountIconList[accountIcon] == accountIconData + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.surface, + shape: BoxShape.circle,), + child: Icon( + accountIconData, + color: accountIconList[accountIcon] == accountIconData + ? Colors.white + : Theme.of(context).colorScheme.primary, + size: 24, + ), + ), + ); + }, + itemCount: accountIconList.length, + ), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 20, + ), + Column( + children: [ + Text('Or you can skip this step and start from 0', + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: blue1)), + const SizedBox(height: 10), + ElevatedButton( + onPressed: () { + ref.watch(currencyStateNotifier.notifier).insertAll(); + Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('START FROM 0 ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1)), + const Icon(Icons.arrow_forward, + size: 15, color: blue1), + ], + ), + SizedBox( + width: MediaQuery.sizeOf(context).width/3, + child: const Divider( + color: blue1, + thickness: 1, + ), + ) + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0,vertical: 15), + child: SizedBox( + width: MediaQuery.sizeOf(context).width, + height: 48, + child: ElevatedButton( + onPressed: () { + if(_validName && _validAmount){ + ref.watch(accountsProvider.notifier).addAccount(accountNameController.text, num.tryParse(amountController.text)); + ref.watch(currencyStateNotifier.notifier).insertAll(); + Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: _validName && _validAmount ? blue5 : grey2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('START TRACKING YOUR EXPENSES', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + ), + ], + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/add_budget.dart b/lib/pages/onboarding_page/widgets/add_budget.dart new file mode 100644 index 00000000..baa05760 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/add_budget.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../constants/functions.dart'; +import '../../../constants/style.dart'; +import '../../../model/budget.dart'; +import '../../../model/category_transaction.dart'; +import '../../../providers/budgets_provider.dart'; + +class AddBudget extends ConsumerStatefulWidget { + final CategoryTransaction category; + + const AddBudget(this.category, {Key? key}) : super(key: key); + + @override + ConsumerState createState() => _AddBudgetState(); +} + +class _AddBudgetState extends ConsumerState with Functions { + final TextEditingController amountController = TextEditingController(); + + List? budgetsList = []; + @override + void didChangeDependencies() { + super.didChangeDependencies(); + // Initialize the text controller with the current budget amount + budgetsList = ref.watch(budgetsProvider).value; + const Budget defaultBudget = Budget(idCategory: 99999, name: '', amountLimit: 9999, active: false); + + final Budget? budget = budgetsList?.firstWhere((element) => element.idCategory == widget.category.id, orElse: () => defaultBudget); + + if (budget != null) { + amountController.text = budget.amountLimit.toString(); + } + if(budget == defaultBudget){ + amountController.text = ""; + } + + } + + @override + void dispose() { + amountController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text( + 'Add budget for ${widget.category.name}', + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + content: TextField( + controller: amountController, + keyboardType: TextInputType.number, + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('CANCEL', style: Theme.of(context).textTheme.bodyMedium), + ), + ElevatedButton( + onPressed: () async { + await ref.watch(budgetsProvider.notifier).addBudget( + Budget( + name: widget.category.name, + createdAt: DateTime.now(), + idCategory: widget.category.id!, + amountLimit: num.tryParse(amountController.text) ?? 0, + active: true, + )).whenComplete(() => Navigator.pop(context)); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text( + 'CONFIRM', + style: Theme.of(context).textTheme.bodyMedium?.apply(color: white), + ), + ), + ], + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/add_category_button.dart b/lib/pages/onboarding_page/widgets/add_category_button.dart new file mode 100644 index 00000000..b3562543 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/add_category_button.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +import '../../../constants/style.dart'; + +class AddCategoryButton extends StatelessWidget { + const AddCategoryButton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border.all(color: grey2, width: 1.5), + color: grey3, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Icon(Icons.add_circle_outline_outlined, size: 30, color: grey1) + ), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text( + "Add category", + style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: grey1), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/pages/onboarding_page/widgets/budget_setup.dart b/lib/pages/onboarding_page/widgets/budget_setup.dart new file mode 100644 index 00000000..e6aa0ded --- /dev/null +++ b/lib/pages/onboarding_page/widgets/budget_setup.dart @@ -0,0 +1,219 @@ +import 'dart:ui'; + +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '/constants/constants.dart'; +import '/constants/style.dart'; +import '/model/budget.dart'; +import '/pages/onboarding_page/widgets/account_setup.dart'; +import '/pages/onboarding_page/widgets/add_budget.dart'; +import '/providers/budgets_provider.dart'; +import '/providers/categories_provider.dart'; +import 'add_category_button.dart'; +import 'category_button.dart'; + +class BudgetSetup extends ConsumerStatefulWidget { + const BudgetSetup({Key? key}) : super(key: key); + + @override + ConsumerState createState() => _BudgetSetupState(); +} + +class _BudgetSetupState extends ConsumerState { + // sum of the budget of the selected cards + + List? budgetsList = []; + num totalBudget = 0; //ref.read(budgetAmountLimitProvider.notifier).state; + + @override + Widget build(BuildContext context) { + budgetsList = ref.watch(budgetsProvider).value; + totalBudget = budgetsList?.fold( + 0, (total, budget) => total + budget.amountLimit) ?? 0; + final categoriesGrid = ref.watch(categoriesProvider); + return Scaffold( + backgroundColor: blue7, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 16.0, right: 16), + child: Column( + children: [ + Text("STEP 1 OF 2", + style: Theme.of(context).textTheme.labelSmall), + const SizedBox(height: 20), + Text( + "Set up your monthly\nbudgets", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineLarge + ?.copyWith(color: blue1), + ), + const SizedBox(height: 30), + Text( + "Choose which categories you want to set a budget for", + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .bodySmall + ?.copyWith(color: blue1), + ), + const SizedBox(height: 16), + Expanded( + child: NotificationListener( + onNotification: (OverscrollIndicatorNotification overscroll) { + overscroll.disallowIndicator(); + return true; + }, + child: categoriesGrid.when( + data: (categories) => GridView.builder( + itemCount: categories.length + 1, + scrollDirection: Axis.vertical, + gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 300, + childAspectRatio: 3, + crossAxisSpacing: 18, + mainAxisSpacing: 12, + ), + itemBuilder: (context, i) { + if (i < categories.length) { + return GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (context) => + AddBudget(categories.elementAt(i)), + ); + }, + child: CategoryButton( + categoryColor: categoryColorList[categories.elementAt(i).color], + categoryName: categories.elementAt(i).name, + budget: budgetsList?.firstWhereOrNull((budget) => budget.idCategory == categories.elementAt(i).id), + ) + ); + } else { + return GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed('/add-category'), + child: const AddCategoryButton(), + ); + } + }, + ), + error: (err, stack) => Text('Error: $err'), + loading: () => const Center( + child: CircularProgressIndicator(), + ), + ), + ), + ), + + // if the total budget (sum of the budget of the selected cards) is > 0, set the other layout. otherwise set the "continue without budget" button + totalBudget > 0 + ? Center( + child: Column( + children: [ + const SizedBox(height: 10), + Text("Monthly budget total:", + style: Theme.of(context).textTheme.bodySmall), + const SizedBox(height: 10), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: totalBudget.toString(), + style: + Theme.of(context).textTheme.displayMedium, + ), + TextSpan( + text: "€", + style: Theme.of(context) + .textTheme + .bodyMedium + ?.apply( + fontFeatures: [ + const FontFeature.subscripts() + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + SizedBox( + width: MediaQuery.sizeOf(context).width, + height: 48, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const AccountSetup()), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: blue5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('NEXT STEP', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.white)), + ), + ), + ], + ), + ) + : ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const AccountSetup()), + ); + }, + style: ElevatedButton.styleFrom( + elevation: 0.0, + shadowColor: Colors.transparent, + backgroundColor: Colors.transparent, + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('CONTINUE WITHOUT BUDGET ', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: blue1)), + const Icon(Icons.arrow_forward, + size: 15, color: blue1), + ], + ), + SizedBox( + width: MediaQuery.sizeOf(context).width / 1.6, + child: const Divider( + color: blue1, + thickness: 1, + ), + ) + ], + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ), + ); + } +} + + diff --git a/lib/pages/onboarding_page/widgets/category_button.dart b/lib/pages/onboarding_page/widgets/category_button.dart new file mode 100644 index 00000000..e1e38b63 --- /dev/null +++ b/lib/pages/onboarding_page/widgets/category_button.dart @@ -0,0 +1,99 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +import '../../../constants/style.dart'; +import '../../../model/budget.dart'; + +class CategoryButton extends StatelessWidget { + const CategoryButton({super.key, required this.categoryColor, required this.categoryName, this.budget}); + + final Color categoryColor; + final String categoryName; + final Budget? budget; + + @override + Widget build(BuildContext context) { + if(budget != null && budget!.active && budget!.amountLimit > 0) { + return Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: categoryColor, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.only(left: 12), + child: Row( + children: [ + Container( + decoration: const BoxDecoration( + color: white, + shape: BoxShape.circle, + ), + padding: const EdgeInsets.all(2), + child: + Icon(Icons.check_rounded, color: categoryColor, size: 22), + ), + const SizedBox(width: 10), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(color: white), + ), + Text("BUDGET: ${budget?.amountLimit}€", + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith(fontSize: 10, color: white)) + ], + ), + ), + ], + ), + ); + } else { + return Container( + decoration: BoxDecoration( + border: Border.all(color: categoryColor, width: 2.5), + color: HSLColor.fromColor(categoryColor) + .withLightness(clampDouble(0.99, 0.0, 0.9)) + .toColor(), + borderRadius: BorderRadius.circular(8), + ), + alignment: Alignment.center, + child: Row( + children: [ + const Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Icon(Icons.add_circle_outline_outlined, + size: 30, color: blue1)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + categoryName, + textAlign: TextAlign.left, + style: Theme.of(context).textTheme.bodyMedium, + ), + Text("ADD BUDGET", + style: Theme.of(context).textTheme.labelMedium), + ], + ), + ), + ], + ), + ); + } + } +} diff --git a/lib/pages/transactions_page/widgets/month_selector.dart b/lib/pages/transactions_page/widgets/month_selector.dart index 0894b6dc..57f8647c 100644 --- a/lib/pages/transactions_page/widgets/month_selector.dart +++ b/lib/pages/transactions_page/widgets/month_selector.dart @@ -67,9 +67,9 @@ class MonthSelector extends ConsumerWidget with Functions { height: height, width: height, color: Theme.of(context).colorScheme.primary, - child: const Icon( + child: Icon( Icons.chevron_left, - color: Colors.white, + color: Theme.of(context).colorScheme.primaryContainer, ), ), ), @@ -78,7 +78,7 @@ class MonthSelector extends ConsumerWidget with Functions { children: [ Text( getFormattedDateRange(startDate, endDate), - style: Theme.of(context).textTheme.titleLarge, + style: Theme.of(context).textTheme.titleLarge?.copyWith(color: darkWhite), ), RichText( text: TextSpan( @@ -115,9 +115,9 @@ class MonthSelector extends ConsumerWidget with Functions { height: height, width: height, color: Theme.of(context).colorScheme.primary, - child: const Icon( + child: Icon( Icons.chevron_right, - color: Colors.white, + color: Theme.of(context).colorScheme.primaryContainer, ), ), ), diff --git a/lib/providers/budgets_provider.dart b/lib/providers/budgets_provider.dart index b28686fb..c63ae437 100644 --- a/lib/providers/budgets_provider.dart +++ b/lib/providers/budgets_provider.dart @@ -20,7 +20,7 @@ class AsyncBudgetsNotifier extends AsyncNotifier> { Future addBudget(Budget budget) async { state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { - await BudgetMethods().insert(budget); + await BudgetMethods().insertOrUpdate(budget); return _getBudgets(); }); } diff --git a/lib/providers/currency_provider.dart b/lib/providers/currency_provider.dart index 6601e454..2774b518 100644 --- a/lib/providers/currency_provider.dart +++ b/lib/providers/currency_provider.dart @@ -26,6 +26,17 @@ class CurrencyState extends ChangeNotifier { notifyListeners(); } + void insertAll() { + Currency euro = const Currency(symbol: "€", code: "EUR", name: "Euro", mainCurrency: true); + Currency dollar = const Currency(symbol: "\$", code: "USD", name: "United States Dollar", mainCurrency: false); + Currency franc = const Currency(symbol: "CHF", code: "CHF", name: "Switzerland Franc", mainCurrency: false); + Currency pound = const Currency(symbol: "£", code: "GBP", name: "United Kingdom Pound", mainCurrency: false); + + List list = [euro, dollar, franc, pound]; + CurrencyMethods().insertAll(list); + notifyListeners(); + } + void setSelectedCurrency(Currency currency) { selectedCurrency = currency; CurrencyMethods().changeMainCurrency(currency.id!); diff --git a/lib/routes.dart b/lib/routes.dart index eb802944..4be7da9e 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -13,6 +13,7 @@ import 'pages/more_info_page/collaborators_page.dart'; import 'pages/more_info_page/more_info.dart'; import 'pages/more_info_page/privacy_policy.dart'; import 'pages/notifications/notifications_settings.dart'; +import 'pages/onboarding_page/onboarding_page.dart'; import 'pages/planning_page/planning_page.dart'; import 'pages/search_page/search_page.dart'; import 'pages/settings_page.dart'; @@ -24,6 +25,8 @@ Route makeRoute(RouteSettings settings) { switch (settings.name) { case '/': return _materialPageRoute(settings.name, const Structure()); + case '/onboarding': + return _materialPageRoute(settings.name, const Onboarding()); case '/dashboard': return _materialPageRoute(settings.name, const HomePage()); case '/add-page': diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 6bbda399..036b9901 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,12 +5,14 @@ import FlutterMacOS import Foundation +import flutter_local_notifications import shared_preferences_foundation import sqflite import sqlite3_flutter_libs import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 6307e251..e2c052e0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: coverage - sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.4" + version: "1.7.2" crypto: dependency: transitive description: @@ -137,6 +137,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" equatable: dependency: transitive description: @@ -198,6 +206,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: c18f1de98fe0bb9dd5ba91e1330d4febc8b6a7de6aae3ffe475ef423723e72f3 + url: "https://pub.dev" + source: hosted + version: "16.3.2" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03" + url: "https://pub.dev" + source: hosted + version: "4.0.0+1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef" + url: "https://pub.dev" + source: hosted + version: "7.0.0+1" flutter_native_splash: dependency: "direct main" description: @@ -312,6 +344,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -332,26 +388,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -380,10 +436,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_provider_linux: dependency: transitive description: @@ -416,6 +472,54 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.3" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" + url: "https://pub.dev" + source: hosted + version: "11.2.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474" + url: "https://pub.dev" + source: hosted + version: "12.0.5" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 + url: "https://pub.dev" + source: hosted + version: "9.4.4" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" + url: "https://pub.dev" + source: hosted + version: "4.2.1" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" petitparser: dependency: transitive description: @@ -701,6 +805,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.9" + timezone: + dependency: transitive + description: + name: timezone + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + url: "https://pub.dev" + source: hosted + version: "0.9.2" typed_data: dependency: transitive description: @@ -793,10 +905,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "13.0.0" watcher: dependency: transitive description: @@ -837,6 +949,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + workmanager: + dependency: "direct main" + description: + name: workmanager + sha256: ed13530cccd28c5c9959ad42d657cd0666274ca74c56dea0ca183ddd527d3a00 + url: "https://pub.dev" + source: hosted + version: "0.5.2" xdg_directories: dependency: transitive description: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 76d5285b..36f7ed9e 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 22aeaaea..41a82805 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + permission_handler_windows sqlite3_flutter_libs url_launcher_windows )