diff --git a/lib/global.dart b/lib/global.dart index 3b06ab8..e8247d1 100644 --- a/lib/global.dart +++ b/lib/global.dart @@ -20,6 +20,7 @@ import 'package:vikunja_app/models/user.dart'; import 'package:vikunja_app/service/services.dart'; import 'package:timezone/data/latest_all.dart' as tz; import 'package:flutter_local_notifications/flutter_local_notifications.dart'as notifs; +import 'package:workmanager/workmanager.dart'; class VikunjaGlobal extends StatefulWidget { @@ -108,7 +109,18 @@ class VikunjaGlobalState extends State { late String currentTimeZone; - + void updateWorkmanagerDuration() { + Workmanager().cancelAll().then((value) { + settingsManager.getWorkmanagerDuration().then((duration) => + { + if(duration.inMinutes > 0) { + Workmanager().registerPeriodicTask( + "update-tasks", "update-tasks", frequency: duration, + initialDelay: Duration.zero, inputData: {}) + } + }); + }); + } @override void initState() { @@ -129,6 +141,8 @@ class VikunjaGlobalState extends State { versionChecker.postVersionCheckSnackbar(); } }); + + updateWorkmanagerDuration(); } void changeUser(User newUser, {String? token, String? base}) async { @@ -194,6 +208,7 @@ class VikunjaGlobalState extends State { ); } } + print("notifications scheduled successfully"); } diff --git a/lib/main.dart b/lib/main.dart index 8881424..da6ddda 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:workmanager/workmanager.dart'; import 'package:vikunja_app/global.dart'; import 'package:vikunja_app/pages/home.dart'; import 'package:vikunja_app/pages/user/login.dart'; @@ -17,7 +18,21 @@ class IgnoreCertHttpOverrides extends HttpOverrides { } } +@pragma('vm:entry-point') +void callbackDispatcher() { + Workmanager().executeTask((task, inputData) { + print("Native called background task: $task"); //simpleTask will be emitted here. + if(task == "update-tasks") { + //TODO + } + return get(Uri.parse("https://webhook.site/"), headers: {"task":"$task", "data":"$inputData"}).then((value) => Future.value(true)); + }); +} + + void main() { + WidgetsFlutterBinding.ensureInitialized(); + Workmanager().initialize(callbackDispatcher, isInDebugMode: true); runApp(VikunjaGlobal( child: new VikunjaApp(home: HomePage(), key: UniqueKey(),), login: new VikunjaApp(home: LoginPage(), key: UniqueKey(),))); diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 1419a88..03194ed 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -15,36 +15,45 @@ class SettingsPageState extends State { bool? ignoreCertificates; bool? getVersionNotifications; String? versionTag, newestVersionTag; + late TextEditingController durationTextController; + bool initialized = false; + + void init() { + durationTextController = TextEditingController(); + + VikunjaGlobal.of(context) + .listService + .getAll() + .then((value) => setState(() => taskListList = value)); + + VikunjaGlobal.of(context).listService.getDefaultList().then((value) => + setState( + () => defaultList = value == null ? null : int.tryParse(value))); + + VikunjaGlobal.of(context).settingsManager.getIgnoreCertificates().then( + (value) => + setState(() => ignoreCertificates = value == "1" ? true : false)); + + VikunjaGlobal.of(context).settingsManager.getVersionNotifications().then( + (value) => setState( + () => getVersionNotifications = value == "1" ? true : false)); + + VikunjaGlobal.of(context) + .versionChecker + .getCurrentVersionTag() + .then((value) => setState(() => versionTag = value)); + + VikunjaGlobal.of(context) + .settingsManager + .getWorkmanagerDuration() + .then((value) => setState(() => durationTextController.text = (value.inMinutes.toString()))); + + initialized = true; + } @override Widget build(BuildContext context) { - if (taskListList == null) - VikunjaGlobal.of(context) - .listService - .getAll() - .then((value) => setState(() => taskListList = value)); - - if (defaultList == null) - VikunjaGlobal.of(context).listService.getDefaultList().then((value) => - setState( - () => defaultList = value == null ? null : int.tryParse(value))); - - if (ignoreCertificates == null) - VikunjaGlobal.of(context).settingsManager.getIgnoreCertificates().then( - (value) => - setState(() => ignoreCertificates = value == "1" ? true : false)); - - if (getVersionNotifications == null) - VikunjaGlobal.of(context).settingsManager.getVersionNotifications().then( - (value) => setState( - () => getVersionNotifications = value == "1" ? true : false)); - - if (versionTag == null) - VikunjaGlobal.of(context) - .versionChecker - .getCurrentVersionTag() - .then((value) => setState(() => versionTag = value)); - + if (!initialized) init(); return new Scaffold( appBar: AppBar( title: Text("Settings"), @@ -86,20 +95,44 @@ class SettingsPageState extends State { VikunjaGlobal.of(context).client.reload_ignore_certs(value); }) : ListTile(title: Text("...")), + Padding(padding: EdgeInsets.only(left: 15, right: 15), + child: Row(children: [ + Flexible( + child: TextField( + controller: durationTextController, + decoration: InputDecoration( + labelText: 'Background Refresh Interval (minutes): ', + helperText: 'Minimum: 15, Set limit of 0 for no refresh', + ), + )), + TextButton( + onPressed: () => VikunjaGlobal.of(context) + .settingsManager + .setWorkmanagerDuration(Duration( + minutes: int.parse(durationTextController.text))), + child: Text("Save")), + ])) + , getVersionNotifications != null ? CheckboxListTile( title: Text("Get Version Notifications"), value: getVersionNotifications, onChanged: (value) { setState(() => getVersionNotifications = value); - if(value != null) - VikunjaGlobal.of(context).settingsManager.setVersionNotifications(value); + if (value != null) + VikunjaGlobal.of(context) + .settingsManager + .setVersionNotifications(value); }) : ListTile(title: Text("...")), - TextButton(onPressed: () { - sendTestNotification(VikunjaGlobal.of(context).notificationsPlugin - , VikunjaGlobal.of(context).platformChannelSpecificsReminders); - }, child: Text("Send test notification")), + TextButton( + onPressed: () { + sendTestNotification( + VikunjaGlobal.of(context).notificationsPlugin, + VikunjaGlobal.of(context) + .platformChannelSpecificsReminders); + }, + child: Text("Send test notification")), TextButton( onPressed: () => VikunjaGlobal.of(context) .versionChecker diff --git a/lib/service/services.dart b/lib/service/services.dart index 0c413b0..dc15cf8 100644 --- a/lib/service/services.dart +++ b/lib/service/services.dart @@ -231,7 +231,8 @@ class SettingsManager { Map defaults = { "ignore-certificates": "0", - "get-version-notifications": "1" + "get-version-notifications": "1", + "workmanager-duration": "0" }; SettingsManager(this._storage) { @@ -245,16 +246,26 @@ class SettingsManager { Future getIgnoreCertificates() { return _storage.read(key: "ignore-certificates"); } - - Future getVersionNotifications() { - return _storage.read(key: "get-version-notifications"); - } - void setIgnoreCertificates(bool value) { _storage.write(key: "ignore-certificates", value: value ? "1" : "0"); } + + Future getVersionNotifications() { + return _storage.read(key: "get-version-notifications"); + } void setVersionNotifications(bool value) { _storage.write(key: "get-version-notifications", value: value ? "1" : "0"); } + + + Future getWorkmanagerDuration() { + return _storage.read(key: "workmanager-duration").then((value) => Duration(minutes: int.parse(value ?? "0"))); + } + void setWorkmanagerDuration(Duration duration) { + _storage.write(key: "workmanager-duration", value: duration.inMinutes.toString()); + } + + + } diff --git a/pubspec.lock b/pubspec.lock index 55bae18..92b26b1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -70,14 +70,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.2.1" checked_yaml: dependency: transitive description: @@ -98,7 +91,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: @@ -168,7 +161,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" ffi: dependency: transitive description: @@ -400,21 +393,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" mime: dependency: transitive description: @@ -463,7 +456,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" path_drawing: dependency: transitive description: @@ -608,7 +601,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -629,35 +622,35 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.21.1" + version: "1.21.4" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.12" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.4.13" + version: "0.4.16" timezone: dependency: transitive description: @@ -798,6 +791,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.3" + workmanager: + dependency: "direct main" + description: + name: workmanager + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.1" xdg_directories: dependency: transitive description: @@ -820,5 +820,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.17.0 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8eeff34..d9c9297 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: Vikunja as Flutter cross platform app version: 0.0.24-alpha environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.18.0 <3.0.0" dependencies: flutter: @@ -29,6 +29,7 @@ dependencies: dotted_border: ^2.0.0+2 package_info_plus: ^3.0.2 url_launcher: ^6.1.7 + workmanager: ^0.5.1 dev_dependencies: flutter_test: