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
)