From f579245005c638d6677484741c08a56ee12ad25e Mon Sep 17 00:00:00 2001 From: Jens Pfahl Date: Tue, 6 Aug 2024 15:41:13 +0200 Subject: [PATCH 1/5] upgrade an new MD --- android/app/build.gradle | 4 +- android/build.gradle | 6 +- lib/db/database.g.dart | 27 +- lib/model/Schedule.dart | 32 +- lib/service/LocalNotificationService.dart | 7 +- lib/ui/PersonalTaskLoggerScaffold.dart | 821 ++++++++++++---------- lib/ui/components/DynamicPicker.dart | 2 +- lib/ui/dialogs.dart | 7 +- lib/ui/forms/TaskGroupForm.dart | 2 +- lib/util/units.dart | 22 +- pubspec.lock | 434 +++++++----- pubspec.yaml | 59 +- 12 files changed, 768 insertions(+), 655 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 039af46..780bab2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 33 + compileSdkVersion 34 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -35,7 +35,7 @@ android { defaultConfig { applicationId "de.jepfa.personaltasklogger" minSdkVersion 26 - targetSdkVersion 33 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/build.gradle b/android/build.gradle index 57c4f60..64bd047 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.8.22' + ext.kotlin_version = '2.0.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.android.tools.build:gradle:7.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -14,7 +14,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/lib/db/database.g.dart b/lib/db/database.g.dart index 699b203..085942e 100644 --- a/lib/db/database.g.dart +++ b/lib/db/database.g.dart @@ -6,21 +6,32 @@ part of 'database.dart'; // FloorGenerator // ************************************************************************** +abstract class $AppDatabaseBuilderContract { + /// Adds migrations to the builder. + $AppDatabaseBuilderContract addMigrations(List migrations); + + /// Adds a database [Callback] to the builder. + $AppDatabaseBuilderContract addCallback(Callback callback); + + /// Creates the database and initializes it. + Future build(); +} + // ignore: avoid_classes_with_only_static_members class $FloorAppDatabase { /// Creates a database builder for a persistent database. /// Once a database is built, you should keep a reference to it and re-use it. - static _$AppDatabaseBuilder databaseBuilder(String name) => + static $AppDatabaseBuilderContract databaseBuilder(String name) => _$AppDatabaseBuilder(name); /// Creates a database builder for an in memory database. /// Information stored in an in memory database disappears when the process is killed. /// Once a database is built, you should keep a reference to it and re-use it. - static _$AppDatabaseBuilder inMemoryDatabaseBuilder() => + static $AppDatabaseBuilderContract inMemoryDatabaseBuilder() => _$AppDatabaseBuilder(null); } -class _$AppDatabaseBuilder { +class _$AppDatabaseBuilder implements $AppDatabaseBuilderContract { _$AppDatabaseBuilder(this.name); final String? name; @@ -29,19 +40,19 @@ class _$AppDatabaseBuilder { Callback? _callback; - /// Adds migrations to the builder. - _$AppDatabaseBuilder addMigrations(List migrations) { + @override + $AppDatabaseBuilderContract addMigrations(List migrations) { _migrations.addAll(migrations); return this; } - /// Adds a database [Callback] to the builder. - _$AppDatabaseBuilder addCallback(Callback callback) { + @override + $AppDatabaseBuilderContract addCallback(Callback callback) { _callback = callback; return this; } - /// Creates the database and initializes it. + @override Future build() async { final path = name != null ? await sqfliteDatabaseFactory.getDatabasePath(name!) diff --git a/lib/model/Schedule.dart b/lib/model/Schedule.dart index 9cf5704..7383139 100644 --- a/lib/model/Schedule.dart +++ b/lib/model/Schedule.dart @@ -4,7 +4,7 @@ import 'package:jiffy/jiffy.dart'; import 'package:personaltasklogger/util/dates.dart'; import 'package:personaltasklogger/util/extensions.dart'; -import '../util/units.dart'; +import 'package:personaltasklogger/util/units.dart'; import 'When.dart'; enum RepetitionStep {DAILY, EVERY_OTHER_DAY, WEEKLY, EVERY_OTHER_WEEK, MONTHLY, EVERY_OTHER_MONTH, QUARTERLY, HALF_YEARLY, YEARLY, CUSTOM} @@ -55,7 +55,7 @@ class CustomRepetition { CustomRepetition(this.repetitionValue, this.repetitionUnit); DateTime getNextRepetitionFrom(DateTime from) { - var jiffy = Jiffy(from); + var jiffy = Jiffy.parseFromDateTime(from); switch(repetitionUnit) { case RepetitionUnit.MINUTES: return jiffy.add(minutes: repetitionValue).dateTime; case RepetitionUnit.HOURS: return jiffy.add(hours: repetitionValue).dateTime; @@ -67,7 +67,7 @@ class CustomRepetition { } DateTime getPreviousRepetitionFrom(DateTime from) { - var jiffy = Jiffy(from); + var jiffy = Jiffy.parseFromDateTime(from); switch(repetitionUnit) { case RepetitionUnit.MINUTES: return jiffy.subtract(minutes: repetitionValue).dateTime; case RepetitionUnit.HOURS: return jiffy.subtract(hours: repetitionValue).dateTime; @@ -196,11 +196,11 @@ class Schedule { case RepetitionStep.EVERY_OTHER_DAY: return from.add(Duration(days: 2)); case RepetitionStep.WEEKLY: return from.add(Duration(days: 7)); case RepetitionStep.EVERY_OTHER_WEEK: return from.add(Duration(days: 14)); - case RepetitionStep.MONTHLY: return Jiffy(from).add(months: 1).dateTime; - case RepetitionStep.EVERY_OTHER_MONTH: return Jiffy(from).add(months: 2).dateTime; - case RepetitionStep.QUARTERLY: return Jiffy(from).add(months: 3).dateTime; - case RepetitionStep.HALF_YEARLY: return Jiffy(from).add(months: 6).dateTime; - case RepetitionStep.YEARLY: return Jiffy(from).add(years: 1).dateTime; + case RepetitionStep.MONTHLY: return Jiffy.parseFromDateTime(from).add(months: 1).dateTime; + case RepetitionStep.EVERY_OTHER_MONTH: return Jiffy.parseFromDateTime(from).add(months: 2).dateTime; + case RepetitionStep.QUARTERLY: return Jiffy.parseFromDateTime(from).add(months: 3).dateTime; + case RepetitionStep.HALF_YEARLY: return Jiffy.parseFromDateTime(from).add(months: 6).dateTime; + case RepetitionStep.YEARLY: return Jiffy.parseFromDateTime(from).add(years: 1).dateTime; case RepetitionStep.CUSTOM: throw new Exception("custom repetition step not allowed here"); } } @@ -211,11 +211,11 @@ class Schedule { case RepetitionStep.EVERY_OTHER_DAY: return from.subtract(Duration(days: 2)); case RepetitionStep.WEEKLY: return from.subtract(Duration(days: 7)); case RepetitionStep.EVERY_OTHER_WEEK: return from.subtract(Duration(days: 14)); - case RepetitionStep.MONTHLY: return Jiffy(from).subtract(months: 1).dateTime; - case RepetitionStep.EVERY_OTHER_MONTH: return Jiffy(from).subtract(months: 2).dateTime; - case RepetitionStep.QUARTERLY: return Jiffy(from).subtract(months: 3).dateTime; - case RepetitionStep.HALF_YEARLY: return Jiffy(from).subtract(months: 6).dateTime; - case RepetitionStep.YEARLY: return Jiffy(from).subtract(years: 1).dateTime; + case RepetitionStep.MONTHLY: return Jiffy.parseFromDateTime(from).subtract(months: 1).dateTime; + case RepetitionStep.EVERY_OTHER_MONTH: return Jiffy.parseFromDateTime(from).subtract(months: 2).dateTime; + case RepetitionStep.QUARTERLY: return Jiffy.parseFromDateTime(from).subtract(months: 3).dateTime; + case RepetitionStep.HALF_YEARLY: return Jiffy.parseFromDateTime(from).subtract(months: 6).dateTime; + case RepetitionStep.YEARLY: return Jiffy.parseFromDateTime(from).subtract(years: 1).dateTime; case RepetitionStep.CUSTOM: throw new Exception("custom repetition step not allowed here"); } } @@ -277,7 +277,7 @@ class Schedule { return "${translate('model.repetition_step.every')} $unit"; } - static Unit fromCustomRepetitionToUnit(CustomRepetition customRepetition, [Clause? clause]) { + static GeneralUnit fromCustomRepetitionToUnit(CustomRepetition customRepetition, [Clause? clause]) { switch(customRepetition.repetitionUnit) { case RepetitionUnit.MINUTES: return Minutes(customRepetition.repetitionValue, clause); case RepetitionUnit.HOURS: return Hours(customRepetition.repetitionValue, clause); @@ -314,7 +314,7 @@ class Schedule { return dayOfMonth; }, shiftBack: (repetitionValue, from) { - return Jiffy(from).subtract(months: repetitionValue).dateTime; + return Jiffy.parseFromDateTime(from).subtract(months: repetitionValue).dateTime; }, ) ?? nextRegularDueDate; } @@ -328,7 +328,7 @@ class Schedule { return dayOfMonth.value; }, shiftBack: (repetitionValue, from) { - return Jiffy(from).subtract(years: repetitionValue).dateTime; + return Jiffy.parseFromDateTime(from).subtract(years: repetitionValue).dateTime; }, ) ?? nextRegularDueDate; } diff --git a/lib/service/LocalNotificationService.dart b/lib/service/LocalNotificationService.dart index f79e7bf..2228d38 100644 --- a/lib/service/LocalNotificationService.dart +++ b/lib/service/LocalNotificationService.dart @@ -200,9 +200,12 @@ class LocalNotificationService { AndroidFlutterLocalNotificationsPlugin? nativePlugin = _flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); nativePlugin?.getActiveNotifications().then((activeNotifications) { activeNotifications.forEach((element) { - _handleActiveNotification(element.id, element.channelId); + final id = element.id; + if (id != null) { + _handleActiveNotification(id, element.channelId); + } }); - handleActiveNotificationPostHandler(activeNotifications.map((e) => e.id).toList()); + handleActiveNotificationPostHandler(activeNotifications.where((e) => e.id != null).map((e) => e.id!).toList()); }); } diff --git a/lib/ui/PersonalTaskLoggerScaffold.dart b/lib/ui/PersonalTaskLoggerScaffold.dart index a6d99b3..29381d8 100644 --- a/lib/ui/PersonalTaskLoggerScaffold.dart +++ b/lib/ui/PersonalTaskLoggerScaffold.dart @@ -164,417 +164,468 @@ class PersonalTaskLoggerScaffoldState extends State _dismissShowcaseBanner(); }); }, - builder: Builder( - builder : (context) { - return Scaffold( - drawer: _isSearching ? null : SizedBox( - width: 250, - child: Drawer( - child: ListView( - padding: EdgeInsets.zero, - children: [ - SizedBox( - height: 150, - child: DrawerHeader( - decoration: BoxDecoration( - color: PRIMARY_COLOR, - ), - child: Align( - alignment: AlignmentDirectional.bottomStart, - child: Column( - children: [ - Text(""), - Align( - alignment: AlignmentDirectional.centerStart, - child: Row( - children: [ - Text(APP_NAME, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: Colors.black - ), - ), - Icon(Icons.task_alt, color: ACCENT_COLOR), - ], + builder: (context) { + return Scaffold( + drawer: _isSearching ? null : SizedBox( + width: 250, + child: Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: [ + SizedBox( + height: 150, + child: DrawerHeader( + decoration: BoxDecoration( + color: PRIMARY_COLOR, + ), + child: Align( + alignment: AlignmentDirectional.bottomStart, + child: Column( + children: [ + Text(""), + Align( + alignment: AlignmentDirectional.centerStart, + child: Row( + children: [ + Text(APP_NAME, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: Colors.black + ), ), - ), - Align( - alignment: AlignmentDirectional.centerStart, - child: Text(translate('navigation.header_subtitle'), - style: TextStyle(color: Colors.grey[700]))), - ], + Icon(Icons.task_alt, color: ACCENT_COLOR), + ], + ), ), - ), + Align( + alignment: AlignmentDirectional.centerStart, + child: Text( + translate('navigation.header_subtitle'), + style: TextStyle(color: Colors.grey[700]))), + ], ), ), - ListTile( - leading: const Icon(Icons.settings), - title: Text(translate('navigation.menus.settings')), - onTap: () { - Navigator.pop(context); - Navigator.push(super.context, MaterialPageRoute(builder: (context) => SettingsScreen())) - .then((_) { - setState(() { - getSelectedPage().getGlobalKey().currentState?.setState(() { - // refresh current page - debugPrint("refresh .."); - }); - _pages.forEach((page) { - page.getGlobalKey().currentState?.reload(); - }); - }); + ), + ), + ListTile( + leading: const Icon(Icons.settings), + title: Text(translate('navigation.menus.settings')), + onTap: () { + Navigator.pop(context); + Navigator.push(super.context, MaterialPageRoute( + builder: (context) => SettingsScreen())) + .then((_) { + setState(() { + getSelectedPage() + .getGlobalKey() + .currentState + ?.setState(() { + // refresh current page + debugPrint("refresh .."); }); - }, - ), - Divider(), - ListTile( - leading: const Icon(Icons.import_export), - title: Text(translate('navigation.menus.export_as_csv')), - onTap: () async { - Navigator.pop(context); - - showConfirmationDialog(context, - translate('navigation.menus.export_as_csv'), - translate('pages.export.description'), - cancelPressed: () => Navigator.pop(context), - okPressed: () { - Navigator.pop(context); - CsvService().backup(context, - (success, dstPath) { - if (success) { - toastInfo(context, translate('pages.export.export_created', args: {'dst_path' : dstPath })); - } - else { - toastInfo(context, translate('pages.export.export_aborted')); - } - }, (errorMsg) => toastError(context, errorMsg)); - } - ); - - }, - ), - ListTile( - leading: const Icon(Icons.save_alt_outlined), - title: Text(translate('navigation.menus.backup_as_file')), - onTap: () async { - Navigator.pop(context); - - showConfirmationDialog(context, - translate('navigation.menus.backup_as_file'), - translate('pages.backup.description'), - cancelPressed: () => Navigator.pop(context), - okPressed: () { - Navigator.pop(context); - - _backupRestoreService.backup( - (success, dstPath) { - if (success) { - toastInfo(context, translate('pages.backup.backup_created', args: {'dst_path' : dstPath })); - } - else { - toastInfo(context, translate('pages.backup.backup_aborted')); - } - }, (errorMsg) => toastError(context, errorMsg)); - } - ); - - }, - ), - ListTile( - leading: const Icon(Icons.restore), - title: Text(translate('navigation.menus.restore_from_file')), - onTap: () async { - Navigator.pop(context); - showConfirmationDialog(context, translate('pages.restore.dialog.title'), translate('pages.restore.dialog.message'), - icon: const Icon(Icons.warning_amber_outlined), - cancelPressed: () => Navigator.pop(context), - okPressed: () async { - Navigator.pop(context); - await _backupRestoreService.restore((success) async { + _pages.forEach((page) { + page + .getGlobalKey() + .currentState + ?.reload(); + }); + }); + }); + }, + ), + Divider(), + ListTile( + leading: const Icon(Icons.import_export), + title: Text(translate('navigation.menus.export_as_csv')), + onTap: () async { + Navigator.pop(context); + + showConfirmationDialog(context, + translate('navigation.menus.export_as_csv'), + translate('pages.export.description'), + cancelPressed: () => Navigator.pop(context), + okPressed: () { + Navigator.pop(context); + CsvService().backup(context, + (success, dstPath) { if (success) { - await TaskGroupRepository.loadAll(true); // load caches - - toastInfo(context, translate('pages.restore.backup_restored')); - setState(() { - _pages.forEach((page) { - page.getGlobalKey().currentState?.reload(); - }); - }); + toastInfo(context, translate( + 'pages.export.export_created', + args: {'dst_path': dstPath})); } else { - toastInfo(context, translate('pages.restore.restore_aborted')); + toastInfo(context, translate( + 'pages.export.export_aborted')); } }, (errorMsg) => toastError(context, errorMsg)); - }); - }, - ), - Divider(), - ListTile( - leading: const Icon(Icons.run_circle_outlined), - title: Text(translate('navigation.menus.start_app_walk')), - onTap: () { - Navigator.pop(context); - _startAppWalkThrough(context); - }, - ), - ListTile( - leading: const Icon(Icons.help_outline), - title: Text(translate('navigation.menus.online_help')), - onTap: () { - Navigator.pop(context); - launchUrl("https://everydaytasks.jepfa.de"); - }, - ), - ListTile( - leading: const Icon(Icons.info_outline), - title: Text(translate('navigation.menus.about_the_app')), - onTap: () async { - Navigator.pop(context); - final packageInfo = await PackageInfo.fromPlatform(); - final version = packageInfo.version; - - showAboutDialog( - context: context, - applicationVersion: version, - applicationName: APP_NAME, - children: [ - Text(translate('pages.about.message')), - Text(''), - InkWell( - child: Text.rich( - TextSpan( - text: translate('pages.about.star_it', args: {"link": ""}), - children: [ - TextSpan(text: "github.com/jenspfahl/EverydayTasks", style: TextStyle(decoration: TextDecoration.underline)), - ], - ), - ), - onTap: () { - launchUrl("https://github.com/jenspfahl/EverydayTasks"); - }), - Divider(), - Text('© Jens Pfahl 2022 - 2024', style: TextStyle(fontSize: 12)), - ], - applicationIcon: Icon(Icons.task_alt, color: ACCENT_COLOR), - ); - - }, - ), - Divider(), - ListTile( - leading: const Icon(Icons.translate), - title: Text(translate('navigation.menus.help_translate')), - onTap: () async { - Navigator.pop(context); - launchUrl("https://github.com/jenspfahl/EverydayTasks/blob/master/TRANSLATE.md"); - }, - ), - ListTile( - leading: const Icon(Icons.bug_report_outlined), - title: Text(translate('navigation.menus.report_a_bug')), - onTap: () async { - Navigator.pop(context); - final packageInfo = await PackageInfo.fromPlatform(); - final version = packageInfo.version; - final build = packageInfo.buildNumber; - - final title = Uri.encodeComponent("A bug in version $version ($build)"); - final body = Uri.encodeComponent("Please describe .."); - launchUrl("https://github.com/jenspfahl/EverydayTasks/issues/new?title=$title&body=$body"); - }, - ), - ], + } + ); + }, ), - ), - ), - appBar: AppBar( - title: _isSearching ? _buildSearchField() : getSelectedPage().getTitle(), - actions: _buildActions(context), - ), - body: Stack( - children: [ - PageView( - controller: _pageController, - onPageChanged: (newIndex) { - setState(() { - _selectedNavigationIndex = newIndex; - _clearOrCloseSearchBar(context, true); - }); + ListTile( + leading: const Icon(Icons.save_alt_outlined), + title: Text(translate('navigation.menus.backup_as_file')), + onTap: () async { + Navigator.pop(context); + + showConfirmationDialog(context, + translate('navigation.menus.backup_as_file'), + translate('pages.backup.description'), + cancelPressed: () => Navigator.pop(context), + okPressed: () { + Navigator.pop(context); + + _backupRestoreService.backup( + (success, dstPath) { + if (success) { + toastInfo(context, translate( + 'pages.backup.backup_created', + args: {'dst_path': dstPath})); + } + else { + toastInfo(context, translate( + 'pages.backup.backup_aborted')); + } + }, (errorMsg) => toastError(context, errorMsg)); + } + ); }, - children: _pages, ), - Visibility( - visible: _showBanner, - child: SizedBox( - child: Container( - child: MaterialBanner( - // backgroundColor: Colors.transparent, - elevation: 3, - content: Text(translate('walk_through.banner.text')), - actions: [ - TextButton( - onPressed: () { - _startAppWalkThrough(context); - }, - child: Text(translate('walk_through.banner.start_action')), - ), - TextButton( - onPressed: () { - setState(() => _dismissShowcaseBanner()); - }, - child: Text(translate('walk_through.banner.dismiss_action')), - ), - ]), - ), - ), + ListTile( + leading: const Icon(Icons.restore), + title: Text( + translate('navigation.menus.restore_from_file')), + onTap: () async { + Navigator.pop(context); + showConfirmationDialog( + context, translate('pages.restore.dialog.title'), + translate('pages.restore.dialog.message'), + icon: const Icon(Icons.warning_amber_outlined), + cancelPressed: () => Navigator.pop(context), + okPressed: () async { + Navigator.pop(context); + await _backupRestoreService.restore(( + success) async { + if (success) { + await TaskGroupRepository.loadAll( + true); // load caches + + toastInfo(context, + translate('pages.restore.backup_restored')); + setState(() { + _pages.forEach((page) { + page + .getGlobalKey() + .currentState + ?.reload(); + }); + }); + } + else { + toastInfo(context, + translate('pages.restore.restore_aborted')); + } + }, (errorMsg) => toastError(context, errorMsg)); + }); + }, ), - Positioned( - bottom: 0, - right: 0, - child: Center( - child: SizedBox( - width: MediaQuery.of(context).size.width / 4, - height: 150, - child: DraggableScrollableSheet( - controller: _calendarDragScrollController, - initialChildSize: 0.15, - minChildSize: 0.15, - maxChildSize: 0.5, - snap: true, - builder: (context, scrollController) { - return Container( - decoration: BoxDecoration( - color: PRIMARY_COLOR, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(8), - topRight: Radius.circular(8), - ), - border: Border( - // left: BorderSide(), //TODO doesn't work - //right: BorderSide(color: Colors.black54, width: 1), - // top: BorderSide(color: Colors.black54, width: 1), - ), - ), - child: Showcase( - key: showcaseExtensionsIcon, - title: translate('walk_through.extensions.title'), - description: translate('walk_through.extensions.description'), - targetPadding: EdgeInsets.all(8), - overlayOpacity: showcaseOpacity, - child: ListView( - controller: scrollController, - children: [ - Icon(Icons.drag_handle, color: Colors.black38), - Container( - color: isDarkMode(context) ? null: Colors.white54, - child: IconButton( - icon: Icon(Icons.calendar_month_sharp, color: Colors.black54,), - onPressed: () { - _calendarDragScrollController.animateTo(0.15, duration: const Duration(milliseconds: 100), curve: Curves.easeOutBack); - Navigator.push(super.context, MaterialPageRoute(builder: (context) => CalendarPage(_pagesHolder))) - .then((_) { - }); - }, - ), - ), + Divider(), + ListTile( + leading: const Icon(Icons.run_circle_outlined), + title: Text(translate('navigation.menus.start_app_walk')), + onTap: () { + Navigator.pop(context); + _startAppWalkThrough(context); + }, + ), + ListTile( + leading: const Icon(Icons.help_outline), + title: Text(translate('navigation.menus.online_help')), + onTap: () { + Navigator.pop(context); + launchUrl("https://everydaytasks.jepfa.de"); + }, + ), + ListTile( + leading: const Icon(Icons.info_outline), + title: Text(translate('navigation.menus.about_the_app')), + onTap: () async { + Navigator.pop(context); + final packageInfo = await PackageInfo.fromPlatform(); + final version = packageInfo.version; + + showAboutDialog( + context: context, + applicationVersion: version, + applicationName: APP_NAME, + children: [ + Text(translate('pages.about.message')), + Text(''), + InkWell( + child: Text.rich( + TextSpan( + text: translate('pages.about.star_it', + args: {"link": ""}), + children: [ + TextSpan( + text: "github.com/jenspfahl/EverydayTasks", + style: TextStyle( + decoration: TextDecoration + .underline)), ], ), ), - ); - }, - ), - ), - ), + onTap: () { + launchUrl( + "https://github.com/jenspfahl/EverydayTasks"); + }), + Divider(), + Text('© Jens Pfahl 2022 - 2024', + style: TextStyle(fontSize: 12)), + ], + applicationIcon: Icon(Icons.task_alt, + color: ACCENT_COLOR), + ); + }, + ), + Divider(), + ListTile( + leading: const Icon(Icons.translate), + title: Text(translate('navigation.menus.help_translate')), + onTap: () async { + Navigator.pop(context); + launchUrl( + "https://github.com/jenspfahl/EverydayTasks/blob/master/TRANSLATE.md"); + }, + ), + ListTile( + leading: const Icon(Icons.bug_report_outlined), + title: Text(translate('navigation.menus.report_a_bug')), + onTap: () async { + Navigator.pop(context); + final packageInfo = await PackageInfo.fromPlatform(); + final version = packageInfo.version; + final build = packageInfo.buildNumber; + + final title = Uri.encodeComponent( + "A bug in version $version ($build)"); + final body = Uri.encodeComponent("Please describe .."); + launchUrl( + "https://github.com/jenspfahl/EverydayTasks/issues/new?title=$title&body=$body"); + }, ), ], ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: Showcase( - key: showcaseFloatingButton, - title: translate('walk_through.action_button.title'), - description: translate('walk_through.action_button.description'), - targetPadding: EdgeInsets.all(8), - overlayOpacity: showcaseOpacity, - child: FloatingActionButton( - onPressed: () { - getSelectedPage().getGlobalKey().currentState?.handleFABPressed(context); - }, - child: getSelectedPage().getIcon(), - ), + ), + ), + appBar: AppBar( + title: _isSearching ? _buildSearchField() : getSelectedPage() + .getTitle(), + actions: _buildActions(context), + ), + body: Stack( + children: [ + PageView( + controller: _pageController, + onPageChanged: (newIndex) { + setState(() { + _selectedNavigationIndex = newIndex; + _clearOrCloseSearchBar(context, true); + }); + }, + children: _pages, ), - bottomNavigationBar: BottomNavigationBar( - type: BottomNavigationBarType.fixed, - showUnselectedLabels: true, - showSelectedLabels: true, - items: [ - BottomNavigationBarItem( - icon: Showcase( - key: showcaseQuickAddIcon, - title: translate('walk_through.quick_add.title'), - description: translate('walk_through.quick_add.description'), - targetPadding: EdgeInsets.all(16), - overlayOpacity: showcaseOpacity, - child: Icon(Icons.add_circle_outline_outlined), - ), - label: translate('pages.quick_add.title'), - ), - BottomNavigationBarItem( - icon: Showcase( - key: showcaseJournalIcon, - title: translate('walk_through.journal.title'), - description: translate('walk_through.journal.description'), - targetPadding: EdgeInsets.all(16), - overlayOpacity: showcaseOpacity, - child: Icon(Icons.event_available_rounded), - ), - label: translate('pages.journal.title'), + Visibility( + visible: _showBanner, + child: SizedBox( + child: Container( + child: MaterialBanner( + // backgroundColor: Colors.transparent, + elevation: 3, + content: Text(translate('walk_through.banner.text')), + actions: [ + TextButton( + onPressed: () { + _startAppWalkThrough(context); + }, + child: Text( + translate('walk_through.banner.start_action')), + ), + TextButton( + onPressed: () { + setState(() => _dismissShowcaseBanner()); + }, + child: Text(translate( + 'walk_through.banner.dismiss_action')), + ), + ]), ), - BottomNavigationBarItem( - icon: Showcase( - key: showcaseSchedulesIcon, - title: translate('walk_through.schedules.title'), - description: translate('walk_through.schedules.description'), - targetPadding: EdgeInsets.all(16), - overlayOpacity: showcaseOpacity, - child: ValueListenableBuilder( - valueListenable: DueScheduleCountService().count, - - builder: (BuildContext context, int value, Widget? child) { - return Badge( - isLabelVisible: DueScheduleCountService().shouldShowIndicatorValue(), - child: Icon(Icons.next_plan_outlined), - label: Text("$value"), - textColor: Colors.white, - backgroundColor: Colors.red, - ); - }, - ), + ), + ), + Positioned( + bottom: 0, + right: 0, + child: Center( + child: SizedBox( + width: MediaQuery + .of(context) + .size + .width / 4, + height: 150, + child: DraggableScrollableSheet( + controller: _calendarDragScrollController, + initialChildSize: 0.15, + minChildSize: 0.15, + maxChildSize: 0.5, + snap: true, + builder: (context, scrollController) { + return Container( + decoration: BoxDecoration( + color: PRIMARY_COLOR, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + border: Border( + // left: BorderSide(), //TODO doesn't work + //right: BorderSide(color: Colors.black54, width: 1), + // top: BorderSide(color: Colors.black54, width: 1), + ), + ), + child: Showcase( + key: showcaseExtensionsIcon, + title: translate('walk_through.extensions.title'), + description: translate( + 'walk_through.extensions.description'), + targetPadding: EdgeInsets.all(8), + overlayOpacity: showcaseOpacity, + child: ListView( + controller: scrollController, + children: [ + Icon(Icons.drag_handle, color: Colors.black38), + Container( + color: isDarkMode(context) ? null : Colors + .white54, + child: IconButton( + icon: Icon(Icons.calendar_month_sharp, + color: Colors.black54,), + onPressed: () { + _calendarDragScrollController.animateTo( + 0.15, duration: const Duration( + milliseconds: 100), + curve: Curves.easeOutBack); + Navigator.push(super.context, + MaterialPageRoute( + builder: (context) => + CalendarPage(_pagesHolder))) + .then((_) {}); + }, + ), + ), + ], + ), + ), + ); + }, ), - label: translate('pages.schedules.title'), ), - BottomNavigationBarItem( - icon: Showcase( - key: showcaseTasksIcon, - title: translate('walk_through.tasks.title'), - description: translate('walk_through.tasks.description'), - targetPadding: EdgeInsets.all(16), - overlayOpacity: showcaseOpacity, - child: Icon(Icons.task_alt), - ), - label: translate('pages.tasks.title'), + ), + ), + ], + ), + floatingActionButtonLocation: FloatingActionButtonLocation + .centerDocked, + floatingActionButton: Showcase( + key: showcaseFloatingButton, + title: translate('walk_through.action_button.title'), + description: translate('walk_through.action_button.description'), + targetPadding: EdgeInsets.all(8), + overlayOpacity: showcaseOpacity, + child: FloatingActionButton( + onPressed: () { + getSelectedPage() + .getGlobalKey() + .currentState + ?.handleFABPressed(context); + }, + child: getSelectedPage().getIcon(), + ), + ), + bottomNavigationBar: BottomNavigationBar( + type: BottomNavigationBarType.fixed, + showUnselectedLabels: true, + showSelectedLabels: true, + items: [ + BottomNavigationBarItem( + icon: Showcase( + key: showcaseQuickAddIcon, + title: translate('walk_through.quick_add.title'), + description: translate('walk_through.quick_add.description'), + targetPadding: EdgeInsets.all(16), + overlayOpacity: showcaseOpacity, + child: Icon(Icons.add_circle_outline_outlined), + ), + label: translate('pages.quick_add.title'), + ), + BottomNavigationBarItem( + icon: Showcase( + key: showcaseJournalIcon, + title: translate('walk_through.journal.title'), + description: translate('walk_through.journal.description'), + targetPadding: EdgeInsets.all(16), + overlayOpacity: showcaseOpacity, + child: Icon(Icons.event_available_rounded), + ), + label: translate('pages.journal.title'), + ), + BottomNavigationBarItem( + icon: Showcase( + key: showcaseSchedulesIcon, + title: translate('walk_through.schedules.title'), + description: translate('walk_through.schedules.description'), + targetPadding: EdgeInsets.all(16), + overlayOpacity: showcaseOpacity, + child: ValueListenableBuilder( + valueListenable: DueScheduleCountService().count, + + builder: (BuildContext context, int value, Widget? child) { + return Badge( + isLabelVisible: DueScheduleCountService() + .shouldShowIndicatorValue(), + child: Icon(Icons.next_plan_outlined), + label: Text("$value"), + textColor: Colors.white, + backgroundColor: Colors.red, + ); + }, ), - ], - selectedItemColor: ACCENT_COLOR, - unselectedItemColor: Colors.grey.shade600, - currentIndex: _selectedNavigationIndex, - onTap: (index) { - _pageController.animateToPage(index, duration: Duration(milliseconds: 300), curve: Curves.ease); - }, + ), + label: translate('pages.schedules.title'), ), - ); - } - ), + BottomNavigationBarItem( + icon: Showcase( + key: showcaseTasksIcon, + title: translate('walk_through.tasks.title'), + description: translate('walk_through.tasks.description'), + targetPadding: EdgeInsets.all(16), + overlayOpacity: showcaseOpacity, + child: Icon(Icons.task_alt), + ), + label: translate('pages.tasks.title'), + ), + ], + selectedItemColor: ACCENT_COLOR, + unselectedItemColor: Colors.grey.shade600, + currentIndex: _selectedNavigationIndex, + onTap: (index) { + _pageController.animateToPage( + index, duration: Duration(milliseconds: 300), + curve: Curves.ease); + }, + ), + ); + } ); } diff --git a/lib/ui/components/DynamicPicker.dart b/lib/ui/components/DynamicPicker.dart index 27442c7..91d12db 100644 --- a/lib/ui/components/DynamicPicker.dart +++ b/lib/ui/components/DynamicPicker.dart @@ -183,7 +183,7 @@ class _DynamicPickerState extends State { Widget _itemBuilder(BuildContext context, int index) { final themeData = Theme.of(context); - final defaultStyle = widget.textStyle ?? themeData.textTheme.bodyText2; + final defaultStyle = widget.textStyle ?? themeData.textTheme.bodyMedium; final selectedStyle = TextStyle(color: isDarkMode(context) ? Colors.white : BUTTON_COLOR, fontSize: 24); final value = _getValueFromIndex(index % itemCount); diff --git a/lib/ui/dialogs.dart b/lib/ui/dialogs.dart index e001278..8903a64 100644 --- a/lib/ui/dialogs.dart +++ b/lib/ui/dialogs.dart @@ -22,9 +22,9 @@ import 'taskGroupIcons.dart'; final int MAX_DAYS = 7300; // around 20 years -Future showIconPicker(BuildContext context, String title) { +Future showIconPickerDialog(BuildContext context, String title) { - return FlutterIconPicker.showIconPicker(context, + return showIconPicker(context, iconSize: 32.0, title: Text(title), iconColor: BUTTON_COLOR, @@ -111,7 +111,8 @@ Theme _pickerTheme(BuildContext context, Widget? child) { ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( - primary: BUTTON_COLOR, + iconColor: BUTTON_COLOR, + // primary: BUTTON_COLOR, ), ), ), diff --git a/lib/ui/forms/TaskGroupForm.dart b/lib/ui/forms/TaskGroupForm.dart index 64a4c09..c61a7d7 100644 --- a/lib/ui/forms/TaskGroupForm.dart +++ b/lib/ui/forms/TaskGroupForm.dart @@ -123,7 +123,7 @@ class _TaskGroupFormState extends State { children: [ OutlinedButton.icon( onPressed: () async { - final iconData = await showIconPicker(context, translate('forms.task_group.change_icon.message')); + final iconData = await showIconPickerDialog(context, translate('forms.task_group.change_icon.message')); if (iconData != null) { setState(() => _taskGroup!.iconData = iconData); } diff --git a/lib/util/units.dart b/lib/util/units.dart index d4ba3d2..c89ef4b 100644 --- a/lib/util/units.dart +++ b/lib/util/units.dart @@ -15,11 +15,11 @@ Clause? usedClause(BuildContext context, Clause clause) { return null; } -abstract class Unit { +abstract class GeneralUnit { num value; Clause? clause; - Unit(this.value, [this.clause]); + GeneralUnit(this.value, [this.clause]); String getSubKey(); @@ -47,7 +47,7 @@ abstract class Unit { } -class Years extends Unit { +class Years extends GeneralUnit { Years(num value, [Clause? clause]) : super(value, clause); @@ -56,7 +56,7 @@ class Years extends Unit { return "year"; } } -class Months extends Unit { +class Months extends GeneralUnit { Months(num value, [Clause? clause]) : super(value, clause); @@ -66,7 +66,7 @@ class Months extends Unit { } } -class Weeks extends Unit { +class Weeks extends GeneralUnit { Weeks(num value, [Clause? clause]) : super(value, clause); @@ -77,7 +77,7 @@ class Weeks extends Unit { } -class Days extends Unit { +class Days extends GeneralUnit { Days(num value, [Clause? clause]) : super(value, clause); @@ -88,7 +88,7 @@ class Days extends Unit { } -class Hours extends Unit { +class Hours extends GeneralUnit { Hours(num value, [Clause? clause]) : super(value, clause); @@ -99,7 +99,7 @@ class Hours extends Unit { } -class Minutes extends Unit { +class Minutes extends GeneralUnit { Minutes(num value, [Clause? clause]) : super(value, clause); @@ -110,7 +110,7 @@ class Minutes extends Unit { } -class Seconds extends Unit { +class Seconds extends GeneralUnit { Seconds(num value, [Clause? clause]) : super(value, clause); @@ -121,7 +121,7 @@ class Seconds extends Unit { } -class Items extends Unit { +class Items extends GeneralUnit { Items(num value, [Clause? clause]) : super(value, clause); @@ -132,7 +132,7 @@ class Items extends Unit { } -class Schedules extends Unit { +class Schedules extends GeneralUnit { Schedules(num value, [Clause? clause]) : super(value, clause); diff --git a/pubspec.lock b/pubspec.lock index 6fbc4ec..35bd6e7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,34 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "61.0.0" + version: "67.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "5.13.0" + version: "6.4.1" archive: dependency: transitive description: name: archive - sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.4.10" + version: "3.6.1" args: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: transitive description: @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" build_resolvers: dependency: transitive description: @@ -85,18 +85,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.11" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe url: "https://pub.dev" source: hosted - version: "7.2.11" + version: "7.3.1" built_collection: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: built_value - sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.8.1" + version: "8.9.2" calendar_view: dependency: "direct main" description: @@ -172,10 +172,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -184,6 +184,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -196,26 +204,26 @@ packages: dependency: "direct main" description: name: csv - sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e" + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "6.0.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "1.0.8" dart_style: dependency: transitive description: name: dart_style - sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.6" dbus: dependency: transitive description: @@ -224,6 +232,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.10" + dev_build: + dependency: transitive + description: + name: dev_build + sha256: f526d1fbe68875f6119ffc333f114dfe6aa93ad04439276d53968f7977cc410e + url: "https://pub.dev" + source: hosted + version: "1.0.0+11" equatable: dependency: transitive description: @@ -244,26 +260,26 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" file_picker: dependency: "direct main" description: name: file_picker - sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 + sha256: "824f5b9f389bfc4dddac3dea76cd70c51092d9dff0b2ece7ef4f53db8547d258" url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "8.0.6" fixnum: dependency: transitive description: @@ -276,55 +292,63 @@ packages: dependency: "direct main" description: name: fl_chart - sha256: "29da130cdef13f47e1798a66e99fd119e557c293b98be8ebaf6fed2cbc43bf29" + sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb url: "https://pub.dev" source: hosted - version: "0.50.6" + version: "0.68.0" floor: dependency: "direct main" description: name: floor - sha256: "52a8eac2c8d274e7c0c54251226f59786bb5b749365a2d8537d8095aa5132d92" + sha256: c1b06023912b5b8e49deb6a9d867863c535ae1a232d991c3582bba3ee8687867 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.5.0" floor_annotation: dependency: transitive description: name: floor_annotation - sha256: fa3fa4f198cdd1d922a69ceb06e54663fe59256bf1cb3c036eff206b445a6960 + sha256: a40949580a7ab0eee572686e2d3b1638fd6bd6a753e661d792ab4236b365b23b + url: "https://pub.dev" + source: hosted + version: "1.5.0" + floor_common: + dependency: transitive + description: + name: floor_common + sha256: "41c9914862f83a821815e1b1ffd47a1e1ae2130c35ff882ba2d000a67713ba64" url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.5.0" floor_generator: dependency: "direct dev" description: name: floor_generator - sha256: "40aaf1b619adc03367ce4b7c79161e3198d43b572b5ec9cc99a4a89de27b08d2" + sha256: "1499b3ab878a807e6fbe6f140dc014124845cd1df3090a113aae5fa7577a1e77" url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.5.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" flutter_colorpicker: - dependency: "direct dev" + dependency: "direct main" description: name: flutter_colorpicker - sha256: "458a6ed8ea480eb16ff892aedb4b7092b2804affd7e046591fb03127e8d8ef8b" + sha256: "969de5f6f9e2a570ac660fb7b501551451ea2a1ab9e2097e89475f60e07816ea" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.1.0" flutter_iconpicker: - dependency: "direct dev" + dependency: "direct main" description: name: flutter_iconpicker - sha256: a51d1c8ed5447334652d6fe6d004f1d361184d124e982762373f9be6a78a18b6 + sha256: ad21bb678fd315f5c4f4eab2c9489779f818a3cbb77e20a7460d685bc44ddaf4 url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "3.3.3" flutter_launcher_icons: dependency: "direct dev" description: @@ -337,26 +361,26 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: f222919a34545931e47b06000836b5101baeffb0e6eb5a4691d2d42851740dd9 + sha256: dd6676d8c2926537eccdf9f72128bbb2a9d0814689527b17f92c248ff192eaf3 url: "https://pub.dev" source: hosted - version: "12.0.4" + version: "17.2.1+2" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "3c6d6db334f609a92be0c0915f40871ec56f5d2adf01e77ae364162c587c0ca8" + sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "4.0.1" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "7.2.0" flutter_localizations: dependency: "direct main" description: flutter @@ -366,10 +390,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.21" flutter_test: dependency: "direct dev" description: flutter @@ -379,10 +403,10 @@ packages: dependency: "direct main" description: name: flutter_translate - sha256: "8b1c449bf6d17753e6f188185f735ebc0a328d21d745878a43be66857de8ebb3" + sha256: bc09db690098879e3f90eb3aac3499e5282f32d5f9d8f1cc597d67bbc1e065ef url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.1.0" flutter_treeview: dependency: "direct main" description: @@ -400,18 +424,18 @@ packages: dependency: transitive description: name: font_awesome_flutter - sha256: "52671aea66da73b58d42ec6d0912b727a42248dd9a7c76d6c20f275783c48c08" + sha256: "275ff26905134bcb59417cf60ad979136f1f8257f2f449914b2c3e05bbb4cd6f" url: "https://pub.dev" source: hosted - version: "10.6.0" + version: "10.7.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -424,18 +448,18 @@ packages: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" http: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.2" http_multi_server: dependency: transitive description: @@ -456,10 +480,10 @@ packages: dependency: transitive description: name: image - sha256: "49a0d4b0c12402853d3f227fe7c315601b238d126aa4caa5dbb2dcf99421aa4a" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.1.6" + version: "4.2.0" infinite_listview: dependency: transitive description: @@ -472,10 +496,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.19.0" io: dependency: transitive description: @@ -488,26 +512,50 @@ packages: dependency: "direct main" description: name: jiffy - sha256: c3c1da3fe0c08bba3c2c455e8a3e724dfe7ea34dbe8069b992cab90ea1fe40b6 + sha256: "3497caaa36d36a29033e66803c9739ce6bccbc7e241ca46070f76ee9e6f6eb0c" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "6.3.1" js: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: transitive description: name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted - version: "4.8.1" + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lists: dependency: transitive description: @@ -528,42 +576,42 @@ 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" material_design_icons_flutter: dependency: "direct main" description: name: material_design_icons_flutter - sha256: "8c54c21cf336052193559abc64715e4885d6c9220a6dbdfc561a087266cc5385" + sha256: "6f986b7a51f3ad4c00e33c5c84e8de1bdd140489bbcdc8b66fc1283dad4dea5a" url: "https://pub.dev" source: hosted - version: "5.0.6996" + version: "7.0.7296" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.12.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" nested: dependency: transitive description: @@ -616,10 +664,10 @@ packages: dependency: "direct main" 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: @@ -640,10 +688,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" patterns_canvas: dependency: "direct main" description: @@ -656,58 +704,66 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" url: "https://pub.dev" source: hosted - version: "10.4.5" + version: "11.3.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" + sha256: eaf2a1ec4472775451e88ca6a7b86559ef2f1d1ed903942ed135e38ea0097dca url: "https://pub.dev" source: hosted - version: "10.3.6" + version: "12.0.8" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 + url: "https://pub.dev" + source: hosted + version: "9.4.5" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "6cac773d389e045a8d4f85418d07ad58ef9e42a56e063629ce14c4c26344de24" url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "0.1.2" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" + sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "4.2.2" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.2.1" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" platform: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -716,14 +772,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" - url: "https://pub.dev" - source: hosted - version: "3.7.3" pool: dependency: transitive description: @@ -732,22 +780,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + process_run: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: process_run + sha256: c917dfb5f7afad4c7485bc00a4df038621248fce046105020cea276d1a87c820 url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "1.1.0" provider: dependency: transitive description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" pub_semver: dependency: transitive description: @@ -760,10 +808,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 url: "https://pub.dev" source: hosted - version: "1.2.3" + version: "1.3.0" scroll_to_index: dependency: "direct main" description: @@ -784,58 +832,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" + sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833" url: "https://pub.dev" source: hosted - version: "2.3.5" + version: "2.5.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.4.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shelf: dependency: transitive description: @@ -848,18 +896,18 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.0" showcaseview: dependency: "direct main" description: name: showcaseview - sha256: dc62ce38820dead4a27ce39d9e6c98384be89c2f2b4da3255238a59b041c7ccd + sha256: f236c1f44b286e1ba888f8701adca067af92c33e29ea937d0fe9b4a29d4cd41e url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -885,58 +933,66 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.3+1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.5.0+2" + version: "2.5.4" sqflite_common_ffi: dependency: transitive description: name: sqflite_common_ffi - sha256: "35d2fce1e971707c227cc4775cc017d5eafe06c2654c3435ebd5c3ad6c170f5f" + sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5" url: "https://pub.dev" source: hosted - version: "2.3.0+4" + version: "2.3.3" + sqflite_common_ffi_web: + dependency: transitive + description: + name: sqflite_common_ffi_web + sha256: cfc9d1c61a3e06e5b2e96994a44b11125b4f451fee95b9fad8bd473b4613d592 + url: "https://pub.dev" + source: hosted + version: "0.4.3+1" sqlite3: dependency: transitive description: name: sqlite3 - sha256: db65233e6b99e99b2548932f55a987961bc06d82a31a0665451fa0b4fff4c3fb + sha256: fde692580bee3379374af1f624eb3e113ab2865ecb161dbe2d8ac2de9735dbdb url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.4.5" sqlparser: dependency: transitive description: name: sqlparser - sha256: "91f47610aa54d8abf9d795a7b4e49b2a788f65d7493d5a68fbf180c3cbcc6f38" + sha256: "7b20045d1ccfb7bc1df7e8f9fee5ae58673fce6ff62cefbb0e0fd7214e90e5a0" url: "https://pub.dev" source: hosted - version: "0.27.0" + version: "0.34.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -957,10 +1013,10 @@ packages: dependency: transitive description: name: strings - sha256: "5af86299505c299640f5564e187c1a2ee9d6308c540e8d65f6385f5c67019122" + sha256: "052836499f03897d3860a603b330c1ea3c8a14177b21f34b15a1295f36024aae" url: "https://pub.dev" source: hosted - version: "0.2.2" + version: "3.1.2" synchronized: dependency: transitive description: @@ -981,18 +1037,18 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.7.0" timezone: dependency: transitive description: name: timezone - sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.4" timing: dependency: transitive description: @@ -1029,26 +1085,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + sha256: "94d8ad05f44c6d4e2ffe5567ab4d741b82d62e3c8e288cc1fcea45965edf47c9" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.8" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.3.1" url_launcher_linux: dependency: transitive description: @@ -1061,34 +1117,34 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.2.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" vector_math: dependency: transitive description: @@ -1097,6 +1153,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" watcher: dependency: transitive description: @@ -1109,42 +1173,50 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.5.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "3.0.1" win32: - dependency: transitive + dependency: "direct main" description: name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.5.3" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" yaml: dependency: transitive description: @@ -1154,5 +1226,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index bd1de5a..e5a43ef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,42 +15,45 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.0+10700 +version: 1.7.1+10701 environment: - sdk: ">=3.0.0" - flutter: 3.10.5 + sdk: ">=3.4.0" + flutter: 3.22.0 dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter - flutter_local_notifications: ^12.0.4 + flutter_local_notifications: ^17.2.1+2 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - material_design_icons_flutter: ^5.0.6595 + material_design_icons_flutter: ^7.0.7296 floor: ^1.1.0 intl: any numberpicker: ^2.1.1 flutter_treeview: ^1.0.6+1 - jiffy: ^5.0.0 - shared_preferences: ^2.0.0-nullsafety - fl_chart: ^0.50.1 - package_info_plus: ^1.4.2 + jiffy: ^6.3.1 + shared_preferences: ^2.3.1 + fl_chart: ^0.68.0 + package_info_plus: ^8.0.1 url_launcher: ^6.0.20 settings_ui: ^2.0.2 - permission_handler: ^10.4.3 + permission_handler: ^11.3.1 sqflite: ^2.0.1 path: ^1.8.0 - file_picker: ^5.2.2 + file_picker: ^8.0.6 flutter_translate: ^4.0.3 - csv: ^5.0.1 - showcaseview: ^2.0.3 + csv: ^6.0.0 + showcaseview: ^3.0.0 patterns_canvas: ^0.4.0 scroll_to_index: ^3.0.1 ordinal_formatter: ^0.1.4 + flutter_colorpicker: ^1.0.3 + flutter_iconpicker: ^3.3.3 + win32: ^5.5.1 calendar_view: path: ./flutter_calendar_view @@ -61,8 +64,7 @@ dev_dependencies: floor_generator: ^1.1.0 build_runner: ^2.0.0 flutter_launcher_icons: "^0.13.1" - flutter_colorpicker: ^1.0.3 - flutter_iconpicker: ^3.2.2 + dependency_overrides: package_info_plus: ^4.0.1 @@ -98,30 +100,3 @@ flutter: - assets/i18n/fr.json - assets/i18n/ru.json - assets/i18n/es.json - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages - From abc0f0dd6bfea91a38395eb06d5031c4ff814f42 Mon Sep 17 00:00:00 2001 From: Jens Pfahl Date: Tue, 6 Aug 2024 20:08:25 +0200 Subject: [PATCH 2/5] use Material 2, not M3 --- lib/ui/PersonalTaskLoggerApp.dart | 2 ++ lib/ui/forms/ScheduledTaskForm.dart | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/ui/PersonalTaskLoggerApp.dart b/lib/ui/PersonalTaskLoggerApp.dart index 6cb7c22..70709a4 100644 --- a/lib/ui/PersonalTaskLoggerApp.dart +++ b/lib/ui/PersonalTaskLoggerApp.dart @@ -30,6 +30,7 @@ class PersonalTaskLoggerApp extends StatelessWidget { supportedLocales: localizationDelegate.supportedLocales, locale: localizationDelegate.currentLocale, darkTheme: ThemeData( + useMaterial3: false, brightness: Brightness.dark, primaryColor: PRIMARY_COLOR, checkboxTheme: CheckboxThemeData( @@ -60,6 +61,7 @@ class PersonalTaskLoggerApp extends StatelessWidget { ), theme: ThemeData( + useMaterial3: false, brightness: Brightness.light, primaryColor: PRIMARY_COLOR, primarySwatch: BUTTON_COLOR, diff --git a/lib/ui/forms/ScheduledTaskForm.dart b/lib/ui/forms/ScheduledTaskForm.dart index 7d3819e..9f65b62 100644 --- a/lib/ui/forms/ScheduledTaskForm.dart +++ b/lib/ui/forms/ScheduledTaskForm.dart @@ -846,22 +846,39 @@ class _ScheduledTaskFormState extends State { Stack _buildDynamicScheduleIcon(BuildContext context) { return Stack(children: [ Icon(Icons.calendar_today, color: isDarkMode(context) ? (_repetitionMode == RepetitionMode.DYNAMIC ? PRIMARY_COLOR : null) : null,), - Positioned.fill(top: 4, left: 5.25, child: Text("▪", style: TextStyle(color: isDarkMode(context) ? (_repetitionMode == RepetitionMode.DYNAMIC ? PRIMARY_COLOR : null) : null, fontSize: 14,))), - Positioned.fill(top: 8, left: 12, child: Text("?", style: TextStyle(fontWeight: FontWeight.bold, color: isDarkMode(context) ? (_repetitionMode == RepetitionMode.DYNAMIC ? PRIMARY_COLOR : null) : null, fontSize: 12,))), + Positioned(top: 13.0, left: 5.5, + child: SizedBox(height: 4, width: 4, + child: Container( + decoration: BoxDecoration(color: _repetitionMode == RepetitionMode.DYNAMIC ? (isDarkMode(context) ? PRIMARY_COLOR : BUTTON_COLOR) : Colors.grey[600]))) + ), + Positioned.fill(top: 8, left: 13, child: Text("?", style: TextStyle(fontWeight: FontWeight.bold, color: isDarkMode(context) ? (_repetitionMode == RepetitionMode.DYNAMIC ? PRIMARY_COLOR : null) : null, fontSize: 12,))), ]); } Stack _buildFixedScheduleIcon(BuildContext context, bool isHighlighted) { return Stack(children: [ Icon(Icons.calendar_today, color: isDarkMode(context) ? (isHighlighted ? PRIMARY_COLOR : null) : null,), - Positioned.fill(top: 4, left: 5.25, child: Text("▪ ▪", style: TextStyle(color: isDarkMode(context) ? (isHighlighted ? PRIMARY_COLOR : null) : null, fontSize: 14,))), + Positioned(top: 13.0, left: 5.5, + child: SizedBox(height: 4, width: 4, + child: Container( + decoration: BoxDecoration(color: _repetitionMode == RepetitionMode.FIXED ? (isDarkMode(context) ? PRIMARY_COLOR : BUTTON_COLOR) : Colors.grey[600]))) + ), + Positioned(top: 13.0, left: 14.5, + child: SizedBox(height: 4, width: 4, + child: Container( + decoration: BoxDecoration(color: _repetitionMode == RepetitionMode.FIXED ? (isDarkMode(context) ? PRIMARY_COLOR : BUTTON_COLOR) : Colors.grey[600]))) + ), ]); } Stack _buildOneTimeScheduleIcon(BuildContext context, bool isHighlighted) { return Stack(children: [ Icon(Icons.calendar_today, color: isDarkMode(context) ? (isHighlighted ? PRIMARY_COLOR : null) : null,), - Positioned.fill(top: 4, left: 5.25, child: Text("▪ ", style: TextStyle(color: isDarkMode(context) ? (isHighlighted ? PRIMARY_COLOR : null) : null, fontSize: 14,))), + Positioned(top: 13.0, left: 5.5, + child: SizedBox(height: 4, width: 4, + child: Container( + decoration: BoxDecoration(color: _repetitionMode == RepetitionMode.ONE_TIME ? (isDarkMode(context) ? PRIMARY_COLOR : BUTTON_COLOR) : Colors.grey[600]))) + ) ]); } From 555068aa88609a7cddf123479877146082676cbd Mon Sep 17 00:00:00 2001 From: Jens Pfahl Date: Tue, 6 Aug 2024 22:02:38 +0200 Subject: [PATCH 3/5] Fix failed schedule notifications (issue #79) --- android/app/src/main/AndroidManifest.xml | 13 +++++++ lib/service/LocalNotificationService.dart | 45 ++++++++++++++++------- lib/service/PreferenceService.dart | 2 +- metadata/en-US/changelogs/10701.txt | 2 + pubspec.lock | 8 ++++ pubspec.yaml | 1 + 6 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 metadata/en-US/changelogs/10701.txt diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ad1a072..a538285 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -40,9 +40,22 @@ + + + + + + + + + + + + + diff --git a/lib/service/LocalNotificationService.dart b/lib/service/LocalNotificationService.dart index 2228d38..aa0033c 100644 --- a/lib/service/LocalNotificationService.dart +++ b/lib/service/LocalNotificationService.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_timezone/flutter_timezone.dart'; import 'package:flutter_translate/flutter_translate.dart'; import 'package:personaltasklogger/model/Schedule.dart'; import 'package:timezone/data/latest.dart' as tz; @@ -118,6 +119,9 @@ class LocalNotificationService { InitializationSettings(android: initializationSettingsAndroid); tz.initializeTimeZones(); + final String currentTimeZone = await FlutterTimezone.getLocalTimezone(); + debugPrint("currentTimeZone=$currentTimeZone"); + tz.setLocalLocation(tz.getLocation(currentTimeZone)); await _flutterLocalNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse response) async { @@ -145,33 +149,45 @@ class LocalNotificationService { Future scheduleNotification(String receiverKey, int id, String title, message, Duration duration, String channelId, [Color? color, List? actions, bool withTranslation = true, CustomRepetition? snoozePeriod]) async { - final when = tz.TZDateTime.now(tz.local).add(duration); - if (when.isBefore(DateTime.now())) { - debugPrint("Scheduled notification $id in the past, skip ($when)"); + if (duration.isNegative || duration.inSeconds < 10) { + debugPrint( + "Scheduled notification $id in the past, skip"); return; } + final now = DateTime.now().add(duration); + + var zonedTime = tz.TZDateTime.local(now.year, now.month, now.day, now.hour, now.minute, now.second); + if (duration.inMinutes >= 1) { + // truncate to full minutes if duration greater than one minute + zonedTime = zonedTime.subtract(Duration(seconds: zonedTime.second)); + } + final parameterMap = { - 'receiverKey' : receiverKey, - 'id' : id, - 'title' : title, - 'message' : message, - 'channelId' : channelId, - 'color' : color?.value, - 'actions' : actions?.map((a) => a.id + "-" + a.showsUserInterface.toString() + "-" + a.title).toList(), - 'snooze_period_value' : snoozePeriod?.repetitionValue, - 'snooze_period_unit' : snoozePeriod?.repetitionUnit.index, + 'receiverKey': receiverKey, + 'id': id, + 'title': title, + 'message': message, + 'channelId': channelId, + 'color': color?.value, + 'actions': actions?.map((a) => + a.id + "-" + a.showsUserInterface.toString() + "-" + a.title).toList(), + 'snooze_period_value': snoozePeriod?.repetitionValue, + 'snooze_period_unit': snoozePeriod?.repetitionUnit.index, }; final parametersAsJson = jsonEncode(parameterMap); + debugPrint("Schedule $id ($zonedTime), duration=${duration} tz=${tz.local}"); + + await _flutterLocalNotificationsPlugin.zonedSchedule( id, title, message, - when.subtract(Duration(seconds: when.second)), // trunc seconds + zonedTime, NotificationDetails(android: _createNotificationDetails(color, channelId, false, actions, withTranslation)), - androidAllowWhileIdle: true, + androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, payload: receiverKey + "-" + id.toString() + RESCHEDULE_JSON_START_MARKER + parametersAsJson); } @@ -209,6 +225,7 @@ class LocalNotificationService { }); } + void _handlePayload(bool isAppLaunch, String payload, String? actionId) { debugPrint("_handlePayload=$payload $isAppLaunch"); diff --git a/lib/service/PreferenceService.dart b/lib/service/PreferenceService.dart index fc2ade4..77e3979 100644 --- a/lib/service/PreferenceService.dart +++ b/lib/service/PreferenceService.dart @@ -160,7 +160,7 @@ class PreferenceService implements ITranslatePreferences { KeyValueRepository.update(keyValue); } else { - KeyValueRepository.insert(KeyValue(null, key, value)); + KeyValueRepository.insert(KeyValue(null, key, value.toString())); } }); diff --git a/metadata/en-US/changelogs/10701.txt b/metadata/en-US/changelogs/10701.txt new file mode 100644 index 0000000..d572a19 --- /dev/null +++ b/metadata/en-US/changelogs/10701.txt @@ -0,0 +1,2 @@ +* Fix Schedule notification bug #79 +* (Upgrade target version and dependencies) \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 35bd6e7..f08b6b9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -399,6 +399,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_timezone: + dependency: "direct main" + description: + name: flutter_timezone + sha256: "0cb5498dedfaac615c779138194052f04524c31d958fab33d378f22b6cc14686" + url: "https://pub.dev" + source: hosted + version: "2.1.0" flutter_translate: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e5a43ef..2925992 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -27,6 +27,7 @@ dependencies: flutter_localizations: sdk: flutter flutter_local_notifications: ^17.2.1+2 + flutter_timezone: ^2.1.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 From f11c7233d8d753938bfef05317279a0c8d3aadb2 Mon Sep 17 00:00:00 2001 From: Jens Pfahl Date: Thu, 8 Aug 2024 16:56:35 +0200 Subject: [PATCH 4/5] commit ignore wrong locations and go with UTC --- lib/service/LocalNotificationService.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/service/LocalNotificationService.dart b/lib/service/LocalNotificationService.dart index aa0033c..4736eec 100644 --- a/lib/service/LocalNotificationService.dart +++ b/lib/service/LocalNotificationService.dart @@ -119,9 +119,14 @@ class LocalNotificationService { InitializationSettings(android: initializationSettingsAndroid); tz.initializeTimeZones(); - final String currentTimeZone = await FlutterTimezone.getLocalTimezone(); - debugPrint("currentTimeZone=$currentTimeZone"); - tz.setLocalLocation(tz.getLocation(currentTimeZone)); + try { + final String currentTimeZone = await FlutterTimezone.getLocalTimezone(); + debugPrint("currentTimeZone=$currentTimeZone"); + tz.setLocalLocation(tz.getLocation(currentTimeZone)); + } catch (e) { + // ignore instead of failing + print(e); + } await _flutterLocalNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse response) async { From 9bb5e01e6ac3ce4a88f9de5528fce8cd5a6d5644 Mon Sep 17 00:00:00 2001 From: Jens Pfahl Date: Thu, 8 Aug 2024 19:42:06 +0200 Subject: [PATCH 5/5] Make Google happy (scheduled alarms require user permission since Android 14) --- android/app/src/main/AndroidManifest.xml | 2 +- lib/service/LocalNotificationService.dart | 5 +++++ lib/ui/PersonalTaskLoggerScaffold.dart | 1 + metadata/en-US/changelogs/10702.txt | 2 ++ pubspec.yaml | 2 +- 5 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 metadata/en-US/changelogs/10702.txt diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a538285..7d50625 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -55,7 +55,7 @@ - + diff --git a/lib/service/LocalNotificationService.dart b/lib/service/LocalNotificationService.dart index 4736eec..2aaa63e 100644 --- a/lib/service/LocalNotificationService.dart +++ b/lib/service/LocalNotificationService.dart @@ -272,5 +272,10 @@ class LocalNotificationService { actions: actions, ); } + + void requestPermissions() { + AndroidFlutterLocalNotificationsPlugin? nativePlugin = _flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); + nativePlugin?.requestExactAlarmsPermission(); + } } diff --git a/lib/ui/PersonalTaskLoggerScaffold.dart b/lib/ui/PersonalTaskLoggerScaffold.dart index 29381d8..5e16165 100644 --- a/lib/ui/PersonalTaskLoggerScaffold.dart +++ b/lib/ui/PersonalTaskLoggerScaffold.dart @@ -148,6 +148,7 @@ class PersonalTaskLoggerScaffoldState extends State DueScheduleCountService().gather(); }); + _notificationService.requestPermissions(); } PageScaffold getSelectedPage() { diff --git a/metadata/en-US/changelogs/10702.txt b/metadata/en-US/changelogs/10702.txt new file mode 100644 index 0000000..d572a19 --- /dev/null +++ b/metadata/en-US/changelogs/10702.txt @@ -0,0 +1,2 @@ +* Fix Schedule notification bug #79 +* (Upgrade target version and dependencies) \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 2925992..8dc5751 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.1+10701 +version: 1.7.2+10702 environment: sdk: ">=3.4.0"