From 93ec1e852fcaab477083e8a6cd96b0b320a8755e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Caras?= Date: Tue, 31 May 2022 17:55:28 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20pracovat=20na=20ozn=C3=A1men=C3=AD=20p?= =?UTF-8?q?=C5=99ed=20ob=C4=9Bdem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/devcontainer.json | 5 ++ CHANGELOG.md | 3 + lib/lang/lang.dart | 4 ++ lib/lang/lang_cz.dart | 7 ++ lib/lang/lang_en.dart | 6 ++ lib/main.dart | 118 ++++++++++++++++++++++++++++---- lib/okna/nastaveni.dart | 24 +++++++ pubspec.lock | 84 ++++++++++------------- pubspec.yaml | 3 +- 9 files changed, 191 insertions(+), 63 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..abe86c1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,5 @@ +{ + "name": "Flutter", + "image": "matspfeiffer/flutter:beta", + "extensions": ["dart-code.dart-code", "dart-code.flutter"] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d31458..7e7e417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.3.0 +- Odstranit connectivity_plus +- Přidat možnost oznámení s info o obědu v daný čas # 1.2.0 - Přidat možnost zobrazení oznámení v případě neobjednaného jídla na příští týden - Přidat oznámení o rozbitých uložených údajích diff --git a/lib/lang/lang.dart b/lib/lang/lang.dart index f73158d..6575dba 100644 --- a/lib/lang/lang.dart +++ b/lib/lang/lang.dart @@ -145,6 +145,10 @@ abstract class Languages { String get checkOrdered; + String get notifyLunch; + + String get notifyAt; + // Offline String get offline; diff --git a/lib/lang/lang_cz.dart b/lib/lang/lang_cz.dart index fd77801..baffcba 100644 --- a/lib/lang/lang_cz.dart +++ b/lib/lang/lang_cz.dart @@ -207,4 +207,11 @@ class LanguageCz extends Languages { @override String get corrupted => "Nastal problém s dešifrováním uložených údajů, prosím zkuste vyčistit veškerá data této aplikace."; + + @override + String get notifyAt => "Odeslat v"; + + @override + String get notifyLunch => + "V určený čas odeslat notifikaci s informacemi o obědě"; } diff --git a/lib/lang/lang_en.dart b/lib/lang/lang_en.dart index 3b838db..9bd4183 100644 --- a/lib/lang/lang_en.dart +++ b/lib/lang/lang_en.dart @@ -206,4 +206,10 @@ class LanguageEn extends Languages { @override String get corrupted => "The saved credentials seem to be corrupted, please try clearing the application's data."; + + @override + String get notifyAt => "Send notification at"; + + @override + String get notifyLunch => "Send a notification with meal info"; } diff --git a/lib/main.dart b/lib/main.dart index 2adb7f6..6b1c41c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,18 +1,20 @@ import 'dart:convert'; import 'dart:io'; +import 'package:background_fetch/background_fetch.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:opencanteen/lang/lang_cz.dart'; import 'package:opencanteen/loginmanager.dart'; -import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:canteenlib/canteenlib.dart'; import 'package:opencanteen/okna/offline_jidelnicek.dart'; import 'package:opencanteen/okna/welcome.dart'; import 'package:opencanteen/util.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'lang/lang.dart'; import 'lang/lang_en.dart'; @@ -35,14 +37,75 @@ Copyright (C) 2022 Matyáš Caras a přispěvatelé along with this program. If not, see . */ -void main() { +final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + +// Pouze pro Android +void backgroundFetchHeadlessTask(HeadlessTask task) async { + String taskId = task.taskId; + bool isTimeout = task.timeout; + if (isTimeout) { + // Timeout + debugPrint("[BackgroundFetch] Headless task má time-out: $taskId"); + BackgroundFetch.finish(taskId); + return; + } + var prefs = await SharedPreferences.getInstance(); + debugPrint('[BackgroundFetch] Přišel headless event.'); + + if (prefs.getBool("oznamit") ?? false) { + // Oznámení před obědem + if (prefs.getBool("offline") ?? false) { + // TODO možnost brát z offline dat + } else { + // bere online + var d = await LoginManager.getDetails(); // získat údaje + if (d != null) { + // TODO + } + } + } + BackgroundFetch.finish(taskId); +} + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('notif_icon'); + + /// Note: permissions aren't requested here just to demonstrate that can be + /// done later + final IOSInitializationSettings initializationSettingsIOS = + IOSInitializationSettings( + requestAlertPermission: false, + requestBadgePermission: false, + requestSoundPermission: false, + onDidReceiveLocalNotification: ( + int id, + String? title, + String? body, + String? payload, + ) async { + debugPrint(body); + }); + + final InitializationSettings initializationSettings = InitializationSettings( + android: initializationSettingsAndroid, + iOS: initializationSettingsIOS, + ); + await flutterLocalNotificationsPlugin.initialize(initializationSettings, + onSelectNotification: (String? payload) async { + if (payload != null) { + debugPrint('notification payload: $payload'); + } + }); runApp(const MyApp()); + BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( @@ -78,22 +141,49 @@ class _LoginPageState extends State { TextEditingController canteenControl = TextEditingController(); bool rememberMe = false; + void nastavitPozadi() async { + // Configure BackgroundFetch. + int status = await BackgroundFetch.configure( + BackgroundFetchConfig( + minimumFetchInterval: 15, + stopOnTerminate: false, + enableHeadless: true, + requiresBatteryNotLow: false, + requiresCharging: false, + requiresStorageNotLow: false, + requiresDeviceIdle: false, + requiredNetworkType: NetworkType.ANY), (String taskId) async { + // Callback + debugPrint("[BackgroundFetch] Event získán $taskId"); + var d = await LoginManager.getDetails(); + if (d != null) { + // TODO + } + BackgroundFetch.finish(taskId); + }, (String taskId) async { + debugPrint("[BackgroundFetch] TASK TIMEOUT taskId: $taskId"); + BackgroundFetch.finish(taskId); + }); + debugPrint('[BackgroundFetch] úspěšně nakonfigurováno: $status'); + } + @override void initState() { super.initState(); LoginManager.getDetails().then((r) async { - var connectivityResult = await (Connectivity().checkConnectivity()); - if (connectivityResult == ConnectivityResult.none) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(Languages.of(context)!.errorContacting), - ), - ); - goOffline(); + if (Platform.isIOS) { + // žádat o oprávnění na iOS + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + IOSFlutterLocalNotificationsPlugin>() + ?.requestPermissions( + alert: true, + badge: true, + sound: true, + ); } - if (r != null) { + // Automaticky přihlásit showDialog( context: context, barrierDismissible: false, @@ -123,6 +213,7 @@ class _LoginPageState extends State { } const storage = FlutterSecureStorage(); var odsouhlasil = await storage.read(key: "oc_souhlas"); + nastavitPozadi(); if (odsouhlasil == null || odsouhlasil != "ano") { Navigator.pushReplacement( context, @@ -260,6 +351,7 @@ class _LoginPageState extends State { LoginManager.setDetails(userControl.text, passControl.text, canteenControl.text); } + nastavitPozadi(); // souhlas const storage = FlutterSecureStorage(); var odsouhlasil = diff --git a/lib/okna/nastaveni.dart b/lib/okna/nastaveni.dart index 8b43e2d..d65ac6a 100644 --- a/lib/okna/nastaveni.dart +++ b/lib/okna/nastaveni.dart @@ -17,6 +17,8 @@ class _NastaveniState extends State { bool _ukladatOffline = false; bool _preskakovatVikend = false; bool _kontrolovatTyden = false; + bool _oznameniObed = false; + String? _oznameniCas; void najitNastaveni() async { var preferences = await SharedPreferences.getInstance(); @@ -24,6 +26,8 @@ class _NastaveniState extends State { _ukladatOffline = preferences.getBool("offline") ?? false; _preskakovatVikend = preferences.getBool("skip") ?? false; _kontrolovatTyden = preferences.getBool("tyden") ?? false; + _oznameniObed = preferences.getBool("oznamit") ?? false; + _oznameniCas = preferences.getString("oznameni_cas"); }); } @@ -91,6 +95,26 @@ class _NastaveniState extends State { }); }) ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(Languages.of(context)!.skipWeekend), + Switch( + value: _oznameniObed, + onChanged: (value) { + setState(() { + _oznameniObed = value; + zmenitNastaveni("oznamit", value); + }); + }) + ], + ), + Text(Languages.of(context)!.notifyAt), + TimePickerDialog( + initialTime: (_oznameniCas == null) + ? TimeOfDay.now() + : TimeOfDay.fromDateTime(DateTime.parse(_oznameniCas!)), ) ], ), diff --git a/pubspec.lock b/pubspec.lock index da74db2..6d92ce2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.2" + background_fetch: + dependency: "direct main" + description: + name: background_fetch + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" canteenlib: dependency: "direct main" description: @@ -57,48 +64,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" - connectivity_plus: - dependency: "direct main" - description: - name: connectivity_plus - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.1" - connectivity_plus_linux: - dependency: transitive - description: - name: connectivity_plus_linux - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - connectivity_plus_macos: - dependency: transitive - description: - name: connectivity_plus_macos - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - connectivity_plus_platform_interface: - dependency: transitive - description: - name: connectivity_plus_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - connectivity_plus_web: - dependency: transitive - description: - name: connectivity_plus_web - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - connectivity_plus_windows: - dependency: transitive - description: - name: connectivity_plus_windows - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" crypto: dependency: transitive description: @@ -153,6 +118,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "9.5.3+1" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.2" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -268,13 +254,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" - nm: - dependency: transitive - description: - name: nm - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.0" path: dependency: transitive description: @@ -441,6 +420,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + timezone: + dependency: transitive + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index fde98a3..a5fbbf7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,12 +17,13 @@ dependencies: flutter_localizations: sdk: flutter canteenlib: ^0.1.0-alpha.16 - connectivity_plus: ^2.2.1 flutter_secure_storage: ^5.0.2 url_launcher: ^6.0.20 path_provider: ^2.0.9 shared_preferences: ^2.0.13 introduction_screen: ^3.0.1 + flutter_local_notifications: ^9.5.3+1 + background_fetch: ^1.1.0 dev_dependencies: flutter_lints: ^1.0.0