==0.7.5-nightly 2021-11-16==

- added strapi connector
- cleanup code
- updated readme

- TODO:
  - update license & copyright info
  - cleanup code
  - merge code parts to server side
  - complete settings
  - fix 11/12
  - add caching
  - muuuuuuuch more...
This commit is contained in:
Denys Konovalov 2021-11-16 19:41:35 +01:00
parent 11b8435734
commit 223414559e
20 changed files with 614 additions and 734 deletions

@ -4,8 +4,6 @@ import 'package:flutter/material.dart';
class AppearanceSettings extends StatelessWidget {
const AppearanceSettings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
@ -15,9 +13,7 @@ class AppearanceSettings extends StatelessWidget {
),
body: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [
],
children: [],
));
}
}

@ -31,12 +31,12 @@ class DevSettings extends StatelessWidget {
String apiKey = value;
await prefs.setString('api_key', apiKey);
final snackBar = SnackBar(
content: Text('Neuer API-Schlüssel gesetzt: $apiKey'));
content:
Text('Neuer API-Schlüssel gesetzt: $apiKey'));
// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
})),
const Divider(),
Padding(
@ -49,8 +49,7 @@ class DevSettings extends StatelessWidget {
);
},
child: const Text("Benutzerdaten neu laden"),
)
)
))
],
));
}

@ -5,8 +5,6 @@ import 'package:MeinCantor/const.dart';
class InfoSettings extends StatelessWidget {
const InfoSettings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
@ -20,8 +18,7 @@ class InfoSettings extends StatelessWidget {
const ListTile(
leading: Icon(Icons.info_outlined),
title: Text("Version"),
subtitle: Text(version)
),
subtitle: Text(version)),
ListTile(
leading: const Icon(Icons.settings_backup_restore_outlined),
title: const Text("Änderungsverlauf"),
@ -61,9 +58,12 @@ class InfoSettings extends StatelessWidget {
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LicensePage(
applicationIcon: Image.asset("assets/images/meincantor_r.png",
height: 64, width: 64),
MaterialPageRoute(
builder: (context) => LicensePage(
applicationIcon: Image.asset(
"assets/images/meincantor_r.png",
height: 64,
width: 64),
applicationVersion: version,
)),
);

@ -8,10 +8,10 @@ import 'package:cyclop/cyclop.dart';
import 'package:MeinCantor/networking.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../color_presets.dart';
import 'package:MeinCantor/subject_presets.dart';
import 'package:MeinCantor/presets/colors.dart';
import 'package:MeinCantor/presets/subjects.dart';
import '../../teacher_presets.dart';
import 'package:MeinCantor/presets/teachers.dart';
class PlanSettings extends StatefulWidget {
const PlanSettings({Key? key}) : super(key: key);
@ -39,7 +39,12 @@ Future<List<dynamic>> buildLessonsList() async {
}
class _PlanSettingsState extends State<PlanSettings> {
Set<Color> swatches = {...Colors.primaries, ...Colors.accents, Palette.accent, Palette.primary};
Set<Color> swatches = {
...Colors.primaries,
...Colors.accents,
Palette.accent,
Palette.primary
};
@override
Widget build(BuildContext context) {
@ -63,7 +68,8 @@ class _PlanSettingsState extends State<PlanSettings> {
for (var element in (snapshot.data as List<dynamic>)) {
String subject = element['subject'];
String teacher = element['teacher'];
children.add(FutureBuilder(
children.add(
FutureBuilder(
future: buildPlanColors(subject),
builder: (context, snapshot) {
if (snapshot.hasData) {
@ -83,31 +89,28 @@ class _PlanSettingsState extends State<PlanSettings> {
setState(() {
color = value;
});
SharedPreferences prefs = await SharedPreferences
SharedPreferences prefs =
await SharedPreferences
.getInstance();
prefs.setInt(
"color$subject", value.value);
}
),
title: Text(names[subject] ?? ""),
}),
title: Text(subjects[subject] ?? ""),
subtitle: Text(teachers[teacher] ?? ""),
);
} else {
return (const LinearProgressIndicator());
}
}
),
}),
);
}
return Column(
children: children,
);
} else {
return (const Center(
child: CircularProgressIndicator()));
return (const Center(child: CircularProgressIndicator()));
}
}
),
}),
/*FutureBuilder(
future: buildPlanColors("Mat"),
builder: (context, snapshot) {
@ -171,7 +174,6 @@ class _PlanSettingsState extends State<PlanSettings> {
}
),*/
],
)
);
));
}
}

@ -4,8 +4,6 @@ import 'package:flutter/material.dart';
class ServiceSettings extends StatelessWidget {
const ServiceSettings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
@ -15,9 +13,7 @@ class ServiceSettings extends StatelessWidget {
),
body: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [
],
children: [],
));
}
}

@ -17,7 +17,6 @@ class UserSettings extends StatelessWidget {
@override
Widget build(BuildContext context) {
//TextEditingController nameController = TextEditingController(text: "Denys Konovalov");
return Scaffold(
appBar: AppBar(
@ -36,10 +35,8 @@ class UserSettings extends StatelessWidget {
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.scaleDown,
image: AssetImage("assets/images/meincantor_r.png")
)
)
),
image:
AssetImage("assets/images/meincantor_r.png")))),
),
FutureBuilder(
future: getSettingsString("name"),
@ -51,17 +48,16 @@ class UserSettings extends StatelessWidget {
labelText: 'Name',
),
readOnly: true,
controller: TextEditingController(text: snapshot.data as String),
controller:
TextEditingController(text: snapshot.data as String),
);
} else {
return (const Center(child: CircularProgressIndicator()));
}
}
),
}),
Padding(
padding: const EdgeInsets.fromLTRB(5, 20, 5, 5),
child: buildClassesChooser()
),
child: buildClassesChooser()),
],
));
}

