===1.1.0===

- fixed caching issues
- added action on notification tap
- fixed background fetch
- added reset password
This commit is contained in:
Denys Konovalov 2022-01-19 19:30:09 +01:00
parent 225db95b66
commit 819b25c7eb
6 changed files with 113 additions and 26 deletions

@ -92,14 +92,14 @@ Future<void> backgroundFetchTimetable() async {
'Neuer Vertretungsplan für heute geladen!', 'Neuer Vertretungsplan für heute geladen!',
subtitle, subtitle,
platformChannelSpecificsTodayPlan, platformChannelSpecificsTodayPlan,
payload: 'item x'); payload: 'today');
if ((jsonDecode(todayResponse.body)["info"] as String).isNotEmpty) { if ((jsonDecode(todayResponse.body)["info"] as String).isNotEmpty) {
await flutterLocalNotificationsPlugin.show( await flutterLocalNotificationsPlugin.show(
1, 1,
'Informationen für heute', 'Informationen für heute',
(jsonDecode(todayResponse.body)["info"] as String), (jsonDecode(todayResponse.body)["info"] as String),
platformChannelSpecificsTodayInfo, platformChannelSpecificsTodayInfo,
payload: 'item x'); payload: 'today');
} }
prefs.setString("todayTimetable", todayResponse.body); prefs.setString("todayTimetable", todayResponse.body);
} }
@ -162,14 +162,14 @@ Future<void> backgroundFetchTimetable() async {
'Neuer Vertretungsplan für morgen geladen!', 'Neuer Vertretungsplan für morgen geladen!',
subtitle, subtitle,
platformChannelSpecificsTomorrowPlan, platformChannelSpecificsTomorrowPlan,
payload: 'item x'); payload: 'tomorrow');
if ((jsonDecode(tomorrowResponse.body)["info"] as String).isNotEmpty) { if ((jsonDecode(tomorrowResponse.body)["info"] as String).isNotEmpty) {
await flutterLocalNotificationsPlugin.show( await flutterLocalNotificationsPlugin.show(
3, 3,
'Informationen für morgen', 'Informationen für morgen',
(jsonDecode(tomorrowResponse.body)["info"] as String), (jsonDecode(tomorrowResponse.body)["info"] as String),
platformChannelSpecificsTomorrowInfo, platformChannelSpecificsTomorrowInfo,
payload: 'item x'); payload: 'tomorrow');
} }
prefs.setString("tomorrowTimetable", tomorrowResponse.body); prefs.setString("tomorrowTimetable", tomorrowResponse.body);
} }
@ -224,7 +224,7 @@ Future<void> backgroundFetchArticles() async {
'Neuer Inhalt von der Schülerzeitung verfügbar!', 'Neuer Inhalt von der Schülerzeitung verfügbar!',
subtitle, subtitle,
platformChannelSpecificsSZ, platformChannelSpecificsSZ,
payload: 'item x'); payload: 'sz');
prefs.setString("articles", fetchedArticles.body); prefs.setString("articles", fetchedArticles.body);
} }
} }
@ -267,7 +267,7 @@ Future<void> backgroundFetchArticles() async {
'Neue Informationen verfügbar!', 'Neue Informationen verfügbar!',
subtitle, subtitle,
platformChannelSpecificsNews, platformChannelSpecificsNews,
payload: 'item x'); payload: 'articles');
prefs.setString("news", fetchedNews.body); prefs.setString("news", fetchedNews.body);
} }
} }

@ -18,6 +18,7 @@ import 'dart:convert';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
Future<String> getCachedTimetable(String ext, String? presetClassNum) async { Future<String> getCachedTimetable(String ext, String? presetClassNum) async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -31,8 +32,23 @@ Future<String> getCachedTimetable(String ext, String? presetClassNum) async {
} }
var apiKey = prefs.getString('api_key'); var apiKey = prefs.getString('api_key');
var headers = {"x-api-key": "$apiKey"}; var headers = {"x-api-key": "$apiKey"};
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( var file = await DefaultCacheManager().getSingleFile(
"https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum", "https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum",
headers: headers); headers: headers);
return (utf8.decode(await file.readAsBytes())); return (utf8.decode(await file.readAsBytes()));
} else {
DefaultCacheManager().putFile(
"https://mein.cantorgymnasium.de/api/timetable/$ext/$classNum",
response.bodyBytes);
return (utf8.decode(response.bodyBytes));
}
} }

@ -18,6 +18,7 @@ import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:background_fetch/background_fetch.dart'; 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/background_fetch.dart';
import 'package:meincantor/const.dart'; import 'package:meincantor/const.dart';
import 'package:meincantor/schuelerzeitung.dart'; import 'package:meincantor/schuelerzeitung.dart';
@ -267,6 +268,66 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
void initState() { void initState() {
super.initState(); super.initState();
initPlatformState(); initPlatformState();
initNotifications();
}
Future<void> 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<void>(
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<void>(
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<void>(
builder: (context) => const SZ()),
);
} else if (payload == "articles") {
await Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const News()),
);
}
} }
Future<void> initPlatformState() async { Future<void> initPlatformState() async {

@ -22,6 +22,9 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:meincantor/networking.dart'; import 'package:meincantor/networking.dart';
import 'package:meincantor/dashboard.dart'; import 'package:meincantor/dashboard.dart';
import 'package:url_launcher/url_launcher.dart';
import 'main.dart';
Future<bool> checkKey() async { Future<bool> checkKey() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); 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"),
)
], ],
), ),
))))); )))));

@ -15,7 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart'; 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:shared_preferences/shared_preferences.dart';
import 'package:meincantor/dashboard.dart'; import 'package:meincantor/dashboard.dart';
import 'package:meincantor/login.dart'; import 'package:meincantor/login.dart';
@ -33,24 +33,16 @@ void backgroundFetchHeadlessTask(HeadlessTask task) async {
return; return;
} }
print('[BackgroundFetch] Headless event received.'); print('[BackgroundFetch] Headless event received.');
// Do your work here...
await backgroundFetchTimetable();
await backgroundFetchArticles();
BackgroundFetch.finish(taskId); BackgroundFetch.finish(taskId);
} }
void main() async { void main() async {
runApp(const App()); 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); BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
} }

@ -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. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.1 version: 1.1.0
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"