==0.7.5==
- added A LOT, TLTD Settings menu, updated homepage tiles, added color settings... - TODO: - update README - 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:
parent
bae624dd67
commit
6ad143195a
@ -44,7 +44,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "de.cantorgymnasium.meincantor"
|
applicationId "de.cantorgymnasium.meincantor"
|
||||||
minSdkVersion 16
|
minSdkVersion 18
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
23
lib/Settings/Pages/appearance_settings.dart
Normal file
23
lib/Settings/Pages/appearance_settings.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AppearanceSettings extends StatelessWidget {
|
||||||
|
const AppearanceSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Aussehen"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
57
lib/Settings/Pages/dev_settings.dart
Normal file
57
lib/Settings/Pages/dev_settings.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../login.dart';
|
||||||
|
|
||||||
|
class DevSettings extends StatelessWidget {
|
||||||
|
const DevSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Entwickler-Einstellungen"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||||
|
child: TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
icon: Icon(MdiIcons.keyOutline),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelText: 'MeinCantor API-Schlüssel',
|
||||||
|
),
|
||||||
|
onSubmitted: (String value) async {
|
||||||
|
SharedPreferences prefs =
|
||||||
|
await SharedPreferences.getInstance();
|
||||||
|
String apiKey = value;
|
||||||
|
await prefs.setString('api_key', apiKey);
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
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);
|
||||||
|
})),
|
||||||
|
const Divider(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => Login()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text("Benutzerdaten neu laden"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
75
lib/Settings/Pages/info_settings.dart
Normal file
75
lib/Settings/Pages/info_settings.dart
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:MeinCantor/const.dart';
|
||||||
|
|
||||||
|
class InfoSettings extends StatelessWidget {
|
||||||
|
const InfoSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Informationen"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
const ListTile(
|
||||||
|
leading: Icon(Icons.info_outlined),
|
||||||
|
title: Text("Version"),
|
||||||
|
subtitle: Text(version)
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.settings_backup_restore_outlined),
|
||||||
|
title: const Text("Änderungsverlauf"),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
isScrollControlled: true,
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
height: 400,
|
||||||
|
//color: Colors.amber,
|
||||||
|
child: Column(
|
||||||
|
//mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
AppBar(
|
||||||
|
title: const Text("Änderungsverlauf"),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: Text(""),
|
||||||
|
),
|
||||||
|
/*ElevatedButton(
|
||||||
|
child: const Text('Close BottomSheet'),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
)*/
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.copyright_outlined),
|
||||||
|
title: const Text("Lizenzen"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => LicensePage(
|
||||||
|
applicationIcon: Image.asset("assets/images/meincantor_r.png",
|
||||||
|
height: 64, width: 64),
|
||||||
|
applicationVersion: version,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
177
lib/Settings/Pages/plan_settings.dart
Normal file
177
lib/Settings/Pages/plan_settings.dart
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:MeinCantor/main.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
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 '../../teacher_presets.dart';
|
||||||
|
|
||||||
|
class PlanSettings extends StatefulWidget {
|
||||||
|
const PlanSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _PlanSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Color> buildPlanColors(lesson) async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
if (!prefs.containsKey("color$lesson")) {
|
||||||
|
prefs.setInt("color$lesson", colors[lesson].value ?? Colors.grey.value);
|
||||||
|
}
|
||||||
|
await fetchLessonList();
|
||||||
|
Color colorDeu = Color(prefs.getInt("color$lesson")!);
|
||||||
|
return colorDeu;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<dynamic>> buildLessonsList() async {
|
||||||
|
await fetchLessonList();
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
String lessonsJson = prefs.getString("lessons")!;
|
||||||
|
List<dynamic> lessons = jsonDecode(lessonsJson);
|
||||||
|
return lessons;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PlanSettingsState extends State<PlanSettings> {
|
||||||
|
Set<Color> swatches = {...Colors.primaries, ...Colors.accents, Palette.accent, Palette.primary};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Plan"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
const ListTile(
|
||||||
|
title: Text("Kurse/Fächer"),
|
||||||
|
leading: Icon(Icons.list_alt_outlined),
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: buildLessonsList(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
for (var element in (snapshot.data as List<dynamic>)) {
|
||||||
|
String subject = element['subject'];
|
||||||
|
String teacher = element['teacher'];
|
||||||
|
children.add(FutureBuilder(
|
||||||
|
future: buildPlanColors(subject),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
Color color = snapshot.data as Color;
|
||||||
|
return ListTile(
|
||||||
|
leading: ColorButton(
|
||||||
|
key: const Key('c1'),
|
||||||
|
color: color,
|
||||||
|
config: const ColorPickerConfig(
|
||||||
|
enableEyePicker: false),
|
||||||
|
onSwatchesChanged: (Set<Color> value) {
|
||||||
|
swatches = value;
|
||||||
|
},
|
||||||
|
size: 32,
|
||||||
|
swatches: swatches,
|
||||||
|
onColorChanged: (Color value) async {
|
||||||
|
setState(() {
|
||||||
|
color = value;
|
||||||
|
});
|
||||||
|
SharedPreferences prefs = await SharedPreferences
|
||||||
|
.getInstance();
|
||||||
|
prefs.setInt(
|
||||||
|
"color$subject", value.value);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
title: Text(names[subject] ?? ""),
|
||||||
|
subtitle: Text(teachers[teacher] ?? ""),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (const LinearProgressIndicator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
children: children,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (const Center(
|
||||||
|
child: CircularProgressIndicator()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
/*FutureBuilder(
|
||||||
|
future: buildPlanColors("Mat"),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
Color color = snapshot.data as Color;
|
||||||
|
return ListTile(
|
||||||
|
leading: ColorButton(
|
||||||
|
key: const Key('c1'),
|
||||||
|
color: color,
|
||||||
|
//boxShape: BoxShape.circle, // default : circle
|
||||||
|
config: const ColorPickerConfig(enableEyePicker: false),
|
||||||
|
onSwatchesChanged: (Set<Color> value) {
|
||||||
|
swatches = value;
|
||||||
|
},
|
||||||
|
size: 32,
|
||||||
|
swatches: swatches,
|
||||||
|
onColorChanged: (Color value) async {
|
||||||
|
setState(() {
|
||||||
|
color = value;
|
||||||
|
});
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setInt("colorMat", value.value);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
title: const Text("Mathematik"),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (const Center(child: CircularProgressIndicator()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: buildPlanColors("Bio"),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
Color color = snapshot.data as Color;
|
||||||
|
return ListTile(
|
||||||
|
leading: ColorButton(
|
||||||
|
key: const Key('c1'),
|
||||||
|
color: color,
|
||||||
|
//boxShape: BoxShape.circle, // default : circle
|
||||||
|
config: const ColorPickerConfig(enableEyePicker: false),
|
||||||
|
onSwatchesChanged: (Set<Color> value) {
|
||||||
|
swatches = value;
|
||||||
|
},
|
||||||
|
size: 32,
|
||||||
|
swatches: swatches,
|
||||||
|
onColorChanged: (Color value) async {
|
||||||
|
setState(() {
|
||||||
|
color = value;
|
||||||
|
});
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setInt("colorBio", value.value);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
title: const Text("Biologie"),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (const Center(child: CircularProgressIndicator()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),*/
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
23
lib/Settings/Pages/service_settings.dart
Normal file
23
lib/Settings/Pages/service_settings.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ServiceSettings extends StatelessWidget {
|
||||||
|
const ServiceSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Dienste"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
68
lib/Settings/Pages/user_settings.dart
Normal file
68
lib/Settings/Pages/user_settings.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:MeinCantor/networking.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
Future<String> getSettingsString(String key) async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
String? value = prefs.getString(key);
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserSettings extends StatelessWidget {
|
||||||
|
const UserSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
//TextEditingController nameController = TextEditingController(text: "Denys Konovalov");
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Benutzereinstellungen"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
|
child: Container(
|
||||||
|
width: 128.0,
|
||||||
|
height: 128.0,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
image: AssetImage("assets/images/meincantor_r.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: getSettingsString("name"),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
return TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelText: 'Name',
|
||||||
|
),
|
||||||
|
readOnly: true,
|
||||||
|
controller: TextEditingController(text: snapshot.data as String),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (const Center(child: CircularProgressIndicator()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 20, 5, 5),
|
||||||
|
child: buildClassesChooser()
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
100
lib/Settings/dashboard.dart
Normal file
100
lib/Settings/dashboard.dart
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import 'package:MeinCantor/Settings/Pages/appearance_settings.dart';
|
||||||
|
import 'package:MeinCantor/Settings/Pages/service_settings.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
|
||||||
|
import 'Pages/dev_settings.dart';
|
||||||
|
import 'Pages/info_settings.dart';
|
||||||
|
import 'Pages/plan_settings.dart';
|
||||||
|
import 'Pages/user_settings.dart';
|
||||||
|
|
||||||
|
class Settings extends StatelessWidget {
|
||||||
|
const Settings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Einstellungen"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
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"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const UserSettings()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
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"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const PlanSettings()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
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()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(MdiIcons.server, color: Colors.lightGreen),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
title: const Text("Dienste"),
|
||||||
|
subtitle: const Text("Konten, Plattformen & mehr"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const ServiceSettings()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
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"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const DevSettings()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
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"),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const InfoSettings()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
45
lib/color_presets.dart
Normal file
45
lib/color_presets.dart
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
dynamic colors = {
|
||||||
|
'Bio': Colors.green,
|
||||||
|
'Mat': Colors.indigo,
|
||||||
|
'matL1': Colors.indigo,
|
||||||
|
'matL2': Colors.indigo,
|
||||||
|
'matL3': Colors.indigo,
|
||||||
|
'Deu': Colors.red,
|
||||||
|
'deu1': Colors.red,
|
||||||
|
'deu2': Colors.red,
|
||||||
|
'deu3': Colors.red,
|
||||||
|
'Kun': Colors.deepPurple,
|
||||||
|
'kun1': Colors.deepPurple,
|
||||||
|
'kun2': Colors.deepPurple,
|
||||||
|
'kun3': Colors.deepPurple,
|
||||||
|
'Geo': Colors.brown,
|
||||||
|
'Lat': Colors.teal,
|
||||||
|
'lat1': Colors.teal,
|
||||||
|
'lat2': Colors.teal,
|
||||||
|
'lat3': Colors.teal,
|
||||||
|
'Che': Colors.lightGreen,
|
||||||
|
'Eng': Colors.amber,
|
||||||
|
'eng1': Colors.amber,
|
||||||
|
'eng2': Colors.amber,
|
||||||
|
'eng3': Colors.amber,
|
||||||
|
'Phy': Colors.cyan,
|
||||||
|
'phy1': Colors.cyan,
|
||||||
|
'phy2': Colors.cyan,
|
||||||
|
'phy3': Colors.cyan,
|
||||||
|
'Inf': Colors.tealAccent[400],
|
||||||
|
'Mus': Colors.deepOrange,
|
||||||
|
'mus1': Colors.deepOrange,
|
||||||
|
'mus2': Colors.deepOrange,
|
||||||
|
'mus3': Colors.deepOrange,
|
||||||
|
'Lme': Colors.amber[700],
|
||||||
|
'Ges': Colors.grey,
|
||||||
|
'ges1': Colors.grey,
|
||||||
|
'ges2': Colors.grey,
|
||||||
|
'ges3': Colors.grey,
|
||||||
|
'Spa': Colors.redAccent,
|
||||||
|
'Frz': Colors.amberAccent[700],
|
||||||
|
'frz1': Colors.amberAccent[700],
|
||||||
|
'---': Colors.white
|
||||||
|
};
|
@ -7,10 +7,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'settings.dart';
|
import 'Settings/dashboard.dart';
|
||||||
|
// import 'settings.dart';
|
||||||
|
import 'main.dart';
|
||||||
import 'networking.dart';
|
import 'networking.dart';
|
||||||
import 'login.dart';
|
import 'login.dart';
|
||||||
import 'schuelerzeitung.dart';
|
import 'schuelerzeitung.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
|
||||||
class Dashboard extends StatefulWidget {
|
class Dashboard extends StatefulWidget {
|
||||||
const Dashboard({Key? key, this.restorationId}) : super(key: key);
|
const Dashboard({Key? key, this.restorationId}) : super(key: key);
|
||||||
@ -31,7 +34,7 @@ Future<String> getSettingsString(String key) async {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildSettingsString(String key, TextStyle style) {
|
Widget buildSettingsString(String key, TextStyle? style) {
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: getSettingsString(key),
|
future: getSettingsString(key),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
@ -52,9 +55,10 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
|
|||||||
UserAccountsDrawerHeader(
|
UserAccountsDrawerHeader(
|
||||||
accountName: buildSettingsString('name', const TextStyle()),
|
accountName: buildSettingsString('name', const TextStyle()),
|
||||||
accountEmail: buildSettingsString('user', const TextStyle()),
|
accountEmail: buildSettingsString('user', const TextStyle()),
|
||||||
currentAccountPicture: const CircularProgressIndicator(
|
currentAccountPicture: Image.asset("assets/images/meincantor_r.png")
|
||||||
|
/*const CircularProgressIndicator(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
),
|
),*/
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text("Einstellungen"),
|
title: const Text("Einstellungen"),
|
||||||
@ -64,7 +68,7 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
|
|||||||
MaterialPageRoute(builder: (context) => Settings()),
|
MaterialPageRoute(builder: (context) => Settings()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
leading: const Icon(CupertinoIcons.settings),
|
leading: const Icon(Icons.settings_outlined),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text("Abmelden"),
|
title: const Text("Abmelden"),
|
||||||
@ -78,31 +82,20 @@ class _DashboardState extends State<Dashboard> with RestorationMixin {
|
|||||||
},
|
},
|
||||||
leading: const Icon(Icons.exit_to_app_outlined),
|
leading: const Icon(Icons.exit_to_app_outlined),
|
||||||
),
|
),
|
||||||
AboutListTile(
|
|
||||||
child: const Text("Info"),
|
|
||||||
icon: const Icon(CupertinoIcons.info),
|
|
||||||
applicationVersion: "0.6.5-alpha",
|
|
||||||
applicationIcon: Image.asset("assets/images/meincantor_r.png",
|
|
||||||
height: 64, width: 64),
|
|
||||||
applicationName: "MeinCantor",
|
|
||||||
aboutBoxChildren: const [
|
|
||||||
Text(
|
|
||||||
"MeinCantor ist die Schulplatform für Schüler des Georg-Cantor-Gymnasiums in Halle (Saale)."),
|
|
||||||
Divider(),
|
|
||||||
Text("Copyright © 2021 Denys Konovalov")
|
|
||||||
],
|
|
||||||
// applicationIcon: Image.,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
var bottomNavBarItems = [
|
var bottomNavBarItems = [
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
icon: Icon(CupertinoIcons.home),
|
icon: Icon(MdiIcons.homeOutline),
|
||||||
label: "Startseite",
|
label: "Startseite",
|
||||||
),
|
),
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
icon: Icon(CupertinoIcons.rectangle_grid_1x2),
|
icon: Icon(MdiIcons.timetable),
|
||||||
label: "Vertretungsplan"),
|
label: "Vertretungsplan"),
|
||||||
|
const BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.notifications_outlined),
|
||||||
|
label: "Hinweise"
|
||||||
|
),
|
||||||
];
|
];
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -256,13 +249,159 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
|
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: buildTodayClassTimetableLesson(lessonCount),
|
child: buildTodayClassTimetableLesson(lessonCount),
|
||||||
),
|
),
|
||||||
Row(mainAxisSize: MainAxisSize.max, children: [
|
Padding(
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
|
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: Column(
|
child: Wrap(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
SizedBox(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const SZ()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Card(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: ListTile(
|
||||||
|
title: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: Icon(
|
||||||
|
MdiIcons.newspaper,
|
||||||
|
color: Palette.accent,
|
||||||
|
size: 48,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
'Schülerzeitung',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
width: 175,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 175,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const SB()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Card(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: ListTile(
|
||||||
|
title: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: Icon(
|
||||||
|
MdiIcons.libraryShelves,
|
||||||
|
color: Palette.accent,
|
||||||
|
size: 48,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
'Schulbibliothek',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 175,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const SC()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Card(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: ListTile(
|
||||||
|
title: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: Icon(
|
||||||
|
MdiIcons.laptop,
|
||||||
|
color: Palette.accent,
|
||||||
|
size: 48,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
'Schulcomputer',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 175,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const RoomOverview()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Card(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: ListTile(
|
||||||
|
title: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
|
||||||
|
child: Icon(
|
||||||
|
MdiIcons.door,
|
||||||
|
color: Palette.accent,
|
||||||
|
size: 48,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
'Raumübersicht',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
/*GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
@ -276,27 +415,28 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
//mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(20, 20, 10, 10),
|
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CupertinoIcons.news,
|
MdiIcons.newspaper,
|
||||||
color: Color(0xFFFFBC3B),
|
color: Palette.accent,
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
//mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment(0, 0),
|
alignment: Alignment(0, 0),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 50, 0, 15),
|
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Schülerzeitung',
|
'Schülerzeitung',
|
||||||
),
|
),
|
||||||
@ -320,6 +460,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: [
|
children: [
|
||||||
@ -327,9 +468,9 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(20, 20, 10, 10),
|
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CupertinoIcons.book,
|
MdiIcons.libraryShelves,
|
||||||
color: Color(0xFFFFBC3B),
|
color: Color(0xFFFFBC3B),
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
@ -340,7 +481,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 50, 0, 15),
|
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Schulbibliothek',
|
'Schulbibliothek',
|
||||||
),
|
),
|
||||||
@ -349,6 +490,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -370,9 +512,9 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(20, 20, 10, 10),
|
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CupertinoIcons.device_laptop,
|
MdiIcons.laptop,
|
||||||
color: Color(0xFFFFBC3B),
|
color: Color(0xFFFFBC3B),
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
@ -383,7 +525,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 50, 0, 15),
|
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Schulcomputer',
|
'Schulcomputer',
|
||||||
),
|
),
|
||||||
@ -413,9 +555,9 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(20, 20, 10, 10),
|
padding: EdgeInsets.fromLTRB(20, 20, 20, 10),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CupertinoIcons.house_alt,
|
MdiIcons.door,
|
||||||
color: Color(0xFFFFBC3B),
|
color: Color(0xFFFFBC3B),
|
||||||
size: 48,
|
size: 48,
|
||||||
),
|
),
|
||||||
@ -426,7 +568,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: const [
|
children: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(15, 50, 0, 15),
|
padding: EdgeInsets.fromLTRB(15, 50, 15, 15),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Raumübersicht',
|
'Raumübersicht',
|
||||||
),
|
),
|
||||||
@ -436,14 +578,12 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),*/
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
]),
|
]),
|
||||||
],
|
);
|
||||||
));
|
|
||||||
return view;
|
return view;
|
||||||
} else if (item.label == "Vertretungsplan") {
|
} else if (item.label == "Vertretungsplan") {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
@ -471,7 +611,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
initialIndex: 0,
|
initialIndex: 0,
|
||||||
length: 2,
|
length: 3,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@ -481,6 +621,10 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
text: "Heute",
|
text: "Heute",
|
||||||
icon: Icon(CupertinoIcons.calendar_today),
|
icon: Icon(CupertinoIcons.calendar_today),
|
||||||
),
|
),
|
||||||
|
Tab(
|
||||||
|
text: "Morgen",
|
||||||
|
icon: Icon(CupertinoIcons.calendar_today),
|
||||||
|
),
|
||||||
Tab(
|
Tab(
|
||||||
text: "Neuster Plan",
|
text: "Neuster Plan",
|
||||||
icon: Icon(CupertinoIcons.calendar),
|
icon: Icon(CupertinoIcons.calendar),
|
||||||
@ -495,12 +639,8 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
buildTodayClassTimetable(),
|
buildTodayClassTimetable(),
|
||||||
|
buildTomorrowClassTimetable(),
|
||||||
buildClassTimetable(),
|
buildClassTimetable(),
|
||||||
/*
|
|
||||||
Center(
|
|
||||||
child: Text("It's sunny here"),
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -509,8 +649,7 @@ class _DashboardBottomNavView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return const Text("Such page does not exist.");
|
return const Center(child: Text("Derzeit nichts hier..."));
|
||||||
}
|
}
|
||||||
// return materialCard(item.label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ class Login extends StatelessWidget {
|
|||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
double widgetWidth = constraints.maxWidth;
|
double widgetWidth = constraints.maxWidth;
|
||||||
double widgetHeight = constraints.maxHeight;
|
//double widgetHeight = constraints.maxHeight;
|
||||||
var factor;
|
var factor;
|
||||||
|
|
||||||
if (widgetWidth <= 600) {
|
if (widgetWidth <= 600) {
|
||||||
@ -93,7 +93,7 @@ class Login extends StatelessWidget {
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
controller: otpController,
|
controller: otpController,
|
||||||
),
|
),
|
||||||
const Divider(),
|
/*const Divider(),
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
icon: Icon(CupertinoIcons.device_laptop),
|
icon: Icon(CupertinoIcons.device_laptop),
|
||||||
@ -101,7 +101,7 @@ class Login extends StatelessWidget {
|
|||||||
labelText: 'Gerätebezeichnung',
|
labelText: 'Gerätebezeichnung',
|
||||||
),
|
),
|
||||||
controller: devIdController,
|
controller: devIdController,
|
||||||
),
|
),*/
|
||||||
const Divider(),
|
const Divider(),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@ -146,12 +146,14 @@ class Login extends StatelessWidget {
|
|||||||
prefs
|
prefs
|
||||||
.getString('api_key')!
|
.getString('api_key')!
|
||||||
.isNotEmpty) {
|
.isNotEmpty) {
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
const Dashboard()),
|
const Dashboard()),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Text("Anmelden"))
|
child: const Text("Anmelden"))
|
||||||
|
@ -46,7 +46,7 @@ class App extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
darkTheme: ThemeData.from(
|
darkTheme: ThemeData.from(
|
||||||
colorScheme: const ColorScheme.dark(primary: Palette.accent)),
|
colorScheme: const ColorScheme.dark(primary: Palette.accent, secondary: Palette.accent)),
|
||||||
title: "GCG.MeinCantor",
|
title: "GCG.MeinCantor",
|
||||||
home: buildHomePage(),
|
home: buildHomePage(),
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/painting.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -68,6 +69,45 @@ Future<http.Response> fetchTodayClassTimetable() async {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<http.Response> fetchTomorrowClassTimetable() async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
String classNum;
|
||||||
|
print(prefs.getString('class_num'));
|
||||||
|
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/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)); } );
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
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([]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Widget buildClassTimetable() {
|
Widget buildClassTimetable() {
|
||||||
return FutureBuilder<http.Response>(
|
return FutureBuilder<http.Response>(
|
||||||
future: fetchClassTimetable(),
|
future: fetchClassTimetable(),
|
||||||
@ -75,9 +115,9 @@ Widget buildClassTimetable() {
|
|||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
int statusCode = snapshot.data!.statusCode;
|
int statusCode = snapshot.data!.statusCode;
|
||||||
if (statusCode == 200) {
|
if (statusCode == 200) {
|
||||||
ListView timetableView = ClassTimetableBuilder.buildView(
|
Widget timetableView = ClassTimetableBuilder.buildView(
|
||||||
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)))
|
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), context)
|
||||||
.view;
|
.view.child;
|
||||||
return timetableView;
|
return timetableView;
|
||||||
} else if (statusCode == 400) {
|
} else if (statusCode == 400) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
@ -110,18 +150,93 @@ Widget buildTodayClassTimetable() {
|
|||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
int statusCode = snapshot.data!.statusCode;
|
int statusCode = snapshot.data!.statusCode;
|
||||||
if (statusCode == 200) {
|
if (statusCode == 200) {
|
||||||
ListView timetableView = ClassTimetableBuilder.buildView(
|
Widget timetableView = ClassTimetableBuilder.buildView(
|
||||||
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)))
|
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), context)
|
||||||
.view;
|
.view.child;
|
||||||
return timetableView;
|
return timetableView;
|
||||||
} else if (statusCode == 400) {
|
} else if (statusCode == 400) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context, MaterialPageRoute(builder: (context) => Login()));
|
context, MaterialPageRoute(builder: (context) => Login()));
|
||||||
} else if (statusCode == 500) {
|
} 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 Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||||
|
child: ListView(
|
||||||
|
children: [card],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (statusCode == 404) {
|
||||||
return const Padding(
|
return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
child: Center(child: Text("Es konnte kein Vertretungsplan für heute gefunden werden.")),
|
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'));
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text('$snapshot.error');
|
||||||
|
} else {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildTomorrowClassTimetable() {
|
||||||
|
return FutureBuilder<http.Response>(
|
||||||
|
future: fetchTomorrowClassTimetable(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
int statusCode = snapshot.data!.statusCode;
|
||||||
|
if (statusCode == 200) {
|
||||||
|
Widget timetableView = ClassTimetableBuilder.buildView(
|
||||||
|
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)), 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 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(
|
||||||
|
children: cardChildren,
|
||||||
|
));
|
||||||
|
return Padding(
|
||||||
|
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.")),
|
||||||
|
);*/
|
||||||
} else if (statusCode == 404) {
|
} else if (statusCode == 404) {
|
||||||
return const Padding(
|
return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
@ -153,10 +268,25 @@ Widget buildClassTimetableLesson(int count) {
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context, MaterialPageRoute(builder: (context) => Login()));
|
context, MaterialPageRoute(builder: (context) => Login()));
|
||||||
} else if (statusCode == 500) {
|
} else if (statusCode == 500) {
|
||||||
return const Padding(
|
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))
|
||||||
|
));
|
||||||
|
Card card = Card(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Column(
|
||||||
|
children: cardChildren,
|
||||||
|
));
|
||||||
|
return card;
|
||||||
|
/*return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
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) {
|
} else if (statusCode == 404) {
|
||||||
return const Padding(
|
return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
@ -203,13 +333,34 @@ Widget buildTodayClassTimetableLesson(int count) {
|
|||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
} else if (statusCode == 400) {
|
} else if (statusCode == 400) {
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context, MaterialPageRoute(builder: (context) => Login()));
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
Login()),
|
||||||
|
);
|
||||||
|
});
|
||||||
} else if (statusCode == 500) {
|
} else if (statusCode == 500) {
|
||||||
return const Padding(
|
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;
|
||||||
|
/*return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
child: Center(child: Text("Es konnte kein Vertretungsplan für heute gefunden werden.")),
|
child: Center(child: Text("Es konnte kein Vertretungsplan für heute gefunden werden.")),
|
||||||
);
|
);*/
|
||||||
} else if (statusCode == 404) {
|
} else if (statusCode == 404) {
|
||||||
return const Padding(
|
return const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
@ -304,7 +455,7 @@ class _ClassesChooserState extends State<ClassesChooser> {
|
|||||||
return DropdownButtonFormField<String>(
|
return DropdownButtonFormField<String>(
|
||||||
value: dropdownValue,
|
value: dropdownValue,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
icon: Icon(CupertinoIcons.number),
|
icon: Icon(Icons.people_outline),
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
labelText: 'Klasse (05/1, 07/3, 10/2...)',
|
labelText: 'Klasse (05/1, 07/3, 10/2...)',
|
||||||
),
|
),
|
||||||
|
@ -11,8 +11,64 @@ class SZ extends StatelessWidget {
|
|||||||
title: const Text("Schülerzeitung"),
|
title: const Text("Schülerzeitung"),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: const Center(
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
child: Column(children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||||
|
child: ListTile(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => Article()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
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...")),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
/*const Center(
|
||||||
child: Text("Derzeit nichts hier..."),
|
child: Text("Derzeit nichts hier..."),
|
||||||
|
)*/
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Article extends StatelessWidget {
|
||||||
|
const Article({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text(
|
||||||
|
"Schülersprecherwahl 2021: Kandidatenduos im Interview"),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||||
|
children: const [
|
||||||
|
Text("""
|
||||||
|
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||||
|
|
||||||
|
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||||
|
|
||||||
|
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||||
|
|
||||||
|
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer
|
||||||
|
""")
|
||||||
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'networking.dart';
|
|
||||||
|
|
||||||
class Settings extends StatelessWidget {
|
|
||||||
const Settings({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text("Einstellungen"),
|
|
||||||
centerTitle: true,
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
|
|
||||||
children: [
|
|
||||||
const ListTile(
|
|
||||||
leading: Icon(CupertinoIcons.rectangle_grid_1x2),
|
|
||||||
title: Text("Plan")),
|
|
||||||
/*
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
|
|
||||||
child: TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
icon: Icon(CupertinoIcons.lock),
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'API Key (POST /login)',
|
|
||||||
),
|
|
||||||
onSubmitted: (String value) async {
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
String api_key = value;
|
|
||||||
print('Set new API key to $api_key');
|
|
||||||
await prefs.setString('api_key', api_key);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
const Divider(),
|
|
||||||
buildClassesChooser(),
|
|
||||||
const Divider(),
|
|
||||||
const ListTile(
|
|
||||||
leading: Icon(Icons.code), title: Text("Entwickleroptionen")),
|
|
||||||
const Divider(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
|
||||||
child: TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
icon: Icon(CupertinoIcons.lock),
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'API Key (POST /login)',
|
|
||||||
),
|
|
||||||
onSubmitted: (String value) async {
|
|
||||||
SharedPreferences prefs =
|
|
||||||
await SharedPreferences.getInstance();
|
|
||||||
String apiKey = value;
|
|
||||||
print('Set new API key to $apiKey');
|
|
||||||
await prefs.setString('api_key', apiKey);
|
|
||||||
})),
|
|
||||||
const Divider(),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
33
lib/subject_presets.dart
Normal file
33
lib/subject_presets.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
dynamic names = {
|
||||||
|
'Bio': 'Biologie',
|
||||||
|
'Mat': 'Mathematik',
|
||||||
|
'matL1': 'Mathematik Leistungskurs 1',
|
||||||
|
'Kun': 'Kunst',
|
||||||
|
'Mus': 'Musik',
|
||||||
|
'Geo': 'Geographie',
|
||||||
|
'Ges': 'Geschichte',
|
||||||
|
'Che': 'Chemie',
|
||||||
|
'Lat': 'Latein',
|
||||||
|
'Inf': 'Informatik',
|
||||||
|
'Eng': 'Englisch',
|
||||||
|
'Frz': 'Französisch',
|
||||||
|
'frz1': 'Französisch 1',
|
||||||
|
'frz2': 'Französisch 2',
|
||||||
|
'frz3': 'Französisch 3',
|
||||||
|
'Phy': 'Physik',
|
||||||
|
'---': '---',
|
||||||
|
'Spo': 'Sport',
|
||||||
|
'Deu': 'Deutsch',
|
||||||
|
'deu1': 'Deutsch 1',
|
||||||
|
'deu2': 'Deutsch 2',
|
||||||
|
'deu3': 'Deutsch 3',
|
||||||
|
'Lme': 'Lernmethoden',
|
||||||
|
'Eth': 'Ethik',
|
||||||
|
'EvR': 'Evangelische Religion',
|
||||||
|
'Soz': 'Sozialkunde',
|
||||||
|
'Ast': 'Astronomie',
|
||||||
|
'Spa': 'Spanisch',
|
||||||
|
'FK': 'Fachkurs',
|
||||||
|
'JIA': 'Junior-Ingenieur-Akademie',
|
||||||
|
'WoU': 'Wahlobligatorischer Unterricht'
|
||||||
|
};
|
55
lib/teacher_presets.dart
Normal file
55
lib/teacher_presets.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
dynamic teachers = {
|
||||||
|
'Poli': 'Herr Polity',
|
||||||
|
'Zura': 'Frau Zuralski',
|
||||||
|
'Enzi': 'Frau Enzian',
|
||||||
|
'Bütt': 'Frau Büttner',
|
||||||
|
'Brod': 'Herr Brode',
|
||||||
|
'Rink': 'Frau Rinke',
|
||||||
|
'Schk': 'Frau Schmidt',
|
||||||
|
'Rudo': 'Frau Rudolph',
|
||||||
|
'Kipp': 'Frau Kipping',
|
||||||
|
'Bach': 'Frau Bachran',
|
||||||
|
'Bad': 'Herr Bader',
|
||||||
|
'Prei': 'Frau Preiß',
|
||||||
|
'Scha': 'Frau Schapitz',
|
||||||
|
' ': '',
|
||||||
|
'Link': 'Herr Linke',
|
||||||
|
'Stei': 'Herr Stein',
|
||||||
|
'Tupp': 'Frau Tuppack',
|
||||||
|
'Hoff': 'Frau Hoffman',
|
||||||
|
'Knol': 'Frau Knoll',
|
||||||
|
'Bet': 'Frau Bethin',
|
||||||
|
'Schu': 'Frau Schulz',
|
||||||
|
'Seid': 'Frau Seidel',
|
||||||
|
'Krug': 'Frau Krug',
|
||||||
|
'Laer': 'Frau Langer',
|
||||||
|
'Youn': 'Frau Younso',
|
||||||
|
'Härt': 'Frau Härtig',
|
||||||
|
'Bros': 'Frau Brosig',
|
||||||
|
'Ber': 'Frau Bernhardt',
|
||||||
|
'Stüb': 'Frau Stüber',
|
||||||
|
'Bor': 'Frau Borchert',
|
||||||
|
'Dubb': 'Frau Dubberstein',
|
||||||
|
'Tren': 'Frau Trentsch',
|
||||||
|
'Meit': 'Herr Meitzner',
|
||||||
|
'Stol': 'Frau Stolpe',
|
||||||
|
'Jac': 'Frau Jacob',
|
||||||
|
'Jüne': 'Herr Jünemann',
|
||||||
|
'Bert': 'Frau Berthelmann',
|
||||||
|
'Felk': 'Frau Felke',
|
||||||
|
'Kimm': 'Herr Kimmel',
|
||||||
|
'PM1': 'Pädagosische(r) Mitarbeiter(in) 1',
|
||||||
|
'Schet': 'Herr Schettler',
|
||||||
|
'Mani': 'Herr Manigk',
|
||||||
|
'Segg': 'Frau von Seggern',
|
||||||
|
'Opel': 'Frau Opel-Fritzler',
|
||||||
|
'Möll': 'Frau Möller',
|
||||||
|
'Laen': 'Herr Langen',
|
||||||
|
'Plin': 'Herr Plinke',
|
||||||
|
'Koch': 'Herr Koch',
|
||||||
|
'Gors': 'Herr Gorsler',
|
||||||
|
'Krau': 'Herr Krause',
|
||||||
|
'Henk': 'Frau Henke',
|
||||||
|
'Wolf': 'Herr Wolf',
|
||||||
|
'Gitt': 'Herr Gitter',
|
||||||
|
};
|
@ -1,15 +1,80 @@
|
|||||||
|
import 'package:MeinCantor/teacher_presets.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.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 {
|
class ClassTimetableBuilder {
|
||||||
final ListView view;
|
final RefreshIndicator view;
|
||||||
ClassTimetableBuilder({required this.view});
|
ClassTimetableBuilder({required this.view});
|
||||||
factory ClassTimetableBuilder.buildView(Map<String, dynamic> json) {
|
factory ClassTimetableBuilder.buildView(Map<String, dynamic> json, BuildContext context) {
|
||||||
return ClassTimetableBuilder(
|
List<Widget> list = LessonsListBuilder.buildList(json).lessons;
|
||||||
view: ListView(
|
String info = TimetableInfo.fromJson(json).info;
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
if(info.isNotEmpty) {
|
||||||
children: LessonsListBuilder.buildList(json).lessons));
|
list.insert(0, ListTile(title: Text("Informationen"), leading: Icon(MdiIcons.information), onTap: () {
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(25.0),
|
||||||
|
),
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
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),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Text(info),
|
||||||
|
),
|
||||||
|
/*ElevatedButton(
|
||||||
|
child: const Text('Close BottomSheet'),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
)*/
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
return ClassTimetableBuilder(
|
||||||
|
view: RefreshIndicator(
|
||||||
|
onRefresh: () {
|
||||||
|
return Future.delayed(const Duration(seconds: 1));
|
||||||
|
},
|
||||||
|
child: ListView(
|
||||||
|
//shrinkWrap: true,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
children: list,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Color> buildLessonColor(String lesson) async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
if (!prefs.containsKey("color$lesson")) {
|
||||||
|
Color lessonPresetColor = colors[lesson] ?? Colors.grey[700];
|
||||||
|
prefs.setInt("color$lesson", lessonPresetColor.value);
|
||||||
|
}
|
||||||
|
Color lessonColor = Color(prefs.getInt("color$lesson")!);
|
||||||
|
return lessonColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LessonsListBuilder {
|
class LessonsListBuilder {
|
||||||
@ -21,7 +86,6 @@ class LessonsListBuilder {
|
|||||||
List<Widget> cardChildren = [];
|
List<Widget> cardChildren = [];
|
||||||
print(element.count.toString() + " " + count.toString());
|
print(element.count.toString() + " " + count.toString());
|
||||||
if (element.count.toString() == count.toString() || count == 0) {
|
if (element.count.toString() == count.toString() || count == 0) {
|
||||||
print("teeee");
|
|
||||||
cardChildren.add(ListTile(
|
cardChildren.add(ListTile(
|
||||||
title: Text(element.count.toString() + '.' + ' ' + element.name,
|
title: Text(element.count.toString() + '.' + ' ' + element.name,
|
||||||
style: TextStyle(color: element.fontColor)),
|
style: TextStyle(color: element.fontColor)),
|
||||||
@ -40,14 +104,23 @@ class LessonsListBuilder {
|
|||||||
title: Text(element.info,
|
title: Text(element.info,
|
||||||
style: TextStyle(color: element.fontColor))));
|
style: TextStyle(color: element.fontColor))));
|
||||||
}
|
}
|
||||||
Card card = Card(
|
Widget card = FutureBuilder(
|
||||||
|
future: element.color,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
return Card(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(15.0),
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
),
|
),
|
||||||
color: element.color,
|
color: snapshot.data as Color,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: cardChildren,
|
children: cardChildren,
|
||||||
));
|
));
|
||||||
|
} else {
|
||||||
|
return (const Center(child: CircularProgressIndicator()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
children.add(card);
|
children.add(card);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -55,6 +128,14 @@ class LessonsListBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TimetableInfo {
|
||||||
|
final String info;
|
||||||
|
TimetableInfo({required this.info});
|
||||||
|
factory TimetableInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return TimetableInfo(info: json['info']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ClassTimetable {
|
class ClassTimetable {
|
||||||
final List timetable;
|
final List timetable;
|
||||||
ClassTimetable({required this.timetable});
|
ClassTimetable({required this.timetable});
|
||||||
@ -65,60 +146,7 @@ class ClassTimetable {
|
|||||||
var name;
|
var name;
|
||||||
var teacher;
|
var teacher;
|
||||||
var room;
|
var room;
|
||||||
dynamic teachers = {
|
|
||||||
'Poli': 'Herr Polity',
|
|
||||||
'Zura': 'Frau Zuralski',
|
|
||||||
'Enzi': 'Frau Enzian',
|
|
||||||
'Bütt': 'Frau Büttner',
|
|
||||||
'Brod': 'Herr Brode',
|
|
||||||
'Rink': 'Frau Rinke',
|
|
||||||
'Schk': 'Frau Schmidt',
|
|
||||||
'Rudo': 'Frau Rudolph',
|
|
||||||
'Kipp': 'Frau Kipping',
|
|
||||||
'Bach': 'Frau Bachran',
|
|
||||||
'Bad': 'Herr Bader',
|
|
||||||
'Prei': 'Frau Preiß',
|
|
||||||
'Scha': 'Frau Schapitz',
|
|
||||||
' ': '',
|
|
||||||
'Link': 'Herr Linke',
|
|
||||||
'Stei': 'Herr Stein',
|
|
||||||
'Tupp': 'Frau Tuppack',
|
|
||||||
'Hoff': 'Frau Hoffman',
|
|
||||||
'Knol': 'Frau Knoll',
|
|
||||||
'Bet': 'Frau Bethin',
|
|
||||||
'Schu': 'Frau Schulz',
|
|
||||||
'Seid': 'Frau Seidel',
|
|
||||||
'Krug': 'Frau Krug',
|
|
||||||
'Laer': 'Frau Langer',
|
|
||||||
'Youn': 'Frau Younso',
|
|
||||||
'Härt': 'Frau Härtig',
|
|
||||||
'Bros': 'Frau Brosig',
|
|
||||||
'Ber': 'Frau Bernhardt',
|
|
||||||
'Stüb': 'Frau Stüber',
|
|
||||||
'Bor': 'Frau Borchert',
|
|
||||||
'Dubb': 'Frau Dubberstein',
|
|
||||||
'Tren': 'Frau Trentsch',
|
|
||||||
'Meit': 'Herr Meitzner',
|
|
||||||
'Stol': 'Frau Stolpe',
|
|
||||||
'Jac': 'Frau Jacob',
|
|
||||||
'Jüne': 'Herr Jünemann',
|
|
||||||
'Bert': 'Frau Berthelmann',
|
|
||||||
'Felk': 'Frau Felke',
|
|
||||||
'Kimm': 'Herr Kimmel',
|
|
||||||
'PM1': 'Pädagosische(r) Mitarbeiter(in) 1',
|
|
||||||
'Schet': 'Herr Schetler',
|
|
||||||
'Mani': 'Herr Manigk',
|
|
||||||
'Segg': 'Frau Seggern',
|
|
||||||
'Opel': 'Frau Opel-Fritzler',
|
|
||||||
'Möll': 'Frau Möller',
|
|
||||||
'Laen': 'Herr Langen',
|
|
||||||
'Plin': 'Herr Plinke',
|
|
||||||
'Koch': 'Herr Koch',
|
|
||||||
'Gors': 'Herr Gorsler',
|
|
||||||
'Krau': 'Herr Krause',
|
|
||||||
'Henk': 'Frau Henke',
|
|
||||||
'Wolf': 'Herr Wolf'
|
|
||||||
};
|
|
||||||
if (value['Fa'].runtimeType != String) {
|
if (value['Fa'].runtimeType != String) {
|
||||||
name = value['Fa']['#text'];
|
name = value['Fa']['#text'];
|
||||||
} else {
|
} else {
|
||||||
@ -156,81 +184,7 @@ class ClassTimetable {
|
|||||||
info = value['If'];
|
info = value['If'];
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic colors = {
|
Future<Color> lessonColor = buildLessonColor(name);
|
||||||
'Bio': Colors.green,
|
|
||||||
'Mat': Colors.indigo,
|
|
||||||
'matL1': Colors.indigo,
|
|
||||||
'matL2': Colors.indigo,
|
|
||||||
'matL3': Colors.indigo,
|
|
||||||
'Deu': Colors.red,
|
|
||||||
'deu1': Colors.red,
|
|
||||||
'deu2': Colors.red,
|
|
||||||
'deu3': Colors.red,
|
|
||||||
'Kun': Colors.deepPurple,
|
|
||||||
'kun1': Colors.deepPurple,
|
|
||||||
'kun2': Colors.deepPurple,
|
|
||||||
'kun3': Colors.deepPurple,
|
|
||||||
'Geo': Colors.brown,
|
|
||||||
'Lat': Colors.teal,
|
|
||||||
'lat1': Colors.teal,
|
|
||||||
'lat2': Colors.teal,
|
|
||||||
'lat3': Colors.teal,
|
|
||||||
'Che': Colors.lightGreen,
|
|
||||||
'Eng': Colors.amber,
|
|
||||||
'eng1': Colors.amber,
|
|
||||||
'eng2': Colors.amber,
|
|
||||||
'eng3': Colors.amber,
|
|
||||||
'Phy': Colors.cyan,
|
|
||||||
'phy1': Colors.cyan,
|
|
||||||
'phy2': Colors.cyan,
|
|
||||||
'phy3': Colors.cyan,
|
|
||||||
'Inf': Colors.tealAccent[400],
|
|
||||||
'Mus': Colors.deepOrange,
|
|
||||||
'mus1': Colors.deepOrange,
|
|
||||||
'mus2': Colors.deepOrange,
|
|
||||||
'mus3': Colors.deepOrange,
|
|
||||||
'Lme': Colors.amber[700],
|
|
||||||
'Ges': Colors.grey,
|
|
||||||
'ges1': Colors.grey,
|
|
||||||
'ges2': Colors.grey,
|
|
||||||
'ges3': Colors.grey,
|
|
||||||
'Spa': Colors.redAccent,
|
|
||||||
'Frz': Colors.amberAccent[700],
|
|
||||||
'frz1': Colors.amberAccent[700],
|
|
||||||
'---': Colors.white
|
|
||||||
};
|
|
||||||
|
|
||||||
dynamic names = {
|
|
||||||
'Bio': 'Biologie',
|
|
||||||
'Mat': 'Mathematik',
|
|
||||||
'matL1': 'Mathematik Leistungskurs 1',
|
|
||||||
'Kun': 'Kunst',
|
|
||||||
'Mus': 'Musik',
|
|
||||||
'Geo': 'Geographie',
|
|
||||||
'Ges': 'Geschichte',
|
|
||||||
'Che': 'Chemie',
|
|
||||||
'Lat': 'Latein',
|
|
||||||
'Inf': 'Informatik',
|
|
||||||
'Eng': 'Englisch',
|
|
||||||
'Frz': 'Französisch',
|
|
||||||
'frz1': 'Französisch 1',
|
|
||||||
'Phy': 'Physik',
|
|
||||||
'---': '---',
|
|
||||||
'Spo': 'Sport',
|
|
||||||
'Deu': 'Deutsch',
|
|
||||||
'deu1': 'Deutsch 1',
|
|
||||||
'deu2': 'Deutsch 2',
|
|
||||||
'deu3': 'Deutsch 3',
|
|
||||||
'Lme': 'Lernmethoden',
|
|
||||||
'Eth': 'Ethik',
|
|
||||||
'EvR': 'Evangelische Religion',
|
|
||||||
'Soz': 'Sozialkunde',
|
|
||||||
'Ast': 'Astronomie',
|
|
||||||
'Spa': 'Spanisch',
|
|
||||||
'FK': 'Fachkurs',
|
|
||||||
'JIA': 'Junior-Ingenieur-Akademie',
|
|
||||||
'WoU': 'Wahlobligatorischer Unterricht'
|
|
||||||
};
|
|
||||||
|
|
||||||
lessons.add(TimetableLesson(
|
lessons.add(TimetableLesson(
|
||||||
value['St'],
|
value['St'],
|
||||||
@ -238,7 +192,7 @@ class ClassTimetable {
|
|||||||
teachers[teacher] ?? teacher.toString(),
|
teachers[teacher] ?? teacher.toString(),
|
||||||
room.toString(),
|
room.toString(),
|
||||||
value['If'].toString(),
|
value['If'].toString(),
|
||||||
colors[name] ?? Colors.grey[700],
|
lessonColor,
|
||||||
fontColor,
|
fontColor,
|
||||||
info));
|
info));
|
||||||
});
|
});
|
||||||
@ -253,7 +207,7 @@ class TimetableLesson {
|
|||||||
final String teacher;
|
final String teacher;
|
||||||
final String room;
|
final String room;
|
||||||
final String comment;
|
final String comment;
|
||||||
final Color color;
|
final Future<Color> color;
|
||||||
final Color fontColor;
|
final Color fontColor;
|
||||||
final String info;
|
final String info;
|
||||||
const TimetableLesson(this.count, this.name, this.teacher, this.room,
|
const TimetableLesson(this.count, this.name, this.teacher, this.room,
|
||||||
|
@ -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: 0.6.5-alpha
|
version: 0.7.5-beta1.nightly2021-11-04
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.12.0 <3.0.0"
|
sdk: ">=2.12.0 <3.0.0"
|
||||||
@ -38,6 +38,9 @@ dependencies:
|
|||||||
time: ^2.0.0
|
time: ^2.0.0
|
||||||
flutter_launcher_icons: "^0.9.1"
|
flutter_launcher_icons: "^0.9.1"
|
||||||
fluttertoast: ^8.0.8
|
fluttertoast: ^8.0.8
|
||||||
|
flutter_colorpicker: ^0.6.0
|
||||||
|
material_design_icons_flutter: 5.0.5955-rc.1
|
||||||
|
cyclop: ^0.5.2
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
# image_path: "assets/images/icon-128x128.png"
|
# image_path: "assets/images/icon-128x128.png"
|
||||||
|
Reference in New Issue
Block a user