@ -23,7 +23,8 @@ class Settings extends StatelessWidget {
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [
ListTile(
leading: const Icon(MdiIcons.accountSettingsOutline, color: Colors.cyan),
leading: const Icon(MdiIcons.accountSettingsOutline,
color: Colors.cyan),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Benutzer"),
subtitle: const Text("Profilbild, Klasse & mehr"),
@ -35,7 +36,8 @@ class Settings extends StatelessWidget {
},
),
ListTile(
leading: const Icon(MdiIcons.timetable, color: Colors.orangeAccent),
leading:
const Icon(MdiIcons.timetable, color: Colors.orangeAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Plan"),
subtitle: const Text("Kurse/Fächer, Farben & mehr"),
@ -47,14 +49,16 @@ class Settings extends StatelessWidget {
},
),
ListTile(
leading: const Icon(Icons.color_lens_outlined, color: Colors.pinkAccent),
leading: const Icon(Icons.color_lens_outlined,
color: Colors.pinkAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Aussehen"),
subtitle: const Text("Widgets, Design & mehr"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AppearanceSettings()),
MaterialPageRoute(
builder: (context) => const AppearanceSettings()),
);
},
),
@ -66,12 +70,14 @@ class Settings extends StatelessWidget {
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ServiceSettings()),
MaterialPageRoute(
builder: (context) => const ServiceSettings()),
);
},
),
ListTile(
leading: const Icon(Icons.developer_mode_outlined, color: Colors.deepOrangeAccent),
leading: const Icon(Icons.developer_mode_outlined,
color: Colors.deepOrangeAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Entwickleroptionen"),
subtitle: const Text("API, Benutzerdaten & mehr"),
@ -83,7 +89,8 @@ class Settings extends StatelessWidget {
},
),
ListTile(
leading: const Icon(Icons.info_outlined, color: Colors.greenAccent),
leading:
const Icon(Icons.info_outlined, color: Colors.greenAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Informationen"),
subtitle: const Text("Version, Lizenzen & mehr"),

@ -1,18 +1,17 @@
//import 'package:MeinCantor/timetable.dart';
//import 'package:MeinCantor/main.dart';
import 'package:MeinCantor/raumuebersicht.dart';
import 'package:MeinCantor/schulbibliothek.dart';
import 'package:MeinCantor/schulcomputer.dart';
import 'package:MeinCantor/schuelerzeitung.dart';
import 'package:MeinCantor/Settings/dashboard.dart';
import 'package:MeinCantor/main.dart';
import 'package:MeinCantor/networking.dart';
import 'package:MeinCantor/login.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Settings/dashboard.dart';
// import 'settings.dart';
import 'main.dart';
import 'networking.dart';
import 'login.dart';
import 'schuelerzeitung.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class Dashboard extends StatefulWidget {
@ -30,7 +29,6 @@ Future<String> getSettingsString(String key) async {
if (value == null || value.isEmpty) {
value = "";
}
print(value);
return value;
}
@ -55,17 +53,14 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
UserAccountsDrawerHeader(
accountName: buildSettingsString('name', const TextStyle()),
accountEmail: buildSettingsString('user', const TextStyle()),
currentAccountPicture: Image.asset("assets/images/meincantor_r.png")
/*const CircularProgressIndicator(
backgroundColor: Colors.black,
),*/
),
currentAccountPicture:
Image.asset("assets/images/meincantor_r.png")),
ListTile(
title: const Text("Einstellungen"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Settings()),
MaterialPageRoute(builder: (context) => const Settings()),
);
},
leading: const Icon(Icons.settings_outlined),
@ -90,12 +85,9 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
label: "Startseite",
),
const BottomNavigationBarItem(
icon: Icon(MdiIcons.timetable),
label: "Vertretungsplan"),
icon: Icon(MdiIcons.timetable), label: "Vertretungsplan"),
const BottomNavigationBarItem(
icon: Icon(Icons.notifications_outlined),
label: "Hinweise"
),
icon: Icon(Icons.notifications_outlined), label: "Hinweise"),
];
return Scaffold(
appBar: AppBar(
@ -115,7 +107,6 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
setState(() {
_currentIndex.value = index;
});
//print(index);
},
),
);
@ -139,7 +130,7 @@ class _DashboardBottomNavView extends StatelessWidget {
Widget build(BuildContext context) {
if (item.label == "Startseite") {
double _timeOfDayToDouble(TimeOfDay tod) => tod.hour + tod.minute / 60.0;
var lessonCount;
int lessonCount;
if (_timeOfDayToDouble(TimeOfDay.now()) <=
_timeOfDayToDouble(const TimeOfDay(hour: 7, minute: 30))) {
lessonCount = 1;
@ -187,20 +178,8 @@ class _DashboardBottomNavView extends StatelessWidget {
lessonCount = -1;
}
/*
Widget timetable;
if (_timeOfDayToDouble(TimeOfDay.now()) >
_timeOfDayToDouble(const TimeOfDay(hour: , minute: 55))) {
timetable = buildClassTimetable();
} else {
timetable = buildTodayClassTimetable();
}
*/
print(lessonCount);
var view = SingleChildScrollView(
child: Column(
children: [
child: Column(children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
@ -285,8 +264,7 @@ class _DashboardBottomNavView extends StatelessWidget {
),
),
),
)
),
)),
),
width: 175,
),
@ -323,8 +301,7 @@ class _DashboardBottomNavView extends StatelessWidget {
),
),
),
)
),
)),
),
),
SizedBox(
@ -360,8 +337,7 @@ class _DashboardBottomNavView extends StatelessWidget {
),
),
),
)
),
)),
),
),
SizedBox(
@ -370,7 +346,8 @@ class _DashboardBottomNavView extends StatelessWidget {
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const RoomOverview()),
MaterialPageRoute(
builder: (context) => const RoomOverview()),
);
},
child: Card(
@ -397,188 +374,9 @@ class _DashboardBottomNavView extends StatelessWidget {
),
),
),
)
),
)),
),
)
/*GestureDetector(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SZ()),
);
},
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
//mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
child: Icon(
MdiIcons.newspaper,
color: Palette.accent,
size: 48,
),
)
],
),
Row(
//mainAxisSize: MainAxisSize.max,
children: const [
Align(
alignment: Alignment(0, 0),
child: Padding(
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
child: Text(
'Schülerzeitung',
),
),
),
],
)
],
),
),
),
GestureDetector(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SB()),
);
},
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
child: Icon(
MdiIcons.libraryShelves,
color: Color(0xFFFFBC3B),
size: 48,
),
)
],
),
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
child: Text(
'Schulbibliothek',
),
)
],
)
],
),
)
),
),
GestureDetector(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SC()),
);
},
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
child: Icon(
MdiIcons.laptop,
color: Color(0xFFFFBC3B),
size: 48,
),
)
],
),
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
child: Text(
'Schulcomputer',
),
)
],
)
],
),
),
),
GestureDetector(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const RoomOverview()),
);
},
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
child: Icon(
MdiIcons.door,
color: Color(0xFFFFBC3B),
size: 48,
),
)
],
),
Row(
mainAxisSize: MainAxisSize.max,
children: const [
Padding(
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
child: Text(
'Raumübersicht',
),
)
],
)
],
),
),
),*/
],
),
),
@ -588,8 +386,8 @@ class _DashboardBottomNavView extends StatelessWidget {
} else if (item.label == "Vertretungsplan") {
return LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
// double widgetHeight = constraints.maxHeight;
var factor;
int factor;
if (widgetWidth <= 600) {
factor = 1;
@ -597,6 +395,8 @@ class _DashboardBottomNavView extends StatelessWidget {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
// print(screenType);
@ -629,10 +429,6 @@ class _DashboardBottomNavView extends StatelessWidget {
text: "Neuster Plan",
icon: Icon(CupertinoIcons.calendar),
),
/*Tab(
text: "Archiv",
icon: Icon(CupertinoIcons.archivebox),
),*/
],
),
),

