2021-08-27 19:24:30 +02:00
import ' dart:convert ' ;
2021-12-13 13:39:06 +01:00
import ' dart:io ' ;
2021-08-27 19:24:30 +02:00
2021-12-13 13:39:06 +01:00
import ' package:flutter_local_notifications/flutter_local_notifications.dart ' ;
import ' package:meincantor/cache_manager.dart ' ;
2021-08-27 19:24:30 +02:00
import ' package:flutter/cupertino.dart ' ;
2021-11-06 11:01:44 +01:00
import ' package:flutter/painting.dart ' ;
2021-12-13 13:39:06 +01:00
import ' package:flutter_cache_manager/flutter_cache_manager.dart ' ;
2021-08-27 19:24:30 +02:00
import ' package:http/http.dart ' as http ;
import ' package:flutter/material.dart ' ;
2021-12-13 13:39:06 +01:00
import ' package:intl/intl.dart ' ;
2021-08-27 19:24:30 +02:00
import ' package:shared_preferences/shared_preferences.dart ' ;
2021-12-13 13:39:06 +01:00
import ' package:meincantor/const.dart ' ;
import ' package:meincantor/timetable.dart ' ;
import ' package:meincantor/login.dart ' ;
import ' package:meincantor/main.dart ' ;
2021-11-16 19:41:35 +01:00
Future < http . Response > getArticles ( ) async {
2021-12-13 13:39:06 +01:00
var uri = Uri . https ( szUrl [ " url " ] ! , " /articles " ) ;
final response = await http . get ( uri ) ;
return ( response ) ;
}
Future < http . Response > getNews ( ) async {
var uri = Uri . https ( szUrl [ " url " ] ! , " /aktuelles " ) ;
final response = await http . get ( uri ) ;
return ( response ) ;
2021-11-16 19:41:35 +01:00
}
2021-08-27 19:24:30 +02:00
2021-09-14 20:55:58 +02:00
Future < http . Response > getToken (
2021-08-27 19:24:30 +02:00
String user , String password , String otp , String devId ) async {
2021-08-31 17:49:57 +02:00
var uri = Uri . https ( " mein.cantorgymnasium.de " , " /login " ) ;
2021-08-27 19:24:30 +02:00
String body =
' {"user":" $ user ", "password": " $ password ", "otp": " $ otp ", "devid": " $ devId "} ' ;
final response = await http . post ( uri , body: body ) ;
2021-09-14 20:55:58 +02:00
return ( response ) ;
2021-08-27 19:24:30 +02:00
}
Future < String > getUserInfo (
String user , String password , String otp , String devId ) async {
2021-08-31 17:49:57 +02:00
var uri = Uri . https ( " mein.cantorgymnasium.de " , " /api/userinfo " ) ;
2021-08-27 19:24:30 +02:00
String body =
' {"user":" $ user ", "password": " $ password ", "otp": " $ otp ", "devid": " $ devId "} ' ;
final response = await http . post ( uri , body: body ) ;
if ( response . statusCode = = 200 ) {
return utf8 . decode ( response . bodyBytes ) ;
} else {
throw Exception ( ' Failed to log in ' ) ;
}
}
2021-11-19 20:12:42 +01:00
Future < http . Response > fetchClassTimetable ( String ext ) async {
2021-12-13 13:39:06 +01:00
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin ( ) ;
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails ( ' de.cantorgymnasium.meincantor ' , ' GCG.MeinCantor ' ,
channelDescription: ' ' ,
importance: Importance . max ,
priority: Priority . high ,
ticker: ' ticker ' ) ;
const NotificationDetails platformChannelSpecifics =
NotificationDetails ( android: androidPlatformChannelSpecifics ) ;
await flutterLocalNotificationsPlugin . show (
0 , ' Neuer Vertretungsplan geladen! ' , ' Du hast folgende Vertretungen: \n St. 8 Deutsch Frau Rinke, Raum 203 \n St. 4 Biologie Frau Borchert, Raum 107 ' , platformChannelSpecifics ,
payload: ' item x ' ) ;
try {
return ( http . Response ( await getCachedTimetable ( ext ) , 200 ) ) ;
} on HttpExceptionWithStatus catch ( e ) {
return http . Response ( e . message , e . statusCode ) ;
} on HttpException catch ( e ) {
return http . Response ( e . message , 500 ) ;
} on SocketException catch ( e ) {
return http . Response ( e . message , 404 ) ;
2021-08-27 19:24:30 +02:00
}
2021-12-13 13:39:06 +01:00
/ * SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
2021-09-14 20:55:58 +02:00
String classNum ;
if ( prefs . getString ( ' class_num ' ) ! = null ) {
classNum = prefs . getString ( ' class_num ' ) ! . replaceAll ( " / " , " _ " ) ;
} else {
classNum = ' 05_1 ' ;
}
var apiKey = prefs . getString ( ' api_key ' ) ;
2021-12-13 13:39:06 +01:00
var uri = Uri . https ( " mein.cantorgymnasium.de " , " /api/timetable/ $ classNum $ ext " ) ;
2021-09-14 20:55:58 +02:00
var headers = { " x-api-key " : " $ apiKey " } ;
2021-11-16 19:41:35 +01:00
final response = http . get ( uri , headers: headers ) . onError ( ( error , stackTrace ) {
return ( http . Response ( " " , 404 ) ) ;
} ) ;
2021-12-13 13:39:06 +01:00
return response ; * /
2021-08-27 19:24:30 +02:00
}
2021-11-06 11:01:44 +01:00
fetchLessonList ( ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
String classNum ;
if ( prefs . getString ( ' class_num ' ) ! = null ) {
classNum = prefs . getString ( ' class_num ' ) ! . replaceAll ( " / " , " _ " ) ;
} else {
classNum = ' 05_1 ' ;
}
var apiKey = prefs . getString ( ' api_key ' ) ;
var uri = Uri . https ( " mein.cantorgymnasium.de " , " /api/lessons/ $ classNum " ) ;
var headers = { " x-api-key " : " $ apiKey " } ;
2021-11-16 19:41:35 +01:00
final response =
await http . get ( uri , headers: headers ) . onError ( ( error , stackTrace ) {
return ( http . Response ( " " , 404 ) ) ;
} ) ;
2021-11-06 11:01:44 +01:00
if ( response . statusCode = = 200 ) {
prefs . setString ( " lessons " , utf8 . decode ( response . bodyBytes ) ) ;
} else {
prefs . setString ( " lessons " , jsonEncode ( [ ] ) ) ;
}
}
2021-11-19 20:12:42 +01:00
Widget buildTimetable ( Future < http . Response > future , String info ) {
2021-09-14 20:55:58 +02:00
return FutureBuilder < http . Response > (
2021-11-19 20:12:42 +01:00
future: future ,
2021-09-14 20:55:58 +02:00
builder: ( context , snapshot ) {
if ( snapshot . hasData ) {
int statusCode = snapshot . data ! . statusCode ;
if ( statusCode = = 200 ) {
2021-11-06 11:01:44 +01:00
Widget timetableView = ClassTimetableBuilder . buildView (
2021-12-13 13:39:06 +01:00
jsonDecode ( snapshot . data ! . body ) , context )
2021-11-16 19:41:35 +01:00
. view
. child ;
2021-09-14 20:55:58 +02:00
return timetableView ;
} else if ( statusCode = = 400 ) {
Navigator . push (
context , MaterialPageRoute ( builder: ( context ) = > Login ( ) ) ) ;
} else if ( statusCode = = 500 ) {
2021-12-13 13:39:06 +01:00
var chars = Runes ( ' Es konnte kein $ info gefunden werden. \u{1F937} ' ) ;
2021-11-06 11:01:44 +01:00
List < Widget > cardChildren = [ ] ;
cardChildren . add ( ListTile (
2021-11-16 19:41:35 +01:00
title: Text ( String . fromCharCodes ( chars ) ,
style: const TextStyle ( color: Palette . primary ) ) ,
) ) ;
2021-11-06 11:01:44 +01:00
Card card = Card (
shape: RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 15.0 ) ,
) ,
color: Colors . white ,
child: Column (
children: cardChildren ,
) ) ;
return Padding (
2021-11-19 20:12:42 +01:00
padding: const EdgeInsets . fromLTRB ( 20 , 20 , 20 , 20 ) ,
2021-11-06 11:01:44 +01:00
child: ListView (
children: [ card ] ,
2021-11-16 19:41:35 +01:00
) ) ;
2021-11-06 11:01:44 +01:00
} else if ( statusCode = = 404 ) {
2021-11-16 19:41:35 +01:00
var chars = Runes (
2021-11-19 20:12:42 +01:00
' Keine Verbindung mit dem MeinCantor-Server möglich. Bitte prüfe deine Internet-Verbindung und deine DNS-Einstellungen oder wende dich an den MeinCantor-Support. \u{1F4e1} ' ) ;
2021-11-06 11:01:44 +01:00
List < Widget > cardChildren = [ ] ;
cardChildren . add ( ListTile (
title: Text ( String . fromCharCodes ( chars ) ,
style: const TextStyle ( color: Palette . primary ) ) ,
2021-11-16 19:41:35 +01:00
) ) ;
2021-11-06 11:01:44 +01:00
Card card = Card (
shape: RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 15.0 ) ,
) ,
color: Colors . white ,
child: Column (
children: cardChildren ,
) ) ;
return Padding (
2021-11-19 20:12:42 +01:00
padding: const EdgeInsets . fromLTRB ( 20 , 20 , 20 , 20 ) ,
2021-11-06 11:01:44 +01:00
child: ListView (
children: [ card ] ,
2021-12-13 13:39:06 +01:00
) ) ;
2021-09-14 20:55:58 +02:00
}
return Center ( child: Text ( ' Error $ statusCode ' ) ) ;
} else if ( snapshot . hasError ) {
return Text ( ' $ snapshot .error ' ) ;
} else {
return const Center ( child: CircularProgressIndicator ( ) ) ;
}
} ,
) ;
}
Widget buildTodayClassTimetableLesson ( int count ) {
return FutureBuilder < http . Response > (
2021-12-13 13:39:06 +01:00
future: fetchClassTimetable (
" / ${ DateFormat ( " yyyyMMdd " ) . format ( DateTime . now ( ) ) } " ) ,
2021-09-14 20:55:58 +02:00
builder: ( context , snapshot ) {
if ( snapshot . hasData ) {
int statusCode = snapshot . data ! . statusCode ;
if ( statusCode = = 200 ) {
List < Widget > lessons = LessonsListBuilder . buildList (
2021-12-13 13:39:06 +01:00
jsonDecode ( snapshot . data ! . body ) ,
2021-11-16 19:41:35 +01:00
count: count )
2021-09-14 20:55:58 +02:00
. lessons ;
if ( lessons . isNotEmpty ) {
return Column ( children: lessons ) ;
} else {
2021-11-16 19:41:35 +01:00
var chars = Runes (
' Keine Stunden mehr gefunden. Sieht so aus als hättest du Schluss für heute \u{1F389} ' ) ;
2021-09-14 20:55:58 +02:00
List < Widget > cardChildren = [ ] ;
cardChildren . add ( ListTile (
title: Text ( String . fromCharCodes ( chars ) ,
2021-11-16 19:41:35 +01:00
style: const TextStyle ( color: Palette . primary ) ) ) ) ;
2021-09-14 20:55:58 +02:00
Card card = Card (
shape: RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 15.0 ) ,
) ,
color: Colors . white ,
child: Column (
children: cardChildren ,
) ) ;
2021-12-13 13:39:06 +01:00
return Column ( children: [ card ] ) ;
2021-09-14 20:55:58 +02:00
}
} else if ( statusCode = = 400 ) {
2021-11-06 11:01:44 +01:00
Future . delayed ( Duration . zero , ( ) {
Navigator . push (
context ,
2021-11-16 19:41:35 +01:00
MaterialPageRoute ( builder: ( context ) = > Login ( ) ) ,
2021-11-06 11:01:44 +01:00
) ;
} ) ;
2021-09-14 20:55:58 +02:00
} else if ( statusCode = = 500 ) {
2021-11-16 19:41:35 +01:00
var chars = Runes (
' Es konnte kein Vertretungsplan für heute gefunden werden. \u{1F937} ' ) ;
2021-11-06 11:01:44 +01:00
List < Widget > cardChildren = [ ] ;
cardChildren . add ( ListTile (
title: Text ( String . fromCharCodes ( chars ) ,
2021-11-16 19:41:35 +01:00
style: const TextStyle ( color: Palette . primary ) ) ) ) ;
2021-11-06 11:01:44 +01:00
Card card = Card (
shape: RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 15.0 ) ,
) ,
color: Colors . white ,
child: Column (
children: cardChildren ,
) ) ;
return card ;
2021-09-14 20:55:58 +02:00
} else if ( statusCode = = 404 ) {
2021-11-19 20:12:42 +01:00
var chars = Runes (
' Keine Verbindung mit dem MeinCantor-Server möglich. Bitte prüfe deine Internet-Verbindung und deine DNS-Einstellungen oder wende dich an den MeinCantor-Support. \u{1F4e1} ' ) ;
List < Widget > cardChildren = [ ] ;
cardChildren . add ( ListTile (
title: Text ( String . fromCharCodes ( chars ) ,
style: const TextStyle ( color: Palette . primary ) ) ,
) ) ;
Card card = Card (
shape: RoundedRectangleBorder (
borderRadius: BorderRadius . circular ( 15.0 ) ,
) ,
color: Colors . white ,
child: Column (
children: cardChildren ,
) ) ;
2021-12-13 13:39:06 +01:00
return Column (
children: [ card ] ,
2021-09-14 20:55:58 +02:00
) ;
}
return Center ( child: Text ( ' Error $ statusCode ' ) ) ;
} else if ( snapshot . hasError ) {
return Text ( ' $ snapshot .error ' ) ;
} else {
return const Center ( child: CircularProgressIndicator ( ) ) ;
2021-08-27 19:24:30 +02:00
}
} ,
) ;
}
Future < http . Response > fetchClassesList ( ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
2021-09-14 20:55:58 +02:00
var apiKey = prefs . getString ( ' api_key ' ) ;
2021-08-27 19:24:30 +02:00
var uri = Uri . https ( " mein.cantorgymnasium.de " , " /api/classes " ) ;
2021-09-14 20:55:58 +02:00
var headers = { " x-api-key " : " $ apiKey " } ;
2021-11-16 19:41:35 +01:00
final response = http . get ( uri , headers: headers ) . onError ( ( error , stackTrace ) {
return ( http . Response ( " " , 404 ) ) ;
} ) ;
2021-08-27 19:24:30 +02:00
return response ;
}
Widget buildClassesChooser ( ) {
return FutureBuilder < http . Response > (
future: fetchClassesList ( ) ,
builder: ( context , snapshot ) {
if ( snapshot . hasData ) {
int statusCode = snapshot . data ! . statusCode ;
if ( statusCode = = 200 ) {
List < String > items = [ ] ;
jsonDecode ( utf8 . decode ( snapshot . data ! . bodyBytes ) ) . forEach ( ( value ) {
items . add ( value . . toString ( ) ) ;
} ) ;
return ClassesChooser ( items: items ) ;
2021-09-14 20:55:58 +02:00
} else if ( statusCode = = 400 ) {
Navigator . push (
context , MaterialPageRoute ( builder: ( context ) = > Login ( ) ) ) ;
} else if ( statusCode = = 500 ) {
return const Padding (
padding: EdgeInsets . fromLTRB ( 10 , 10 , 10 , 10 ) ,
2021-11-16 19:41:35 +01:00
child: Center (
child: Text (
" Serverfehler. Bitte wende dich an den MeinCantor-Support. " ) ) ,
2021-09-14 20:55:58 +02:00
) ;
} else if ( statusCode = = 404 ) {
return const Padding (
padding: EdgeInsets . fromLTRB ( 10 , 10 , 10 , 10 ) ,
2021-11-16 19:41:35 +01:00
child: Center (
child: Text (
" Keine Verbindung mit dem MeinCantor-Server möglich. Bitte prüfe deine Internetverbindung und deine DNS-Einstellungen oder wende dich an den MeinCantor-Support " ) ) ,
2021-09-14 20:55:58 +02:00
) ;
2021-08-27 19:24:30 +02:00
}
return Text ( ' $ statusCode ' ) ;
} else if ( snapshot . hasError ) {
return Text ( ' $ snapshot .error ' ) ;
} else {
2021-09-14 20:55:58 +02:00
return const Center ( child: CircularProgressIndicator ( ) ) ;
2021-08-27 19:24:30 +02:00
}
} ,
) ;
}
class ClassesChooser extends StatefulWidget {
final List < String > items ;
const ClassesChooser ( { Key ? key , required this . items } ) : super ( key: key ) ;
@ override
State < ClassesChooser > createState ( ) = > _ClassesChooserState ( items ) ;
}
class _ClassesChooserState extends State < ClassesChooser > {
final List < String > items ;
//final String dropdownValue;
2021-09-14 20:55:58 +02:00
String ? dropdownValue ;
2021-08-27 19:24:30 +02:00
_ClassesChooserState ( this . items ) ;
2021-09-14 20:55:58 +02:00
@ override
void initState ( ) {
super . initState ( ) ;
_read ( ) ; // read in initState
}
_read ( ) async {
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
setState ( ( ) {
dropdownValue = prefs . getString ( " class_num " ) ; // get the value
} ) ;
}
2021-08-27 19:24:30 +02:00
@ override
Widget build ( BuildContext context ) {
return DropdownButtonFormField < String > (
2021-09-14 20:55:58 +02:00
value: dropdownValue ,
decoration: const InputDecoration (
2021-11-06 11:01:44 +01:00
icon: Icon ( Icons . people_outline ) ,
2021-08-27 19:24:30 +02:00
border: OutlineInputBorder ( ) ,
2021-09-14 20:55:58 +02:00
labelText: ' Klasse (05/1, 07/3, 10/2...) ' ,
2021-08-27 19:24:30 +02:00
) ,
onChanged: ( String ? newValue ) {
setState ( ( ) async {
dropdownValue = newValue ! ;
SharedPreferences prefs = await SharedPreferences . getInstance ( ) ;
2021-09-14 20:55:58 +02:00
String classNum = newValue ;
await prefs . setString ( ' class_num ' , classNum ) ;
2021-08-27 19:24:30 +02:00
} ) ;
} ,
items: items . map < DropdownMenuItem < String > > ( ( String value ) {
return DropdownMenuItem < String > (
value: value ,
child: Text ( value ) ,
) ;
} ) . toList ( ) ,
) ;
}
}