This repository has been archived on 2023-06-24. You can view files and clone it, but cannot push or open issues or pull requests.
meincantor-app/lib/networking.dart

359 lines
13 KiB
Dart
Raw Permalink Normal View History

2022-01-16 15:28:42 +01:00
// GCG.MeinCantor - Die Schulplattform für Cantorianer.
// Copyright (C) 2021-2022 Georg-Cantor-Gymnasium Halle (Saale)
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:convert';
import 'dart:io';
import 'package:meincantor/cache_manager.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:meincantor/const.dart';
import 'package:meincantor/timetable.dart';
import 'package:meincantor/login.dart';
import 'package:meincantor/main.dart';
Future<http.Response> getArticles() async {
var uri = Uri.https(szUrl["url"]! as String, "/api/articles");
final response =
await http.get(uri, headers: szUrl["headers"]! as Map<String, String>);
return (response);
}
Future<http.Response> getNews() async {
var uri = Uri.https(szUrl["url"]! as String, "/api/aktuelles");
final response =
await http.get(uri, headers: szUrl["headers"]! as Map<String, String>);
return (response);
}
Future<http.Response> getToken(
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");
String body =
'{"user":"$user", "password": "$password", "otp": "$otp", "devid": "$devId"}';
final response = await http.post(uri, body: body);
return (response);
}
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");
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');
}
}
Future<http.Response> fetchClassTimetable(String ext, String? classNum) async {
try {
return (http.Response(await getCachedTimetable(ext, classNum), 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);
}
}
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"};
final response =
await http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
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) {
return FutureBuilder<http.Response>(
2021-11-19 20:12:42 +01:00
future: future,
builder: (context, snapshot) {
if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) {
Widget timetableView = ClassTimetableBuilder.buildView(
jsonDecode(snapshot.data!.body), context)
.view
.child;
return timetableView;
} else if (statusCode == 400) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Login()));
} else if (statusCode == 500) {
var chars = Runes('Es konnte kein $info gefunden werden. \u{1F937}');
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,
));
return Padding(
2021-11-19 20:12:42 +01:00
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
child: ListView(
children: [card],
));
} else if (statusCode == 404) {
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}');
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,
));
return Padding(
2021-11-19 20:12:42 +01:00
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
child: ListView(
children: [card],
));
}
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>(
future: fetchClassTimetable(
"/${DateFormat("yyyyMMdd").format(DateTime.now())}", null),
builder: (context, snapshot) {
if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) {
List<Widget> lessons = LessonsListBuilder.buildList(
jsonDecode(snapshot.data!.body),
count: count)
.lessons;
if (lessons.isNotEmpty) {
return Column(children: lessons);
} else {
var chars = Runes(
'Keine Stunden mehr gefunden. Sieht so aus als hättest du Schluss für heute \u{1F389}');
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,
));
return Column(children: [card]);
}
} else if (statusCode == 400) {
Future.delayed(Duration.zero, () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Login()),
);
});
} else if (statusCode == 500) {
var chars = Runes(
'Es konnte kein Vertretungsplan für heute gefunden werden. \u{1F937}');
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,
));
return card;
} 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,
));
return Column(
children: [card],
);
}
return Center(child: Text('Error $statusCode'));
} else if (snapshot.hasError) {
return Text('$snapshot.error');
} else {
return const Center(child: CircularProgressIndicator());
}
},
);
}
Future<http.Response> fetchClassesList() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var apiKey = prefs.getString('api_key');
var uri = Uri.https("mein.cantorgymnasium.de", "/api/classes");
var headers = {"x-api-key": "$apiKey"};
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
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);
} 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),
child: Center(
child: Text(
"Serverfehler. Bitte wende dich an den MeinCantor-Support.")),
);
} else if (statusCode == 404) {
return const Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
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")),
);
}
return Text('$statusCode');
} else if (snapshot.hasError) {
return Text('$snapshot.error');
} else {
return const Center(child: CircularProgressIndicator());
}
},
);
}
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;
String? dropdownValue;
_ClassesChooserState(this.items);
@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
});
}
@override
Widget build(BuildContext context) {
return DropdownButtonFormField<String>(
value: dropdownValue,
decoration: const InputDecoration(
icon: Icon(Icons.people_outline),
border: OutlineInputBorder(),
labelText: 'Klasse (05/1, 07/3, 10/2...)',
),
onChanged: (String? newValue) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String classNum = newValue!;
prefs.setString('class_num', classNum);
prefs.remove("lessons");
prefs.remove("todayTImetable");
prefs.remove("tomorrowTimetable");
setState(() {
dropdownValue = newValue;
});
},
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}