==1.0.0==

- removed obsolete deps
- fixed many issues
- improved features
- added:
  * favourites
  * account console
  * push notifications
  * background sync
  * improved settings
This commit is contained in:
Denys Konovalov 2021-12-19 22:20:56 +01:00
parent db6c41a1ce
commit ba75ce8d6d
71 changed files with 6614 additions and 1468 deletions

19
.vscode/launch.json vendored Normal file

@ -0,0 +1,19 @@
{
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "app",
"request": "launch",
"type": "dart"
},
{
"name": "app (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
}
]
}

BIN
android.zip Normal file

Binary file not shown.

@ -4,15 +4,21 @@
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="PLATFORM" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android" />
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android" />
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/background_fetch-1.0.3/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_local_notifications-10.0.0-dev.1/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.5/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.8/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-2.0.0+4/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_android-6.0.13/android" />
<option value="$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter_android-2.8.0/android" />
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />

@ -26,5 +26,55 @@
<option name="name" value="Google3" /> <option name="name" value="Google3" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" /> <option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$PROJECT_DIR$/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_local_notifications-10.0.0-dev.1/android/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.5/android/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-2.0.0+4/android/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter_android-2.8.0/android/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_android-6.0.13/android/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/background_fetch-1.0.3/android/libs/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$PROJECT_DIR$/app/libs" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="file:$USER_HOME$/tools/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.8/android/libs" />
</remote-repository>
</component> </component>
</project> </project>

@ -1,7 +0,0 @@
<component name="libraryTable">
<library name="Flutter Plugins" type="FlutterPluginsLibraryType">
<CLASSES />
<JAVADOC />
<SOURCES />
</library>
</component>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.activity:activity:1.0.0@aar"> <library name="Gradle: androidx.activity:activity:1.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/68dbf8ea01a1dbd974fc87b5753550f0/jetified-activity-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/68dbf8ea01a1dbd974fc87b5753550f0/jetified-activity-1.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/68dbf8ea01a1dbd974fc87b5753550f0/jetified-activity-1.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/68dbf8ea01a1dbd974fc87b5753550f0/jetified-activity-1.0.0/AndroidManifest.xml" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/7d4bfe2a8fe4cc7cfb1eb08c8f16cfa7/transformed/jetified-activity-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/7d4bfe2a8fe4cc7cfb1eb08c8f16cfa7/transformed/jetified-activity-1.0.0/AndroidManifest.xml" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/7d4bfe2a8fe4cc7cfb1eb08c8f16cfa7/transformed/jetified-activity-1.0.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: androidx.annotation:annotation:1.1.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/e3a6fb2f40e3a3842e6b7472628ba4ce416ea4c8/annotation-1.1.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/408af38ec57369afe3fd6466e1c4bfdd5f15fc92/annotation-1.1.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/8b7bdc00eb4d998bfbc76767b098620990f2a805/annotation-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar"> <library name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/5f606c30f064eed94124828de37fadc0/core-runtime-2.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/5f606c30f064eed94124828de37fadc0/core-runtime-2.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/5f606c30f064eed94124828de37fadc0/core-runtime-2.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/5f606c30f064eed94124828de37fadc0/core-runtime-2.0.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/b15e9b60227c1d77e2391c0767d49728/transformed/core-runtime-2.0.0/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/b15e9b60227c1d77e2391c0767d49728/transformed/core-runtime-2.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/b15e9b60227c1d77e2391c0767d49728/transformed/core-runtime-2.0.0/AndroidManifest.xml" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,16 +0,0 @@
<component name="libraryTable">
<library name="Gradle: androidx.core:core:1.1.0@aar">
<ANNOTATIONS>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2e94107f30f39be366a17347c2bf100b/core-1.1.0/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2e94107f30f39be366a17347c2bf100b/core-1.1.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2e94107f30f39be366a17347c2bf100b/core-1.1.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2e94107f30f39be366a17347c2bf100b/core-1.1.0/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.core/core/1.1.0/4ae37fad1fe95b42aa47a720908df37ba5d3c85e/core-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.customview:customview:1.0.0@aar"> <library name="Gradle: androidx.customview:customview:1.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/bc28a09d8d2212ffd5788fe6c1853326/customview-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/bc28a09d8d2212ffd5788fe6c1853326/customview-1.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/bc28a09d8d2212ffd5788fe6c1853326/customview-1.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/bc28a09d8d2212ffd5788fe6c1853326/customview-1.0.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/1329a52a6813b6f962d4a50f002a018d/transformed/customview-1.0.0/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/1329a52a6813b6f962d4a50f002a018d/transformed/customview-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/1329a52a6813b6f962d4a50f002a018d/transformed/customview-1.0.0/AndroidManifest.xml" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,12 +1,13 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.fragment:fragment:1.1.0@aar"> <library name="Gradle: androidx.fragment:fragment:1.1.0@aar">
<ANNOTATIONS> <ANNOTATIONS>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2fd9120a6da4df3dbabdd40f6a2d8995/fragment-1.1.0/annotations.zip!/" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/cc4bb60650edfa741e4e3dc70607dcac/transformed/fragment-1.1.0/annotations.zip!/" />
</ANNOTATIONS> </ANNOTATIONS>
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2fd9120a6da4df3dbabdd40f6a2d8995/fragment-1.1.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2fd9120a6da4df3dbabdd40f6a2d8995/fragment-1.1.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2fd9120a6da4df3dbabdd40f6a2d8995/fragment-1.1.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2fd9120a6da4df3dbabdd40f6a2d8995/fragment-1.1.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/cc4bb60650edfa741e4e3dc70607dcac/transformed/fragment-1.1.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/cc4bb60650edfa741e4e3dc70607dcac/transformed/fragment-1.1.0/AndroidManifest.xml" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/cc4bb60650edfa741e4e3dc70607dcac/transformed/fragment-1.1.0/jars/classes.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar"> <library name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/fb333fb43575d8a3b51161295454427f/lifecycle-livedata-2.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/fb333fb43575d8a3b51161295454427f/lifecycle-livedata-2.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/fb333fb43575d8a3b51161295454427f/lifecycle-livedata-2.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/fb333fb43575d8a3b51161295454427f/lifecycle-livedata-2.0.0/AndroidManifest.xml" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/f3888261453da560a886165dfa0f8c7b/transformed/lifecycle-livedata-2.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/f3888261453da560a886165dfa0f8c7b/transformed/lifecycle-livedata-2.0.0/AndroidManifest.xml" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/f3888261453da560a886165dfa0f8c7b/transformed/lifecycle-livedata-2.0.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar"> <library name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cad25976877a6ae855ef6821534f58a1/lifecycle-livedata-core-2.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cad25976877a6ae855ef6821534f58a1/lifecycle-livedata-core-2.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cad25976877a6ae855ef6821534f58a1/lifecycle-livedata-core-2.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cad25976877a6ae855ef6821534f58a1/lifecycle-livedata-core-2.0.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/d804499608d4fe82c9642c020be13091/transformed/lifecycle-livedata-core-2.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/d804499608d4fe82c9642c020be13091/transformed/lifecycle-livedata-core-2.0.0/AndroidManifest.xml" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/d804499608d4fe82c9642c020be13091/transformed/lifecycle-livedata-core-2.0.0/jars/classes.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar"> <library name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/ca6b214160bd0909b103aa12202ef51c/lifecycle-runtime-2.2.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/ca6b214160bd0909b103aa12202ef51c/lifecycle-runtime-2.2.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/ca6b214160bd0909b103aa12202ef51c/lifecycle-runtime-2.2.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/ca6b214160bd0909b103aa12202ef51c/lifecycle-runtime-2.2.0/AndroidManifest.xml" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/b8be27952265c4f463c642420b3d8ef4/transformed/lifecycle-runtime-2.2.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/b8be27952265c4f463c642420b3d8ef4/transformed/lifecycle-runtime-2.2.0/AndroidManifest.xml" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/b8be27952265c4f463c642420b3d8ef4/transformed/lifecycle-runtime-2.2.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar"> <library name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/15792e6083b2b5b5a7ffa285d47daa24/lifecycle-viewmodel-2.1.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/15792e6083b2b5b5a7ffa285d47daa24/lifecycle-viewmodel-2.1.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/15792e6083b2b5b5a7ffa285d47daa24/lifecycle-viewmodel-2.1.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/15792e6083b2b5b5a7ffa285d47daa24/lifecycle-viewmodel-2.1.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/34ecbfc28f9f64b9b10e605849457cf1/transformed/lifecycle-viewmodel-2.1.0/AndroidManifest.xml" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/34ecbfc28f9f64b9b10e605849457cf1/transformed/lifecycle-viewmodel-2.1.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/34ecbfc28f9f64b9b10e605849457cf1/transformed/lifecycle-viewmodel-2.1.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.loader:loader:1.0.0@aar"> <library name="Gradle: androidx.loader:loader:1.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d9536c14ffde0b7289f12ba6def6bfa4/loader-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d9536c14ffde0b7289f12ba6def6bfa4/loader-1.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d9536c14ffde0b7289f12ba6def6bfa4/loader-1.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d9536c14ffde0b7289f12ba6def6bfa4/loader-1.0.0/AndroidManifest.xml" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-3/024a36b1ca020dc1ffa8d7896e3bf5ff/transformed/loader-1.0.0/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-3/024a36b1ca020dc1ffa8d7896e3bf5ff/transformed/loader-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/024a36b1ca020dc1ffa8d7896e3bf5ff/transformed/loader-1.0.0/AndroidManifest.xml" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.savedstate:savedstate:1.0.0@aar"> <library name="Gradle: androidx.savedstate:savedstate:1.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2271d874344878e62b9a8e309af0c39d/jetified-savedstate-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2271d874344878e62b9a8e309af0c39d/jetified-savedstate-1.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2271d874344878e62b9a8e309af0c39d/jetified-savedstate-1.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/2271d874344878e62b9a8e309af0c39d/jetified-savedstate-1.0.0/AndroidManifest.xml" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/a564c650009ac14109f29da32f460971/transformed/jetified-savedstate-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/a564c650009ac14109f29da32f460971/transformed/jetified-savedstate-1.0.0/AndroidManifest.xml" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/a564c650009ac14109f29da32f460971/transformed/jetified-savedstate-1.0.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/96aee308bccd03bc62c306516c23a410/versionedparcelable-1.1.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/96aee308bccd03bc62c306516c23a410/versionedparcelable-1.1.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/96aee308bccd03bc62c306516c23a410/versionedparcelable-1.1.0/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.versionedparcelable/versionedparcelable/1.1.0/d9085927216387af679d18b6f472bc0fc5c7cc81/versionedparcelable-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>

@ -1,9 +1,10 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: androidx.viewpager:viewpager:1.0.0@aar"> <library name="Gradle: androidx.viewpager:viewpager:1.0.0@aar">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/eb26273f8f7192460456ce62b9bdf9ef/viewpager-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/eb26273f8f7192460456ce62b9bdf9ef/viewpager-1.0.0/res" /> <root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/eb26273f8f7192460456ce62b9bdf9ef/viewpager-1.0.0/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/eb26273f8f7192460456ce62b9bdf9ef/viewpager-1.0.0/AndroidManifest.xml" /> <root url="jar://$USER_HOME$/.gradle/caches/transforms-3/8552b7074c8a7488b55dc3c476b7f2c3/transformed/viewpager-1.0.0/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/8552b7074c8a7488b55dc3c476b7f2c3/transformed/viewpager-1.0.0/AndroidManifest.xml" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-3/8552b7074c8a7488b55dc3c476b7f2c3/transformed/viewpager-1.0.0/res" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>

@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="Gradle: io.flutter:arm64_v8a_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/arm64_v8a_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/31ce772b217fad9767b2b4c312be45723d5a4aff/arm64_v8a_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="Gradle: io.flutter:armeabi_v7a_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/armeabi_v7a_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/2451328148067a2ba68f9f8c9cdf9721b03e9bf6/armeabi_v7a_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/flutter_embedding_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/25be3a5a8b2782d003516239ea5de35152305ff5/flutter_embedding_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/flutter_embedding_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/e95f95dfa6111331ce75c3fdd7298c114320748b/flutter_embedding_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce-sources.jar!/" />
</SOURCES>
</library>
</component>

@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="Gradle: io.flutter:x86_64_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/x86_64_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/128a82a6af9a80d7230ba29ebed9c428e4a1fe9b/x86_64_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -1,9 +0,0 @@
<component name="libraryTable">
<library name="Gradle: io.flutter:x86_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/x86_debug/1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce/61fa4ea55499c66fda687ac6d38002af1fac8ab2/x86_debug-1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -3,7 +3,7 @@
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<type id="android" /> <type id="android" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