@ -46,7 +46,8 @@ class App extends StatelessWidget {
),
),
darkTheme: ThemeData.from(
colorScheme: const ColorScheme.dark(primary: Palette.accent, secondary: Palette.accent)),
colorScheme: const ColorScheme.dark(
primary: Palette.accent, secondary: Palette.accent)),
title: "GCG.MeinCantor",
home: buildHomePage(),
);

@ -5,9 +5,20 @@ import 'package:flutter/painting.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'timetable.dart';
import 'login.dart';
import 'main.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 {
print("hjkl0");
var uri = Uri.https(szUrl["url"]!, "/articles");
print(uri.toString());
final response = await http.get(uri);
print("hji");
print(response);
return (response);
}
Future<http.Response> getToken(
String user, String password, String otp, String devId) async {
@ -47,7 +58,9 @@ Future<http.Response> fetchClassTimetable() async {
var uri = Uri.https("mein.cantorgymnasium.de", "/api/timetable/$classNum");
var headers = {"x-api-key": "$apiKey"};
print(uri);
final response = http.get(uri, headers: headers).onError((error, stackTrace) { return(http.Response("", 404)); } );
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
return response;
}
@ -65,7 +78,9 @@ Future<http.Response> fetchTodayClassTimetable() async {
Uri.https("mein.cantorgymnasium.de", "/api/timetable/$classNum/today");
var headers = {"x-api-key": "$apiKey"};
print(uri);
final response = http.get(uri, headers: headers).onError((error, stackTrace) { return(http.Response("", 404)); } );
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
return response;
}
@ -83,7 +98,9 @@ Future<http.Response> fetchTomorrowClassTimetable() async {
Uri.https("mein.cantorgymnasium.de", "/api/timetable/$classNum/tomorrow");
var headers = {"x-api-key": "$apiKey"};
print(uri);
final response = http.get(uri, headers: headers).onError((error, stackTrace) { return(http.Response("", 404)); } );
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
return response;
}
@ -98,7 +115,10 @@ fetchLessonList() async {
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)); } );
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 {
@ -106,8 +126,6 @@ fetchLessonList() async {
}
}
Widget buildClassTimetable() {
return FutureBuilder<http.Response>(
future: fetchClassTimetable(),
@ -117,7 +135,8 @@ Widget buildClassTimetable() {
if (statusCode == 200) {
Widget timetableView = ClassTimetableBuilder.buildView(
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), context)
.view.child;
.view
.child;
return timetableView;
} else if (statusCode == 400) {
Navigator.pushReplacement(
@ -125,12 +144,15 @@ Widget buildClassTimetable() {
} else if (statusCode == 500) {
return const Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Center(child: Text("Es konnte kein Vertretungsplan gefunden werden.")),
child: Center(
child: Text("Es konnte kein Vertretungsplan gefunden werden.")),
);
} 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.")),
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 Center(child: Text('Error $statusCode'));
@ -152,23 +174,23 @@ Widget buildTodayClassTimetable() {
if (statusCode == 200) {
Widget timetableView = ClassTimetableBuilder.buildView(
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), context)
.view.child;
.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 Vertretungsplan für heute gefunden werden. \u{1F937}');
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(
@ -178,12 +200,13 @@ Widget buildTodayClassTimetable() {
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: ListView(
children: [card],
)
);
));
} 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.")),
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 Center(child: Text('Error $statusCode'));
@ -205,23 +228,23 @@ Widget buildTomorrowClassTimetable() {
if (statusCode == 200) {
Widget timetableView = ClassTimetableBuilder.buildView(
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), context)
.view.child;
.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 Vertretungsplan für morgen gefunden werden. \u{1F937}');
var chars = Runes(
'Es konnte kein Vertretungsplan für morgen 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(
@ -231,8 +254,7 @@ Widget buildTomorrowClassTimetable() {
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: ListView(
children: [card],
)
);
));
/*return const Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Center(child: Text("Es konnte kein Vertretungsplan für heute gefunden werden.")),
@ -240,7 +262,9 @@ Widget buildTomorrowClassTimetable() {
} 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.")),
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 Center(child: Text('Error $statusCode'));
@ -261,19 +285,20 @@ Widget buildClassTimetableLesson(int count) {
int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) {
List<Widget> lessons = LessonsListBuilder.buildList(
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), count: count)
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)),
count: count)
.lessons;
return Column(children: lessons);
} else if (statusCode == 400) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Login()));
} else if (statusCode == 500) {
var chars = Runes('Es konnte kein Vertretungsplan für gefunden werden. \u{1F937}');
var chars = Runes(
'Es konnte kein Vertretungsplan für gefunden werden. \u{1F937}');
List<Widget> cardChildren = [];
cardChildren.add(ListTile(
title: Text(String.fromCharCodes(chars),
style: const TextStyle(color: Palette.primary))
));
style: const TextStyle(color: Palette.primary))));
Card card = Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
@ -290,7 +315,9 @@ Widget buildClassTimetableLesson(int count) {
} 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")),
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 Center(child: Text('Error $statusCode'));
@ -311,17 +338,18 @@ Widget buildTodayClassTimetableLesson(int count) {
int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) {
List<Widget> lessons = LessonsListBuilder.buildList(
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), count: count)
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)),
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}');
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))
));
style: const TextStyle(color: Palette.primary))));
Card card = Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
@ -336,18 +364,16 @@ Widget buildTodayClassTimetableLesson(int count) {
Future.delayed(Duration.zero, () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Login()),
MaterialPageRoute(builder: (context) => Login()),
);
});
} else if (statusCode == 500) {
var chars = Runes('Es konnte kein Vertretungsplan für heute gefunden werden. \u{1F937}');
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))
));
style: const TextStyle(color: Palette.primary))));
Card card = Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
@ -364,7 +390,9 @@ Widget buildTodayClassTimetableLesson(int count) {
} 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")),
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 Center(child: Text('Error $statusCode'));
@ -383,7 +411,9 @@ Future<http.Response> fetchClassesList() async {
var uri = Uri.https("mein.cantorgymnasium.de", "/api/classes");
var headers = {"x-api-key": "$apiKey"};
print(uri);
final response = http.get(uri, headers: headers).onError((error, stackTrace) { return(http.Response("", 404)); } );
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
return response;
}
@ -405,12 +435,16 @@ Widget buildClassesChooser() {
} 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.")),
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")),
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');

@ -1,4 +1,5 @@
dynamic names = {
dynamic subjects = {
'---': '---',
'Bio': 'Biologie',
'Mat': 'Mathematik',
'matL1': 'Mathematik Leistungskurs 1',
@ -15,7 +16,6 @@ dynamic names = {
'frz2': 'Französisch 2',
'frz3': 'Französisch 3',
'Phy': 'Physik',
'---': '---',
'Spo': 'Sport',
'Deu': 'Deutsch',
'deu1': 'Deutsch 1',

@ -1,6 +1,12 @@
import 'dart:convert';
import 'package:MeinCantor/networking.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class SZ extends StatelessWidget {
const SZ({Key? key}) : super(key: key);
@ -11,45 +17,93 @@ class SZ extends StatelessWidget {
title: const Text("Schülerzeitung"),
centerTitle: true,
),
body: ListView(
children: [
Card(
body: FutureBuilder<http.Response>(
future: getArticles(),
builder: (context, snapshot) {
if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) {
String data = utf8.decode(snapshot.data!.bodyBytes);
List articles = jsonDecode(data);
List<Widget> articleTiles = [];
for (var element in articles) {
Card card = Card(
child: Column(children: [
Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Article()),
MaterialPageRoute(builder: (context) => Article.fromData(element["title"], element["content"], element["author"], element["published_at"]).widget),
);
},
title: const Text(
"Schülersprecherwahl 2021: Kandidatenduos im Interview",
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: const Text(
"17.09.2021, Halle(Saale) Drei Trios stellen sich dieses Jahr zur Wahl...")),
title: Text(element["title"],
style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text(
element["summary"])),
)
]),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
)
],
)
/*const Center(
child: Text("Derzeit nichts hier..."),
)*/
);
articleTiles.add(card);
}
return ListView(
children: articleTiles.reversed.toList(),
);
} else {
return(const Center(
child: Text("Uups... Irgendwas ist schief gelaufen")
));
}
} else {
return(const Center(
child: CircularProgressIndicator()
));
}
},
),
);
}
}
class Article extends StatelessWidget {
const Article({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
class Article {
Widget widget;
//const Article({Key? key}) : super(key: key);
Article({required this.widget});
factory Article.fromData(String title, String content, String author, String publishDate, ) {
return Article(widget: Scaffold(
appBar: AppBar(
title: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Text(title)
),
),
centerTitle: true,
),
body: ListView(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
children: [
ListTile(
leading: Icon(MdiIcons.accountOutline),
title: Text(author),
),
ListTile(
leading: Icon(MdiIcons.calendarOutline),
title: Text("${DateTime.parse(publishDate).day.toString()}.${DateTime.parse(publishDate).month.toString()}.${DateTime.parse(publishDate).year.toString()}"),
),
Text(content)
],
)
)
);
}
//@override
/*Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
@ -70,5 +124,5 @@ class Article extends StatelessWidget {
""")
],
));
}
}*/
}

@ -1,20 +1,26 @@
import 'package:MeinCantor/teacher_presets.dart';
import 'package:MeinCantor/presets/teachers.dart';
import 'package:MeinCantor/presets/subjects.dart';
import 'package:MeinCantor/presets/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'subject_presets.dart';
import 'color_presets.dart';
class ClassTimetableBuilder {
final RefreshIndicator view;
ClassTimetableBuilder({required this.view});
factory ClassTimetableBuilder.buildView(Map<String, dynamic> json, BuildContext context) {
factory ClassTimetableBuilder.buildView(
Map<String, dynamic> json, BuildContext context) {
List<Widget> list = LessonsListBuilder.buildList(json).lessons;
String info = TimetableInfo.fromJson(json).info;
if (info.isNotEmpty) {
list.insert(0, ListTile(title: Text("Informationen"), leading: Icon(MdiIcons.information), onTap: () {
list.insert(
0,
ListTile(
title: const Text("Informationen"),
leading: const Icon(MdiIcons.information),
onTap: () {
showModalBottomSheet<void>(
isScrollControlled: true,
shape: RoundedRectangleBorder(
@ -22,15 +28,14 @@ class ClassTimetableBuilder {
),
context: context,
builder: (BuildContext context) {
return Container(
return SizedBox(
height: 400,
child: ListView(
//mainAxisAlignment: MainAxisAlignment.center,
//mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text("Informationen", style: TextStyle(fontWeight: FontWeight.bold)),
leading: Icon(Icons.arrow_back),
title: const Text("Informationen",
style: TextStyle(fontWeight: FontWeight.bold)),
leading: const Icon(Icons.arrow_back),
onTap: () {
Navigator.of(context).pop();
},
@ -39,18 +44,13 @@ class ClassTimetableBuilder {
padding: const EdgeInsets.all(20),
child: Text(info),
),
/*ElevatedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
)*/
],
),
);
},
);
},
)
);
));
}
return ClassTimetableBuilder(
view: RefreshIndicator(
@ -58,7 +58,6 @@ class ClassTimetableBuilder {
return Future.delayed(const Duration(seconds: 1));
},
child: ListView(
//shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
children: list,
),
@ -80,11 +79,11 @@ Future<Color> buildLessonColor(String lesson) async {
class LessonsListBuilder {
final List<Widget> lessons;
LessonsListBuilder({required this.lessons});
factory LessonsListBuilder.buildList(Map<String, dynamic> json, {int count: 0}) {
factory LessonsListBuilder.buildList(Map<String, dynamic> json,
{int count = 0}) {
List<Widget> children = [];
ClassTimetable.fromJson(json).timetable.forEach((element) {
for (var element in ClassTimetable.fromJson(json).timetable) {
List<Widget> cardChildren = [];
print(element.count.toString() + " " + count.toString());
if (element.count.toString() == count.toString() || count == 0) {
cardChildren.add(ListTile(
title: Text(element.count.toString() + '.' + ' ' + element.name,
@ -123,7 +122,7 @@ class LessonsListBuilder {
);
children.add(card);
}
});
}
return LessonsListBuilder(lessons: children);
}
}
@ -140,55 +139,55 @@ class ClassTimetable {
final List timetable;
ClassTimetable({required this.timetable});
factory ClassTimetable.fromJson(Map<String, dynamic> json) {
print(json);
List<TimetableLesson> lessons = [];
json['courses'].forEach((value) {
var name;
var teacher;
var room;
String subject;
String teacher;
String room;
String info;
Color fontColor;
if (value['Fa'].runtimeType != String) {
name = value['Fa']['#text'];
subject = value['Fa']['#text'];
} else {
name = value['Fa'];
subject = value['Fa'];
}
if (value['Le'].runtimeType != String) {
teacher = value['Le']['#text'];
} else {
teacher = value['Le'];
}
print(value['Ra']);
if (value['Ra'].runtimeType != String && value['Ra'].runtimeType != int) {
if (value['Ra']['#text'] == '&nbsp;') {
room = '';
} else if (value['Ra']['#text'] == null) {
if (value['Ra']['#text'] == '&nbsp;' || value['Ra']['#text'] == null) {
room = '';
} else {
room = value['Ra']['#text'];
room = value['Ra']['#text'].toString();
}
} else if (value['Ra'] == '&nbsp;') {
room = '';
} else {
room = value['Ra'];
room = value['Ra'].toString();
}
Color fontColor;
if (name == '---') {
if (subject == '---') {
fontColor = Colors.red;
} else {
fontColor = Colors.white;
}
var info;
if (value['If'].runtimeType != String) {
info = '';
} else {
info = value['If'];
}
Future<Color> lessonColor = buildLessonColor(name);
Future<Color> lessonColor = buildLessonColor(subject);
lessons.add(TimetableLesson(
value['St'],
names[name] ?? name.toString(),
subjects[subject] ?? subject.toString(),
teachers[teacher] ?? teacher.toString(),
room.toString(),
value['If'].toString(),

@ -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: 0.7.5-beta1.nightly2021-11-04
version: 0.7.5-beta1.nightly2021-11-16
environment:
sdk: ">=2.12.0 <3.0.0"
@ -36,10 +36,10 @@ dependencies:
http: ^0.13.3
google_fonts: ^2.1.0
time: ^2.0.0
flutter_launcher_icons: "^0.9.1"
flutter_launcher_icons: ^0.9.1
fluttertoast: ^8.0.8
flutter_colorpicker: ^0.6.0
material_design_icons_flutter: 5.0.5955-rc.1
material_design_icons_flutter: ^5.0.5955-rc.1
cyclop: ^0.5.2
flutter_icons: