From 819b25c7eb70ebc33870709e51b64575ba73ebe0 Mon Sep 17 00:00:00 2001 From: Denys Konovalov Date: Wed, 19 Jan 2022 19:30:09 +0100 Subject: [PATCH] ===1.1.0=== - fixed caching issues - added action on notification tap - fixed background fetch - added reset password --- lib/background_fetch.dart | 12 ++++---- lib/cache_manager.dart | 24 ++++++++++++--- lib/dashboard.dart | 61 +++++++++++++++++++++++++++++++++++++++ lib/login.dart | 20 ++++++++++++- lib/main.dart | 20 ++++--------- pubspec.yaml | 2 +- 6 files changed, 113 insertions(+), 26 deletions(-) diff --git a/lib/background_fetch.dart b/lib/background_fetch.dart index ad22841..8126267 100644 --- a/lib/background_fetch.dart +++ b/lib/background_fetch.dart @@ -92,14 +92,14 @@ Future backgroundFetchTimetable() async { 'Neuer Vertretungsplan für heute geladen!', subtitle, platformChannelSpecificsTodayPlan, - payload: 'item x'); + payload: 'today'); if ((jsonDecode(todayResponse.body)["info"] as String).isNotEmpty) { await flutterLocalNotificationsPlugin.show( 1, 'Informationen für heute', (jsonDecode(todayResponse.body)["info"] as String), platformChannelSpecificsTodayInfo, - payload: 'item x'); + payload: 'today'); } prefs.setString("todayTimetable", todayResponse.body); } @@ -162,14 +162,14 @@ Future backgroundFetchTimetable() async { 'Neuer Vertretungsplan für morgen geladen!', subtitle, platformChannelSpecificsTomorrowPlan, - payload: 'item x'); + payload: 'tomorrow'); if ((jsonDecode(tomorrowResponse.body)["info"] as String).isNotEmpty) { await flutterLocalNotificationsPlugin.show( 3, 'Informationen für morgen', (jsonDecode(tomorrowResponse.body)["info"] as String), platformChannelSpecificsTomorrowInfo, - payload: 'item x'); + payload: 'tomorrow'); } prefs.setString("tomorrowTimetable", tomorrowResponse.body); } @@ -224,7 +224,7 @@ Future backgroundFetchArticles() async { 'Neuer Inhalt von der Schülerzeitung verfügbar!', subtitle, platformChannelSpecificsSZ, - payload: 'item x'); + payload: 'sz'); prefs.setString("articles", fetchedArticles.body); } } @@ -267,7 +267,7 @@ Future backgroundFetchArticles() async { 'Neue Informationen verfügbar!', subtitle, platformChannelSpecificsNews, - payload: 'item x'); + payload: 'articles'); prefs.setString("news", fetchedNews.body); } } diff --git a/lib/cache_manager.dart b/lib/cache_manager.dart index 72459f7..7bed663 100644 --- a/lib/cache_manager.dart +++ b/lib/cache_manager.dart @@ -18,6 +18,7 @@ import 'dart:convert'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; Future getCachedTimetable(String ext, String? presetClassNum) async { SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -31,8 +32,23 @@ Future getCachedTimetable(String ext, String? presetClassNum) async { } var apiKey = prefs.getString('api_key'); var headers = {"x-api-key": "$apiKey"}; - var file = await DefaultCacheManager().getSingleFile( - "https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum", - headers: headers); - return (utf8.decode(await file.readAsBytes())); + + var uri = + Uri.https("mein.cantorgymnasium.de", "/api/timetable/$ext/$classNum"); + final response = + await http.get(uri, headers: headers).onError((error, stackTrace) { + return http.Response("", 404); + }); + + if (response.statusCode == 404) { + var file = await DefaultCacheManager().getSingleFile( + "https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum", + headers: headers); + return (utf8.decode(await file.readAsBytes())); + } else { + DefaultCacheManager().putFile( + "https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum", + response.bodyBytes); + return (utf8.decode(response.bodyBytes)); + } } diff --git a/lib/dashboard.dart b/lib/dashboard.dart index 89abb68..5d24d3d 100644 --- a/lib/dashboard.dart +++ b/lib/dashboard.dart @@ -18,6 +18,7 @@ import 'dart:convert'; import 'dart:math'; import 'package:background_fetch/background_fetch.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:meincantor/background_fetch.dart'; import 'package:meincantor/const.dart'; import 'package:meincantor/schuelerzeitung.dart'; @@ -267,6 +268,66 @@ class _DashboardState extends State with RestorationMixin { void initState() { super.initState(); initPlatformState(); + initNotifications(); + } + + Future initNotifications() async { + FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('app_icon'); + const DarwinInitializationSettings initializationSettingsDarwin = + DarwinInitializationSettings(); + const InitializationSettings initializationSettings = + InitializationSettings( + android: initializationSettingsAndroid, + iOS: initializationSettingsDarwin, + macOS: initializationSettingsDarwin); + await flutterLocalNotificationsPlugin.initialize(initializationSettings, + onSelectNotification: selectNotification); + } + + void selectNotification(String? payload) async { + if (payload == null) { + debugPrint('notification payload: $payload'); + } else if (payload == "today") { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => Scaffold( + appBar: AppBar(title: const Text("Vertretungsplan für heute")), + body: buildTimetable( + fetchClassTimetable( + "/${DateFormat("yyyyMMdd").format(DateTime.now())}", + null), + "Vertretungsplan für heute"))), + ); + } else if (payload == "tomorrow") { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => Scaffold( + appBar: AppBar(title: const Text("Vertretungsplan für morgen")), + body: buildTimetable( + fetchClassTimetable( + "/${DateFormat("yyyyMMdd").format(DateTime.now().add(const Duration(days: 1)))}", + null), + "Vertretungsplan für morgen"))), + ); + } else if (payload == "sz") { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const SZ()), + ); + } else if (payload == "articles") { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const News()), + ); + } } Future initPlatformState() async { diff --git a/lib/login.dart b/lib/login.dart index 0b18fb3..527cb83 100644 --- a/lib/login.dart +++ b/lib/login.dart @@ -22,6 +22,9 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart import 'package:shared_preferences/shared_preferences.dart'; import 'package:meincantor/networking.dart'; import 'package:meincantor/dashboard.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'main.dart'; Future checkKey() async { SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -169,7 +172,22 @@ class Login extends StatelessWidget { }); } }, - child: const Text("Anmelden")) + child: const Text("Anmelden")), + const Divider(), + ListTile( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15.0)), + title: const Text( + "Passwort vergessen?", + //style: TextStyle(color: Palette.accent) + ), + subtitle: const Text( + "Jetzt das Passwort zurücksetzen", + //style: TextStyle(color: Palette.accent) + ), + onTap: () => launch( + "https://mein.cantorgymnasium.de/auth/realms/GCG.MeinCantor/login-actions/reset-credentials"), + ) ], ), ))))); diff --git a/lib/main.dart b/lib/main.dart index bd27791..d8be48d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,7 +15,7 @@ // along with this program. If not, see . import 'package:flutter/material.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:meincantor/background_fetch.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:meincantor/dashboard.dart'; import 'package:meincantor/login.dart'; @@ -33,24 +33,16 @@ void backgroundFetchHeadlessTask(HeadlessTask task) async { return; } print('[BackgroundFetch] Headless event received.'); - // Do your work here... + + await backgroundFetchTimetable(); + await backgroundFetchArticles(); + BackgroundFetch.finish(taskId); } void main() async { runApp(const App()); - FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project - const AndroidInitializationSettings initializationSettingsAndroid = - AndroidInitializationSettings('app_icon'); - const DarwinInitializationSettings initializationSettingsDarwin = - DarwinInitializationSettings(); - const InitializationSettings initializationSettings = InitializationSettings( - android: initializationSettingsAndroid, - iOS: initializationSettingsDarwin, - macOS: initializationSettingsDarwin); - await flutterLocalNotificationsPlugin.initialize(initializationSettings); + BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); } diff --git a/pubspec.yaml b/pubspec.yaml index 9ae3356..4c82e4d 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.0.1 +version: 1.1.0 environment: sdk: ">=2.12.0 <3.0.0"