@ -4,8 +4,13 @@
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/android.iml" filepath="$PROJECT_DIR$/.idea/modules/android.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/modules/android.iml" filepath="$PROJECT_DIR$/.idea/modules/android.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/android.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/android.app.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/modules/app/android.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/android.app.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-442492029/android.path_provider.iml" filepath="$PROJECT_DIR$/.idea/modules/-442492029/android.path_provider.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/modules/-1506358272/android.background_fetch.iml" filepath="$PROJECT_DIR$/.idea/modules/-1506358272/android.background_fetch.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/1049519328/android.shared_preferences.iml" filepath="$PROJECT_DIR$/.idea/modules/1049519328/android.shared_preferences.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/modules/-731377546/android.flutter_local_notifications.iml" filepath="$PROJECT_DIR$/.idea/modules/-731377546/android.flutter_local_notifications.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-1978775972/android.sqflite.iml" filepath="$PROJECT_DIR$/.idea/modules/-1978775972/android.sqflite.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/2112108985/android.url_launcher_android.iml" filepath="$PROJECT_DIR$/.idea/modules/2112108985/android.url_launcher_android.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/1177527115/android.webview_flutter_android.iml" filepath="$PROJECT_DIR$/.idea/modules/1177527115/android.webview_flutter_android.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-1981079475/io.flutter.plugins.pathprovider.android.path_provider.iml" filepath="$PROJECT_DIR$/.idea/modules/-1981079475/io.flutter.plugins.pathprovider.android.path_provider.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/1076383611/io.flutter.plugins.sharedpreferences.android.shared_preferences.iml" filepath="$PROJECT_DIR$/.idea/modules/1076383611/io.flutter.plugins.sharedpreferences.android.shared_preferences.iml" />
</modules> </modules>
</component> </component>
</project> </project>

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":path_provider" external.linked.project.path="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="io.flutter.plugins.pathprovider" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":path_provider" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="4.1.0" />
<option name="LAST_KNOWN_AGP_VERSION" value="4.1.0" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/main/res;file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/debug/res;file://$MODULE_DIR$/../../../../build/path_provider/generated/res/rs/debug;file://$MODULE_DIR$/../../../../build/path_provider/generated/res/resValues/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/androidTest/res;file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/androidTestDebug/res;file://$MODULE_DIR$/../../../../build/path_provider/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../../build/path_provider/generated/res/resValues/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/../../../../build/path_provider/intermediates/javac/debug/classes" />
<output-test url="file://$MODULE_DIR$/../../../../build/path_provider/intermediates/javac/debugUnitTest/classes" />
<exclude-output />
<content url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2">
<sourceFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/main/java" isTestSource="false" />
<sourceFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/src/test/java" isTestSource="true" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/.dart_tool" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/.pub" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/android/.gradle" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/build" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/example/.dart_tool" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/example/.pub" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.2/example/build" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/aidl_source_output_dir/debug/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/aidl_source_output_dir/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/ap_generated_sources/debug/out">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/path_provider/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/ap_generated_sources/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/ap_generated_sources/debugUnitTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/renderscript_source_output_dir/debug/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/renderscript_source_output_dir/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/res/resValues/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/res/resValues/debug">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/path_provider/generated/res/resValues/debug" type="java-resource" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/res/rs/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/res/rs/debug" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/source/buildConfig/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/path_provider/generated/source/buildConfig/debug">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/path_provider/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
</content>
<orderEntry type="jdk" jdkName="Android API 29 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common-java8:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-common:2.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.annotation:annotation:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: com.google.guava:guava:28.1-android" level="project" />
<orderEntry type="library" name="Gradle: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Gradle: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Gradle: org.checkerframework:checker-compat-qual:2.5.5" level="project" />
<orderEntry type="library" name="Gradle: com.google.errorprone:error_prone_annotations:2.3.2" level="project" />
<orderEntry type="library" name="Gradle: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Gradle: org.codehaus.mojo:animal-sniffer-annotations:1.18" level="project" />
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.activity:activity:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.loader:loader:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.core:core:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.savedstate:savedstate:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
</component>
</module>

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":shared_preferences" external.linked.project.path="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="io.flutter.plugins.sharedpreferences" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":shared_preferences" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="4.1.0" />
<option name="LAST_KNOWN_AGP_VERSION" value="4.1.0" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/src/main/res;file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/src/debug/res;file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/rs/debug;file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/resValues/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/src/androidTest/res;file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/src/androidTestDebug/res;file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/resValues/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/../../../../build/shared_preferences/intermediates/javac/debug/classes" />
<output-test url="file://$MODULE_DIR$/../../../../build/shared_preferences/intermediates/javac/debugUnitTest/classes" />
<exclude-output />
<content url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6">
<sourceFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/src/main/java" isTestSource="false" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/.dart_tool" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/.pub" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/android/.gradle" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/build" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/example/.dart_tool" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/example/.pub" />
<excludeFolder url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shared_preferences-2.0.6/example/build" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/aidl_source_output_dir/debug/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/aidl_source_output_dir/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/ap_generated_sources/debug/out">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/ap_generated_sources/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/ap_generated_sources/debugUnitTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/renderscript_source_output_dir/debug/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/renderscript_source_output_dir/debugAndroidTest/out" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/resValues/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/resValues/debug">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/resValues/debug" type="java-resource" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/rs/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/res/rs/debug" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/source/buildConfig/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/source/buildConfig/debug">
<sourceFolder url="file://$MODULE_DIR$/../../../../build/shared_preferences/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
</content>
<orderEntry type="jdk" jdkName="Android API 29 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common-java8:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-common:2.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.annotation:annotation:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.activity:activity:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.loader:loader:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.core:core:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.savedstate:savedstate:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar" level="project" />
</component>
</module>

@ -3,12 +3,11 @@
<component name="FacetManager"> <component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle"> <facet type="java-gradle" name="Java-Gradle">
<configuration> <configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../build" />
<option name="BUILDABLE" value="false" /> <option name="BUILDABLE" value="false" />
</configuration> </configuration>
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager" inherit-compiler-output="true"> <component name="NewModuleRootManager">
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$/../.."> <content url="file://$MODULE_DIR$/../..">
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" /> <excludeFolder url="file://$MODULE_DIR$/../../.gradle" />

File diff suppressed because one or more lines are too long

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 30 compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -45,7 +45,7 @@ android {
// 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 20 minSdkVersion 20
targetSdkVersion 30 targetSdkVersion rootProject.ext.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }

@ -1,6 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="de.cantorgymnasium.meincantor"> package="de.cantorgymnasium.meincantor">
<uses-permission android:name="android.permission.INTERNET"/>
<application <application
tools:replace="android:label"
android:label="GCG.MeinCantor" android:label="GCG.MeinCantor"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@ -9,9 +12,9 @@
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
android:showWhenLocked="true" android:showWhenLocked="true"
android:turnScreenOn="true" android:turnScreenOn="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
@ -40,5 +43,4 @@
android:name="flutterEmbedding" android:name="flutterEmbedding"
android:value="2" /> android:value="2" />
</application> </application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest> </manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

@ -1,12 +1,17 @@
buildscript { buildscript {
ext.kotlin_version = '1.3.50' ext.kotlin_version = '1.3.72'
ext {
compileSdkVersion = 30 // or latest
targetSdkVersion = 30 // or latest
appCompatVersion = "1.1.0" // or latest
}
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }
@ -15,6 +20,10 @@ allprojects {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven {
// [required] background_fetch
url "${project(':background_fetch').projectDir}/libs"
}
} }
} }

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

2132
android/hs_err_pid12837.log Normal file

File diff suppressed because it is too large Load Diff

1732
android/hs_err_pid6124.log Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1025.8879"
height="560.1051"
viewBox="0 0 271.43285 148.19448"
version="1.1"
id="svg5"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
sodipodi:docname="meincantor-big-dark.svg"
inkscape:export-filename="/home/denyskon/meincantor-big.png"
inkscape:export-xdpi="95.810593"
inkscape:export-ydpi="95.810593"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
units="px"
width="1024px"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.45892536"
inkscape:cx="290.89698"
inkscape:cy="459.76975"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2">
<rect
x="35.424603"
y="436.05106"
width="722.85211"
height="273.31204"
id="rect3787" />
<rect
id="rect101"
width="1231.0179"
height="630.59302"
x="-576.46198"
y="149.707" />
</defs>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0.24979931,0.24999975)">
<g
id="layer1-6"
transform="matrix(0.21011832,0,0,0.21011832,219.07839,-31.22162)"
inkscape:export-filename="/home/denys/GCG/Moodle/GCG Logo.png"
inkscape:export-xdpi="14.6812"
inkscape:export-ydpi="14.6812"
style="stroke:#1a1a37;stroke-width:2.37961;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
style="fill:#ffbc38;fill-opacity:1;stroke:#1a1a37;stroke-width:2.37961;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path94"
d="m -800.20189,148.59075 c -15.66268,0.005 -30.93737,0.32979 -35.92752,0.97152 -24.97802,3.21209 -46.06623,10.40832 -71.03494,24.24038 -39.97029,22.14261 -74.9122,57.98028 -99.47355,102.02323 -30.8652,55.34705 -42.151,113.50098 -32.8321,169.17882 5.8702,35.07216 16.8579,61.17871 40.68799,96.67317 7.95457,11.84812 11.84213,16.78099 24.46931,31.04978 14.63989,16.54318 27.57386,28.10203 42.20104,37.7145 28.86973,18.97219 57.71137,30.08127 95.58848,36.81738 v 10e-4 c 5.82412,1.03579 11.34034,1.26458 31.88746,1.32448 29.27973,0.0855 41.98501,-0.79986 60.14103,-4.19251 28.56955,-5.3386 57.43662,-16.77149 86.12757,-34.11008 33.44712,-20.21282 61.80706,-48.4681 81.46479,-81.16454 2.61834,-4.35506 4.64965,-8.00301 4.51392,-8.10649 -1.17086,-0.89357 -95.91117,-53.61068 -96.34604,-53.61068 -0.31474,0 -1.29111,1.27902 -2.16939,2.84169 -6.00422,10.68316 -23.40278,29.78738 -34.7033,38.10569 -38.44099,28.29642 -85.40586,35.86808 -129.74092,20.91759 -44.55018,-15.02312 -79.25266,-52.35019 -90.71746,-97.57855 -3.25589,-12.8444 -4.07642,-19.7718 -4.10362,-34.62114 -0.0427,-24.05789 4.0303,-42.064 14.11128,-62.38792 23.94487,-48.27458 71.92399,-78.04898 125.76906,-78.04898 37.71851,0 72.5558,14.34737 98.97588,40.76237 7.22351,7.22214 17.36655,20.0891 21.37491,27.11514 1.14192,2.00157 2.27232,3.55695 2.51201,3.45663 0.23966,-0.1005 21.42683,-11.94867 47.08239,-26.32914 30.23246,-16.94596 46.47755,-26.42693 46.16617,-26.94409 -15.24453,-25.3227 -37.5117,-51.05103 -60.39477,-69.78282 -19.53739,-15.99307 -45.92463,-31.3187 -70.29079,-40.8249 -21.82173,-8.51359 -38.29612,-12.71106 -57.08179,-14.54278 -6.5434,-0.63855 -22.59441,-0.95366 -38.2571,-0.94878 z m 71.03339,248.12387 c -33.16717,0 -60.11718,0.18715 -59.88884,0.41548 0.22842,0.22842 27.12928,15.96042 59.77929,34.95962 32.65006,18.9992 59.59962,34.55902 59.88834,34.57722 0.28884,0.0183 0.52504,-15.7137 0.52504,-34.95962 v -34.9927 z" />
<text
style="font-style:normal;font-weight:400;font-size:499.798px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect101);fill:#ffbc38;fill-opacity:1;stroke:#1a1a37;stroke-width:1.75069;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="text99"
transform="matrix(1.3592448,0,0,1.3592448,227.35348,-182.72846)"
xml:space="preserve"><tspan
x="-576.46289"
y="601.60773"
id="tspan4911"><tspan
style="font-weight:900;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Heavy';shape-inside:url(#rect101)"
id="tspan4909">CG</tspan></tspan></text>
</g>
<g
aria-label="MeinCantor"
transform="matrix(1.2948467,0,0,1.2948467,-47.577624,-464.38522)"
id="text3785"
style="font-size:40px;line-height:1.25;white-space:pre;shape-inside:url(#rect3787);fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:export-filename="/home/denyskon/meincantor/app/assets/images/meincantor-big-dark.png"
inkscape:export-xdpi="95.810593"
inkscape:export-ydpi="95.810593">
<path
d="m 63.463828,444.49745 h -8.32 l -3.88,18.8 -4.16,-18.8 h -8.28 l -2.08,27.72 h 6.4 l 0.48,-10.76 c 0.16,-3.88 0.16,-7.32 -0.12,-11.4 l 4.56,19.24 h 6.2 l 4.28,-19.24 c -0.2,3.44 -0.12,7.44 0.08,11.32 l 0.48,10.84 h 6.44 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28345" />
<path
d="m 87.943756,461.17745 c 0,-6.88 -3.72,-10.88 -9.8,-10.88 -6.44,0 -9.92,5.04 -9.92,11.4 0,6.64 3.6,11.2 10.68,11.2 3.44,0 6.16,-1.28 8.28,-2.96 l -2.6,-3.52 c -1.84,1.28 -3.36,1.88 -5.08,1.88 -2.6,0 -4.4,-1.04 -4.8,-4.84 h 13.12 c 0.08,-0.64 0.12,-1.6 0.12,-2.28 z m -6.2,-1.52 h -7.08 c 0.32,-3.84 1.52,-5.16 3.64,-5.16 2.52,0 3.4,2 3.44,4.88 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28347" />
<path
d="m 94.703714,439.77745 c -2.2,0 -3.72,1.56 -3.72,3.6 0,2.04 1.52,3.6 3.72,3.6 2.2,0 3.76,-1.56 3.76,-3.6 0,-2.04 -1.56,-3.6 -3.76,-3.6 z m 3.2,11.2 h -6.32 v 21.24 h 6.32 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28349" />
<path
d="m 115.3037,450.29745 c -2.64,0 -4.68,1.12 -6.48,3.2 l -0.44,-2.52 h -5.52 v 21.24 h 6.32 v -14.52 c 1.12,-1.76 2.28,-2.76 3.68,-2.76 1.24,0 2,0.6 2,2.84 v 14.44 h 6.32 v -15.52 c 0,-4.04 -2.2,-6.4 -5.88,-6.4 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28351" />
<path
d="m 137.26368,443.81745 c -7.12,0 -12.48,5.2 -12.48,14.48 0,9.48 5.08,14.6 12.68,14.6 3.84,0 6.88,-1.72 8.68,-3.56 l -2.96,-3.84 c -1.6,1.24 -3.2,2.32 -5.4,2.32 -3.68,0 -6.12,-2.84 -6.12,-9.52 0,-6.8 2.48,-9.64 6,-9.64 1.92,0 3.48,0.72 4.96,2 l 3.2,-3.8 c -2.28,-1.92 -4.8,-3.04 -8.56,-3.04 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28353" />
<path
d="m 165.82364,466.05745 v -8.24 c 0,-4.92 -2.64,-7.52 -8.8,-7.52 -2.4,0 -5.32,0.56 -8,1.56 l 1.44,4.16 c 2.12,-0.72 4.2,-1.12 5.56,-1.12 2.6,0 3.6,0.76 3.6,3.28 v 0.92 h -2.16 c -6.44,0 -9.96,2.52 -9.96,7.16 0,3.88 2.68,6.64 6.92,6.64 2.52,0 4.88,-0.84 6.4,-3.16 1,2.08 2.64,2.84 5.12,3.04 l 1.32,-4.12 c -1,-0.36 -1.44,-0.96 -1.44,-2.6 z m -9.56,2.32 c -1.56,0 -2.48,-1 -2.48,-2.68 0,-2.12 1.4,-3.12 4.28,-3.12 h 1.56 v 3.8 c -0.76,1.24 -1.92,2 -3.36,2 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28355" />
<path
d="m 183.30358,450.29745 c -2.64,0 -4.68,1.12 -6.48,3.2 l -0.44,-2.52 h -5.52 v 21.24 h 6.32 v -14.52 c 1.12,-1.76 2.28,-2.76 3.68,-2.76 1.24,0 2,0.6 2,2.84 v 14.44 h 6.32 v -15.52 c 0,-4.04 -2.2,-6.4 -5.88,-6.4 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28357" />
<path
d="m 205.14356,467.17745 c -0.84,0.52 -1.56,0.72 -2.28,0.72 -1.32,0 -2,-0.72 -2,-2.76 v -9.76 h 4.2 l 0.68,-4.4 h -4.88 v -5.32 l -6.32,0.72 v 4.6 h -3 v 4.4 h 3 v 9.84 c 0,5 2.28,7.64 6.96,7.68 1.92,0 4.16,-0.56 5.76,-1.68 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28359" />
<path
d="m 218.18354,450.29745 c -6.48,0 -10.4,4.48 -10.4,11.28 0,7.16 3.96,11.32 10.4,11.32 6.48,0 10.4,-4.48 10.4,-11.28 0,-7.16 -3.92,-11.32 -10.4,-11.32 z m 0,4.64 c 2.56,0 3.84,1.96 3.84,6.68 0,4.6 -1.28,6.64 -3.84,6.64 -2.56,0 -3.84,-1.96 -3.84,-6.68 0,-4.6 1.28,-6.64 3.84,-6.64 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28361" />
<path
d="m 243.86353,450.37745 c -2.44,0 -4.52,1.76 -5.48,4.68 l -0.52,-4.08 h -5.52 v 21.24 h 6.32 v -10.6 c 0.68,-3.2 1.8,-5.12 4.4,-5.12 0.72,0 1.24,0.12 1.92,0.28 l 1,-6.12 c -0.68,-0.2 -1.32,-0.28 -2.12,-0.28 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#ffbc3b;fill-opacity:1;stroke:#1a1a37;stroke-width:0.3861461;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28363" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1025.8879"
height="560.1051"
viewBox="0 0 271.43285 148.19448"
version="1.1"
id="svg5"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
sodipodi:docname="meincantor-big.svg"
inkscape:export-filename="/home/denyskon/meincantor-big.png"
inkscape:export-xdpi="95.810593"
inkscape:export-ydpi="95.810593"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
units="px"
width="1024px"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.45892536"
inkscape:cx="290.89698"
inkscape:cy="459.76975"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2">
<rect
x="35.424603"
y="436.05106"
width="722.85211"
height="273.31204"
id="rect3787" />
<rect
id="rect101"
width="1231.0179"
height="630.59302"
x="-576.46198"
y="149.707" />
</defs>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0.24979931,0.24999975)">
<g
id="layer1-6"
transform="matrix(0.21011832,0,0,0.21011832,219.07839,-31.22162)"
inkscape:export-filename="/home/denys/GCG/Moodle/GCG Logo.png"
inkscape:export-xdpi="14.6812"
inkscape:export-ydpi="14.6812"
style="stroke:#1a1a37;stroke-width:2.37961;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
style="fill:#ffbc38;fill-opacity:1;stroke:#1a1a37;stroke-width:2.37961;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path94"
d="m -800.20189,148.59075 c -15.66268,0.005 -30.93737,0.32979 -35.92752,0.97152 -24.97802,3.21209 -46.06623,10.40832 -71.03494,24.24038 -39.97029,22.14261 -74.9122,57.98028 -99.47355,102.02323 -30.8652,55.34705 -42.151,113.50098 -32.8321,169.17882 5.8702,35.07216 16.8579,61.17871 40.68799,96.67317 7.95457,11.84812 11.84213,16.78099 24.46931,31.04978 14.63989,16.54318 27.57386,28.10203 42.20104,37.7145 28.86973,18.97219 57.71137,30.08127 95.58848,36.81738 v 10e-4 c 5.82412,1.03579 11.34034,1.26458 31.88746,1.32448 29.27973,0.0855 41.98501,-0.79986 60.14103,-4.19251 28.56955,-5.3386 57.43662,-16.77149 86.12757,-34.11008 33.44712,-20.21282 61.80706,-48.4681 81.46479,-81.16454 2.61834,-4.35506 4.64965,-8.00301 4.51392,-8.10649 -1.17086,-0.89357 -95.91117,-53.61068 -96.34604,-53.61068 -0.31474,0 -1.29111,1.27902 -2.16939,2.84169 -6.00422,10.68316 -23.40278,29.78738 -34.7033,38.10569 -38.44099,28.29642 -85.40586,35.86808 -129.74092,20.91759 -44.55018,-15.02312 -79.25266,-52.35019 -90.71746,-97.57855 -3.25589,-12.8444 -4.07642,-19.7718 -4.10362,-34.62114 -0.0427,-24.05789 4.0303,-42.064 14.11128,-62.38792 23.94487,-48.27458 71.92399,-78.04898 125.76906,-78.04898 37.71851,0 72.5558,14.34737 98.97588,40.76237 7.22351,7.22214 17.36655,20.0891 21.37491,27.11514 1.14192,2.00157 2.27232,3.55695 2.51201,3.45663 0.23966,-0.1005 21.42683,-11.94867 47.08239,-26.32914 30.23246,-16.94596 46.47755,-26.42693 46.16617,-26.94409 -15.24453,-25.3227 -37.5117,-51.05103 -60.39477,-69.78282 -19.53739,-15.99307 -45.92463,-31.3187 -70.29079,-40.8249 -21.82173,-8.51359 -38.29612,-12.71106 -57.08179,-14.54278 -6.5434,-0.63855 -22.59441,-0.95366 -38.2571,-0.94878 z m 71.03339,248.12387 c -33.16717,0 -60.11718,0.18715 -59.88884,0.41548 0.22842,0.22842 27.12928,15.96042 59.77929,34.95962 32.65006,18.9992 59.59962,34.55902 59.88834,34.57722 0.28884,0.0183 0.52504,-15.7137 0.52504,-34.95962 v -34.9927 z" />
<text
style="font-style:normal;font-weight:400;font-size:499.798px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect101);fill:#ffbc38;fill-opacity:1;stroke:#1a1a37;stroke-width:1.75069;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="text99"
transform="matrix(1.3592448,0,0,1.3592448,227.35348,-182.72846)"
xml:space="preserve"><tspan
x="-576.46289"
y="601.60773"
id="tspan4975"><tspan
style="font-weight:900;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Heavy';shape-inside:url(#rect101)"
id="tspan4973">CG</tspan></tspan></text>
</g>
<g
aria-label="MeinCantor"
transform="matrix(1.2948467,0,0,1.2948467,-47.577624,-464.38522)"
id="text3785"
style="font-size:40px;line-height:1.25;white-space:pre;shape-inside:url(#rect3787);fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:export-filename="/home/denyskon/meincantor/app/assets/images/meincantor-big-dark.png"
inkscape:export-xdpi="95.810593"
inkscape:export-ydpi="95.810593">
<path
d="m 63.463828,444.49745 h -8.32 l -3.88,18.8 -4.16,-18.8 h -8.28 l -2.08,27.72 h 6.4 l 0.48,-10.76 c 0.16,-3.88 0.16,-7.32 -0.12,-11.4 l 4.56,19.24 h 6.2 l 4.28,-19.24 c -0.2,3.44 -0.12,7.44 0.08,11.32 l 0.48,10.84 h 6.44 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28345" />
<path
d="m 87.943756,461.17745 c 0,-6.88 -3.72,-10.88 -9.8,-10.88 -6.44,0 -9.92,5.04 -9.92,11.4 0,6.64 3.6,11.2 10.68,11.2 3.44,0 6.16,-1.28 8.28,-2.96 l -2.6,-3.52 c -1.84,1.28 -3.36,1.88 -5.08,1.88 -2.6,0 -4.4,-1.04 -4.8,-4.84 h 13.12 c 0.08,-0.64 0.12,-1.6 0.12,-2.28 z m -6.2,-1.52 h -7.08 c 0.32,-3.84 1.52,-5.16 3.64,-5.16 2.52,0 3.4,2 3.44,4.88 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28347" />
<path
d="m 94.703714,439.77745 c -2.2,0 -3.72,1.56 -3.72,3.6 0,2.04 1.52,3.6 3.72,3.6 2.2,0 3.76,-1.56 3.76,-3.6 0,-2.04 -1.56,-3.6 -3.76,-3.6 z m 3.2,11.2 h -6.32 v 21.24 h 6.32 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28349" />
<path
d="m 115.3037,450.29745 c -2.64,0 -4.68,1.12 -6.48,3.2 l -0.44,-2.52 h -5.52 v 21.24 h 6.32 v -14.52 c 1.12,-1.76 2.28,-2.76 3.68,-2.76 1.24,0 2,0.6 2,2.84 v 14.44 h 6.32 v -15.52 c 0,-4.04 -2.2,-6.4 -5.88,-6.4 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28351" />
<path
d="m 137.26368,443.81745 c -7.12,0 -12.48,5.2 -12.48,14.48 0,9.48 5.08,14.6 12.68,14.6 3.84,0 6.88,-1.72 8.68,-3.56 l -2.96,-3.84 c -1.6,1.24 -3.2,2.32 -5.4,2.32 -3.68,0 -6.12,-2.84 -6.12,-9.52 0,-6.8 2.48,-9.64 6,-9.64 1.92,0 3.48,0.72 4.96,2 l 3.2,-3.8 c -2.28,-1.92 -4.8,-3.04 -8.56,-3.04 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28353" />
<path
d="m 165.82364,466.05745 v -8.24 c 0,-4.92 -2.64,-7.52 -8.8,-7.52 -2.4,0 -5.32,0.56 -8,1.56 l 1.44,4.16 c 2.12,-0.72 4.2,-1.12 5.56,-1.12 2.6,0 3.6,0.76 3.6,3.28 v 0.92 h -2.16 c -6.44,0 -9.96,2.52 -9.96,7.16 0,3.88 2.68,6.64 6.92,6.64 2.52,0 4.88,-0.84 6.4,-3.16 1,2.08 2.64,2.84 5.12,3.04 l 1.32,-4.12 c -1,-0.36 -1.44,-0.96 -1.44,-2.6 z m -9.56,2.32 c -1.56,0 -2.48,-1 -2.48,-2.68 0,-2.12 1.4,-3.12 4.28,-3.12 h 1.56 v 3.8 c -0.76,1.24 -1.92,2 -3.36,2 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28355" />
<path
d="m 183.30358,450.29745 c -2.64,0 -4.68,1.12 -6.48,3.2 l -0.44,-2.52 h -5.52 v 21.24 h 6.32 v -14.52 c 1.12,-1.76 2.28,-2.76 3.68,-2.76 1.24,0 2,0.6 2,2.84 v 14.44 h 6.32 v -15.52 c 0,-4.04 -2.2,-6.4 -5.88,-6.4 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28357" />
<path
d="m 205.14356,467.17745 c -0.84,0.52 -1.56,0.72 -2.28,0.72 -1.32,0 -2,-0.72 -2,-2.76 v -9.76 h 4.2 l 0.68,-4.4 h -4.88 v -5.32 l -6.32,0.72 v 4.6 h -3 v 4.4 h 3 v 9.84 c 0,5 2.28,7.64 6.96,7.68 1.92,0 4.16,-0.56 5.76,-1.68 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28359" />
<path
d="m 218.18354,450.29745 c -6.48,0 -10.4,4.48 -10.4,11.28 0,7.16 3.96,11.32 10.4,11.32 6.48,0 10.4,-4.48 10.4,-11.28 0,-7.16 -3.92,-11.32 -10.4,-11.32 z m 0,4.64 c 2.56,0 3.84,1.96 3.84,6.68 0,4.6 -1.28,6.64 -3.84,6.64 -2.56,0 -3.84,-1.96 -3.84,-6.68 0,-4.6 1.28,-6.64 3.84,-6.64 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28361" />
<path
d="m 243.86353,450.37745 c -2.44,0 -4.52,1.76 -5.48,4.68 l -0.52,-4.08 h -5.52 v 21.24 h 6.32 v -10.6 c 0.68,-3.2 1.8,-5.12 4.4,-5.12 0.72,0 1.24,0.12 1.92,0.28 l 1,-6.12 c -0.68,-0.2 -1.32,-0.28 -2.12,-0.28 z"
style="font-weight:bold;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';fill:#1a1a37;fill-opacity:1;stroke:none;stroke-width:0.386146;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path28363" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AppearanceSettings extends StatelessWidget { class AppearanceSettings extends StatelessWidget {
@ -13,7 +12,7 @@ class AppearanceSettings extends StatelessWidget {
), ),
body: ListView( body: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [], children: const [],
)); ));
} }
} }

@ -1,12 +1,29 @@
import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:meincantor/background_fetch.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../../login.dart'; import 'package:meincantor/login.dart';
class DevSettings extends StatelessWidget { class DevSettings extends StatefulWidget {
const DevSettings({Key? key}) : super(key: key); const DevSettings({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _DevSettingsState();
}
class _DevSettingsState extends State<DevSettings> {
int _status = 0;
void _onClickStatus() async {
int status = await BackgroundFetch.status;
print('[BackgroundFetch] status: $status');
setState(() {
_status = status;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -14,7 +31,28 @@ class DevSettings extends StatelessWidget {
title: const Text("Entwickler-Einstellungen"), title: const Text("Entwickler-Einstellungen"),
centerTitle: true, centerTitle: true,
), ),
body: ListView( body: LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
int factor;
if (widgetWidth <= 600) {
factor = 1;
} else if (widgetWidth <= 1400) {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
return Center(
heightFactor: 1,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / factor,
),
child: ListView(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20), padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
children: [ children: [
Padding( Padding(
@ -31,9 +69,10 @@ class DevSettings extends StatelessWidget {
String apiKey = value; String apiKey = value;
await prefs.setString('api_key', apiKey); await prefs.setString('api_key', apiKey);
final snackBar = SnackBar( final snackBar = SnackBar(
content: content: Text(
Text('Neuer API-Schlüssel gesetzt: $apiKey')); 'Neuer API-Schlüssel gesetzt: $apiKey'));
ScaffoldMessenger.of(context).showSnackBar(snackBar); ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
})), })),
const Divider(), const Divider(),
Padding( Padding(
@ -46,9 +85,44 @@ class DevSettings extends StatelessWidget {
); );
}, },
child: const Text("Benutzerdaten neu laden"), child: const Text("Benutzerdaten neu laden"),
) )),
) const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: OutlinedButton(
onPressed: () {
_onClickStatus();
},
child: const Text(
"Status der Hintergrundoperation anzeigen"),
)),
const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Text(_status.toString())),
const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: OutlinedButton(
onPressed: () async {
await backgroundFetchTimetable();
},
child: const Text(
"Stundenplan im Hintergrund neu laden"),
)),
const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: OutlinedButton(
onPressed: () async {
await backgroundFetchArticles();
},
child: const Text(
"Schülerzeitung im Hintergrund neu laden"),
)),
], ],
)); )),
);
}));
} }
} }

@ -1,6 +1,3 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:meincantor/const.dart'; import 'package:meincantor/const.dart';
@ -17,20 +14,54 @@ class InfoSettings extends StatelessWidget {
title: const Text("Informationen"), title: const Text("Informationen"),
centerTitle: true, centerTitle: true,
), ),
body: ListView( body: LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
int factor;
if (widgetWidth <= 600) {
factor = 1;
} else if (widgetWidth <= 1400) {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
return Center(
heightFactor: 1,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / factor,
),
child: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [ children: [
const ListTile( const Padding(
padding: EdgeInsets.all(5),
child: ListTile(
leading: Icon(Icons.info_outlined), leading: Icon(Icons.info_outlined),
title: Text("Version"), title: Text("Version"),
subtitle: Text(version)), subtitle: Text(version)),
ListTile(
leading: Icon(Icons.person_outlined),
title: Text("Autor"),
subtitle: Text(author),
onTap: () => launch("https://git.cantorgymnasium.de/denyskon"),
), ),
ListTile( Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(Icons.person_outlined),
title: const Text("Autor"),
subtitle: const Text(author),
onTap: () =>
launch("https://git.cantorgymnasium.de/denyskon"),
),
),
Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(Icons.source_outlined), leading: const Icon(Icons.source_outlined),
title: const Text("Quellcode"), title: const Text("Quellcode"),
subtitle: Linkify( subtitle: Linkify(
@ -41,12 +72,20 @@ class InfoSettings extends StatelessWidget {
throw 'Could not launch $link'; throw 'Could not launch $link';
} }
}, },
text: "https://git.cantorgymnasium.de/cantortechnik/meincantor-app", text:
"https://git.cantorgymnasium.de/cantortechnik/meincantor-app",
linkStyle: const TextStyle(color: Palette.accent), linkStyle: const TextStyle(color: Palette.accent),
), ),
onTap: () => launch(
"https://git.cantorgymnasium.de/cantortechnik/meincantor-app")),
), ),
ListTile( Padding(
leading: const Icon(Icons.settings_backup_restore_outlined), padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading:
const Icon(Icons.settings_backup_restore_outlined),
title: const Text("Änderungsverlauf"), title: const Text("Änderungsverlauf"),
subtitle: const Text("Was ist neu?"), subtitle: const Text("Was ist neu?"),
onTap: () { onTap: () {
@ -63,7 +102,8 @@ class InfoSettings extends StatelessWidget {
), ),
const Padding( const Padding(
padding: EdgeInsets.all(10), padding: EdgeInsets.all(10),
child: Text("1.0 --\nErste Release-Version!"), child: Text(
"1.0.0 --\nErste Release-Version!"),
), ),
], ],
), ),
@ -72,7 +112,12 @@ class InfoSettings extends StatelessWidget {
); );
}, },
), ),
ListTile( ),
Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(Icons.copyright_outlined), leading: const Icon(Icons.copyright_outlined),
title: const Text("Lizenzen"), title: const Text("Lizenzen"),
onTap: () { onTap: () {
@ -80,16 +125,25 @@ class InfoSettings extends StatelessWidget {
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => LicensePage( builder: (context) => LicensePage(
applicationIcon: Image.asset( applicationIcon: Padding(
"assets/images/meincantor_r.png", padding: const EdgeInsets.all(5),
height: 64, child: MediaQuery.of(context).platformBrightness == Brightness.light
width: 64), ? Image.asset(
"assets/images/meincantor-big.png",
width: 196)
: Image.asset(
"assets/images/meincantor-big-dark.png",
width: 196)
),
applicationVersion: version, applicationVersion: version,
)), )),
); );
}, },
), ),
),
], ],
)); )),
);
}));
} }
} }

@ -1,9 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:meincantor/main.dart'; import 'package:meincantor/main.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cyclop/cyclop.dart'; import 'package:cyclop/cyclop.dart';
import 'package:meincantor/networking.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -12,52 +12,6 @@ import 'package:meincantor/presets/subjects.dart';
import 'package:meincantor/presets/teachers.dart'; import 'package:meincantor/presets/teachers.dart';
class PlanSettings extends StatelessWidget {
const PlanSettings({Key? key}) : super(key: key);
@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: [
ListTile(
leading: const Icon(Icons.list_alt_outlined, color: Colors.red),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Kurse"),
subtitle: const Text("Konfiguration der Kurse (Whitelist)"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const WhitelistSettings()),
);
},
),
ListTile(
leading:
const Icon(Icons.color_lens_outlined, color: Colors.teal),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Farben"),
subtitle:
const Text("Konfiguration der Farben für die Plankacheln"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const PlanColorSettings()),
);
},
),
],
));
}
}
class WhitelistSettings extends StatefulWidget { class WhitelistSettings extends StatefulWidget {
const WhitelistSettings({Key? key}) : super(key: key); const WhitelistSettings({Key? key}) : super(key: key);
@ -77,7 +31,7 @@ class _WhitelistSettingsState extends State<WhitelistSettings> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text("Farben"), title: const Text("Kurse"),
centerTitle: true, centerTitle: true,
), ),
body: ListView( body: ListView(
@ -106,26 +60,35 @@ class _WhitelistSettingsState extends State<WhitelistSettings> {
snapshot.data! as List<dynamic>; snapshot.data! as List<dynamic>;
final _blacklisted = final _blacklisted =
_blacklist.contains(id); _blacklist.contains(id);
return ListTile( return Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(
15.0)),
leading: Checkbox( leading: Checkbox(
value: value: _blacklisted
_blacklisted ? false : true, ? false
: true,
onChanged: (state) async { onChanged: (state) async {
SharedPreferences prefs = SharedPreferences prefs =
await SharedPreferences await SharedPreferences
.getInstance(); .getInstance();
setState(() { setState(() {
_blacklisted _blacklisted
? _blacklist.remove(id) ? _blacklist
.remove(id)
: _blacklist.add(id); : _blacklist.add(id);
}); });
prefs.setString("blacklist", prefs.setString("blacklist",
jsonEncode(_blacklist)); jsonEncode(_blacklist));
}, },
activeColor: color), activeColor: color),
title: Text(subjects[subject] ?? ""), title: Text(
subtitle: subjects[subject] ?? subject),
Text(teachers[teacher] ?? ""), subtitle: Text(
teachers[teacher] ?? teacher),
onTap: () async { onTap: () async {
SharedPreferences prefs = SharedPreferences prefs =
await SharedPreferences await SharedPreferences
@ -138,7 +101,7 @@ class _WhitelistSettingsState extends State<WhitelistSettings> {
prefs.setString("blacklist", prefs.setString("blacklist",
jsonEncode(_blacklist)); jsonEncode(_blacklist));
}, },
); ));
} else { } else {
return const LinearProgressIndicator(); return const LinearProgressIndicator();
} }
@ -187,8 +150,12 @@ Future<Color> buildPlanColors(String lesson) async {
Future<List<dynamic>> buildLessonsList() async { Future<List<dynamic>> buildLessonsList() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String lessonsJson = prefs.getString("lessons")!; String? lessonsJson = prefs.getString("lessons");
List<dynamic> lessons = jsonDecode(lessonsJson); if (lessonsJson == null || lessonsJson.isEmpty) {
await fetchLessonList();
lessonsJson = prefs.getString("lessons");
}
List<dynamic> lessons = jsonDecode(lessonsJson!);
return lessons; return lessons;
} }
@ -235,13 +202,19 @@ class _PlanColorSettingsState extends State<PlanColorSettings> {
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
Color color = snapshot.data as Color; Color color = snapshot.data as Color;
return ListTile( return Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(15.0)),
leading: ColorButton( leading: ColorButton(
key: const Key('c1'), key: const Key('c1'),
color: color, color: color,
config: const ColorPickerConfig( config: const ColorPickerConfig(
enableEyePicker: false), enableEyePicker: false),
onSwatchesChanged: (Set<Color> value) { onSwatchesChanged:
(Set<Color> value) {
swatches = value; swatches = value;
}, },
size: 32, size: 32,
@ -256,9 +229,10 @@ class _PlanColorSettingsState extends State<PlanColorSettings> {
prefs.setInt( prefs.setInt(
"color$subject", value.value); "color$subject", value.value);
}), }),
title: Text(subjects[subject] ?? ""), title: Text(subjects[subject] ?? subject),
subtitle: Text(teachers[teacher] ?? ""), subtitle:
); Text(teachers[teacher] ?? teacher),
));
} else { } else {
return (const LinearProgressIndicator()); return (const LinearProgressIndicator());
} }

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ServiceSettings extends StatelessWidget { class ServiceSettings extends StatelessWidget {
@ -13,7 +12,7 @@ class ServiceSettings extends StatelessWidget {
), ),
body: ListView( body: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [], children: const [],
)); ));
} }
} }

@ -1,14 +1,10 @@
import 'package:cyclop/cyclop.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:meincantor/Settings/Pages/plan_settings.dart';
import 'package:meincantor/networking.dart'; import 'package:meincantor/networking.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:io' show Platform;
import '../../const.dart'; import 'package:meincantor/const.dart';
import 'package:webviewx/webviewx.dart';
Future<String> getSettingsString(String key) async { Future<String> getSettingsString(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -30,14 +26,36 @@ class UserSettings extends StatelessWidget {
title: const Text("Benutzereinstellungen"), title: const Text("Benutzereinstellungen"),
centerTitle: true, centerTitle: true,
), ),
body: ListView( body: LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
int factor;
if (widgetWidth <= 600) {
factor = 1;
} else if (widgetWidth <= 1400) {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
return Center(
heightFactor: 1,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / factor,
),
child: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10), padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: FutureBuilder( child: FutureBuilder(
future: Future.sync(() async { future: Future.sync(() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs =
await SharedPreferences.getInstance();
String? user = prefs.getString("user"); String? user = prefs.getString("user");
if (user == null || user.isEmpty) { if (user == null || user.isEmpty) {
user = ""; user = "";
@ -46,13 +64,13 @@ class UserSettings extends StatelessWidget {
if (name == null || name.isEmpty) { if (name == null || name.isEmpty) {
name = ""; name = "";
} }
Map data = {"user": user, "name": name }; Map data = {"user": user, "name": name};
return data; return data;
}), }),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
// .svg?text=${(snapshot.data! as Map)['name'][0]} String url =
String url = "$avatarUrl/${(snapshot.data! as Map)['user']}"; "$avatarUrl/${(snapshot.data! as Map)['user']}";
return Container( return Container(
width: 120.0, width: 120.0,
height: 120.0, height: 120.0,
@ -60,17 +78,16 @@ class UserSettings extends StatelessWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
image: DecorationImage( image: DecorationImage(
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
image: NetworkImage(url) image: NetworkImage(url))));
)
)
);
} else { } else {
return const CircularProgressIndicator(); return const CircularProgressIndicator();
} }
}, },
), ),
), ),
FutureBuilder( Padding(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
child: FutureBuilder(
future: getSettingsString("name"), future: getSettingsString("name"),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
@ -78,19 +95,67 @@ class UserSettings extends StatelessWidget {
decoration: const InputDecoration( decoration: const InputDecoration(
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: 'Name', labelText: 'Name',
), icon: Icon(MdiIcons.passport)),
readOnly: true, readOnly: true,
controller: controller: TextEditingController(
TextEditingController(text: snapshot.data as String), text: snapshot.data as String),
); );
} else { } else {
return (const Center(child: CircularProgressIndicator())); return (const Center(
child: CircularProgressIndicator()));
} }
}), }),
),
const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
child: FutureBuilder(
future: getSettingsString("user"),
builder: (context, snapshot) {
if (snapshot.hasData) {
return TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Benutzername',
icon: Icon(MdiIcons.identifier)),
readOnly: true,
controller: TextEditingController(
text: snapshot.data as String),
);
} else {
return (const Center(
child: CircularProgressIndicator()));
}
}),
),
const Divider(),
Padding(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
child: FutureBuilder(
future: getSettingsString("email"),
builder: (context, snapshot) {
if (snapshot.hasData) {
return TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'E-Mail-Adresse',
icon: Icon(Icons.email_outlined)),
readOnly: true,
controller: TextEditingController(
text: snapshot.data as String),
);
} else {
return (const Center(
child: CircularProgressIndicator()));
}
}),
),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(5, 20, 5, 5), padding: const EdgeInsets.fromLTRB(5, 20, 5, 5),
child: buildClassesChooser()), child: buildClassesChooser()),
ListTile( ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(MdiIcons.accountSettingsOutline), leading: const Icon(MdiIcons.accountSettingsOutline),
trailing: const Icon(Icons.link, size: 16), trailing: const Icon(Icons.link, size: 16),
title: const Text("Account-Konsole"), title: const Text("Account-Konsole"),
@ -99,35 +164,34 @@ class UserSettings extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => AccountConsole()), builder: (context) => const AccountConsole()),
); );
}, },
), ),
], ],
) )),
); );
}));
} }
} }
class AccountConsole extends StatefulWidget { class AccountConsole extends StatefulWidget {
const AccountConsole({Key? key}) : super(key: key);
@override @override
AccountConsoleState createState() => AccountConsoleState(); AccountConsoleState createState() => AccountConsoleState();
} }
class AccountConsoleState extends State<AccountConsole> { class AccountConsoleState extends State<AccountConsole> {
@override
void initState() {
super.initState();
// Enable virtual display.
if (Platform.isAndroid) WebView.platform = AndroidWebView();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const WebView( return WebViewX(
initialUrl: 'https://mein.cantorgymnasium.de/auth/realms/GCG.MeinCantor/account/', height: MediaQuery.of(context).size.height,
initialContent: 'https://mein.cantorgymnasium.de/auth/realms/GCG.MeinCantor/account/',
initialSourceType: SourceType.url,
javascriptMode: JavascriptMode.unrestricted,
width: MediaQuery.of(context).size.width
); );
} }
} }

@ -1,13 +1,10 @@
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:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'Pages/dev_settings.dart'; import 'package:meincantor/Settings/Pages/dev_settings.dart';
import 'Pages/info_settings.dart'; import 'package:meincantor/Settings/Pages/info_settings.dart';
import 'Pages/plan_settings.dart'; import 'package:meincantor/Settings/Pages/plan_settings.dart';
import 'Pages/user_settings.dart'; import 'package:meincantor/Settings/Pages/user_settings.dart';
class Settings extends StatelessWidget { class Settings extends StatelessWidget {
const Settings({Key? key}) : super(key: key); const Settings({Key? key}) : super(key: key);
@ -22,7 +19,11 @@ class Settings extends StatelessWidget {
body: ListView( body: ListView(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5), padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
children: [ children: [
ListTile( Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(MdiIcons.accountSettingsOutline, leading: const Icon(MdiIcons.accountSettingsOutline,
color: Colors.cyan), color: Colors.cyan),
trailing: const Icon(Icons.arrow_forward_ios, size: 16), trailing: const Icon(Icons.arrow_forward_ios, size: 16),
@ -31,51 +32,55 @@ class Settings extends StatelessWidget {
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => const UserSettings()), MaterialPageRoute(
builder: (context) => const UserSettings()),
); );
}, },
), ),
ListTile( ),
Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(Icons.list_alt_outlined, color: Colors.red),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Kurse"),
subtitle: const Text("Konfiguration der Kurse"),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const WhitelistSettings()),
);
},
),
),
Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: leading:
const Icon(MdiIcons.timetable, color: Colors.orangeAccent), const Icon(Icons.color_lens_outlined, color: Colors.teal),
trailing: const Icon(Icons.arrow_forward_ios, size: 16), trailing: const Icon(Icons.arrow_forward_ios, size: 16),
title: const Text("Plan"), title: const Text("Farben"),
subtitle: const Text("Kurse/Fächer, Farben & mehr"), subtitle:
onTap: () { const Text("Konfiguration der Farben für die Plankacheln"),
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: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const AppearanceSettings()), builder: (context) => const PlanColorSettings()),
); );
}, },
), ),
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( Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: const Icon(Icons.developer_mode_outlined, leading: const Icon(Icons.developer_mode_outlined,
color: Colors.deepOrangeAccent), color: Colors.deepOrangeAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16), trailing: const Icon(Icons.arrow_forward_ios, size: 16),
@ -84,11 +89,17 @@ class Settings extends StatelessWidget {
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => const DevSettings()), MaterialPageRoute(
builder: (context) => const DevSettings()),
); );
}, },
), ),
ListTile( ),
Padding(
padding: const EdgeInsets.all(5),
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
leading: leading:
const Icon(Icons.info_outlined, color: Colors.greenAccent), const Icon(Icons.info_outlined, color: Colors.greenAccent),
trailing: const Icon(Icons.arrow_forward_ios, size: 16), trailing: const Icon(Icons.arrow_forward_ios, size: 16),
@ -97,10 +108,12 @@ class Settings extends StatelessWidget {
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) => const InfoSettings()), MaterialPageRoute(
builder: (context) => const InfoSettings()),
); );
}, },
), ),
),
], ],
)); ));
} }

258
lib/background_fetch.dart Normal file

@ -0,0 +1,258 @@
import 'dart:convert';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import 'package:meincantor/timetable.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'package:meincantor/networking.dart';
Future<void> backgroundFetchTimetable() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? todayTimetable = prefs.getString("todayTimetable");
String? tomorrowTimetable = prefs.getString("tomorrowTimetable");
http.Response todayResponse = await fetchClassTimetable(
"/${DateFormat("yyyyMMdd").format(DateTime.now())}", null);
http.Response tomorrowResponse = await fetchClassTimetable(
"/${DateFormat("yyyyMMdd").format(DateTime.now().add(const Duration(days: 1)))}",
null);
if (todayResponse.statusCode == 200) {
if (todayTimetable != todayResponse.body) {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationDetails
androidPlatformChannelSpecificsTodayPlan = AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.today.plan',
'Vertretungsplan für heute',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsTodayPlan =
NotificationDetails(
android: androidPlatformChannelSpecificsTodayPlan);
const AndroidNotificationDetails
androidPlatformChannelSpecificsTodayInfo = AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.today.info',
'Informationen für heute',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsTodayInfo =
NotificationDetails(
android: androidPlatformChannelSpecificsTodayInfo);
List<TimetableLesson> lessonsList =
ClassTimetable.fromJson(jsonDecode(todayResponse.body)).timetable;
List<int> changedLessons = [];
for (var element in lessonsList) {
if (element.info.isNotEmpty) {
changedLessons.add(element.count);
}
}
String subtitle;
if (changedLessons.isNotEmpty && changedLessons.length > 1) {
subtitle = "Änderungen in den Stunden ";
for (var i in changedLessons) {
subtitle += "$i";
if (changedLessons.indexOf(i) != changedLessons.length - 1) {
subtitle += ", ";
}
}
} else if (changedLessons.isNotEmpty && changedLessons.length == 1) {
subtitle = "Änderungen in Stunde ${changedLessons[0]}";
} else {
subtitle = "Keine Änderungen im Plan gefunden!";
}
await flutterLocalNotificationsPlugin.show(
0,
'Neuer Vertretungsplan für heute geladen!',
subtitle,
platformChannelSpecificsTodayPlan,
payload: 'item x');
if ((jsonDecode(todayResponse.body)["info"] as String).isNotEmpty) {
await flutterLocalNotificationsPlugin.show(
1,
'Informationen für heute',
(jsonDecode(todayResponse.body)["info"] as String),
platformChannelSpecificsTodayInfo,
payload: 'item x');
}
prefs.setString("todayTimetable", todayResponse.body);
}
}
if (tomorrowResponse.statusCode == 200) {
if (tomorrowTimetable != tomorrowResponse.body) {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationDetails
androidPlatformChannelSpecificsTomorrowPlan =
AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.tomorrow.plan',
'Vertretungsplan für morgen',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsTomorrowPlan =
NotificationDetails(
android: androidPlatformChannelSpecificsTomorrowPlan);
const AndroidNotificationDetails
androidPlatformChannelSpecificsTomorrowInfo =
AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.tomorrow.info',
'Informationen für morgen',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsTomorrowInfo =
NotificationDetails(
android: androidPlatformChannelSpecificsTomorrowInfo);
List<TimetableLesson> lessonsList =
ClassTimetable.fromJson(jsonDecode(tomorrowResponse.body)).timetable;
List<int> changedLessons = [];
for (var element in lessonsList) {
if (element.info.isNotEmpty) {
changedLessons.add(element.count);
}
}
String subtitle;
if (changedLessons.isNotEmpty && changedLessons.length > 1) {
subtitle = "Änderungen in den Stunden ";
for (var i in changedLessons) {
subtitle += "$i";
if (changedLessons.indexOf(i) != changedLessons.length - 1) {
subtitle += ", ";
}
}
} else if (changedLessons.isNotEmpty && changedLessons.length == 1) {
subtitle = "Änderungen in Stunde ${changedLessons[0]}";
} else {
subtitle = "Keine Änderungen im Plan gefunden!";
}
await flutterLocalNotificationsPlugin.show(
2,
'Neuer Vertretungsplan für morgen geladen!',
subtitle,
platformChannelSpecificsTomorrowPlan,
payload: 'item x');
if ((jsonDecode(tomorrowResponse.body)["info"] as String).isNotEmpty) {
await flutterLocalNotificationsPlugin.show(
3,
'Informationen für morgen',
(jsonDecode(tomorrowResponse.body)["info"] as String),
platformChannelSpecificsTomorrowInfo,
payload: 'item x');
}
prefs.setString("tomorrowTimetable", tomorrowResponse.body);
}
}
}
Future<void> backgroundFetchArticles() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? articles = prefs.getString("articles");
String? news = prefs.getString("news");
http.Response fetchedArticles = await getArticles();
http.Response fetchedNews = await getNews();
if (fetchedArticles.statusCode == 200) {
if (articles != fetchedArticles.body) {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationDetails androidPlatformChannelSpecificsSZ =
AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.sz', 'Schülerzeitung',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsSZ =
NotificationDetails(android: androidPlatformChannelSpecificsSZ);
String subtitle;
List listFetchedArticles = jsonDecode(fetchedArticles.body)["data"];
if (articles != null && articles.isNotEmpty) {
List listSavedArticles = jsonDecode(articles)["data"];
int diff = listFetchedArticles.length - listSavedArticles.length;
diff == 1
? subtitle = "1 neuer Artikel!"
: diff > 1
? subtitle = "$diff neue Artikel!"
: subtitle = "Fehler beim Ermitteln der Änderungen!";
} else {
int len = listFetchedArticles.length;
len == 1
? subtitle = "1 neuer Artikel!"
: len > 1
? subtitle = "$len neue Artikel!"
: subtitle = "Fehler beim Ermitteln der Änderungen!";
}
await flutterLocalNotificationsPlugin.show(
4,
'Neuer Inhalt von der Schülerzeitung verfügbar!',
subtitle,
platformChannelSpecificsSZ,
payload: 'item x');
prefs.setString("articles", fetchedArticles.body);
}
}
if (fetchedNews.statusCode == 200) {
if (news != fetchedNews.body) {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationDetails androidPlatformChannelSpecificsNews =
AndroidNotificationDetails(
'de.cantorgymnasium.meincantor.news', 'Aktuelles',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecificsNews =
NotificationDetails(android: androidPlatformChannelSpecificsNews);
String subtitle;
List listFetchedNews = jsonDecode(fetchedNews.body)["data"];
if (news != null && news.isNotEmpty) {
List listSavedNews = jsonDecode(news)["data"];
int diff = listFetchedNews.length - listSavedNews.length;
diff == 1
? subtitle = "1 neuer Artikel!"
: diff > 1
? subtitle = "$diff neue Artikel!"
: subtitle = "Fehler beim Ermitteln der Änderungen!";
} else {
int len = listFetchedNews.length;
len == 1
? subtitle = "1 neuer Artikel!"
: len > 1
? subtitle = "$len neue Artikel!"
: subtitle = "Fehler beim Ermitteln der Änderungen!";
}
await flutterLocalNotificationsPlugin.show(
5,
'Neue Informationen verfügbar!',
subtitle,
platformChannelSpecificsNews,
payload: 'item x');
prefs.setString("news", fetchedNews.body);
}
}
}

@ -3,10 +3,12 @@ import 'dart:convert';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
Future<String> getCachedTimetable(String ext) async { Future<String> getCachedTimetable(String ext, String? presetClassNum) async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String classNum; String classNum;
if (prefs.getString('class_num') != null) { if (presetClassNum != null) {
classNum = presetClassNum.replaceAll("/", "_");
} else if (prefs.getString('class_num') != null) {
classNum = prefs.getString('class_num')!.replaceAll("/", "_"); classNum = prefs.getString('class_num')!.replaceAll("/", "_");
} else { } else {
classNum = '05_1'; classNum = '05_1';

File diff suppressed because it is too large Load Diff

@ -3,9 +3,10 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'networking.dart'; import 'package:meincantor/networking.dart';
import 'dashboard.dart'; import 'package:meincantor/dashboard.dart';
Future<bool> checkKey() async { Future<bool> checkKey() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -14,6 +15,7 @@ Future<bool> checkKey() async {
} }
class Login extends StatelessWidget { class Login extends StatelessWidget {
Login({Key? key}) : super(key: key);
final userController = TextEditingController(); final userController = TextEditingController();
final passwordController = TextEditingController(); final passwordController = TextEditingController();
@ -39,9 +41,6 @@ class Login extends StatelessWidget {
} }
return Scaffold( return Scaffold(
appBar: AppBar(
title: const Text("Anmelden"),
),
body: Center( body: Center(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
@ -54,8 +53,14 @@ class Login extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Image.asset("assets/images/meincantor_r.png", MediaQuery.of(context).platformBrightness ==
height: 192, width: 192), Brightness.light
? Image.asset(
"assets/images/meincantor-big.png",
width: 256)
: Image.asset(
"assets/images/meincantor-big-dark.png",
width: 256),
const Divider(), const Divider(),
AutofillGroup( AutofillGroup(
child: Column( child: Column(
@ -65,7 +70,7 @@ class Login extends StatelessWidget {
AutofillHints.username AutofillHints.username
], ],
decoration: const InputDecoration( decoration: const InputDecoration(
icon: Icon(CupertinoIcons.person), icon: Icon(MdiIcons.identifier),
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: 'Benutzername', labelText: 'Benutzername',
), ),
@ -77,7 +82,7 @@ class Login extends StatelessWidget {
AutofillHints.password AutofillHints.password
], ],
decoration: const InputDecoration( decoration: const InputDecoration(
icon: Icon(CupertinoIcons.lock), icon: Icon(MdiIcons.lock),
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: 'Passwort', labelText: 'Passwort',
), ),
@ -89,9 +94,9 @@ class Login extends StatelessWidget {
const Divider(), const Divider(),
TextField( TextField(
decoration: const InputDecoration( decoration: const InputDecoration(
icon: Icon(CupertinoIcons.lock), icon: Icon(MdiIcons.twoFactorAuthentication),
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: '2F2-Code (OTP) [falls aktiviert]', labelText: '2F2-Code',
), ),
obscureText: true, obscureText: true,
controller: otpController, controller: otpController,
@ -109,18 +114,21 @@ class Login extends StatelessWidget {
if (loginResponse.statusCode == 200) { if (loginResponse.statusCode == 200) {
String apiKey = jsonDecode(utf8.decode( String apiKey = jsonDecode(utf8.decode(
loginResponse.bodyBytes))['token']; loginResponse.bodyBytes))['token'];
await prefs.setString('api_key', apiKey); prefs.setString('api_key', apiKey);
dynamic userinfo = jsonDecode( dynamic userinfo = jsonDecode(
await getUserInfo( await getUserInfo(
userController.text, userController.text,
passwordController.text, passwordController.text,
otpController.text, otpController.text,
devIdController.text)); devIdController.text));
await prefs.setString('user', prefs.setString('user',
userinfo['preferred_username']); userinfo['preferred_username']);
await prefs.setString( prefs.setString('user',
'name', userinfo['name']); userinfo['preferred_username']);
await prefs.setString( prefs.setString('name', userinfo['name']);
prefs.setString(
'email', userinfo['email']);
prefs.setString(
'class_num', 'class_num',
userinfo['groups'][0] userinfo['groups'][0]
.replaceAll("_", "/")); .replaceAll("_", "/"));

@ -1,32 +1,52 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'dashboard.dart'; import 'package:meincantor/dashboard.dart';
import 'login.dart'; import 'package:meincantor/login.dart';
import 'dart:math'; import 'dart:math';
import 'package:background_fetch/background_fetch.dart';
void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
// This task has exceeded its allowed running-time.
// You must stop what you're doing and immediately .finish(taskId)
print("[BackgroundFetch] Headless task timed-out: $taskId");
BackgroundFetch.finish(taskId);
return;
}
print('[BackgroundFetch] Headless event received.');
// Do your work here...
BackgroundFetch.finish(taskId);
}
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); runApp(const App());
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin(); FlutterLocalNotificationsPlugin();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon'); AndroidInitializationSettings('app_icon');
final IOSInitializationSettings initializationSettingsIOS = const IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(); IOSInitializationSettings();
final MacOSInitializationSettings initializationSettingsMacOS = const MacOSInitializationSettings initializationSettingsMacOS =
MacOSInitializationSettings(); MacOSInitializationSettings();
final InitializationSettings initializationSettings = InitializationSettings( const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, android: initializationSettingsAndroid,
iOS: initializationSettingsIOS, iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS); macOS: initializationSettingsMacOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings); await flutterLocalNotificationsPlugin.initialize(initializationSettings);
runApp(const App()); BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
} }
class App extends StatelessWidget { class App extends StatefulWidget {
const App({Key? key}) : super(key: key); const App({Key? key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
MaterialColor generateMaterialColor(Color color) { MaterialColor generateMaterialColor(Color color) {
return MaterialColor(color.value, { return MaterialColor(color.value, {
50: tintColor(color, 0.5), 50: tintColor(color, 0.5),

@ -1,10 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:meincantor/cache_manager.dart'; import 'package:meincantor/cache_manager.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/painting.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.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';
@ -16,14 +13,16 @@ import 'package:meincantor/login.dart';
import 'package:meincantor/main.dart'; import 'package:meincantor/main.dart';
Future<http.Response> getArticles() async { Future<http.Response> getArticles() async {
var uri = Uri.https(szUrl["url"]!, "/articles"); var uri = Uri.https(szUrl["url"]! as String, "/api/articles");
final response = await http.get(uri); final response =
await http.get(uri, headers: szUrl["headers"]! as Map<String, String>);
return (response); return (response);
} }
Future<http.Response> getNews() async { Future<http.Response> getNews() async {
var uri = Uri.https(szUrl["url"]!, "/aktuelles"); var uri = Uri.https(szUrl["url"]! as String, "/api/aktuelles");
final response = await http.get(uri); final response =
await http.get(uri, headers: szUrl["headers"]! as Map<String, String>);
return (response); return (response);
} }
@ -50,21 +49,9 @@ Future<String> getUserInfo(
} }
} }
Future<http.Response> fetchClassTimetable(String ext) async { Future<http.Response> fetchClassTimetable(String ext, String? classNum) async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('de.cantorgymnasium.meincantor', 'GCG.MeinCantor',
channelDescription: '',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'Neuer Vertretungsplan geladen!', 'Du hast folgende Vertretungen:\nSt. 8 Deutsch Frau Rinke, Raum 203\nSt. 4 Biologie Frau Borchert, Raum 107', platformChannelSpecifics,
payload: 'item x');
try { try {
return (http.Response(await getCachedTimetable(ext), 200)); return (http.Response(await getCachedTimetable(ext, classNum), 200));
} on HttpExceptionWithStatus catch (e) { } on HttpExceptionWithStatus catch (e) {
return http.Response(e.message, e.statusCode); return http.Response(e.message, e.statusCode);
} on HttpException catch (e) { } on HttpException catch (e) {
@ -72,20 +59,6 @@ Future<http.Response> fetchClassTimetable(String ext) async {
} on SocketException catch (e) { } on SocketException catch (e) {
return http.Response(e.message, 404); return http.Response(e.message, 404);
} }
/*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/timetable/$classNum$ext");
var headers = {"x-api-key": "$apiKey"};
final response = http.get(uri, headers: headers).onError((error, stackTrace) {
return (http.Response("", 404));
});
return response;*/
} }
fetchLessonList() async { fetchLessonList() async {
@ -180,7 +153,7 @@ Widget buildTimetable(Future<http.Response> future, String info) {
Widget buildTodayClassTimetableLesson(int count) { Widget buildTodayClassTimetableLesson(int count) {
return FutureBuilder<http.Response>( return FutureBuilder<http.Response>(
future: fetchClassTimetable( future: fetchClassTimetable(
"/${DateFormat("yyyyMMdd").format(DateTime.now())}"), "/${DateFormat("yyyyMMdd").format(DateTime.now())}", null),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode; int statusCode = snapshot.data!.statusCode;
@ -281,7 +254,7 @@ Widget buildClassesChooser() {
if (statusCode == 200) { if (statusCode == 200) {
List<String> items = []; List<String> items = [];
jsonDecode(utf8.decode(snapshot.data!.bodyBytes)).forEach((value) { jsonDecode(utf8.decode(snapshot.data!.bodyBytes)).forEach((value) {
items.add(value..toString()); items.add(value.toString());
}); });
return ClassesChooser(items: items); return ClassesChooser(items: items);
} else if (statusCode == 400) { } else if (statusCode == 400) {
@ -322,7 +295,6 @@ class ClassesChooser extends StatefulWidget {
class _ClassesChooserState extends State<ClassesChooser> { class _ClassesChooserState extends State<ClassesChooser> {
final List<String> items; final List<String> items;
//final String dropdownValue;
String? dropdownValue; String? dropdownValue;
_ClassesChooserState(this.items); _ClassesChooserState(this.items);
@ -348,12 +320,15 @@ class _ClassesChooserState extends State<ClassesChooser> {
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: 'Klasse (05/1, 07/3, 10/2...)', labelText: 'Klasse (05/1, 07/3, 10/2...)',
), ),
onChanged: (String? newValue) { onChanged: (String? newValue) async {
setState(() async {
dropdownValue = newValue!;
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String classNum = newValue; String classNum = newValue!;
await prefs.setString('class_num', classNum); prefs.setString('class_num', classNum);
prefs.remove("lessons");
prefs.remove("todayTImetable");
prefs.remove("tomorrowTimetable");
setState(() {
dropdownValue = newValue;
}); });
}, },
items: items.map<DropdownMenuItem<String>>((String value) { items: items.map<DropdownMenuItem<String>>((String value) {

@ -34,23 +34,47 @@ class _NewsState extends State<News> {
title: const Text("Aktuelles"), title: const Text("Aktuelles"),
centerTitle: true, centerTitle: true,
), ),
body: FutureBuilder<http.Response>( body: LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
int factor;
if (widgetWidth <= 600) {
factor = 1;
} else if (widgetWidth <= 1400) {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
return Center(
heightFactor: 1,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / factor,
),
child: FutureBuilder<http.Response>(
future: getNews(), future: getNews(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode; int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) { if (statusCode == 200) {
String data = utf8.decode(snapshot.data!.bodyBytes); String data = utf8.decode(snapshot.data!.bodyBytes);
List articles = jsonDecode(data); List articles = jsonDecode(data)["data"];
List<Widget> articleTiles = []; List<Widget> articleTiles = [];
for (var element in articles) { for (var element in articles) {
int id = element["id"];
element = element["attributes"];
Color color = Colors.white70; Color color = Colors.white70;
Widget card = FutureBuilder( Widget card = FutureBuilder(
future: getNewsRead(), future: getNewsRead(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
List<dynamic> readList = snapshot.data! as List<dynamic>; List<dynamic> readList =
if (!readList.contains(element["id"])) { snapshot.data! as List<dynamic>;
if (!readList.contains(id)) {
return GestureDetector( return GestureDetector(
onTap: () async { onTap: () async {
SharedPreferences prefs = SharedPreferences prefs =
@ -58,15 +82,17 @@ class _NewsState extends State<News> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Article.fromData( builder: (context) =>
Article.fromData(
element["title"], element["title"],
element["content"], element["content"],
element["author"], element["author"],
element["published_at"]) element["publish_date"])
.widget), .widget),
); );
readList.add(element["id"]); readList.add(id);
prefs.setString("newsRead", jsonEncode(readList)); prefs.setString(
"newsRead", jsonEncode(readList));
setState(() { setState(() {
color = Colors.transparent; color = Colors.transparent;
}); });
@ -74,8 +100,8 @@ class _NewsState extends State<News> {
child: Card( child: Card(
color: color, color: color,
child: Padding( child: Padding(
padding: padding: const EdgeInsets.fromLTRB(
const EdgeInsets.fromLTRB(10, 10, 10, 10), 10, 10, 10, 10),
child: FutureBuilder( child: FutureBuilder(
future: Future.delayed( future: Future.delayed(
const Duration(seconds: 0)), const Duration(seconds: 0)),
@ -86,23 +112,26 @@ class _NewsState extends State<News> {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
subtitle: Text( subtitle: Text(
element["summary"], element["summary"],
overflow: TextOverflow.ellipsis, overflow:
TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
softWrap: true, softWrap: true,
), ),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} else { } else {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} }
}, },
@ -117,18 +146,19 @@ class _NewsState extends State<News> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Article.fromData( builder: (context) =>
Article.fromData(
element["title"], element["title"],
element["content"], element["content"],
element["author"], element["author"],
element["published_at"]) element["publish_date"])
.widget), .widget),
); );
}, },
child: Card( child: Card(
child: Padding( child: Padding(
padding: padding: const EdgeInsets.fromLTRB(
const EdgeInsets.fromLTRB(10, 10, 10, 10), 10, 10, 10, 10),
child: FutureBuilder( child: FutureBuilder(
future: Future.delayed( future: Future.delayed(
const Duration(seconds: 0)), const Duration(seconds: 0)),
@ -139,24 +169,26 @@ class _NewsState extends State<News> {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
subtitle: Text( subtitle: Text(
element["summary"], element["summary"],
overflow: TextOverflow.ellipsis, overflow:
TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
softWrap: true, softWrap: true,
), ),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} else { } else {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold) fontWeight:
), FontWeight.bold)),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} }
}, },
@ -178,14 +210,17 @@ class _NewsState extends State<News> {
); );
} else { } else {
return (const Center( return (const Center(
child: Text("Uups... Irgendwas ist schief gelaufen"))); child:
Text("Uups... Irgendwas ist schief gelaufen")));
} }
} else { } else {
return (const Center(child: CircularProgressIndicator())); return (const Center(child: CircularProgressIndicator()));
} }
}, },
), ),
),
); );
}));
} }
} }

@ -1 +0,0 @@

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
Map colors = { Map colors = {
'Bio': Colors.green, 'Bio': Colors.green,
'bio1': Colors.green,
'bioL1': Colors.green,
'Mat': Colors.indigo, 'Mat': Colors.indigo,
'matL1': Colors.indigo, 'matL1': Colors.indigo,
'matL2': Colors.indigo, 'matL2': Colors.indigo,
@ -10,20 +12,26 @@ Map colors = {
'deu1': Colors.red, 'deu1': Colors.red,
'deu2': Colors.red, 'deu2': Colors.red,
'deu3': Colors.red, 'deu3': Colors.red,
'deuL1': Colors.red,
'Kun': Colors.deepPurple, 'Kun': Colors.deepPurple,
'kun1': Colors.deepPurple, 'kun1': Colors.deepPurple,
'kun2': Colors.deepPurple, 'kun2': Colors.deepPurple,
'kun3': Colors.deepPurple, 'kun3': Colors.deepPurple,
'Geo': Colors.brown, 'Geo': Colors.brown,
'geo1': Colors.brown,
'Lat': Colors.teal, 'Lat': Colors.teal,
'lat1': Colors.teal, 'lat1': Colors.teal,
'lat2': Colors.teal, 'lat2': Colors.teal,
'lat3': Colors.teal, 'lat3': Colors.teal,
'Che': Colors.lightGreen, 'Che': Colors.lightGreen,
'che1': Colors.lightGreen,
'cheL1': Colors.lightGreen,
'Eng': Colors.amber, 'Eng': Colors.amber,
'eng1': Colors.amber, 'eng1': Colors.amber,
'eng2': Colors.amber, 'eng2': Colors.amber,
'eng3': Colors.amber, 'eng3': Colors.amber,
'engL1': Colors.amber,
'engL2': Colors.amber,
'Phy': Colors.cyan, 'Phy': Colors.cyan,
'phy1': Colors.cyan, 'phy1': Colors.cyan,
'phy2': Colors.cyan, 'phy2': Colors.cyan,

@ -1,30 +1,63 @@
dynamic subjects = { dynamic subjects = {
'---': '---', '---': '---',
'Bio': 'Biologie', 'Bio': 'Biologie',
'bio1': 'Biologie 1',
'bioL1': 'Biologie Leistungskurs 1',
'Mat': 'Mathematik', 'Mat': 'Mathematik',
'matL1': 'Mathematik Leistungskurs 1', 'matL1': 'Mathematik Leistungskurs 1',
'matL2': 'Mathematik Leistungskurs 2',
'matL3': 'Mathematik Leistungskurs 3',
'Kun': 'Kunst', 'Kun': 'Kunst',
'kun1': 'Kunst 1',
'Mus': 'Musik', 'Mus': 'Musik',
'mus1': 'Musik 1',
'mus2': 'Musik 2',
'Geo': 'Geographie', 'Geo': 'Geographie',
'geo1': 'Geographie 1',
'Ges': 'Geschichte', 'Ges': 'Geschichte',
'ges1': 'Geschichte 1',
'ges2': 'Geschichte 2',
'ges3': 'Geschichte 3',
'Che': 'Chemie', 'Che': 'Chemie',
'che1': 'Chemie 1',
'cheL1': 'Chemie Leistungskurs 1',
'Lat': 'Latein', 'Lat': 'Latein',
'lat1': 'Latein 1',
'Inf': 'Informatik', 'Inf': 'Informatik',
'inf1': 'Informatik 1',
'inf2': 'Informatik 2',
'infL1': 'Informatik Leistungskurs 1',
'Eng': 'Englisch', 'Eng': 'Englisch',
'eng1': 'Englisch 1',
'eng2': 'Englisch 2',
'engL1': 'Englisch Leistungskurs 1',
'engL2': 'Englisch Leistungskurs 2',
'Frz': 'Französisch', 'Frz': 'Französisch',
'frz1': 'Französisch 1', 'frz1': 'Französisch 1',
'frz2': 'Französisch 2', 'frz2': 'Französisch 2',
'frz3': 'Französisch 3', 'frz3': 'Französisch 3',
'Phy': 'Physik', 'Phy': 'Physik',
'phy1': 'Physik 1',
'phyL1': 'Physik Leistungskurs 1',
'phyL2': 'Physik Leistungskurs 2',
'psy1': 'Psychologie 1',
'Spo': 'Sport', 'Spo': 'Sport',
'spo1': 'Sport 1',
'spo2': 'Sport 2',
'spo3': 'Sport 3',
'Deu': 'Deutsch', 'Deu': 'Deutsch',
'deu1': 'Deutsch 1', 'deu1': 'Deutsch 1',
'deu2': 'Deutsch 2', 'deu2': 'Deutsch 2',
'deu3': 'Deutsch 3', 'deu3': 'Deutsch 3',
'deuL1': 'Deutsch Leistungskurs 1',
'Lme': 'Lernmethoden', 'Lme': 'Lernmethoden',
'Eth': 'Ethik', 'Eth': 'Ethik',
'eth1': 'Ethik 1',
'EvR': 'Evangelische Religion', 'EvR': 'Evangelische Religion',
'evr1': 'Evangelische Religion 1',
'Soz': 'Sozialkunde', 'Soz': 'Sozialkunde',
'soz1': 'Sozialkunde 1',
'soz2': 'Sozialkunde 2',
'Ast': 'Astronomie', 'Ast': 'Astronomie',
'Spa': 'Spanisch', 'Spa': 'Spanisch',
'FK': 'Fachkurs', 'FK': 'Fachkurs',

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class RoomOverview extends StatelessWidget { class RoomOverview extends StatelessWidget {

198
lib/saved.dart Normal file

@ -0,0 +1,198 @@
// SizedBox(
// width: 170,
// 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: 170,
// 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: 170,
// 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',
// ),
// ),
// ),
// ),
// )),
// ),
// ),
// 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()),
// );
// },
// ),
// class PlanSettings extends StatelessWidget {
// const PlanSettings({Key? key}) : super(key: key);
// @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: [
// ListTile(
// leading: const Icon(Icons.list_alt_outlined, color: Colors.red),
// trailing: const Icon(Icons.arrow_forward_ios, size: 16),
// title: const Text("Kurse"),
// subtitle: const Text("Konfiguration der Kurse"),
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const WhitelistSettings()),
// );
// },
// ),
// ListTile(
// leading:
// const Icon(Icons.color_lens_outlined, color: Colors.teal),
// trailing: const Icon(Icons.arrow_forward_ios, size: 16),
// title: const Text("Farben"),
// subtitle:
// const Text("Konfiguration der Farben für die Plankacheln"),
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const PlanColorSettings()),
// );
// },
// ),
// ],
// ));
// }
// }

@ -5,6 +5,8 @@ import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:markdown/markdown.dart' as md;
Future<List> getSZread() async { Future<List> getSZread() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -34,23 +36,47 @@ class _SZState extends State<SZ> {
title: const Text("Schülerzeitung"), title: const Text("Schülerzeitung"),
centerTitle: true, centerTitle: true,
), ),
body: FutureBuilder<http.Response>( body: LayoutBuilder(builder: (context, constraints) {
double widgetWidth = constraints.maxWidth;
int factor;
if (widgetWidth <= 600) {
factor = 1;
} else if (widgetWidth <= 1400) {
factor = 2;
} else if (widgetWidth <= 2000) {
factor = 3;
} else {
factor = 1;
}
return Center(
heightFactor: 1,
child: Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / factor,
),
child: FutureBuilder<http.Response>(
future: getArticles(), future: getArticles(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
int statusCode = snapshot.data!.statusCode; int statusCode = snapshot.data!.statusCode;
if (statusCode == 200) { if (statusCode == 200) {
String data = utf8.decode(snapshot.data!.bodyBytes); String data = utf8.decode(snapshot.data!.bodyBytes);
List articles = jsonDecode(data); List articles = jsonDecode(data)["data"];
List<Widget> articleTiles = []; List<Widget> articleTiles = [];
for (var element in articles) { for (var element in articles) {
int id = element["id"];
element = element["attributes"];
Color color = Colors.white70; Color color = Colors.white70;
Widget card = FutureBuilder( Widget card = FutureBuilder(
future: getSZread(), future: getSZread(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
List<dynamic> readList = snapshot.data! as List<dynamic>; List<dynamic> readList =
if (!readList.contains(element["id"])) { snapshot.data! as List<dynamic>;
if (!readList.contains(id)) {
return GestureDetector( return GestureDetector(
onTap: () async { onTap: () async {
SharedPreferences prefs = SharedPreferences prefs =
@ -58,15 +84,17 @@ class _SZState extends State<SZ> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Article.fromData( builder: (context) =>
Article.fromData(
element["title"], element["title"],
element["content"], element["content"],
element["author"], element["author"],
element["published_at"]) element["publish_date"])
.widget), .widget),
); );
readList.add(element["id"]); readList.add(id);
prefs.setString("SZread", jsonEncode(readList)); prefs.setString(
"SZread", jsonEncode(readList));
setState(() { setState(() {
color = Colors.transparent; color = Colors.transparent;
}); });
@ -74,8 +102,8 @@ class _SZState extends State<SZ> {
child: Card( child: Card(
color: color, color: color,
child: Padding( child: Padding(
padding: padding: const EdgeInsets.fromLTRB(
const EdgeInsets.fromLTRB(10, 10, 10, 10), 10, 10, 10, 10),
child: FutureBuilder( child: FutureBuilder(
future: Future.delayed( future: Future.delayed(
const Duration(seconds: 0)), const Duration(seconds: 0)),
@ -86,23 +114,26 @@ class _SZState extends State<SZ> {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
subtitle: Text( subtitle: Text(
element["summary"], element["summary"],
overflow: TextOverflow.ellipsis, overflow:
TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
softWrap: true, softWrap: true,
), ),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} else { } else {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} }
}, },
@ -117,18 +148,19 @@ class _SZState extends State<SZ> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Article.fromData( builder: (context) =>
Article.fromData(
element["title"], element["title"],
element["content"], element["content"],
element["author"], element["author"],
element["published_at"]) element["publish_date"])
.widget), .widget),
); );
}, },
child: Card( child: Card(
child: Padding( child: Padding(
padding: padding: const EdgeInsets.fromLTRB(
const EdgeInsets.fromLTRB(10, 10, 10, 10), 10, 10, 10, 10),
child: FutureBuilder( child: FutureBuilder(
future: Future.delayed( future: Future.delayed(
const Duration(seconds: 0)), const Duration(seconds: 0)),
@ -139,23 +171,26 @@ class _SZState extends State<SZ> {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
subtitle: Text( subtitle: Text(
element["summary"], element["summary"],
overflow: TextOverflow.ellipsis, overflow:
TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
softWrap: true, softWrap: true,
), ),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} else { } else {
return ListTile( return ListTile(
title: Text(element["title"], title: Text(element["title"],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold)), fontWeight:
FontWeight.bold)),
trailing: Text( trailing: Text(
"${DateTime.parse(element["published_at"]).day.toString()}.${DateTime.parse(element["published_at"]).month.toString()}.${DateTime.parse(element["published_at"]).year.toString()}"), "${DateTime.parse(element["publish_date"]).day.toString()}.${DateTime.parse(element["publish_date"]).month.toString()}.${DateTime.parse(element["publish_date"]).year.toString()}"),
); );
} }
}, },
@ -177,14 +212,17 @@ class _SZState extends State<SZ> {
); );
} else { } else {
return (const Center( return (const Center(
child: Text("Uups... Irgendwas ist schief gelaufen"))); child:
Text("Uups... Irgendwas ist schief gelaufen")));
} }
} else { } else {
return (const Center(child: CircularProgressIndicator())); return (const Center(child: CircularProgressIndicator()));
} }
}, },
), ),
),
); );
}));
} }
} }
@ -216,7 +254,14 @@ class Article {
title: Text( title: Text(
"${DateTime.parse(publishDate).day.toString()}.${DateTime.parse(publishDate).month.toString()}.${DateTime.parse(publishDate).year.toString()}"), "${DateTime.parse(publishDate).day.toString()}.${DateTime.parse(publishDate).month.toString()}.${DateTime.parse(publishDate).year.toString()}"),
), ),
MarkdownBody(data: content) MarkdownBody(
data: content,
onTapLink: (text, url, title) {
launch(url!);
},
extensionSet: md.ExtensionSet.commonMark,
imageDirectory: "https://cms.mein.cantorgymnasium.de",
)
], ],
))); )));
} }

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SB extends StatelessWidget { class SB extends StatelessWidget {

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SC extends StatelessWidget { class SC extends StatelessWidget {

@ -3,7 +3,6 @@ import 'package:meincantor/presets/subjects.dart';
import 'package:meincantor/presets/colors.dart'; import 'package:meincantor/presets/colors.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -25,8 +24,10 @@ class ClassTimetableBuilder {
onTap: () { onTap: () {
showModalBottomSheet<void>( showModalBottomSheet<void>(
isScrollControlled: true, isScrollControlled: true,
shape: RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0), borderRadius: BorderRadius.only(
topLeft: Radius.circular(25.0),
topRight: Radius.circular(25.0)),
), ),
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
@ -35,6 +36,8 @@ class ClassTimetableBuilder {
child: ListView( child: ListView(
children: <Widget>[ children: <Widget>[
ListTile( ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
title: const Text("Informationen", title: const Text("Informationen",
style: TextStyle(fontWeight: FontWeight.bold)), style: TextStyle(fontWeight: FontWeight.bold)),
leading: const Icon(Icons.arrow_back), leading: const Icon(Icons.arrow_back),
@ -90,15 +93,15 @@ class LessonsListBuilder {
title: Text(element.count.toString() + '.' + ' ' + element.name, title: Text(element.count.toString() + '.' + ' ' + element.name,
style: TextStyle(color: element.fontColor)), style: TextStyle(color: element.fontColor)),
subtitle: Row(children: [ subtitle: Row(children: [
Icon(CupertinoIcons.person, color: element.fontColor), Icon(Icons.person_outline, color: element.fontColor),
const SizedBox(width: 5), const SizedBox(width: 5),
Text(element.teacher, style: TextStyle(color: element.fontColor)), Text(element.teacher, style: TextStyle(color: element.fontColor)),
const Spacer(), const Spacer(),
Icon(CupertinoIcons.home, color: element.fontColor), Icon(MdiIcons.door, color: element.fontColor),
const SizedBox(width: 5), const SizedBox(width: 5),
Text(element.room, style: TextStyle(color: element.fontColor)) Text(element.room, style: TextStyle(color: element.fontColor))
]), ]),
leading: Icon(CupertinoIcons.time, color: element.fontColor))); leading: Icon(MdiIcons.clockOutline, color: element.fontColor)));
if (element.info != '') { if (element.info != '') {
cardChildren.add(ListTile( cardChildren.add(ListTile(
title: Text(element.info, title: Text(element.info,
@ -150,7 +153,7 @@ class TimetableInfo {
} }
class ClassTimetable { class ClassTimetable {
final List timetable; final List<TimetableLesson> timetable;
ClassTimetable({required this.timetable}); ClassTimetable({required this.timetable});
factory ClassTimetable.fromJson(Map<String, dynamic> json) { factory ClassTimetable.fromJson(Map<String, dynamic> json) {
List<TimetableLesson> lessons = []; List<TimetableLesson> lessons = [];
@ -201,11 +204,10 @@ class ClassTimetable {
lessons.add(TimetableLesson( lessons.add(TimetableLesson(
value['St'], value['St'],
value["Nr"], value["Nr"] ?? 0,
subjects[subject] ?? subject.toString(), subject == '&nbsp;' ? "---" : subjects[subject] ?? subject.toString(),
teachers[teacher] ?? teacher.toString(), teachers[teacher] ?? teacher.toString(),
room.toString(), room.toString(),
value['If'].toString(),
lessonColor, lessonColor,
fontColor, fontColor,
info)); info));
@ -221,10 +223,9 @@ class TimetableLesson {
final String name; final String name;
final String teacher; final String teacher;
final String room; final String room;
final String comment;
final Future<Color> color; final Future<Color> color;
final Color fontColor; final Color fontColor;
final String info; final String info;
const TimetableLesson(this.count, this.id, this.name, this.teacher, this.room, const TimetableLesson(this.count, this.id, this.name, this.teacher, this.room,
this.comment, this.color, this.fontColor, this.info); this.color, this.fontColor, this.info);
} }

@ -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.8.0-dev version: 1.0.0
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
@ -31,7 +31,7 @@ dependencies:
sdk: flutter sdk: flutter
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 # cupertino_icons: ^1.0.2
shared_preferences: ^2.0.6 shared_preferences: ^2.0.6
http: ^0.13.3 http: ^0.13.3
google_fonts: ^2.1.0 google_fonts: ^2.1.0
@ -45,7 +45,7 @@ dependencies:
url_launcher: ^6.0.17 url_launcher: ^6.0.17
flutter_linkify: ^5.0.2 flutter_linkify: ^5.0.2
flutter_svg: ^1.0.0 flutter_svg: ^1.0.0
webview_flutter: ^3.0.0 webviewx: ^0.2.1
flutter_local_notifications: ^10.0.0-dev.1 flutter_local_notifications: ^10.0.0-dev.1
background_fetch: ^1.0.3 background_fetch: ^1.0.3
@ -83,6 +83,8 @@ flutter:
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
assets: assets:
- assets/images/meincantor_r.png - assets/images/meincantor_r.png
- assets/images/meincantor-big.png
- assets/images/meincantor-big-dark.png
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see