Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
007e4404c1 | ||
|
|
4bc578ef06 | ||
|
|
8a3002ade1 | ||
|
|
ca06073f37 | ||
|
|
52dd14d10b | ||
|
|
dd787effbc | ||
|
|
7eac57b94d | ||
|
|
ee0ba71c8f | ||
|
|
ab64faeadb | ||
|
|
1460f2aa4e | ||
|
|
8925b3a5f8 | ||
|
|
eb0308cbed | ||
|
|
c90e01737c | ||
|
|
05c406657a | ||
|
|
fc402eef16 | ||
|
|
e9cfc7bbfc | ||
|
|
7e711d64e8 | ||
|
|
80008d8f00 | ||
|
|
81267d54e3 | ||
|
|
0dc921c603 | ||
|
|
4e23b745f3 | ||
|
|
ce91b47ad1 | ||
|
|
250ed2f105 | ||
|
|
4cde28cd72 | ||
|
|
df63c258b3 | ||
|
|
1b6992132e | ||
|
|
55350b0e5d | ||
|
|
8d532a442d | ||
|
|
cc4091e165 | ||
|
|
1f05f1d091 | ||
|
|
cc04293ead | ||
|
|
e1cae2f698 | ||
|
|
84a3e46ff7 | ||
|
|
a9360c6dc8 | ||
|
|
5d9c975b98 | ||
|
|
0b47155862 | ||
|
|
8662775e21 | ||
|
|
2ac948539c | ||
|
|
b93ea7193d | ||
|
|
b6b5c71cef | ||
|
|
0cf62aea86 | ||
|
|
f2f3366e2c | ||
|
|
4b7845c31e | ||
|
|
08519ebf27 | ||
|
|
894b3ac5b5 | ||
|
|
4135503a30 | ||
|
|
7f9bd34a82 | ||
|
|
64dfe4a814 | ||
|
|
6568e3c588 | ||
|
|
1109c08cf5 | ||
|
|
9cfbcc932b | ||
|
|
843224f348 | ||
|
|
b5ee1afe05 | ||
|
|
67649cc5fd | ||
|
|
ee0e724b8a | ||
|
|
d6e783f375 | ||
|
|
1e89359333 | ||
|
|
24f8804f60 | ||
|
|
300b951014 | ||
|
|
8b49007cca | ||
|
|
4101dc7c17 | ||
|
|
939cc6bbe2 | ||
|
|
13e00f8462 | ||
|
|
7d89ea0f5d | ||
|
|
fe4d7b318e | ||
|
|
0464624648 | ||
|
|
d09f3772a3 | ||
|
|
a7ff9e7825 | ||
|
|
bc3f8cfff9 | ||
|
|
063cc99d1a | ||
|
|
739e75160d | ||
|
|
889d0d6057 | ||
|
|
f5a7820991 | ||
|
|
580f93fa6f | ||
|
|
654c12e9fb | ||
|
|
7ab14756a6 | ||
|
|
0a02d4e831 | ||
|
|
ac3429f30f | ||
|
|
6388650c77 | ||
|
|
728534170c |
9
.gitignore
vendored
@@ -12,10 +12,10 @@ refilc/build/
|
|||||||
refilc/android/key.properties
|
refilc/android/key.properties
|
||||||
refilc/android/debug.keystore
|
refilc/android/debug.keystore
|
||||||
|
|
||||||
refilc_desktop_ui/.flutter-plugins
|
# refilc_desktop_ui/.flutter-plugins
|
||||||
refilc_desktop_ui/.flutter-plugins-dependencies
|
# refilc_desktop_ui/.flutter-plugins-dependencies
|
||||||
refilc_desktop_ui/pubspec.lock
|
# refilc_desktop_ui/pubspec.lock
|
||||||
refilc_desktop_ui/.dart_tool/
|
# refilc_desktop_ui/.dart_tool/
|
||||||
|
|
||||||
refilc_kreta_api/.flutter-plugins
|
refilc_kreta_api/.flutter-plugins
|
||||||
refilc_kreta_api/.flutter-plugins-dependencies
|
refilc_kreta_api/.flutter-plugins-dependencies
|
||||||
@@ -37,6 +37,7 @@ refilc_mobile_ui/.dart_tool/
|
|||||||
.idea
|
.idea
|
||||||
.gitmodules
|
.gitmodules
|
||||||
.gradle
|
.gradle
|
||||||
|
.kotlin
|
||||||
|
|
||||||
refilc/.DS_Store
|
refilc/.DS_Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "naplo-plus"]
|
|
||||||
path = refilc_plus
|
|
||||||
url = git@github.com:refilc/naplo-plus.git
|
|
||||||
1286
.idea/libraries/Dart_Packages.xml
generated
41
.idea/libraries/Dart_SDK.xml
generated
@@ -1,25 +1,28 @@
|
|||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="Dart SDK">
|
<library name="Dart SDK">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/async" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/async" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/cli" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/cli" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/collection" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/collection" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/convert" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/concurrent" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/core" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/convert" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/developer" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/core" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/ffi" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/developer" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/html" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/ffi" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/html" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/io" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/indexed_db" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/isolate" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/io" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/isolate" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/js_util" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/js" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/math" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/js_interop" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/js_interop_unsafe" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/svg" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/js_util" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/math" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/mirrors" />
|
||||||
<root url="file:///opt/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/svg" />
|
||||||
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/typed_data" />
|
||||||
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/web_audio" />
|
||||||
|
<root url="file://P:/flutter/bin/cache/dart-sdk/lib/web_gl" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC />
|
<JAVADOC />
|
||||||
<SOURCES />
|
<SOURCES />
|
||||||
|
|||||||
1
.idea/misc.xml
generated
@@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 33, extension level 3 Platform" project-jdk-type="Android SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Android API 33, extension level 3 Platform" project-jdk-type="Android SDK" />
|
||||||
</project>
|
</project>
|
||||||
13
.idea/naplo.iml
generated
@@ -60,8 +60,21 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/build" />
|
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/build" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.pub" />
|
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.pub" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.dart_tool" />
|
<excludeFolder url="file://$MODULE_DIR$/filcnaplo/linux/flutter/ephemeral/.plugin_symlinks/flutter_acrylic/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc/build" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_kreta_api/build" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_mobile_ui/build" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_plus/.dart_tool" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_plus/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/refilc_plus/build" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
5
.idea/vcs.xml
generated
@@ -2,9 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/filcnaplo_desktop_ui" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/refilc_plus" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/filcnaplo_kreta_api" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/filcnaplo_mobile_ui" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$/filcnaplo_premium" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
56
Jenkinsfile
vendored
@@ -1,56 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent any
|
|
||||||
|
|
||||||
environment {
|
|
||||||
ANDROID_SDK = '/home/jenkins/flutter_things/android-sdk'
|
|
||||||
ANDROID_PATH="$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools"
|
|
||||||
FLUTTER = '/home/jenkins/flutter_things/flutter/bin'
|
|
||||||
PATH = "$PATH:$ANDROID_PATH:$FLUTTER"
|
|
||||||
//TODO: need to fix flutter
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
stages {
|
|
||||||
stage('Copy Key Properties') {
|
|
||||||
steps {
|
|
||||||
// Copy the key.properties file
|
|
||||||
sh 'cp /home/jenkins/key.properties refilc/android/key.properties'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Flutter Doctor') {
|
|
||||||
steps {
|
|
||||||
// Ensure Flutter is set up correctly
|
|
||||||
sh 'flutter doctor'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Dependencies') {
|
|
||||||
steps {
|
|
||||||
// Get Flutter dependencies
|
|
||||||
sh 'cd refilc && flutter pub get'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
// Build the Flutter project
|
|
||||||
sh 'cd refilc && flutter build apk --release'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Archive') {
|
|
||||||
steps {
|
|
||||||
// Archive the APK
|
|
||||||
archiveArtifacts artifacts: 'build/app/outputs/flutter-apk/app-release.apk', fingerprint: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
// Clean up workspace after build
|
|
||||||
cleanWs()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
47
README.md
@@ -1,34 +1,43 @@
|
|||||||
<p align=center>
|
<p align=center>
|
||||||
<img src="https://refilc.hu/image/brand/logo.png" width=150>
|
<img src="https://raw.githubusercontent.com/Laky2k8/Refilc-2-Episode-1/refs/heads/master/refilc-2-real.png" width=150>
|
||||||
<h1 align=center><b>reFilc</b></h1>
|
<h1 align=center><b>reFilc</b></h1>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
#### Nem hivatalos e-napló alkalmazás az e-KRÉTA rendszerhez - tanulóktól, tanulóknak.
|
#### Nem hivatalos e-napló alkalmazás az e-KRÉTA rendszerhez - tanulóktól, tanulóknak.
|
||||||
|
|
||||||
[](https://github.com/refilc/naplo/releases) [](https://dc.refilc.hu)
|
[](https://github.com/refilc/naplo/releases) [](https://discord.gg/refilc-1111649116020285532)
|
||||||
|
|
||||||
## Setup
|
## Környezet felállítása
|
||||||
|
|
||||||
### Clone the project
|
### Source code letöltése
|
||||||
|
|
||||||
<em>A teljes source eléréséhez szükséged lesz a naplo-plus repo-ra is, mely biztonsági okokból privát. Írj Discord szerverünkön, hogy kaphass hozzáférést.</em>
|
*Az építhéshez szükséged lesz a refilc_plus repora is, amit itt találsz: [student-plus](https://git.qwit.cloud/refilc/student-plus)*
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone --branch dev https://github.com/refilc/naplo --recursive
|
git clone https://git.qwit.cloud/refilc/student-legacy.git --recursive
|
||||||
cd naplo
|
cd naplo
|
||||||
|
# ha ez nem töltött le refilc plus repoba értelmes dolgokat futtasd a többi parancsot is
|
||||||
|
rm -rf refilc_plus
|
||||||
|
git clone https://git.qwit.cloud/refilc/student-plus.git refilc_plus
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install packages
|
### Csomagok telepítése
|
||||||
|
|
||||||
Run `fix-pub.sh`
|
Menj be minden mappába és futtasd a következő parancsokat:
|
||||||
|
```sh
|
||||||
|
flutter clean
|
||||||
|
flutter pub get
|
||||||
|
```
|
||||||
|
|
||||||
### Run the app
|
### Alkalmazás építése
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd refilc
|
cd refilc
|
||||||
flutter run (--release)
|
flutter build apk --release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*Ez egy apk fájlt fog építeni*
|
||||||
|
|
||||||
### Contribution
|
### Contribution
|
||||||
|
|
||||||
**Nézd meg a [Contribution guide](CONTRIBUTING.md)-ot!**
|
**Nézd meg a [Contribution guide](CONTRIBUTING.md)-ot!**
|
||||||
@@ -37,16 +46,22 @@ Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a relea
|
|||||||
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
# Team
|
# Csapatunk
|
||||||
|
|
||||||
**kima:** head developer / project manager
|
**Management**
|
||||||
|
- Zypherift
|
||||||
|
- hayn
|
||||||
|
- Pearoo
|
||||||
|
- Zizi
|
||||||
|
- mnus
|
||||||
|
- xou
|
||||||
|
|
||||||
**Reiner, pdf, Pearoo, Zizi:** community- and project manager / developer
|
**Designerek**
|
||||||
|
- dwe
|
||||||
|
- xou
|
||||||
|
|
||||||
**vrolandd, TMarccci:** head developer
|
**vrolandd, TMarccci:** head developer
|
||||||
|
|
||||||
**dwe., xou:** designer
|
|
||||||
|
|
||||||
**Péter:** video editor
|
**Péter:** video editor
|
||||||
|
|
||||||
<em>**annon:** a régi Filc Napló fejlesztője (ez az app, ha bár sokban változott, alapjaiban a Filc-re épül)</em>
|
***annon:** a régi Filc Napló fejlesztője (ez az app, ha bár sokban változott, alapjaiban a Filc-re épül)*
|
||||||
|
|||||||
7
check-outdated.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
cd refilc && flutter pub outdated && cd ..
|
||||||
|
cd refilc_kreta_api && flutter pub outdated && cd ..
|
||||||
|
cd refilc_mobile_ui && flutter pub outdated && cd ..
|
||||||
|
# cd refilc_desktop_ui && flutter pub upgrade && cd ..
|
||||||
|
cd refilc_plus && flutter pub outdated && cd ..
|
||||||
|
|
||||||
|
echo Outdated version list above.
|
||||||
7
major-upgrade-pub.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
cd refilc && flutter pub upgrade --major-versions && cd ..
|
||||||
|
cd refilc_kreta_api && flutter pub upgrade --major-versions && cd ..
|
||||||
|
cd refilc_mobile_ui && flutter pub upgrade --major-versions && cd ..
|
||||||
|
# cd refilc_desktop_ui && flutter pub upgrade && cd ..
|
||||||
|
cd refilc_plus && flutter pub upgrade --major-versions && cd ..
|
||||||
|
|
||||||
|
echo "Upgraded pub (major)."
|
||||||
1
refilc/android/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.jks
|
||||||
@@ -39,8 +39,23 @@ def debugKeystoreProperties = new Properties()
|
|||||||
def debugKeystorePropertiesFile = rootProject.file("debugkey.properties")
|
def debugKeystorePropertiesFile = rootProject.file("debugkey.properties")
|
||||||
debugKeystoreProperties.load(new FileInputStream(debugKeystorePropertiesFile))
|
debugKeystoreProperties.load(new FileInputStream(debugKeystorePropertiesFile))
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
afterEvaluate { project ->
|
||||||
|
if (project.hasProperty('android')) {
|
||||||
|
project.android {
|
||||||
|
if (!hasProperty('namespace') || namespace == null || namespace.isEmpty()) {
|
||||||
|
// Assign a default namespace based on the project name or group
|
||||||
|
namespace = project.group.toString() ?: "com.example.${project.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
ndkVersion "25.1.8937393"
|
namespace = "hu.refilc.naplo"
|
||||||
|
|
||||||
|
ndkVersion "27.2.12479018"
|
||||||
|
|
||||||
// compileSdkVersion rootProject.ext.compileSdkVersion
|
// compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
compileSdkVersion 34
|
compileSdkVersion 34
|
||||||
@@ -70,8 +85,16 @@ android {
|
|||||||
// Flag to enable support for the new language APIs
|
// Flag to enable support for the new language APIs
|
||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
// Sets Java compatibility to Java 8
|
// Sets Java compatibility to Java 8
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
// sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
// targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
// sourceCompatibility JavaVersion.VERSION_21
|
||||||
|
// targetCompatibility JavaVersion.VERSION_21
|
||||||
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@@ -97,7 +120,13 @@ android {
|
|||||||
|
|
||||||
release {
|
release {
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
shrinkResources false
|
shrinkResources true
|
||||||
|
minifyEnabled true
|
||||||
|
debuggable false
|
||||||
|
jniDebuggable false
|
||||||
|
renderscriptDebuggable false
|
||||||
|
pseudoLocalesEnabled false
|
||||||
|
zipAlignEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +146,7 @@ dependencies {
|
|||||||
implementation 'joda-time:joda-time:2.9.4'
|
implementation 'joda-time:joda-time:2.9.4'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||||
implementation 'androidx.window:window:1.0.0'
|
implementation 'androidx.window:window:1.0.0'
|
||||||
implementation 'androidx.window:window-java:1.0.0'
|
implementation 'androidx.window:window-java:1.0.0'
|
||||||
}
|
}
|
||||||
|
|||||||
5
refilc/android/app/proguard-rules.pro
vendored
@@ -9,3 +9,8 @@
|
|||||||
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error
|
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error
|
||||||
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter
|
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter
|
||||||
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider
|
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider
|
||||||
|
|
||||||
|
-dontwarn org.joda.convert.FromString
|
||||||
|
-dontwarn org.joda.convert.ToString
|
||||||
|
|
||||||
|
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
@@ -2,9 +2,6 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
xmlns:tools="http://schemas.android.com/tools" package="hu.refilc.naplo">
|
||||||
<application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
|
<application android:name="${applicationName}" android:label="reFilc" tools:replace="android:label" android:icon="@mipmap/ic_launcher"
|
||||||
android:requestLegacyExternalStorage="true" android:enableOnBackInvokedCallback="false">
|
android:requestLegacyExternalStorage="true" android:enableOnBackInvokedCallback="false">
|
||||||
<service
|
|
||||||
android:name="com.solusibejo.flutter_dynamic_icon_plus.FlutterDynamicIconPlusService"
|
|
||||||
android:stopWithTask="false"/>
|
|
||||||
|
|
||||||
<activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
|
<activity android:exported="true" android:name="hu.refilc.naplo.MainActivity"
|
||||||
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
|
android:launchMode="singleTop" android:theme="@style/LaunchTheme"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 69 B |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 69 B |
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground>
|
||||||
|
<inset
|
||||||
|
android:drawable="@drawable/ic_launcher_foreground"
|
||||||
|
android:inset="16%" />
|
||||||
|
</foreground>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -6,7 +6,7 @@
|
|||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
<item name="android:windowSplashScreenBackground">#03112D</item>
|
<item name="android:windowSplashScreenBackground">#7CA021</item>
|
||||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<item name="android:windowFullscreen">false</item>
|
<item name="android:windowFullscreen">false</item>
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
<item name="android:windowSplashScreenBackground">#03112D</item>
|
<item name="android:windowSplashScreenBackground">#7CA021</item>
|
||||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="ic_launcher_background">#03112D</color>
|
<color name="ic_launcher_background">#7CA021</color>
|
||||||
|
|
||||||
<color name="purple_200">#FFBB86FC</color>
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
<color name="purple_500">#FF6200EE</color>
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
org.gradle.jvmargs=-Xmx1536M \
|
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
|
||||||
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
|
|
||||||
--add-opens=java.base/java.lang=ALL-UNNAMED \
|
|
||||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
|
|
||||||
--add-opens=java.base/java.io=ALL-UNNAMED \
|
|
||||||
--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
# kotlin.jvm.target.validation.mode=IGNORE
|
||||||
@@ -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-7.3.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version "7.1.1" apply false
|
id "com.android.application" version "8.7.3" apply false
|
||||||
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
|
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include ":app"
|
include ":app"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 87 KiB |
2
refilc/build.sh
Normal file → Executable file
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
flutter build apk --release --dart-define=APPVER=$(cat pubspec.yaml | grep version: | cut -d' ' -f2 | cut -d+ -f1) --no-tree-shake-icons
|
flutter build apk --release --tree-shake-icons --split-debug-info=debug-info --split-per-abi --target-platform android-arm,android-arm64 --obfuscate
|
||||||
|
|||||||
@@ -517,9 +517,11 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
FLUTTER_BUILD_NAME = 5.1.1;
|
||||||
|
FLUTTER_BUILD_NUMBER = 283;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
@@ -527,7 +529,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.1.0;
|
MARKETING_VERSION = 5.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -549,7 +551,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 276;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -563,7 +565,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.0.5;
|
MARKETING_VERSION = 5.1.1;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
||||||
@@ -591,7 +593,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 276;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -605,7 +607,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.0.5;
|
MARKETING_VERSION = 5.1.1;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -631,7 +633,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 276;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -645,7 +647,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.0.5;
|
MARKETING_VERSION = 5.1.1;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc.livecard;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -775,9 +777,11 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
FLUTTER_BUILD_NAME = 5.1.1;
|
||||||
|
FLUTTER_BUILD_NUMBER = 283;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
@@ -785,7 +789,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.1.0;
|
MARKETING_VERSION = 5.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -803,9 +807,11 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 283;
|
||||||
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
DEVELOPMENT_TEAM = 4J97JVC2FG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
|
FLUTTER_BUILD_NAME = 5.1.1;
|
||||||
|
FLUTTER_BUILD_NUMBER = 283;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
INFOPLIST_KEY_CFBundleDisplayName = reFilc;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
|
||||||
@@ -813,7 +819,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 5.1.0;
|
MARKETING_VERSION = 5.1.1;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
PRODUCT_BUNDLE_IDENTIFIER = hu.qwit.refilc;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 69 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 84 KiB |
@@ -38,7 +38,7 @@
|
|||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="LaunchImage" width="1700" height="1700"/>
|
<image name="LaunchImage" width="2700" height="2700"/>
|
||||||
<image name="LaunchBackground" width="1" height="1"/>
|
<image name="LaunchBackground" width="1" height="1"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -11,6 +11,17 @@ struct Widgets: WidgetBundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// text contrast background
|
||||||
|
extension Text {
|
||||||
|
func getContrastText(backgroundColor: Color) -> some View {
|
||||||
|
var r, g, b, a: CGFloat
|
||||||
|
(r, g, b, a) = (0, 0, 0, 0)
|
||||||
|
UIColor(backgroundColor).getRed(&r, green: &g, blue: &b, alpha: &a)
|
||||||
|
let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
||||||
|
return luminance < 0.6 ? self.foregroundColor(.white) : self.foregroundColor(.black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Color Converter
|
// Color Converter
|
||||||
extension Color {
|
extension Color {
|
||||||
init(hex: String, alpha: Double = 1.0) {
|
init(hex: String, alpha: Double = 1.0) {
|
||||||
@@ -62,7 +73,6 @@ struct LockScreenLiveActivityView: View {
|
|||||||
.font(.body)
|
.font(.body)
|
||||||
.bold()
|
.bold()
|
||||||
.padding(.trailing, 90)
|
.padding(.trailing, 90)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
MultilineTextView(text: "\(context.state.index) \(context.state.title) - \(context.state.subtitle)", limit: 25)
|
MultilineTextView(text: "\(context.state.index) \(context.state.title) - \(context.state.subtitle)", limit: 25)
|
||||||
.font(.body)
|
.font(.body)
|
||||||
@@ -84,6 +94,7 @@ struct LockScreenLiveActivityView: View {
|
|||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: CGFloat(8), height: CGFloat(8))
|
.frame(width: CGFloat(8), height: CGFloat(8))
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
Text("\(context.state.nextSubject) - \(context.state.nextRoom)")
|
Text("\(context.state.nextSubject) - \(context.state.nextRoom)")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
@@ -107,11 +118,15 @@ struct LockScreenLiveActivityView: View {
|
|||||||
.monospacedDigit()
|
.monospacedDigit()
|
||||||
.padding(.trailing)
|
.padding(.trailing)
|
||||||
}
|
}
|
||||||
|
// .activityBackgroundTint(
|
||||||
|
// context.state.color != "#676767"
|
||||||
|
// ? Color(hex: context.state.color)
|
||||||
|
// : Color.clear
|
||||||
|
// )
|
||||||
.activityBackgroundTint(
|
.activityBackgroundTint(
|
||||||
context.state.color != "#676767"
|
Color.clear
|
||||||
? Color(hex: context.state.color)
|
|
||||||
: Color.clear
|
|
||||||
)
|
)
|
||||||
|
.foregroundStyle(Color(hex: context.state.color))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,45 +21,48 @@ class FilcAPI {
|
|||||||
static const baseUrl = "https://api.refilcapp.hu";
|
static const baseUrl = "https://api.refilcapp.hu";
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
static const schoolList = "$baseUrl/v3/public/school-list";
|
static const schoolList = "https://api.refilcapp.hu/v3/public/school-list";
|
||||||
static const news = "$baseUrl/v4/public/news";
|
static const news = "https://staticrf-api.pages.dev/news/index.json";
|
||||||
static const supporters = "$baseUrl/v3/public/supporters";
|
static const supporters = "0.0.0.0";
|
||||||
|
|
||||||
// Private API
|
// Private API
|
||||||
static const ads = "$baseUrl/v3/private/ads";
|
static const ads = "0.0.0.0";
|
||||||
static const config = "$baseUrl/v3/private/config";
|
static const config = "$baseUrl/v3/private/config";
|
||||||
static const reportApi = "$baseUrl/v3/private/crash-report";
|
static const reportApi = "$baseUrl/v3/private/crash-report";
|
||||||
static const rfPlus = "$baseUrl/v3/rf-plus";
|
static const rfPlus = "0.0.0.0";
|
||||||
static const plusAuthLogin = "$rfPlus/auth/login";
|
static const plusAuthLogin = "0.0.0.0";
|
||||||
static const plusAuthCallback = "$rfPlus/auth/callback";
|
static const plusAuthCallback = "0.0.0.0";
|
||||||
static const plusActivation = "$rfPlus/activate";
|
static const plusActivation = "0.0.0.0";
|
||||||
static const plusScopes = "$rfPlus/scopes";
|
static const plusScopes = "0.0.0.0/";
|
||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
static const repo = "refilc/naplo";
|
static const repo = "refilc/naplo";
|
||||||
static const releases = "https://api.github.com/repos/$repo/releases";
|
static const releases = "https://api.github.com/repos/$repo/releases";
|
||||||
|
|
||||||
// Share API
|
// Share API
|
||||||
static const themeShare = "$baseUrl/v3/shared/theme/add";
|
static const themeShare = "https://api.refilcapp.hu/v3/shared/theme/add";
|
||||||
static const themeGet = "$baseUrl/v3/shared/theme/get";
|
static const themeGet = "https://api.refilcapp.hu/v3/shared/theme/get";
|
||||||
static const allThemes = "$themeGet/all";
|
static const allThemes = "$themeGet/all";
|
||||||
static const themeByID = "$themeGet/";
|
static const themeByID = "$themeGet/";
|
||||||
|
|
||||||
static const gradeColorsShare = "$baseUrl/v3/shared/grade-colors/add";
|
static const gradeColorsShare = "https://api.refilcapp.hu/v3/shared/grade-colors/add";
|
||||||
static const gradeColorsGet = "$baseUrl/v3/shared/grade-colors/get";
|
static const gradeColorsGet = "https://api.refilcapp.hu/v3/shared/grade-colors/get";
|
||||||
static const allGradeColors = "$gradeColorsGet/all";
|
static const allGradeColors = "$gradeColorsGet/all";
|
||||||
static const gradeColorsByID = "$gradeColorsGet/";
|
static const gradeColorsByID = "$gradeColorsGet/";
|
||||||
|
|
||||||
// Payment API
|
// Payment API
|
||||||
static const payment = "$baseUrl/v4/payment";
|
static const payment = "0.0.0.0";
|
||||||
static const stripeSheet = "$payment/stripe-sheet";
|
static const stripeSheet = "0.0.0.0";
|
||||||
|
|
||||||
// Cloud Sync
|
// Cloud Sync
|
||||||
static const cloudSyncApi = "$baseUrl/v4/me/cloud-sync";
|
// cloud sync? for what reason
|
||||||
|
static const cloudSyncApi = "0.0.0.0";
|
||||||
|
|
||||||
static Future<bool> checkConnectivity() async =>
|
static Future<bool> checkConnectivity() async =>
|
||||||
(await Connectivity().checkConnectivity())[0] != ConnectivityResult.none;
|
(await Connectivity().checkConnectivity())[0] != ConnectivityResult.none;
|
||||||
|
|
||||||
|
|
||||||
|
// nem tudom nem vazar-e senkit se, de mar ertelmetlen ez
|
||||||
static Future<List<School>?> getSchools() async {
|
static Future<List<School>?> getSchools() async {
|
||||||
try {
|
try {
|
||||||
http.Response res = await http.get(Uri.parse(schoolList));
|
http.Response res = await http.get(Uri.parse(schoolList));
|
||||||
@@ -69,16 +72,6 @@ class FilcAPI {
|
|||||||
.cast<Map>()
|
.cast<Map>()
|
||||||
.map((json) => School.fromJson(json))
|
.map((json) => School.fromJson(json))
|
||||||
.toList();
|
.toList();
|
||||||
schools.add(School(
|
|
||||||
city: "Stockholm",
|
|
||||||
instituteCode: "refilc-test-sweden",
|
|
||||||
name: "reFilc Test SE - Leo Ekström High School",
|
|
||||||
));
|
|
||||||
schools.add(School(
|
|
||||||
city: "Madrid",
|
|
||||||
instituteCode: "refilc-test-spain",
|
|
||||||
name: "reFilc Test ES - Emilio Obrero University",
|
|
||||||
));
|
|
||||||
return schools;
|
return schools;
|
||||||
} else {
|
} else {
|
||||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
throw "HTTP ${res.statusCode}: ${res.body}";
|
||||||
@@ -101,9 +94,7 @@ class FilcAPI {
|
|||||||
"rf-platform-version": settings.analyticsEnabled
|
"rf-platform-version": settings.analyticsEnabled
|
||||||
? Platform.operatingSystemVersion
|
? Platform.operatingSystemVersion
|
||||||
: "unknown",
|
: "unknown",
|
||||||
"rf-app-version": settings.analyticsEnabled
|
"rf-app-version": const String.fromEnvironment("APPVER", defaultValue: "?"),
|
||||||
? const String.fromEnvironment("APPVER", defaultValue: "?")
|
|
||||||
: "unknown",
|
|
||||||
"rf-uinid": settings.xFilcId,
|
"rf-uinid": settings.xFilcId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +125,8 @@ class FilcAPI {
|
|||||||
http.Response res = await http.get(Uri.parse(news));
|
http.Response res = await http.get(Uri.parse(news));
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
return (jsonDecode(res.body) as List)
|
String utf8Body = utf8.decode(res.bodyBytes);
|
||||||
|
return (jsonDecode(utf8Body) as List)
|
||||||
.cast<Map>()
|
.cast<Map>()
|
||||||
.map((e) => News.fromJson(e))
|
.map((e) => News.fromJson(e))
|
||||||
.toList();
|
.toList();
|
||||||
@@ -396,27 +388,6 @@ class FilcAPI {
|
|||||||
|
|
||||||
// cloud sync
|
// cloud sync
|
||||||
static Future<Map?> cloudSync(Map<String, String> data, String token) async {
|
static Future<Map?> cloudSync(Map<String, String> data, String token) async {
|
||||||
try {
|
|
||||||
var client = http.Client();
|
|
||||||
|
|
||||||
http.Response res = await client.post(
|
|
||||||
Uri.parse(cloudSyncApi),
|
|
||||||
body: data,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
'Authorization': 'Bearer $token',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res.statusCode != 200) {
|
|
||||||
throw "HTTP ${res.statusCode}: ${res.body}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonDecode(res.body);
|
|
||||||
} on Exception catch (error, stacktrace) {
|
|
||||||
log("ERROR: FilcAPI.cloudSync: $error $stacktrace");
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class AdProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetch() async {
|
Future<void> fetch() async {
|
||||||
_ads = await FilcAPI.getAds() ?? [];
|
_ads = [];
|
||||||
_ads.sort((a, b) => -a.date.compareTo(b.date));
|
_ads.sort((a, b) => -a.date.compareTo(b.date));
|
||||||
|
|
||||||
// check for new ads
|
// check for new ads
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:refilc/database/query.dart';
|
import 'package:refilc/database/query.dart';
|
||||||
import 'package:refilc/database/store.dart';
|
import 'package:refilc/database/store.dart';
|
||||||
// ignore: depend_on_referenced_packages
|
// ignore: depend_on_referenced_packages
|
||||||
@@ -15,11 +13,7 @@ class DatabaseProvider {
|
|||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
Database db;
|
Database db;
|
||||||
|
|
||||||
if (Platform.isLinux || Platform.isWindows) {
|
|
||||||
db = await databaseFactoryFfi.openDatabase("app.db");
|
|
||||||
} else {
|
|
||||||
db = await openDatabase("app.db");
|
db = await openDatabase("app.db");
|
||||||
}
|
|
||||||
|
|
||||||
query = DatabaseQuery(db: db);
|
query = DatabaseQuery(db: db);
|
||||||
store = DatabaseStore(db: db);
|
store = DatabaseStore(db: db);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'dart:async';
|
|||||||
import 'package:refilc/api/providers/liveactivity/platform_channel.dart';
|
import 'package:refilc/api/providers/liveactivity/platform_channel.dart';
|
||||||
import 'package:refilc/helpers/subject.dart';
|
import 'package:refilc/helpers/subject.dart';
|
||||||
import 'package:refilc/models/settings.dart';
|
import 'package:refilc/models/settings.dart';
|
||||||
|
import 'package:refilc/ui/flutter_colorpicker/utils.dart';
|
||||||
import 'package:refilc_kreta_api/models/lesson.dart';
|
import 'package:refilc_kreta_api/models/lesson.dart';
|
||||||
import 'package:refilc_kreta_api/models/week.dart';
|
import 'package:refilc_kreta_api/models/week.dart';
|
||||||
import 'package:refilc/utils/format.dart';
|
import 'package:refilc/utils/format.dart';
|
||||||
@@ -84,11 +85,14 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> toMap() {
|
Map<String, String> toMap() {
|
||||||
|
// print("LIVE ACTIVITY COLOR BELOW:");
|
||||||
|
// print(_settings.liveActivityColor.toHexString().substring(2));
|
||||||
|
String color = '#${_settings.liveActivityColor.toHexString().substring(2)}';
|
||||||
|
|
||||||
switch (currentState) {
|
switch (currentState) {
|
||||||
case LiveCardState.morning:
|
case LiveCardState.morning:
|
||||||
return {
|
return {
|
||||||
"color":
|
"color": color,
|
||||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
|
||||||
"icon": nextLesson != null
|
"icon": nextLesson != null
|
||||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||||
: "book",
|
: "book",
|
||||||
@@ -112,8 +116,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
case LiveCardState.afternoon:
|
case LiveCardState.afternoon:
|
||||||
return {
|
return {
|
||||||
"color":
|
"color": color,
|
||||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
|
||||||
"icon": nextLesson != null
|
"icon": nextLesson != null
|
||||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||||
: "book",
|
: "book",
|
||||||
@@ -137,8 +140,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
case LiveCardState.night:
|
case LiveCardState.night:
|
||||||
return {
|
return {
|
||||||
"color":
|
"color": color,
|
||||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
|
||||||
"icon": nextLesson != null
|
"icon": nextLesson != null
|
||||||
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
? SubjectIcon.resolveName(subject: nextLesson?.subject)
|
||||||
: "book",
|
: "book",
|
||||||
@@ -162,8 +164,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
case LiveCardState.duringLesson:
|
case LiveCardState.duringLesson:
|
||||||
return {
|
return {
|
||||||
"color":
|
"color": color,
|
||||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
|
||||||
"icon": currentLesson != null
|
"icon": currentLesson != null
|
||||||
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
? SubjectIcon.resolveName(subject: currentLesson?.subject)
|
||||||
: "book",
|
: "book",
|
||||||
@@ -174,7 +175,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
ShortSubject.resolve(subject: currentLesson?.subject)
|
ShortSubject.resolve(subject: currentLesson?.subject)
|
||||||
.capital()
|
.capital()
|
||||||
: "",
|
: "",
|
||||||
"subtitle": "Terem: ${currentLesson?.room.replaceAll("_", " ") ?? ""}",
|
"subtitle":
|
||||||
|
"Terem: ${currentLesson?.room.replaceAll("_", " ") ?? ""}",
|
||||||
"description": currentLesson?.description ?? "",
|
"description": currentLesson?.description ?? "",
|
||||||
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
|
"startDate": ((currentLesson?.start.millisecondsSinceEpoch ?? 0) -
|
||||||
_delay.inMilliseconds)
|
_delay.inMilliseconds)
|
||||||
@@ -199,8 +201,7 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
final diff = getFloorDifference();
|
final diff = getFloorDifference();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"color":
|
"color": color,
|
||||||
'#${_settings.liveActivityColor.toString().substring(10, 16)}',
|
|
||||||
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
"icon": iconFloorMap[diff] ?? "cup.and.saucer",
|
||||||
"title": "Szünet",
|
"title": "Szünet",
|
||||||
"description": "go $diff".i18n.fill([
|
"description": "go $diff".i18n.fill([
|
||||||
@@ -362,7 +363,11 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//END
|
//END
|
||||||
if ((currentState == LiveCardState.afternoon || currentState == LiveCardState.morning || currentState == LiveCardState.night) && hasActivityStarted && nextLesson != null &&
|
if ((currentState == LiveCardState.afternoon ||
|
||||||
|
currentState == LiveCardState.morning ||
|
||||||
|
currentState == LiveCardState.night) &&
|
||||||
|
hasActivityStarted &&
|
||||||
|
nextLesson != null &&
|
||||||
nextLesson!.start.difference(now).inMinutes > 60) {
|
nextLesson!.start.difference(now).inMinutes > 60) {
|
||||||
debugPrint("Több, mint 1 óra van az első óráig. Befejezés...");
|
debugPrint("Több, mint 1 óra van az első óráig. Befejezés...");
|
||||||
PlatformChannel.endLiveActivity();
|
PlatformChannel.endLiveActivity();
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ import 'package:refilc_mobile_ui/screens/settings/settings_route.dart'
|
|||||||
import 'package:refilc_mobile_ui/screens/settings/settings_screen.dart'
|
import 'package:refilc_mobile_ui/screens/settings/settings_screen.dart'
|
||||||
as mobile;
|
as mobile;
|
||||||
|
|
||||||
// Desktop UI
|
// Desktop UI (no more desktop ui)
|
||||||
import 'package:refilc_desktop_ui/screens/navigation/navigation_screen.dart'
|
// import 'package:refilc_desktop_ui/screens/navigation/navigation_screen.dart'
|
||||||
as desktop;
|
// as desktop;
|
||||||
import 'package:refilc_desktop_ui/screens/login/login_screen.dart' as desktop;
|
// import 'package:refilc_desktop_ui/screens/login/login_screen.dart' as desktop;
|
||||||
import 'package:refilc_desktop_ui/screens/login/login_route.dart' as desktop;
|
// import 'package:refilc_desktop_ui/screens/login/login_route.dart' as desktop;
|
||||||
|
|
||||||
// Providers
|
// Providers
|
||||||
import 'package:refilc/models/settings.dart';
|
import 'package:refilc/models/settings.dart';
|
||||||
@@ -248,17 +248,18 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
Route? rootNavigator(RouteSettings route) {
|
Route? rootNavigator(RouteSettings route) {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
switch (route.name) {
|
return null;
|
||||||
case "login_back":
|
// switch (route.name) {
|
||||||
return CupertinoPageRoute(
|
// case "login_back":
|
||||||
builder: (context) => const desktop.LoginScreen(back: true));
|
// return CupertinoPageRoute(
|
||||||
case "login":
|
// builder: (context) => const desktop.LoginScreen(back: true));
|
||||||
return _rootRoute(const desktop.LoginScreen());
|
// case "login":
|
||||||
case "navigation":
|
// return _rootRoute(const desktop.LoginScreen());
|
||||||
return _rootRoute(const desktop.NavigationScreen());
|
// case "navigation":
|
||||||
case "login_to_navigation":
|
// return _rootRoute(const desktop.NavigationScreen());
|
||||||
return desktop.loginRoute(const desktop.NavigationScreen());
|
// case "login_to_navigation":
|
||||||
}
|
// return desktop.loginRoute(const desktop.NavigationScreen());
|
||||||
|
// }
|
||||||
} else if (Platform.isAndroid || Platform.isIOS) {
|
} else if (Platform.isAndroid || Platform.isIOS) {
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case "login_back":
|
case "login_back":
|
||||||
@@ -274,17 +275,18 @@ class App extends StatelessWidget {
|
|||||||
return mobile.settingsRoute(const mobile.SettingsScreen());
|
return mobile.settingsRoute(const mobile.SettingsScreen());
|
||||||
}
|
}
|
||||||
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
} else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
|
||||||
switch (route.name) {
|
return null;
|
||||||
case "login_back":
|
// switch (route.name) {
|
||||||
return CupertinoPageRoute(
|
// case "login_back":
|
||||||
builder: (context) => const desktop.LoginScreen(back: true));
|
// return CupertinoPageRoute(
|
||||||
case "login":
|
// builder: (context) => const desktop.LoginScreen(back: true));
|
||||||
return _rootRoute(const desktop.LoginScreen());
|
// case "login":
|
||||||
case "navigation":
|
// return _rootRoute(const desktop.LoginScreen());
|
||||||
return _rootRoute(const desktop.NavigationScreen());
|
// case "navigation":
|
||||||
case "login_to_navigation":
|
// return _rootRoute(const desktop.NavigationScreen());
|
||||||
return desktop.loginRoute(const desktop.NavigationScreen());
|
// case "login_to_navigation":
|
||||||
}
|
// return desktop.loginRoute(const desktop.NavigationScreen());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import 'package:refilc/models/settings.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
// ignore: depend_on_referenced_packages
|
// ignore: depend_on_referenced_packages
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
// import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
||||||
|
|
||||||
const settingsDB = DatabaseStruct("settings", {
|
const settingsDB = DatabaseStruct("settings", {
|
||||||
"language": String, "start_page": int, "rounding": int, "theme": int,
|
"language": String, "start_page": int, "rounding": int, "theme": int,
|
||||||
@@ -110,7 +110,8 @@ Future<Database> initDB(DatabaseProvider database) async {
|
|||||||
Database db;
|
Database db;
|
||||||
|
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
db = await databaseFactoryFfiWeb.openDatabase("app.db");
|
// db = await databaseFactoryFfiWeb.openDatabase("app.db");
|
||||||
|
throw "web is not supported";
|
||||||
} else if (Platform.isLinux || Platform.isWindows) {
|
} else if (Platform.isLinux || Platform.isWindows) {
|
||||||
sqfliteFfiInit();
|
sqfliteFfiInit();
|
||||||
db = await databaseFactoryFfi.openDatabase("app.db");
|
db = await databaseFactoryFfi.openDatabase("app.db");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
import 'package:refilc/api/providers/user_provider.dart';
|
import 'package:refilc/api/providers/user_provider.dart';
|
||||||
import 'package:refilc/api/providers/database_provider.dart';
|
import 'package:refilc/api/providers/database_provider.dart';
|
||||||
import 'package:refilc/database/init.dart';
|
import 'package:refilc/database/init.dart';
|
||||||
import 'package:refilc/helpers/notification_helper.dart';
|
// import 'package:refilc/helpers/notification_helper.dart';
|
||||||
import 'package:refilc/models/settings.dart';
|
import 'package:refilc/models/settings.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -104,7 +104,7 @@ class Startup {
|
|||||||
user = await database.query.getUsers(settings);
|
user = await database.query.getUsers(settings);
|
||||||
|
|
||||||
// Set all notification categories to seen to avoid having notifications that the user has already seen in the app
|
// Set all notification categories to seen to avoid having notifications that the user has already seen in the app
|
||||||
NotificationsHelper().setAllCategoriesSeen(user);
|
// NotificationsHelper().setAllCategoriesSeen(user);
|
||||||
|
|
||||||
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
||||||
// Notifications setup
|
// Notifications setup
|
||||||
@@ -146,30 +146,30 @@ class Startup {
|
|||||||
|
|
||||||
// Platform specific settings
|
// Platform specific settings
|
||||||
if (!kIsWeb) {
|
if (!kIsWeb) {
|
||||||
const DarwinInitializationSettings initializationSettingsDarwin =
|
// const DarwinInitializationSettings initializationSettingsDarwin =
|
||||||
DarwinInitializationSettings(
|
// DarwinInitializationSettings(
|
||||||
requestSoundPermission: true,
|
// requestSoundPermission: true,
|
||||||
requestBadgePermission: true,
|
// requestBadgePermission: true,
|
||||||
requestAlertPermission: false,
|
// requestAlertPermission: false,
|
||||||
);
|
// );
|
||||||
const AndroidInitializationSettings initializationSettingsAndroid =
|
// const AndroidInitializationSettings initializationSettingsAndroid =
|
||||||
AndroidInitializationSettings('ic_notification');
|
// AndroidInitializationSettings('ic_notification');
|
||||||
const LinuxInitializationSettings initializationSettingsLinux =
|
// const LinuxInitializationSettings initializationSettingsLinux =
|
||||||
LinuxInitializationSettings(defaultActionName: 'Open notification');
|
// LinuxInitializationSettings(defaultActionName: 'Open notification');
|
||||||
const InitializationSettings initializationSettings =
|
// const InitializationSettings initializationSettings =
|
||||||
InitializationSettings(
|
// InitializationSettings(
|
||||||
android: initializationSettingsAndroid,
|
// android: initializationSettingsAndroid,
|
||||||
iOS: initializationSettingsDarwin,
|
// iOS: initializationSettingsDarwin,
|
||||||
macOS: initializationSettingsDarwin,
|
// macOS: initializationSettingsDarwin,
|
||||||
linux: initializationSettingsLinux,
|
// linux: initializationSettingsLinux,
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Initialize notifications
|
// Initialize notifications
|
||||||
await flutterLocalNotificationsPlugin.initialize(
|
// await flutterLocalNotificationsPlugin.initialize(
|
||||||
initializationSettings,
|
// initializationSettings,
|
||||||
onDidReceiveNotificationResponse:
|
// onDidReceiveNotificationResponse:
|
||||||
NotificationsHelper().onDidReceiveNotificationResponse,
|
// NotificationsHelper().onDidReceiveNotificationResponse,
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (Platform.isAndroid || Platform.isIOS) {
|
// if (Platform.isAndroid || Platform.isIOS) {
|
||||||
@@ -239,7 +239,7 @@ Future<void> initPlatformState() async {
|
|||||||
if (!Platform.isIOS) return;
|
if (!Platform.isIOS) return;
|
||||||
LiveActivityHelper().backgroundJob();
|
LiveActivityHelper().backgroundJob();
|
||||||
} else {
|
} else {
|
||||||
NotificationsHelper().backgroundJob();
|
// NotificationsHelper().backgroundJob();
|
||||||
}
|
}
|
||||||
BackgroundFetch.finish(taskId);
|
BackgroundFetch.finish(taskId);
|
||||||
}, (String taskId) async {
|
}, (String taskId) async {
|
||||||
@@ -279,7 +279,7 @@ void backgroundHeadlessTask(HeadlessTask task) {
|
|||||||
if (!Platform.isIOS) return;
|
if (!Platform.isIOS) return;
|
||||||
LiveActivityHelper().backgroundJob();
|
LiveActivityHelper().backgroundJob();
|
||||||
} else {
|
} else {
|
||||||
NotificationsHelper().backgroundJob();
|
// NotificationsHelper().backgroundJob();
|
||||||
}
|
}
|
||||||
BackgroundFetch.finish(task.taskId);
|
BackgroundFetch.finish(task.taskId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
notificationsMessagesEnabled: true,
|
notificationsMessagesEnabled: true,
|
||||||
notificationsLessonsEnabled: true,
|
notificationsLessonsEnabled: true,
|
||||||
notificationsBitfield: 255,
|
notificationsBitfield: 255,
|
||||||
developerMode: false,
|
developerMode: true,
|
||||||
notificationPollInterval: 1,
|
notificationPollInterval: 1,
|
||||||
vibrate: VibrationStrength.medium,
|
vibrate: VibrationStrength.medium,
|
||||||
abWeeks: false,
|
abWeeks: false,
|
||||||
@@ -478,7 +478,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
updateChannel: UpdateChannel.stable,
|
updateChannel: UpdateChannel.stable,
|
||||||
config: Config.fromJson({}),
|
config: Config.fromJson({}),
|
||||||
xFilcId: const Uuid().v4(),
|
xFilcId: const Uuid().v4(),
|
||||||
analyticsEnabled: true,
|
analyticsEnabled: false,
|
||||||
graphClassAvg: false,
|
graphClassAvg: false,
|
||||||
goodStudent: false,
|
goodStudent: false,
|
||||||
presentationMode: false,
|
presentationMode: false,
|
||||||
@@ -500,13 +500,13 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
renameSubjectsItalics: false,
|
renameSubjectsItalics: false,
|
||||||
renameTeachersEnabled: false,
|
renameTeachersEnabled: false,
|
||||||
renameTeachersItalics: false,
|
renameTeachersItalics: false,
|
||||||
liveActivityColor: const Color(0xFF676767),
|
liveActivityColor: const Color(0x00000000),
|
||||||
welcomeMessage: '',
|
welcomeMessage: '',
|
||||||
appIcon: 'refilc_default',
|
appIcon: 'refilc_default',
|
||||||
currentThemeId: '',
|
currentThemeId: '',
|
||||||
currentThemeDisplayName: '',
|
currentThemeDisplayName: '',
|
||||||
currentThemeCreator: 'reFilc',
|
currentThemeCreator: 'reFilc',
|
||||||
showBreaks: true,
|
showBreaks: false,
|
||||||
pinSetGeneral: '',
|
pinSetGeneral: '',
|
||||||
pinSetPersonalize: '',
|
pinSetPersonalize: '',
|
||||||
pinSetNotify: '',
|
pinSetNotify: '',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:refilc/theme/colors/dark_desktop.dart';
|
// import 'package:refilc/theme/colors/dark_desktop.dart';
|
||||||
import 'package:refilc/theme/colors/dark_mobile.dart';
|
import 'package:refilc/theme/colors/dark_mobile.dart';
|
||||||
import 'package:refilc/theme/colors/light_desktop.dart';
|
// import 'package:refilc/theme/colors/light_desktop.dart';
|
||||||
import 'package:refilc/theme/colors/light_mobile.dart';
|
import 'package:refilc/theme/colors/light_mobile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -21,10 +21,16 @@ class AppColors {
|
|||||||
} else {
|
} else {
|
||||||
switch (brightness) {
|
switch (brightness) {
|
||||||
case Brightness.light:
|
case Brightness.light:
|
||||||
return LightDesktopAppColors();
|
return LightMobileAppColors();
|
||||||
case Brightness.dark:
|
case Brightness.dark:
|
||||||
return DarkDesktopAppColors();
|
return DarkMobileAppColors();
|
||||||
}
|
}
|
||||||
|
// switch (brightness) {
|
||||||
|
// case Brightness.light:
|
||||||
|
// return LightDesktopAppColors();
|
||||||
|
// case Brightness.dark:
|
||||||
|
// return DarkDesktopAppColors();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,42 +115,42 @@ class AppTheme {
|
|||||||
primary: accent,
|
primary: accent,
|
||||||
onPrimary:
|
onPrimary:
|
||||||
(accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
(accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
secondary: newSecondary,
|
secondary: newSecondary,
|
||||||
onSecondary: (newSecondary.computeLuminance() > 0.5
|
onSecondary: (newSecondary.computeLuminance() > 0.5
|
||||||
? Colors.black
|
? Colors.black
|
||||||
: Colors.white)
|
: Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
tertiary: newTertiary,
|
tertiary: newTertiary,
|
||||||
onTertiary:
|
onTertiary:
|
||||||
(newTertiary.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
(newTertiary.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
error: lightColors.red,
|
error: lightColors.red,
|
||||||
onError: Colors.white.withOpacity(.9),
|
onError: Colors.white.withValues(alpha: .9),
|
||||||
surface: highlightColor,
|
surface: highlightColor,
|
||||||
onSurface: Colors.black.withOpacity(.9),
|
onSurface: Colors.black.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
shadowColor: lightColors.shadow.withOpacity(.5),
|
shadowColor: lightColors.shadow.withValues(alpha: .5),
|
||||||
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||||
indicatorColor: accent,
|
indicatorColor: accent,
|
||||||
iconTheme: IconThemeData(color: lightColors.text.withOpacity(.75)),
|
iconTheme: IconThemeData(color: lightColors.text.withValues(alpha: .75)),
|
||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
indicatorColor:
|
indicatorColor: accent.withValues(
|
||||||
accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
alpha: accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||||
iconTheme:
|
iconTheme:
|
||||||
WidgetStateProperty.all(IconThemeData(color: lightColors.text)),
|
WidgetStateProperty.all(IconThemeData(color: lightColors.text)),
|
||||||
backgroundColor: highlightColor,
|
backgroundColor: highlightColor,
|
||||||
labelTextStyle: WidgetStateProperty.all(TextStyle(
|
labelTextStyle: WidgetStateProperty.all(TextStyle(
|
||||||
fontSize: 13.0,
|
fontSize: 13.0,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: lightColors.text.withOpacity(0.8),
|
color: lightColors.text.withValues(alpha: 0.8),
|
||||||
)),
|
)),
|
||||||
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||||
height: 76.0,
|
height: 76.0,
|
||||||
),
|
),
|
||||||
sliderTheme: SliderThemeData(
|
sliderTheme: SliderThemeData(
|
||||||
inactiveTrackColor: accent.withOpacity(.3),
|
inactiveTrackColor: accent.withValues(alpha: .3),
|
||||||
),
|
),
|
||||||
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
||||||
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
||||||
@@ -238,48 +238,48 @@ class AppTheme {
|
|||||||
primary: accent,
|
primary: accent,
|
||||||
onPrimary:
|
onPrimary:
|
||||||
(accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
(accent.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
secondary: newSecondary,
|
secondary: newSecondary,
|
||||||
onSecondary: (newSecondary.computeLuminance() > 0.5
|
onSecondary: (newSecondary.computeLuminance() > 0.5
|
||||||
? Colors.black
|
? Colors.black
|
||||||
: Colors.white)
|
: Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
tertiary: newTertiary,
|
tertiary: newTertiary,
|
||||||
onTertiary:
|
onTertiary:
|
||||||
(newTertiary.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
(newTertiary.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
error: darkColors.red,
|
error: darkColors.red,
|
||||||
onError: Colors.black.withOpacity(.9),
|
onError: Colors.black.withValues(alpha: .9),
|
||||||
surface: highlightColor,
|
surface: highlightColor,
|
||||||
onSurface: Colors.white.withOpacity(.9),
|
onSurface: Colors.white.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
shadowColor: highlightColor.withOpacity(.5), //darkColors.shadow,
|
shadowColor: highlightColor.withValues(alpha: .5), //darkColors.shadow,
|
||||||
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
appBarTheme: AppBarTheme(backgroundColor: backgroundColor),
|
||||||
indicatorColor: accent,
|
indicatorColor: accent,
|
||||||
iconTheme: IconThemeData(color: darkColors.text.withOpacity(.75)),
|
iconTheme: IconThemeData(color: darkColors.text.withValues(alpha: .75)),
|
||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
indicatorColor:
|
indicatorColor: accent.withValues(
|
||||||
accent.withOpacity(accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
alpha: accentColor == AccentColor.adaptive ? 0.4 : 0.8),
|
||||||
iconTheme:
|
iconTheme:
|
||||||
WidgetStateProperty.all(IconThemeData(color: darkColors.text)),
|
WidgetStateProperty.all(IconThemeData(color: darkColors.text)),
|
||||||
backgroundColor: highlightColor,
|
backgroundColor: highlightColor,
|
||||||
labelTextStyle: WidgetStateProperty.all(TextStyle(
|
labelTextStyle: WidgetStateProperty.all(TextStyle(
|
||||||
fontSize: 13.0,
|
fontSize: 13.0,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: darkColors.text.withOpacity(0.8),
|
color: darkColors.text.withValues(alpha: 0.8),
|
||||||
)),
|
)),
|
||||||
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
|
||||||
height: 76.0,
|
height: 76.0,
|
||||||
),
|
),
|
||||||
sliderTheme: SliderThemeData(
|
sliderTheme: SliderThemeData(
|
||||||
inactiveTrackColor: accent.withOpacity(.3),
|
inactiveTrackColor: accent.withValues(alpha: .3),
|
||||||
),
|
),
|
||||||
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
progressIndicatorTheme: ProgressIndicatorThemeData(color: accent),
|
||||||
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
expansionTileTheme: ExpansionTileThemeData(iconColor: accent),
|
||||||
cardColor: highlightColor,
|
cardColor: highlightColor,
|
||||||
chipTheme: ChipThemeData(
|
chipTheme: ChipThemeData(
|
||||||
backgroundColor: accent.withOpacity(.2),
|
backgroundColor: accent.withValues(alpha: .2),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
),
|
),
|
||||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ List<Widget> sortDateWidgets(
|
|||||||
width: 150.0,
|
width: 150.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
color: AppColors.of(context).text.withOpacity(.25),
|
color: AppColors.of(context).text.withValues(alpha: .25),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -178,8 +178,7 @@ Future<List<DateWidget>> getFilterWidgets(FilterType activeData,
|
|||||||
// Ads
|
// Ads
|
||||||
case FilterType.ads:
|
case FilterType.ads:
|
||||||
if (adProvider.available) {
|
if (adProvider.available) {
|
||||||
items = ad_filter.getWidgets(
|
items = ad_filter.getWidgets(adProvider.ads, context);
|
||||||
adProvider.ads, context);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -233,8 +232,8 @@ Widget filterItemBuilder(
|
|||||||
BoxShadow(
|
BoxShadow(
|
||||||
offset: const Offset(0, 21),
|
offset: const Offset(0, 21),
|
||||||
blurRadius: 23.0,
|
blurRadius: 23.0,
|
||||||
color: Theme.of(context).shadowColor.withOpacity(
|
color: Theme.of(context).shadowColor.withValues(
|
||||||
Theme.of(context).shadowColor.opacity *
|
alpha: Theme.of(context).shadowColor.opacity *
|
||||||
CurvedAnimation(
|
CurvedAnimation(
|
||||||
parent: CurvedAnimation(
|
parent: CurvedAnimation(
|
||||||
parent: animation,
|
parent: animation,
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ List<DateWidget> getWidgets(List<Grade> providerGrades) {
|
|||||||
List<DateWidget> items = [];
|
List<DateWidget> items = [];
|
||||||
for (var gradeType in GradeType.values) {
|
for (var gradeType in GradeType.values) {
|
||||||
if ([GradeType.midYear, GradeType.unknown, GradeType.levelExam]
|
if ([GradeType.midYear, GradeType.unknown, GradeType.levelExam]
|
||||||
.contains(gradeType)) continue;
|
.contains(gradeType)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
List<Grade> grades =
|
List<Grade> grades =
|
||||||
providerGrades.where((grade) => grade.type == gradeType).toList();
|
providerGrades.where((grade) => grade.type == gradeType).toList();
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import 'package:refilc/ui/date_widget.dart';
|
import 'package:refilc/ui/date_widget.dart';
|
||||||
import 'package:refilc/utils/platform.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
import 'package:refilc_kreta_api/models/grade.dart';
|
||||||
import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart'
|
import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart'
|
||||||
as mobile;
|
as mobile;
|
||||||
import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart'
|
import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart'
|
||||||
as mobile;
|
as mobile;
|
||||||
import 'package:refilc_desktop_ui/common/widgets/grade/grade_viewable.dart'
|
|
||||||
as desktop;
|
|
||||||
|
|
||||||
List<DateWidget> getWidgets(
|
List<DateWidget> getWidgets(
|
||||||
List<Grade> providerGrades, DateTime? lastSeenDate) {
|
List<Grade> providerGrades, DateTime? lastSeenDate) {
|
||||||
@@ -19,9 +16,7 @@ List<DateWidget> getWidgets(
|
|||||||
items.add(DateWidget(
|
items.add(DateWidget(
|
||||||
key: grade.id,
|
key: grade.id,
|
||||||
date: grade.date,
|
date: grade.date,
|
||||||
widget: PlatformUtils.isMobile
|
widget: mobile.GradeViewable(grade),
|
||||||
? mobile.GradeViewable(grade)
|
|
||||||
: desktop.GradeViewable(grade),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/// Blocky Color Picker
|
/// Blocky Color Picker
|
||||||
|
|
||||||
library block_colorpicker;
|
library;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:refilc/theme/colors/accent.dart';
|
import 'package:refilc/theme/colors/accent.dart';
|
||||||
@@ -73,7 +73,7 @@ Widget _defaultItemBuilder(
|
|||||||
color: color,
|
color: color,
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: color.withOpacity(0.8),
|
color: color.withValues(alpha: 0.8),
|
||||||
offset: const Offset(1, 2),
|
offset: const Offset(1, 2),
|
||||||
blurRadius: 5)
|
blurRadius: 5)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
library hsv_picker;
|
library;
|
||||||
|
|
||||||
import 'package:refilc/models/shared_theme.dart';
|
import 'package:refilc/models/shared_theme.dart';
|
||||||
import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
|
import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
|
||||||
@@ -380,7 +380,7 @@ class FilcColorPickerState extends State<FilcColorPicker> {
|
|||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
color: AppColors.of(context)
|
color: AppColors.of(context)
|
||||||
.text
|
.text
|
||||||
.withOpacity(isAdvancedView ? 1.0 : .5),
|
.withValues(alpha: isAdvancedView ? 1.0 : .5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -210,32 +210,32 @@ class TrackPainter extends CustomPainter {
|
|||||||
break;
|
break;
|
||||||
case TrackType.red:
|
case TrackType.red:
|
||||||
final List<Color> colors = [
|
final List<Color> colors = [
|
||||||
hsvColor.toColor().withRed(0).withOpacity(1.0),
|
hsvColor.toColor().withRed(0).withValues(alpha: 1.0),
|
||||||
hsvColor.toColor().withRed(255).withOpacity(1.0),
|
hsvColor.toColor().withRed(255).withValues(alpha: 1.0),
|
||||||
];
|
];
|
||||||
Gradient gradient = LinearGradient(colors: colors);
|
Gradient gradient = LinearGradient(colors: colors);
|
||||||
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
||||||
break;
|
break;
|
||||||
case TrackType.green:
|
case TrackType.green:
|
||||||
final List<Color> colors = [
|
final List<Color> colors = [
|
||||||
hsvColor.toColor().withGreen(0).withOpacity(1.0),
|
hsvColor.toColor().withGreen(0).withValues(alpha: 1.0),
|
||||||
hsvColor.toColor().withGreen(255).withOpacity(1.0),
|
hsvColor.toColor().withGreen(255).withValues(alpha: 1.0),
|
||||||
];
|
];
|
||||||
Gradient gradient = LinearGradient(colors: colors);
|
Gradient gradient = LinearGradient(colors: colors);
|
||||||
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
||||||
break;
|
break;
|
||||||
case TrackType.blue:
|
case TrackType.blue:
|
||||||
final List<Color> colors = [
|
final List<Color> colors = [
|
||||||
hsvColor.toColor().withBlue(0).withOpacity(1.0),
|
hsvColor.toColor().withBlue(0).withValues(alpha: 1.0),
|
||||||
hsvColor.toColor().withBlue(255).withOpacity(1.0),
|
hsvColor.toColor().withBlue(255).withValues(alpha: 1.0),
|
||||||
];
|
];
|
||||||
Gradient gradient = LinearGradient(colors: colors);
|
Gradient gradient = LinearGradient(colors: colors);
|
||||||
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
||||||
break;
|
break;
|
||||||
case TrackType.alpha:
|
case TrackType.alpha:
|
||||||
final List<Color> colors = [
|
final List<Color> colors = [
|
||||||
hsvColor.toColor().withOpacity(0.0),
|
hsvColor.toColor().withValues(alpha: 0.0),
|
||||||
hsvColor.toColor().withOpacity(1.0),
|
hsvColor.toColor().withValues(alpha: 1.0),
|
||||||
];
|
];
|
||||||
Gradient gradient = LinearGradient(colors: colors);
|
Gradient gradient = LinearGradient(colors: colors);
|
||||||
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect));
|
||||||
@@ -390,7 +390,7 @@ class ColorPickerInputState extends State<ColorPickerInput> {
|
|||||||
),
|
),
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
|
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
|
||||||
fillColor: AppColors.of(context).text.withOpacity(.1),
|
fillColor: AppColors.of(context).text.withValues(alpha: .1),
|
||||||
),
|
),
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
String input = value;
|
String input = value;
|
||||||
@@ -603,20 +603,20 @@ class ColorPickerSlider extends StatelessWidget {
|
|||||||
break;
|
break;
|
||||||
case TrackType.red:
|
case TrackType.red:
|
||||||
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().red / 0xff;
|
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().red / 0xff;
|
||||||
thumbColor = hsvColor.toColor().withOpacity(1.0);
|
thumbColor = hsvColor.toColor().withValues(alpha: 1.0);
|
||||||
break;
|
break;
|
||||||
case TrackType.green:
|
case TrackType.green:
|
||||||
thumbOffset +=
|
thumbOffset +=
|
||||||
(box.maxWidth - 30.0) * hsvColor.toColor().green / 0xff;
|
(box.maxWidth - 30.0) * hsvColor.toColor().green / 0xff;
|
||||||
thumbColor = hsvColor.toColor().withOpacity(1.0);
|
thumbColor = hsvColor.toColor().withValues(alpha: 1.0);
|
||||||
break;
|
break;
|
||||||
case TrackType.blue:
|
case TrackType.blue:
|
||||||
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().blue / 0xff;
|
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().blue / 0xff;
|
||||||
thumbColor = hsvColor.toColor().withOpacity(1.0);
|
thumbColor = hsvColor.toColor().withValues(alpha: 1.0);
|
||||||
break;
|
break;
|
||||||
case TrackType.alpha:
|
case TrackType.alpha:
|
||||||
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().opacity;
|
thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().opacity;
|
||||||
thumbColor = hsvColor.toColor().withOpacity(hsvColor.alpha);
|
thumbColor = hsvColor.toColor().withValues(alpha: hsvColor.alpha);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,8 +709,8 @@ class ColorIndicator extends StatelessWidget {
|
|||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: useWhiteForeground(color)
|
color: useWhiteForeground(color)
|
||||||
? Colors.white.withOpacity(.5)
|
? Colors.white.withValues(alpha: .5)
|
||||||
: Colors.black.withOpacity(.5),
|
: Colors.black.withValues(alpha: .5),
|
||||||
offset: const Offset(0, 0),
|
offset: const Offset(0, 0),
|
||||||
blurRadius: 5)
|
blurRadius: 5)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class GradeTile extends StatelessWidget {
|
|||||||
: Icon(
|
: Icon(
|
||||||
SubjectIcon.resolveVariant(
|
SubjectIcon.resolveVariant(
|
||||||
context: context, subject: grade.subject),
|
context: context, subject: grade.subject),
|
||||||
color: AppColors.of(context).text.withOpacity(.5),
|
color: AppColors.of(context).text.withValues(alpha: .5),
|
||||||
),
|
),
|
||||||
minLeadingWidth: isSubjectView ? 32.0 : 0,
|
minLeadingWidth: isSubjectView ? 32.0 : 0,
|
||||||
),
|
),
|
||||||
@@ -288,7 +288,8 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
shadows: [
|
shadows: [
|
||||||
if (value.weight >= 200)
|
if (value.weight >= 200)
|
||||||
Shadow(
|
Shadow(
|
||||||
color: (contrast ? Colors.white : color).withOpacity(.4),
|
color:
|
||||||
|
(contrast ? Colors.white : color).withValues(alpha: .4),
|
||||||
offset: const Offset(-4, -3),
|
offset: const Offset(-4, -3),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -312,7 +313,7 @@ class GradeValueWidget extends StatelessWidget {
|
|||||||
width: size * 1.4,
|
width: size * 1.4,
|
||||||
height: size * 1.4,
|
height: size * 1.4,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color.withOpacity(contrast ? 1.0 : .25),
|
color: color.withValues(alpha: contrast ? 1.0 : .25),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
if (shadow &&
|
if (shadow &&
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lesson.isEmpty) {
|
if (lesson.isEmpty) {
|
||||||
accent = AppColors.of(context).text.withOpacity(0.6);
|
accent = AppColors.of(context).text.withValues(alpha: 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lesson.studentPresence) {
|
if (!lesson.studentPresence) {
|
||||||
@@ -182,9 +182,8 @@ class LessonTile extends StatelessWidget {
|
|||||||
fontSize: 16.5,
|
fontSize: 16.5,
|
||||||
color: fill
|
color: fill
|
||||||
? accent
|
? accent
|
||||||
: AppColors.of(context)
|
: AppColors.of(context).text.withValues(
|
||||||
.text
|
alpha: !lesson.isEmpty ? 1.0 : 0.5),
|
||||||
.withOpacity(!lesson.isEmpty ? 1.0 : 0.5),
|
|
||||||
fontStyle: lesson.subject.isRenamed &&
|
fontStyle: lesson.subject.isRenamed &&
|
||||||
settingsProvider.renamedSubjectsItalics
|
settingsProvider.renamedSubjectsItalics
|
||||||
? FontStyle.italic
|
? FontStyle.italic
|
||||||
@@ -199,8 +198,10 @@ class LessonTile extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(.9)
|
? accent.withValues(alpha: .9)
|
||||||
: AppColors.of(context).text.withOpacity(.9),
|
: AppColors.of(context)
|
||||||
|
.text
|
||||||
|
.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -217,7 +218,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
// color: Theme.of(context)
|
// color: Theme.of(context)
|
||||||
// .colorScheme
|
// .colorScheme
|
||||||
// .secondary
|
// .secondary
|
||||||
// .withOpacity(.15),
|
// .withValues(alpha: .15),
|
||||||
// borderRadius: BorderRadius.circular(10.0),
|
// borderRadius: BorderRadius.circular(10.0),
|
||||||
// ),
|
// ),
|
||||||
// child: Text(
|
// child: Text(
|
||||||
@@ -229,7 +230,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
// color: Theme.of(context)
|
// color: Theme.of(context)
|
||||||
// .colorScheme
|
// .colorScheme
|
||||||
// .secondary
|
// .secondary
|
||||||
// .withOpacity(.9),
|
// .withValues(alpha: .9),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// )
|
// )
|
||||||
@@ -246,11 +247,11 @@ class LessonTile extends StatelessWidget {
|
|||||||
horizontal: 5.5, vertical: 3.0),
|
horizontal: 5.5, vertical: 3.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(.15)
|
? accent.withValues(alpha: .15)
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.tertiary
|
.tertiary
|
||||||
.withOpacity(.15),
|
.withValues(alpha: .15),
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -261,11 +262,11 @@ class LessonTile extends StatelessWidget {
|
|||||||
fontSize: 12.0,
|
fontSize: 12.0,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(0.9)
|
? accent.withValues(alpha: 0.9)
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.secondary
|
.secondary
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -277,7 +278,9 @@ class LessonTile extends StatelessWidget {
|
|||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
color: fill ? accent.withOpacity(0.5) : null,
|
color: fill
|
||||||
|
? accent.withValues(alpha: 0.5)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -344,7 +347,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
? Theme.of(context)
|
? Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.secondary
|
.secondary
|
||||||
.withOpacity(.3)
|
.withValues(alpha: .3)
|
||||||
: const Color(0x00000000),
|
: const Color(0x00000000),
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
@@ -353,7 +356,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.secondary
|
.secondary
|
||||||
.withOpacity(.25),
|
.withValues(alpha: .25),
|
||||||
blurRadius: 6.0,
|
blurRadius: 6.0,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -386,7 +389,7 @@ class LessonTile extends StatelessWidget {
|
|||||||
// fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
// color: AppColors.of(context)
|
// color: AppColors.of(context)
|
||||||
// .text
|
// .text
|
||||||
// .withOpacity(.75),
|
// .withValues(alpha: .75),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
@@ -398,11 +401,11 @@ class LessonTile extends StatelessWidget {
|
|||||||
horizontal: 6.0, vertical: 3.5),
|
horizontal: 6.0, vertical: 3.5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(.15)
|
? accent.withValues(alpha: .15)
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.tertiary
|
.tertiary
|
||||||
.withOpacity(.15),
|
.withValues(alpha: .15),
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -413,11 +416,11 @@ class LessonTile extends StatelessWidget {
|
|||||||
fontSize: 12.5,
|
fontSize: 12.5,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(0.9)
|
? accent.withValues(alpha: 0.9)
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.secondary
|
.secondary
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -438,10 +441,10 @@ class LessonTile extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: fill
|
color: fill
|
||||||
? accent.withOpacity(.9)
|
? accent.withValues(alpha: .9)
|
||||||
: AppColors.of(context)
|
: AppColors.of(context)
|
||||||
.text
|
.text
|
||||||
.withOpacity(.9),
|
.withValues(alpha: .9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -502,8 +505,8 @@ class LessonSubtile extends StatelessWidget {
|
|||||||
Center(
|
Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 30.0,
|
width: 30.0,
|
||||||
child:
|
child: Icon(icon,
|
||||||
Icon(icon, color: iconColor.withOpacity(.75), size: 20.0),
|
color: iconColor.withValues(alpha: .75), size: 20.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -515,7 +518,8 @@ class LessonSubtile extends StatelessWidget {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: AppColors.of(context).text.withOpacity(.65)),
|
color:
|
||||||
|
AppColors.of(context).text.withValues(alpha: .65)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ class MessageTile extends StatelessWidget {
|
|||||||
width: 105,
|
width: 105,
|
||||||
height: 15,
|
height: 15,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.of(context).text.withOpacity(.85),
|
color:
|
||||||
|
AppColors.of(context).text.withValues(alpha: .85),
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -89,7 +90,8 @@ class MessageTile extends StatelessWidget {
|
|||||||
width: 150,
|
width: 150,
|
||||||
height: 10,
|
height: 10,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.of(context).text.withOpacity(.45),
|
color:
|
||||||
|
AppColors.of(context).text.withValues(alpha: .45),
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -109,7 +111,8 @@ class MessageTile extends StatelessWidget {
|
|||||||
width: 35,
|
width: 35,
|
||||||
height: 15,
|
height: 15,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.of(context).text.withOpacity(.45),
|
color:
|
||||||
|
AppColors.of(context).text.withValues(alpha: .45),
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -120,7 +123,7 @@ class MessageTile extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 14.0,
|
fontSize: 14.0,
|
||||||
color: AppColors.of(context).text.withOpacity(.75),
|
color: AppColors.of(context).text.withValues(alpha: .75),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ extension DateFormatUtils on DateTime {
|
|||||||
}
|
}
|
||||||
if (now.year == year &&
|
if (now.year == year &&
|
||||||
now.month == month &&
|
now.month == month &&
|
||||||
now.add(const Duration(days: 1)).day == day) return "Tomorrow".i18n;
|
now.add(const Duration(days: 1)).day == day) {
|
||||||
|
return "Tomorrow".i18n;
|
||||||
|
}
|
||||||
|
|
||||||
String formatString;
|
String formatString;
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ description: "Egy nem hivatalos e-KRÉTA kliens, diákoktól diákoknak."
|
|||||||
homepage: https://refilc.hu
|
homepage: https://refilc.hu
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 5.0.6+277
|
version: 5.1.3+287
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.2 <=3.6.0"
|
sdk: ^3.6.0
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.8
|
||||||
|
|
||||||
# reFilc packages
|
# reFilc packages
|
||||||
refilc_mobile_ui:
|
refilc_mobile_ui:
|
||||||
path: "../refilc_mobile_ui/"
|
path: "../refilc_mobile_ui/"
|
||||||
refilc_desktop_ui:
|
# refilc_desktop_ui:
|
||||||
path: "../refilc_desktop_ui/"
|
# path: "../refilc_desktop_ui/"
|
||||||
refilc_kreta_api:
|
refilc_kreta_api:
|
||||||
path: "../refilc_kreta_api/"
|
path: "../refilc_kreta_api/"
|
||||||
refilc_plus:
|
refilc_plus:
|
||||||
@@ -26,75 +26,59 @@ dependencies:
|
|||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
i18n_extension: ^12.0.1
|
i18n_extension: ^12.0.1
|
||||||
sqflite: ^2.2.0+2
|
sqflite: ^2.4.1
|
||||||
intl: ^0.19.0
|
intl: ^0.19.0
|
||||||
provider: ^6.1.1
|
provider: ^6.1.2
|
||||||
http: ^1.1.2
|
http: ^1.3.0
|
||||||
uuid: ^4.2.1
|
uuid: ^4.5.1
|
||||||
html: ^0.15.0
|
html: ^0.15.5
|
||||||
open_filex: ^4.3.4
|
open_filex: ^4.6.0
|
||||||
# open_file:
|
path_provider: ^2.1.5
|
||||||
# git:
|
permission_handler: ^11.3.1
|
||||||
# url: https://github.com/crazecoder/open_file
|
share_plus: ^10.1.4
|
||||||
# ref: master
|
connectivity_plus: ^6.1.3
|
||||||
path_provider: ^2.0.2
|
|
||||||
permission_handler: ^11.0.1
|
|
||||||
share_plus: ^10.0.3
|
|
||||||
connectivity_plus: ^6.0.3
|
|
||||||
flutter_displaymode: ^0.6.0
|
flutter_displaymode: ^0.6.0
|
||||||
quick_actions: ^1.0.1
|
quick_actions: ^1.1.0
|
||||||
animated_list_plus: ^0.5.0
|
animated_list_plus: ^0.5.2
|
||||||
dynamic_color: ^1.2.2
|
dynamic_color: ^1.7.0
|
||||||
material_color_utilities: ^0.11.1
|
material_color_utilities: ^0.11.1
|
||||||
crypto: ^3.0.2
|
crypto: ^3.0.6
|
||||||
elegant_notification: ^2.2.0
|
elegant_notification: ^2.4.1
|
||||||
flutter_feather_icons: ^2.0.0+1
|
flutter_feather_icons: ^2.0.0+1
|
||||||
# live_activities: ^1.7.4
|
|
||||||
animated_flip_counter: ^0.3.4
|
animated_flip_counter: ^0.3.4
|
||||||
lottie: ^3.1.0
|
lottie: ^3.3.1
|
||||||
rive: ^0.12.4
|
rive: ^0.12.4
|
||||||
animated_background: ^2.0.0
|
animated_background: ^2.0.0
|
||||||
dropdown_button2: ^2.3.9
|
dropdown_button2: ^2.3.9
|
||||||
home_widget:
|
home_widget: ^0.7.0+1
|
||||||
git:
|
flutter_expandable_fab: ^2.3.0
|
||||||
url: https://github.com/refilc/home_widget.git
|
url_launcher: ^6.3.1
|
||||||
ref: flutter-beta
|
flutter_svg: ^2.0.17
|
||||||
flutter_expandable_fab: ^2.0.0
|
image_picker: ^1.1.2
|
||||||
uni_links: ^0.5.1
|
animations: ^2.0.11
|
||||||
url_launcher: ^6.1.6
|
background_fetch: ^1.3.7
|
||||||
# workmanager:
|
|
||||||
# git:
|
|
||||||
# url: https://github.com/refilc/flutter_workmanager.git
|
|
||||||
# ref: v0.5.1
|
|
||||||
flutter_svg: ^2.0.10+1
|
|
||||||
image_picker: ^1.0.7
|
|
||||||
animations: ^2.0.1
|
|
||||||
background_fetch: ^1.1.5
|
|
||||||
flutter_local_notifications: ^18.0.1
|
flutter_local_notifications: ^18.0.1
|
||||||
package_info_plus: ^8.0.0
|
package_info_plus: ^8.2.1
|
||||||
screenshot: ^3.0.0
|
screenshot: ^3.0.0
|
||||||
flutter_staggered_grid_view: ^0.7.0
|
flutter_staggered_grid_view: ^0.7.0
|
||||||
sqflite_common_ffi_web: ^0.4.0
|
image_crop_plus: ^1.0.0
|
||||||
image_crop:
|
|
||||||
git:
|
|
||||||
url: https://github.com/kimaah/image_crop.git
|
|
||||||
googleapis: ^13.2.0
|
googleapis: ^13.2.0
|
||||||
google_sign_in: ^6.2.1
|
google_sign_in: ^6.2.2
|
||||||
extension_google_sign_in_as_googleapis_auth: ^2.0.12
|
extension_google_sign_in_as_googleapis_auth: ^2.0.12
|
||||||
maps_launcher: ^2.2.0
|
maps_launcher: ^3.0.0+1
|
||||||
google_fonts: ^6.1.0
|
google_fonts: ^6.2.1
|
||||||
# flutter_stripe: ^11.3.0
|
get_it: ^7.7.0
|
||||||
get_it: ^7.6.7
|
|
||||||
xml: ^6.5.0
|
xml: ^6.5.0
|
||||||
carousel_slider: ^5.0.0
|
carousel_slider: ^5.0.0
|
||||||
flutter_portal: ^1.1.4
|
flutter_portal: ^1.1.4
|
||||||
shake_flutter: ^17.0.0
|
shake_flutter: ^17.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^5.0.0
|
||||||
flutter_launcher_icons: ^0.14.2
|
flutter_launcher_icons: ^0.14.3
|
||||||
flutter_native_splash: "^2.3.10"
|
flutter_native_splash: ^2.4.4
|
||||||
sqflite_common_ffi: ^2.0.0+3
|
sqflite_common_ffi: ^2.3.4+4
|
||||||
|
dependency_validator: ^5.0.2
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
@@ -188,13 +172,13 @@ flutter:
|
|||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
image_path: assets/icons/ic_android.png
|
image_path: assets/icons/ic_android.png
|
||||||
android: true
|
android: true
|
||||||
adaptive_icon_background: "#03112D"
|
adaptive_icon_background: "#7CA021"
|
||||||
adaptive_icon_foreground: assets/icons/ic_android.png
|
adaptive_icon_foreground: assets/icons/ic_launcher_foreground.png
|
||||||
ios: false
|
ios: false
|
||||||
remove_alpha_ios: false
|
remove_alpha_ios: false
|
||||||
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
color: "#03112D"
|
color: "#7CA021"
|
||||||
image: assets/icons/ic_splash.png
|
image: assets/icons/ic_splash.png
|
||||||
android_12:
|
android_12:
|
||||||
image: assets/icons/ic_splash.png
|
image: assets/icons/ic_splash.png
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
import 'package:refilc/theme/colors/colors.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class FilterBar extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const FilterBar({
|
|
||||||
super.key,
|
|
||||||
required this.items,
|
|
||||||
required this.controller,
|
|
||||||
this.onTap,
|
|
||||||
this.padding = const EdgeInsets.symmetric(horizontal: 24.0),
|
|
||||||
this.disableFading = false,
|
|
||||||
this.scrollable = true,
|
|
||||||
}) : assert(items.length == controller.length);
|
|
||||||
|
|
||||||
final List<Widget> items;
|
|
||||||
final TabController controller;
|
|
||||||
final EdgeInsetsGeometry padding;
|
|
||||||
final Function(int)? onTap;
|
|
||||||
@override
|
|
||||||
final Size preferredSize = const Size.fromHeight(42.0);
|
|
||||||
final bool disableFading;
|
|
||||||
final bool scrollable;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final tabbar = TabBar(
|
|
||||||
controller: controller,
|
|
||||||
isScrollable: scrollable,
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
// Label
|
|
||||||
labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 15.0,
|
|
||||||
),
|
|
||||||
labelPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
|
|
||||||
labelColor: Theme.of(context).colorScheme.secondary,
|
|
||||||
unselectedLabelColor: AppColors.of(context).text.withOpacity(0.65),
|
|
||||||
// Indicator
|
|
||||||
indicatorPadding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
indicator: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.secondary.withOpacity(0.25),
|
|
||||||
borderRadius: BorderRadius.circular(45.0),
|
|
||||||
),
|
|
||||||
overlayColor: WidgetStateProperty.all(const Color(0x00000000)),
|
|
||||||
// Tabs
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
tabs: items,
|
|
||||||
onTap: onTap,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
height: 48.0,
|
|
||||||
padding: padding,
|
|
||||||
child: disableFading
|
|
||||||
? tabbar
|
|
||||||
: AnimatedBuilder(
|
|
||||||
animation: controller.animation!,
|
|
||||||
builder: (ctx, child) {
|
|
||||||
// avoid fading over selected tab
|
|
||||||
return ShaderMask(
|
|
||||||
shaderCallback: (Rect bounds) {
|
|
||||||
final Color bg =
|
|
||||||
Theme.of(context).scaffoldBackgroundColor;
|
|
||||||
final double index = controller.animation!.value;
|
|
||||||
return LinearGradient(
|
|
||||||
begin: Alignment.topLeft,
|
|
||||||
end: Alignment.bottomRight,
|
|
||||||
colors: [
|
|
||||||
index < 0.2 ? Colors.transparent : bg,
|
|
||||||
Colors.transparent,
|
|
||||||
Colors.transparent,
|
|
||||||
index > controller.length - 1.2
|
|
||||||
? Colors.transparent
|
|
||||||
: bg
|
|
||||||
],
|
|
||||||
stops: const [
|
|
||||||
0,
|
|
||||||
0.1,
|
|
||||||
0.9,
|
|
||||||
1
|
|
||||||
]).createShader(bounds);
|
|
||||||
},
|
|
||||||
blendMode: BlendMode.dstOut,
|
|
||||||
child: child);
|
|
||||||
},
|
|
||||||
child: tabbar,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import 'package:refilc/theme/colors/colors.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class PanelButton extends StatelessWidget {
|
|
||||||
const PanelButton({
|
|
||||||
super.key,
|
|
||||||
this.onPressed,
|
|
||||||
this.padding = const EdgeInsets.symmetric(horizontal: 14.0),
|
|
||||||
this.leading,
|
|
||||||
this.title,
|
|
||||||
this.trailing,
|
|
||||||
this.trailingDivider = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
final void Function()? onPressed;
|
|
||||||
final EdgeInsetsGeometry padding;
|
|
||||||
final Widget? leading;
|
|
||||||
final Widget? title;
|
|
||||||
final Widget? trailing;
|
|
||||||
final bool trailingDivider;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
|
||||||
child: RawMaterialButton(
|
|
||||||
onPressed: onPressed,
|
|
||||||
padding: padding,
|
|
||||||
shape:
|
|
||||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
|
||||||
child: ListTile(
|
|
||||||
leading: leading != null
|
|
||||||
? Theme(
|
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
iconTheme: IconThemeData(
|
|
||||||
color: Theme.of(context).colorScheme.secondary)),
|
|
||||||
child: leading!,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
trailing: trailingDivider
|
|
||||||
? Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
margin: const EdgeInsets.only(right: 6.0),
|
|
||||||
width: 2.0,
|
|
||||||
height: 32.0,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColors.of(context).text.withOpacity(.15),
|
|
||||||
borderRadius: BorderRadius.circular(45.0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (trailing != null) trailing!,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: trailing,
|
|
||||||
title: title != null
|
|
||||||
? DefaultTextStyle(
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.titleMedium!
|
|
||||||
.copyWith(fontWeight: FontWeight.w600, fontSize: 14.0),
|
|
||||||
child: title!,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import 'package:refilc/models/user.dart';
|
|
||||||
import 'package:refilc/utils/color.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:refilc/theme/colors/colors.dart';
|
|
||||||
|
|
||||||
class ProfileImage extends StatelessWidget {
|
|
||||||
const ProfileImage({
|
|
||||||
super.key,
|
|
||||||
this.name,
|
|
||||||
this.radius = 20.0,
|
|
||||||
this.role = Role.student,
|
|
||||||
this.backgroundColor,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String? name;
|
|
||||||
final double radius;
|
|
||||||
final Role? role;
|
|
||||||
final Color? backgroundColor;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Color color = ColorUtils.foregroundColor(
|
|
||||||
backgroundColor ?? Theme.of(context).scaffoldBackgroundColor);
|
|
||||||
Color roleColor;
|
|
||||||
|
|
||||||
if (Theme.of(context).brightness == Brightness.light) {
|
|
||||||
roleColor = const Color(0xFF444444);
|
|
||||||
} else {
|
|
||||||
roleColor = const Color(0xFF555555);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
children: [
|
|
||||||
Material(
|
|
||||||
clipBehavior: Clip.hardEdge,
|
|
||||||
shape: const CircleBorder(),
|
|
||||||
color: backgroundColor ?? AppColors.of(context).text.withOpacity(.15),
|
|
||||||
child: InkWell(
|
|
||||||
child: AnimatedContainer(
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
height: radius * 2,
|
|
||||||
width: radius * 2,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: name != null && (name?.trim().length ?? 0) > 0
|
|
||||||
? Center(
|
|
||||||
child: Text(
|
|
||||||
(name?.trim().length ?? 0) > 0
|
|
||||||
? (name ?? "?").trim()[0]
|
|
||||||
: "?",
|
|
||||||
style: TextStyle(
|
|
||||||
color: color,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 18.0 * (radius / 20.0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Role indicator
|
|
||||||
if (role == Role.parent)
|
|
||||||
SizedBox(
|
|
||||||
height: radius * 2,
|
|
||||||
width: radius * 2,
|
|
||||||
child: Container(
|
|
||||||
alignment: Alignment.bottomRight,
|
|
||||||
child: Icon(Icons.shield, color: roleColor, size: radius / 1.3),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
|
||||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
|
||||||
|
|
||||||
class GradeViewable extends StatelessWidget {
|
|
||||||
const GradeViewable(this.grade, {super.key});
|
|
||||||
|
|
||||||
final Grade grade;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GradeTile(grade);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import 'package:refilc_kreta_api/models/lesson.dart';
|
|
||||||
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class LessonViewable extends StatelessWidget {
|
|
||||||
const LessonViewable(this.lesson, {super.key, this.swapDesc = false});
|
|
||||||
|
|
||||||
final Lesson lesson;
|
|
||||||
final bool swapDesc;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final tile = LessonTile(lesson, swapDesc: swapDesc);
|
|
||||||
|
|
||||||
if (lesson.subject.id == '' || tile.lesson.isEmpty) return tile;
|
|
||||||
|
|
||||||
return tile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,408 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
|
||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:refilc/api/providers/update_provider.dart';
|
|
||||||
import 'package:refilc/ui/date_widget.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/absence.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/lesson.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/subject.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/week.dart';
|
|
||||||
import 'package:refilc_kreta_api/providers/absence_provider.dart';
|
|
||||||
import 'package:refilc_kreta_api/providers/note_provider.dart';
|
|
||||||
import 'package:refilc/api/providers/user_provider.dart';
|
|
||||||
import 'package:refilc/theme/colors/colors.dart';
|
|
||||||
import 'package:refilc_kreta_api/providers/timetable_provider.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/action_button.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/empty.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/filter_bar.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/absence/absence_subject_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/absence/absence_viewable.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/miss_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/absences/absence_subject_view.dart';
|
|
||||||
import 'package:refilc/ui/filter/sort.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'absences_page.i18n.dart';
|
|
||||||
|
|
||||||
enum AbsenceFilter { absences, delays, misses }
|
|
||||||
|
|
||||||
class SubjectAbsence {
|
|
||||||
GradeSubject subject;
|
|
||||||
List<Absence> absences;
|
|
||||||
double percentage;
|
|
||||||
|
|
||||||
SubjectAbsence(
|
|
||||||
{required this.subject, this.absences = const [], this.percentage = 0.0});
|
|
||||||
}
|
|
||||||
|
|
||||||
class AbsencesPage extends StatefulWidget {
|
|
||||||
const AbsencesPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
AbsencesPageState createState() => AbsencesPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class AbsencesPageState extends State<AbsencesPage>
|
|
||||||
with TickerProviderStateMixin {
|
|
||||||
late UserProvider user;
|
|
||||||
late AbsenceProvider absenceProvider;
|
|
||||||
late TimetableProvider timetableProvider;
|
|
||||||
late NoteProvider noteProvider;
|
|
||||||
late UpdateProvider updateProvider;
|
|
||||||
late String firstName;
|
|
||||||
late TabController _tabController;
|
|
||||||
late List<SubjectAbsence> absences = [];
|
|
||||||
final Map<GradeSubject, Lesson> _lessonCount = {};
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
_tabController = TabController(length: 3, vsync: this);
|
|
||||||
timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
|
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
|
||||||
for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
|
|
||||||
if (!lesson.isEmpty &&
|
|
||||||
lesson.subject.id != '' &&
|
|
||||||
lesson.lessonYearIndex != null) {
|
|
||||||
_lessonCount.update(
|
|
||||||
lesson.subject,
|
|
||||||
(value) {
|
|
||||||
if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
|
|
||||||
return lesson;
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ifAbsent: () => lesson,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildSubjectAbsences() {
|
|
||||||
// ignore: no_leading_underscores_for_local_identifiers
|
|
||||||
Map<GradeSubject, SubjectAbsence> _absences = {};
|
|
||||||
|
|
||||||
for (final absence in absenceProvider.absences) {
|
|
||||||
if (absence.delay != 0) continue;
|
|
||||||
|
|
||||||
if (!_absences.containsKey(absence.subject)) {
|
|
||||||
_absences[absence.subject] =
|
|
||||||
SubjectAbsence(subject: absence.subject, absences: [absence]);
|
|
||||||
} else {
|
|
||||||
_absences[absence.subject]?.absences.add(absence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_absences.forEach((subject, absence) {
|
|
||||||
final absentLessonsOfSubject = absenceProvider.absences
|
|
||||||
.where((e) => e.subject == subject && e.delay == 0)
|
|
||||||
.length;
|
|
||||||
final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
|
|
||||||
|
|
||||||
double absentLessonsOfSubjectPercentage;
|
|
||||||
|
|
||||||
if (absentLessonsOfSubject <= totalLessonsOfSubject) {
|
|
||||||
absentLessonsOfSubjectPercentage =
|
|
||||||
absentLessonsOfSubject / totalLessonsOfSubject * 100;
|
|
||||||
} else {
|
|
||||||
absentLessonsOfSubjectPercentage = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_absences[subject]?.percentage =
|
|
||||||
absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
|
|
||||||
});
|
|
||||||
|
|
||||||
absences = _absences.values.toList();
|
|
||||||
absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
user = Provider.of<UserProvider>(context);
|
|
||||||
absenceProvider = Provider.of<AbsenceProvider>(context);
|
|
||||||
noteProvider = Provider.of<NoteProvider>(context);
|
|
||||||
updateProvider = Provider.of<UpdateProvider>(context);
|
|
||||||
timetableProvider = Provider.of<TimetableProvider>(context);
|
|
||||||
|
|
||||||
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
|
||||||
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
|
||||||
|
|
||||||
buildSubjectAbsences();
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 12.0),
|
|
||||||
child: NestedScrollView(
|
|
||||||
physics: const BouncingScrollPhysics(
|
|
||||||
parent: AlwaysScrollableScrollPhysics()),
|
|
||||||
headerSliverBuilder: (context, _) => [
|
|
||||||
SliverAppBar(
|
|
||||||
pinned: true,
|
|
||||||
floating: false,
|
|
||||||
snap: false,
|
|
||||||
centerTitle: false,
|
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
shadowColor: Theme.of(context).shadowColor,
|
|
||||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
title: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 8.0),
|
|
||||||
child: Text(
|
|
||||||
"Absences".i18n,
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.of(context).text,
|
|
||||||
fontSize: 32.0,
|
|
||||||
fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
bottom: FilterBar(items: [
|
|
||||||
Tab(text: "Absences".i18n),
|
|
||||||
Tab(text: "Delays".i18n),
|
|
||||||
Tab(text: "Misses".i18n),
|
|
||||||
], controller: _tabController, disableFading: true),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
body: TabBarView(
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
controller: _tabController,
|
|
||||||
children: List.generate(
|
|
||||||
3, (index) => filterViewBuilder(context, index))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DateWidget> getFilterWidgets(AbsenceFilter activeData) {
|
|
||||||
List<DateWidget> items = [];
|
|
||||||
switch (activeData) {
|
|
||||||
case AbsenceFilter.absences:
|
|
||||||
for (var a in absences) {
|
|
||||||
items.add(DateWidget(
|
|
||||||
date: DateTime.fromMillisecondsSinceEpoch(0),
|
|
||||||
widget: AbsenceSubjectTile(
|
|
||||||
a.subject,
|
|
||||||
percentage: a.percentage,
|
|
||||||
excused: a.absences
|
|
||||||
.where((a) => a.state == Justification.excused)
|
|
||||||
.length,
|
|
||||||
unexcused: a.absences
|
|
||||||
.where((a) => a.state == Justification.unexcused)
|
|
||||||
.length,
|
|
||||||
pending: a.absences
|
|
||||||
.where((a) => a.state == Justification.pending)
|
|
||||||
.length,
|
|
||||||
onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
|
|
||||||
context: context),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AbsenceFilter.delays:
|
|
||||||
for (var absence in absenceProvider.absences) {
|
|
||||||
if (absence.delay != 0) {
|
|
||||||
items.add(DateWidget(
|
|
||||||
date: absence.date,
|
|
||||||
widget: AbsenceViewable(
|
|
||||||
absence,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AbsenceFilter.misses:
|
|
||||||
for (var note in noteProvider.notes) {
|
|
||||||
if (note.type?.name == "HaziFeladatHiany" ||
|
|
||||||
note.type?.name == "Felszereleshiany") {
|
|
||||||
items.add(DateWidget(
|
|
||||||
date: note.date,
|
|
||||||
widget: MissTile(note),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget filterViewBuilder(context, int activeData) {
|
|
||||||
List<Widget> filterWidgets = [];
|
|
||||||
|
|
||||||
if (activeData > 0) {
|
|
||||||
filterWidgets = sortDateWidgets(
|
|
||||||
context,
|
|
||||||
dateWidgets: getFilterWidgets(AbsenceFilter.values[activeData]),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
hasShadow: true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
filterWidgets = [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 24.0),
|
|
||||||
child: Panel(
|
|
||||||
title: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text("Subjects".i18n),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 4.0),
|
|
||||||
child: IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12.0)),
|
|
||||||
title: Text("attention".i18n),
|
|
||||||
content: Text("attention_body".i18n),
|
|
||||||
actions: [
|
|
||||||
ActionButton(
|
|
||||||
label: "Ok",
|
|
||||||
onTap: () => Navigator.of(context).pop())
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
splashRadius: 24.0,
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
constraints: BoxConstraints.tight(const Size(42.0, 42.0)),
|
|
||||||
icon: const Icon(FeatherIcons.info),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: PageTransitionSwitcher(
|
|
||||||
transitionBuilder: (
|
|
||||||
Widget child,
|
|
||||||
Animation<double> primaryAnimation,
|
|
||||||
Animation<double> secondaryAnimation,
|
|
||||||
) {
|
|
||||||
return FadeThroughTransition(
|
|
||||||
animation: primaryAnimation,
|
|
||||||
secondaryAnimation: secondaryAnimation,
|
|
||||||
fillColor: Theme.of(context).colorScheme.surface,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
children: getFilterWidgets(AbsenceFilter.values[activeData])
|
|
||||||
.map((e) => e.widget)
|
|
||||||
.cast<Widget>()
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 12.0),
|
|
||||||
child: RefreshIndicator(
|
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
onRefresh: () async {
|
|
||||||
await absenceProvider.fetch();
|
|
||||||
await noteProvider.fetch();
|
|
||||||
},
|
|
||||||
child: ListView.builder(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (filterWidgets.isNotEmpty) {
|
|
||||||
if ((index == 0 && activeData == 1) ||
|
|
||||||
(index == 0 && activeData == 0)) {
|
|
||||||
int value1 = 0;
|
|
||||||
int value2 = 0;
|
|
||||||
String title1 = "";
|
|
||||||
String title2 = "";
|
|
||||||
String suffix = "";
|
|
||||||
|
|
||||||
if (activeData == AbsenceFilter.absences.index) {
|
|
||||||
value1 = absenceProvider.absences
|
|
||||||
.where((e) =>
|
|
||||||
e.delay == 0 && e.state == Justification.excused)
|
|
||||||
.length;
|
|
||||||
value2 = absenceProvider.absences
|
|
||||||
.where((e) =>
|
|
||||||
e.delay == 0 && e.state == Justification.unexcused)
|
|
||||||
.length;
|
|
||||||
title1 = "stat_1".i18n;
|
|
||||||
title2 = "stat_2".i18n;
|
|
||||||
suffix = " ${"hr".i18n}";
|
|
||||||
} else if (activeData == AbsenceFilter.delays.index) {
|
|
||||||
value1 = absenceProvider.absences
|
|
||||||
.where((e) =>
|
|
||||||
e.delay != 0 && e.state == Justification.excused)
|
|
||||||
.map((e) => e.delay)
|
|
||||||
.fold(0, (a, b) => a + b);
|
|
||||||
value2 = absenceProvider.absences
|
|
||||||
.where((e) =>
|
|
||||||
e.delay != 0 && e.state == Justification.unexcused)
|
|
||||||
.map((e) => e.delay)
|
|
||||||
.fold(0, (a, b) => a + b);
|
|
||||||
title1 = "stat_3".i18n;
|
|
||||||
title2 = "stat_4".i18n;
|
|
||||||
suffix = " ${"min".i18n}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
bottom: 24.0, left: 24.0, right: 24.0),
|
|
||||||
child: Row(children: [
|
|
||||||
Expanded(
|
|
||||||
child: StatisticsTile(
|
|
||||||
title: AutoSizeText(
|
|
||||||
title1,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
valueSuffix: suffix,
|
|
||||||
value: value1.toDouble(),
|
|
||||||
decimal: false,
|
|
||||||
color: AppColors.of(context).green,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 24.0),
|
|
||||||
Expanded(
|
|
||||||
child: StatisticsTile(
|
|
||||||
title: AutoSizeText(
|
|
||||||
title2,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
valueSuffix: suffix,
|
|
||||||
value: value2.toDouble(),
|
|
||||||
decimal: false,
|
|
||||||
color: AppColors.of(context).red,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
|
|
||||||
child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return activeData == 1
|
|
||||||
? Empty(subtitle: "emptyDelays".i18n)
|
|
||||||
: Empty(subtitle: "emptyMisses".i18n);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import 'package:i18n_extension/i18n_extension.dart';
|
|
||||||
|
|
||||||
extension ScreensLocalization on String {
|
|
||||||
static final _t = Translations.byLocale("hu_hu") +
|
|
||||||
{
|
|
||||||
"en_en": {
|
|
||||||
"Absences": "Absences",
|
|
||||||
"Delays": "Delays",
|
|
||||||
"Misses": "Misses",
|
|
||||||
"emptyDelays": "You have no delays.",
|
|
||||||
"emptyMisses": "You have no missing homeworks or equipments.",
|
|
||||||
"stat_1": "Excused Absences",
|
|
||||||
"stat_2": "Unexcused Absences",
|
|
||||||
"stat_3": "Excused Delay",
|
|
||||||
"stat_4": "Unexcused Delay",
|
|
||||||
"min": "min",
|
|
||||||
"hr": "hrs",
|
|
||||||
"Subjects": "Subjects",
|
|
||||||
"attention": "Attention!",
|
|
||||||
"attention_body": "Percentage calculations are only an approximation so they may not be accurate.",
|
|
||||||
},
|
|
||||||
"hu_hu": {
|
|
||||||
"Absences": "Hiányzások",
|
|
||||||
"Delays": "Késések",
|
|
||||||
"Misses": "Hiányok",
|
|
||||||
"emptyDelays": "Nincsenek késéseid.",
|
|
||||||
"emptyMisses": "Nincsenek hiányzó házi feladataid, felszereléseid.",
|
|
||||||
"stat_1": "Igazolt hiányzások",
|
|
||||||
"stat_2": "Igazolatlan hiányzások",
|
|
||||||
"stat_3": "Igazolt Késés",
|
|
||||||
"stat_4": "Igazolatlan Késés",
|
|
||||||
"min": "perc",
|
|
||||||
"hr": "óra",
|
|
||||||
"Subjects": "Tantárgyak",
|
|
||||||
"attention": "Figyelem!",
|
|
||||||
"attention_body": "A százalékos számítások csak közelítések, ezért előfordulhat, hogy nem pontosak.",
|
|
||||||
},
|
|
||||||
"de_de": {
|
|
||||||
"Absences": "Fehlen",
|
|
||||||
"Delays": "Verspätung",
|
|
||||||
"Misses": "Fehlt",
|
|
||||||
"emptyDelays": "Sie haben keine Abwesenheiten.",
|
|
||||||
"emptyMisses": "Sie haben noch keine fehlende Hausaufgaben oder Austattung.",
|
|
||||||
"stat_1": "Entschuldigte Fehlen",
|
|
||||||
"stat_2": "Unentschuldigte Fehlen",
|
|
||||||
"stat_3": "Entschuldigte Verspätung",
|
|
||||||
"stat_4": "Unentschuldigte Verspätung",
|
|
||||||
"min": "min",
|
|
||||||
"hr": "hrs",
|
|
||||||
"Subjects": "Fächer",
|
|
||||||
"attention": "Achtung!",
|
|
||||||
"attention_body": "Prozentberechnungen sind nur eine Annäherung und können daher ungenau sein.",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
String get i18n => localize(this, _t);
|
|
||||||
String fill(List<Object> params) => localizeFill(this, params);
|
|
||||||
String plural(int value) => localizePlural(value, this, _t);
|
|
||||||
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
|
||||||
}
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
|
||||||
import 'package:refilc/models/settings.dart';
|
|
||||||
import 'package:refilc/utils/format.dart';
|
|
||||||
import 'package:refilc_kreta_api/providers/grade_provider.dart';
|
|
||||||
import 'package:refilc/helpers/average_helper.dart';
|
|
||||||
import 'package:refilc/helpers/subject.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/subject.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/average_display.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/trend_display.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/cretification/certification_tile.dart';
|
|
||||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator_provider.dart';
|
|
||||||
import 'package:refilc_desktop_ui/pages/grades/grades_count.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/graph.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/subject_grades_container.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
|
||||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'grades_page.i18n.dart';
|
|
||||||
//import 'package:refilc_plus/ui/mobile/goal_planner/new_goal.dart';
|
|
||||||
|
|
||||||
class GradeSubjectView extends StatefulWidget {
|
|
||||||
const GradeSubjectView(this.subject, {super.key, this.groupAverage = 0.0});
|
|
||||||
|
|
||||||
final GradeSubject subject;
|
|
||||||
final double groupAverage;
|
|
||||||
|
|
||||||
void push(BuildContext context, {bool root = false}) {
|
|
||||||
Navigator.of(context, rootNavigator: root)
|
|
||||||
.push(CupertinoPageRoute(builder: (context) => this));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<GradeSubjectView> createState() => _GradeSubjectViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _GradeSubjectViewState extends State<GradeSubjectView> {
|
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
|
||||||
|
|
||||||
// Controllers
|
|
||||||
PersistentBottomSheetController? _sheetController;
|
|
||||||
final ScrollController _scrollController = ScrollController();
|
|
||||||
|
|
||||||
List<Widget> gradeTiles = [];
|
|
||||||
|
|
||||||
// Providers
|
|
||||||
late GradeProvider gradeProvider;
|
|
||||||
late GradeCalculatorProvider calculatorProvider;
|
|
||||||
late SettingsProvider settingsProvider;
|
|
||||||
|
|
||||||
late double average;
|
|
||||||
late Widget gradeGraph;
|
|
||||||
|
|
||||||
bool gradeCalcMode = false;
|
|
||||||
|
|
||||||
List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
|
|
||||||
? gradeProvider.grades.where((e) => e.subject == subject).toList()
|
|
||||||
: calculatorProvider.grades.where((e) => e.subject == subject).toList();
|
|
||||||
|
|
||||||
bool showGraph(List<Grade> subjectGrades) {
|
|
||||||
if (gradeCalcMode) return true;
|
|
||||||
|
|
||||||
final gradeDates = subjectGrades.map((e) => e.date.millisecondsSinceEpoch);
|
|
||||||
final maxGradeDate = gradeDates.fold(0, max);
|
|
||||||
final minGradeDate = gradeDates.fold(0, min);
|
|
||||||
if (maxGradeDate - minGradeDate < const Duration(days: 5).inMilliseconds) {
|
|
||||||
return false; // naplo/#78
|
|
||||||
}
|
|
||||||
|
|
||||||
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildTiles(List<Grade> subjectGrades) {
|
|
||||||
List<Widget> tiles = [];
|
|
||||||
|
|
||||||
if (showGraph(subjectGrades)) {
|
|
||||||
tiles.add(gradeGraph);
|
|
||||||
} else {
|
|
||||||
tiles.add(Container(height: 24.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore: no_leading_underscores_for_local_identifiers
|
|
||||||
List<Widget> _gradeTiles = [];
|
|
||||||
|
|
||||||
if (!gradeCalcMode) {
|
|
||||||
subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
|
|
||||||
for (var grade in subjectGrades) {
|
|
||||||
if (grade.type == GradeType.midYear) {
|
|
||||||
_gradeTiles.add(GradeViewable(grade));
|
|
||||||
} else {
|
|
||||||
_gradeTiles.add(CertificationTile(grade, padding: EdgeInsets.zero));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (subjectGrades.isNotEmpty) {
|
|
||||||
subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
|
|
||||||
for (var grade in subjectGrades) {
|
|
||||||
_gradeTiles.add(GradeTile(grade));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tiles.add(
|
|
||||||
PageTransitionSwitcher(
|
|
||||||
transitionBuilder: (
|
|
||||||
Widget child,
|
|
||||||
Animation<double> primaryAnimation,
|
|
||||||
Animation<double> secondaryAnimation,
|
|
||||||
) {
|
|
||||||
return SharedAxisTransition(
|
|
||||||
animation: primaryAnimation,
|
|
||||||
secondaryAnimation: secondaryAnimation,
|
|
||||||
transitionType: SharedAxisTransitionType.vertical,
|
|
||||||
fillColor: Colors.transparent,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: _gradeTiles.isNotEmpty
|
|
||||||
? Panel(
|
|
||||||
key: ValueKey(gradeCalcMode),
|
|
||||||
title: Text(
|
|
||||||
gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: _gradeTiles,
|
|
||||||
))
|
|
||||||
: const SizedBox(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
tiles.add(Padding(
|
|
||||||
padding: EdgeInsets.only(bottom: !gradeCalcMode ? 24.0 : 250.0)));
|
|
||||||
gradeTiles = List.castFrom(tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
gradeProvider = Provider.of<GradeProvider>(context);
|
|
||||||
calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
|
|
||||||
settingsProvider = Provider.of<SettingsProvider>(context);
|
|
||||||
|
|
||||||
List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
|
|
||||||
average = AverageHelper.averageEvals(subjectGrades);
|
|
||||||
final prevAvg = subjectGrades.isNotEmpty
|
|
||||||
? AverageHelper.averageEvals(subjectGrades
|
|
||||||
.where((e) => e.date.isBefore(subjectGrades
|
|
||||||
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
|
|
||||||
.date
|
|
||||||
.subtract(const Duration(days: 30))))
|
|
||||||
.toList())
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
gradeGraph = Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
|
|
||||||
child: Panel(
|
|
||||||
title: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text("annual_average".i18n),
|
|
||||||
if (average != prevAvg)
|
|
||||||
TrendDisplay(current: average, previous: prevAvg),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.only(top: 12.0, right: 12.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: GradeGraph(subjectGrades,
|
|
||||||
dayThreshold: 5, classAvg: widget.groupAverage)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 24.0),
|
|
||||||
child: GradesCount(grades: subjectGrades),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!gradeCalcMode) {
|
|
||||||
buildTiles(subjectGrades);
|
|
||||||
} else {
|
|
||||||
List<Grade> ghostGrades = calculatorProvider.ghosts
|
|
||||||
.where((e) => e.subject == widget.subject)
|
|
||||||
.toList();
|
|
||||||
buildTiles(ghostGrades);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
key: _scaffoldKey,
|
|
||||||
floatingActionButtonLocation: ExpandableFab.location,
|
|
||||||
floatingActionButton: Visibility(
|
|
||||||
visible: !gradeCalcMode &&
|
|
||||||
subjectGrades
|
|
||||||
.where((e) => e.type == GradeType.midYear)
|
|
||||||
.isNotEmpty,
|
|
||||||
child: ExpandableFab(
|
|
||||||
type: ExpandableFabType.up,
|
|
||||||
distance: 50,
|
|
||||||
children: [
|
|
||||||
FloatingActionButton.small(
|
|
||||||
child: const Icon(FeatherIcons.plus),
|
|
||||||
onPressed: () {
|
|
||||||
gradeCalc(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
// FloatingActionButton.small(
|
|
||||||
// child: const Icon(FeatherIcons.flag, size: 20.0),
|
|
||||||
// onPressed: () {
|
|
||||||
// Navigator.of(context).push(CupertinoPageRoute(builder: (context) => PremiumGoalplannerNewGoalScreen(subject: widget.subject)));
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: RefreshIndicator(
|
|
||||||
onRefresh: () async {},
|
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
child: HeroScrollView(
|
|
||||||
onClose: () {
|
|
||||||
if (_sheetController != null && gradeCalcMode) {
|
|
||||||
_sheetController!.close();
|
|
||||||
} else {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navBarItems: [
|
|
||||||
const SizedBox(width: 6.0),
|
|
||||||
if (widget.groupAverage != 0)
|
|
||||||
Center(
|
|
||||||
child: AverageDisplay(
|
|
||||||
average: widget.groupAverage, border: true)),
|
|
||||||
const SizedBox(width: 6.0),
|
|
||||||
if (average != 0)
|
|
||||||
Center(child: AverageDisplay(average: average)),
|
|
||||||
const SizedBox(width: 12.0),
|
|
||||||
],
|
|
||||||
icon: SubjectIcon.resolveVariant(
|
|
||||||
subject: widget.subject, context: context),
|
|
||||||
scrollController: _scrollController,
|
|
||||||
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
|
|
||||||
italic: widget.subject.isRenamed &&
|
|
||||||
settingsProvider.renamedSubjectsItalics,
|
|
||||||
child: SubjectGradesContainer(
|
|
||||||
child: CupertinoScrollbar(
|
|
||||||
child: ListView.builder(
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemBuilder: (context, index) => gradeTiles[index],
|
|
||||||
itemCount: gradeTiles.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
void gradeCalc(BuildContext context) {
|
|
||||||
// Scroll to the top of the page
|
|
||||||
_scrollController.animateTo(75,
|
|
||||||
duration: const Duration(milliseconds: 500), curve: Curves.ease);
|
|
||||||
|
|
||||||
calculatorProvider.clear();
|
|
||||||
calculatorProvider.addAllGrades(gradeProvider.grades);
|
|
||||||
|
|
||||||
_sheetController = _scaffoldKey.currentState?.showBottomSheet(
|
|
||||||
(context) => RoundedBottomSheet(
|
|
||||||
borderRadius: 14.0,
|
|
||||||
child: GradeCalculator(widget.subject)),
|
|
||||||
backgroundColor: const Color(0x00000000),
|
|
||||||
elevation: 12.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Hide the fab and grades
|
|
||||||
setState(() {
|
|
||||||
gradeCalcMode = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
_sheetController!.closed.then((value) {
|
|
||||||
// Show fab and grades
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
gradeCalcMode = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
|
||||||
import 'package:refilc_desktop_ui/pages/grades/grades_count_item.dart';
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
|
|
||||||
class GradesCount extends StatelessWidget {
|
|
||||||
const GradesCount({super.key, required this.grades});
|
|
||||||
|
|
||||||
final List<Grade> grades;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
List<int> gradesCount = List.generate(5,
|
|
||||||
(int index) => grades.where((e) => e.value.value == index + 1).length);
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
width: 75,
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(bottom: 6.0, top: 6.0, left: 12.0, right: 0.0),
|
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 12.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: gradesCount
|
|
||||||
.mapIndexed(
|
|
||||||
(index, e) => GradesCountItem(count: e, value: index + 1))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class GradesCountItem extends StatelessWidget {
|
|
||||||
const GradesCountItem({super.key, required this.count, required this.value});
|
|
||||||
|
|
||||||
final int count;
|
|
||||||
final int value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text.rich(
|
|
||||||
TextSpan(children: [
|
|
||||||
TextSpan(
|
|
||||||
text: count.toString(),
|
|
||||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
const TextSpan(
|
|
||||||
text: "x",
|
|
||||||
style: TextStyle(fontSize: 13.0),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
style: const TextStyle(fontSize: 15.0),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 5.0),
|
|
||||||
GradeValueWidget(GradeValue(value, "Value", "Value", 100),
|
|
||||||
size: 19.0, fill: true, shadow: false),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:refilc/api/providers/update_provider.dart';
|
|
||||||
import 'package:refilc_kreta_api/providers/grade_provider.dart';
|
|
||||||
import 'package:refilc/api/providers/user_provider.dart';
|
|
||||||
import 'package:refilc/theme/colors/colors.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/grade.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/subject.dart';
|
|
||||||
import 'package:refilc_kreta_api/models/group_average.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/average_display.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/empty.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/statistics_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/widgets/grade/grade_subject_tile.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/trend_display.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/fail_warning.dart';
|
|
||||||
import 'package:refilc_desktop_ui/pages/grades/grades_count.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/graph.dart';
|
|
||||||
import 'package:refilc_desktop_ui/pages/grades/grade_subject_view.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:refilc/helpers/average_helper.dart';
|
|
||||||
import 'package:refilc_mobile_ui/pages/grades/average_selector.dart';
|
|
||||||
import 'grades_page.i18n.dart';
|
|
||||||
|
|
||||||
class GradesPage extends StatefulWidget {
|
|
||||||
const GradesPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
GradesPageState createState() => GradesPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class GradesPageState extends State<GradesPage> {
|
|
||||||
late UserProvider user;
|
|
||||||
late GradeProvider gradeProvider;
|
|
||||||
late UpdateProvider updateProvider;
|
|
||||||
late String firstName;
|
|
||||||
late Widget yearlyGraph;
|
|
||||||
List<Widget> subjectTiles = [];
|
|
||||||
|
|
||||||
int avgDropValue = 0;
|
|
||||||
|
|
||||||
List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
|
|
||||||
gradeProvider.grades
|
|
||||||
.where((e) =>
|
|
||||||
e.subject == subject &&
|
|
||||||
e.type == GradeType.midYear &&
|
|
||||||
(days == 0 ||
|
|
||||||
e.date
|
|
||||||
.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
void generateTiles() {
|
|
||||||
List<GradeSubject> subjects = gradeProvider.grades
|
|
||||||
.map((e) => e.subject)
|
|
||||||
.toSet()
|
|
||||||
.toList()
|
|
||||||
..sort((a, b) => a.name.compareTo(b.name));
|
|
||||||
List<Widget> tiles = [];
|
|
||||||
|
|
||||||
Map<GradeSubject, double> subjectAvgs = {};
|
|
||||||
|
|
||||||
tiles.addAll(subjects.map((subject) {
|
|
||||||
List<Grade> subjectGrades = getSubjectGrades(subject);
|
|
||||||
|
|
||||||
double avg = AverageHelper.averageEvals(subjectGrades);
|
|
||||||
double averageBefore = 0.0;
|
|
||||||
|
|
||||||
if (avgDropValue != 0) {
|
|
||||||
List<Grade> gradesBefore =
|
|
||||||
getSubjectGrades(subject, days: avgDropValue);
|
|
||||||
averageBefore =
|
|
||||||
avgDropValue == 0 ? 0.0 : AverageHelper.averageEvals(gradesBefore);
|
|
||||||
}
|
|
||||||
var nullavg = GroupAverage(average: 0.0, subject: subject, uid: "0");
|
|
||||||
double groupAverage = gradeProvider.groupAverages
|
|
||||||
.firstWhere((e) => e.subject == subject, orElse: () => nullavg)
|
|
||||||
.average;
|
|
||||||
|
|
||||||
if (avg != 0) subjectAvgs[subject] = avg;
|
|
||||||
|
|
||||||
return GradeSubjectTile(
|
|
||||||
subject,
|
|
||||||
averageBefore: averageBefore,
|
|
||||||
average: avg,
|
|
||||||
groupAverage: avgDropValue == 0 ? groupAverage : 0.0,
|
|
||||||
onTap: () {
|
|
||||||
GradeSubjectView(subject, groupAverage: groupAverage)
|
|
||||||
.push(context, root: true);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (tiles.isNotEmpty) {
|
|
||||||
tiles.insert(0, yearlyGraph);
|
|
||||||
tiles.insert(1, FailWarning(subjectAvgs: subjectAvgs));
|
|
||||||
tiles.insert(
|
|
||||||
2,
|
|
||||||
PanelTitle(
|
|
||||||
title: Text(avgDropValue == 0
|
|
||||||
? "Subjects".i18n
|
|
||||||
: "Subjects_changes".i18n)));
|
|
||||||
tiles.insert(3, const PanelHeader(padding: EdgeInsets.only(top: 12.0)));
|
|
||||||
tiles.add(const PanelFooter(padding: EdgeInsets.only(bottom: 12.0)));
|
|
||||||
tiles.add(const Padding(padding: EdgeInsets.only(bottom: 24.0)));
|
|
||||||
} else {
|
|
||||||
tiles.insert(
|
|
||||||
0,
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 24.0),
|
|
||||||
child: Empty(subtitle: "empty".i18n),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
double subjectAvg = subjectAvgs.isNotEmpty
|
|
||||||
? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
|
|
||||||
subjectAvgs.length
|
|
||||||
: 0.0;
|
|
||||||
final double classAvg = gradeProvider.groupAverages.isNotEmpty
|
|
||||||
? gradeProvider.groupAverages
|
|
||||||
.map((e) => e.average)
|
|
||||||
.fold(0.0, (double a, double b) => a + b) /
|
|
||||||
gradeProvider.groupAverages.length
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
if (subjectAvg > 0) {
|
|
||||||
tiles.add(Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: StatisticsTile(
|
|
||||||
fill: true,
|
|
||||||
title: AutoSizeText(
|
|
||||||
"subjectavg".i18n,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
value: subjectAvg,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 24.0),
|
|
||||||
Expanded(
|
|
||||||
child: StatisticsTile(
|
|
||||||
outline: true,
|
|
||||||
title: AutoSizeText(
|
|
||||||
// https://discord.com/channels/1111649116020285532/1153397476578050130
|
|
||||||
"classavg".i18n,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
maxLines: 2,
|
|
||||||
wrapWords: false,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
value: classAvg,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// padding
|
|
||||||
tiles.add(const SizedBox(height: 32.0));
|
|
||||||
|
|
||||||
subjectTiles = List.castFrom(tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
user = Provider.of<UserProvider>(context);
|
|
||||||
gradeProvider = Provider.of<GradeProvider>(context);
|
|
||||||
updateProvider = Provider.of<UpdateProvider>(context);
|
|
||||||
|
|
||||||
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
|
||||||
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
|
||||||
|
|
||||||
final double totalClassAvg = gradeProvider.groupAverages.isEmpty
|
|
||||||
? 0.0
|
|
||||||
: gradeProvider.groupAverages
|
|
||||||
.map((e) => e.average)
|
|
||||||
.fold(0.0, (double a, double b) => a + b) /
|
|
||||||
gradeProvider.groupAverages.length;
|
|
||||||
|
|
||||||
final now = gradeProvider.grades.isNotEmpty
|
|
||||||
? gradeProvider.grades
|
|
||||||
.reduce((v, e) => e.date.isAfter(v.date) ? e : v)
|
|
||||||
.date
|
|
||||||
: DateTime.now();
|
|
||||||
|
|
||||||
final currentStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
|
|
||||||
.where((e) => e.type == GradeType.midYear)
|
|
||||||
.toList());
|
|
||||||
final prevStudentAvg = AverageHelper.averageEvals(gradeProvider.grades
|
|
||||||
.where((e) => e.type == GradeType.midYear)
|
|
||||||
.where((e) => e.date.isBefore(now.subtract(const Duration(days: 30))))
|
|
||||||
.toList());
|
|
||||||
|
|
||||||
List<Grade> graphGrades = gradeProvider.grades
|
|
||||||
.where((e) =>
|
|
||||||
e.type == GradeType.midYear &&
|
|
||||||
(avgDropValue == 0 ||
|
|
||||||
e.date.isAfter(
|
|
||||||
DateTime.now().subtract(Duration(days: avgDropValue)))))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
yearlyGraph = Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
|
|
||||||
child: Panel(
|
|
||||||
title: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
AverageSelector(
|
|
||||||
value: avgDropValue,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
avgDropValue = value!;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
// if (totalClassAvg >= 1.0) AverageDisplay(average: totalClassAvg, border: true),
|
|
||||||
// const SizedBox(width: 4.0),
|
|
||||||
TrendDisplay(
|
|
||||||
previous: prevStudentAvg, current: currentStudentAvg),
|
|
||||||
if (gradeProvider.grades
|
|
||||||
.where((e) => e.type == GradeType.midYear)
|
|
||||||
.isNotEmpty)
|
|
||||||
AverageDisplay(average: currentStudentAvg),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.only(top: 12.0, right: 12.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: GradeGraph(graphGrades,
|
|
||||||
dayThreshold: 2, classAvg: totalClassAvg)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 24.0),
|
|
||||||
child: GradesCount(grades: graphGrades),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
generateTiles();
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 9.0),
|
|
||||||
child: NestedScrollView(
|
|
||||||
physics: const BouncingScrollPhysics(
|
|
||||||
parent: AlwaysScrollableScrollPhysics()),
|
|
||||||
headerSliverBuilder: (context, _) => [
|
|
||||||
SliverAppBar(
|
|
||||||
centerTitle: false,
|
|
||||||
pinned: true,
|
|
||||||
floating: false,
|
|
||||||
snap: false,
|
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
title: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 8.0),
|
|
||||||
child: Text(
|
|
||||||
"page_title_grades".i18n,
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.of(context).text,
|
|
||||||
fontSize: 32.0,
|
|
||||||
fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
shadowColor: Theme.of(context).shadowColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
body: RefreshIndicator(
|
|
||||||
onRefresh: () => gradeProvider.fetch(),
|
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
child: ListView.builder(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
physics: const BouncingScrollPhysics(),
|
|
||||||
itemCount: max(subjectTiles.length, 1),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (subjectTiles.isNotEmpty) {
|
|
||||||
EdgeInsetsGeometry panelPadding =
|
|
||||||
const EdgeInsets.symmetric(horizontal: 24.0);
|
|
||||||
|
|
||||||
if (subjectTiles[index].runtimeType == GradeSubjectTile) {
|
|
||||||
return Padding(
|
|
||||||
padding: panelPadding,
|
|
||||||
child: PanelBody(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: subjectTiles[index],
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
return Padding(
|
|
||||||
padding: panelPadding, child: subjectTiles[index]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
import 'package:i18n_extension/i18n_extension.dart';
|
|
||||||
|
|
||||||
extension Localization on String {
|
|
||||||
static final _t = Translations.byLocale("hu_hu") +
|
|
||||||
{
|
|
||||||
"en_en": {
|
|
||||||
"Grades": "Grades",
|
|
||||||
"Ghost Grades": "Grades",
|
|
||||||
"Subjects": "Subjects",
|
|
||||||
"Subjects_changes": "Subject Differences",
|
|
||||||
"empty": "You don't have any subjects.",
|
|
||||||
"annual_average": "Annual average",
|
|
||||||
"3_months_average": "3 Monthly Average",
|
|
||||||
"30_days_average": "Monthly Average",
|
|
||||||
"14_days_average": "2 Weekly Average",
|
|
||||||
"7_days_average": "Weekly Average",
|
|
||||||
"subjectavg": "Subject Average",
|
|
||||||
"classavg": "Class Average",
|
|
||||||
"fail_warning": "Failure warning",
|
|
||||||
"fail_warning_description": "You are failing %d subjects!"
|
|
||||||
.one("You are failing a subject!"),
|
|
||||||
},
|
|
||||||
"hu_hu": {
|
|
||||||
"Grades": "Jegyek",
|
|
||||||
"Ghost Grades": "Szellem jegyek",
|
|
||||||
"Subjects": "Tantárgyak",
|
|
||||||
"Subjects_changes": "Tantárgyi változások",
|
|
||||||
"empty": "Még nincs egy tárgyad sem.",
|
|
||||||
"annual_average": "Éves átlag",
|
|
||||||
"3_months_average": "Háromhavi átlag",
|
|
||||||
"30_days_average": "Havi átlag",
|
|
||||||
"14_days_average": "Kétheti átlag",
|
|
||||||
"7_days_average": "Heti átlag",
|
|
||||||
"subjectavg": "Tantárgyi átlag",
|
|
||||||
"classavg": "Osztályátlag",
|
|
||||||
"fail_warning": "Bukás figyelmeztető",
|
|
||||||
"fail_warning_description": "Bukásra állsz %d tantárgyból",
|
|
||||||
},
|
|
||||||
"de_de": {
|
|
||||||
"Grades": "Noten",
|
|
||||||
"Ghost Grades": "Geist Noten",
|
|
||||||
"Subjects": "Fächer",
|
|
||||||
"Subjects_changes": "Betreff Änderungen",
|
|
||||||
"empty": "Sie haben keine Fächer.",
|
|
||||||
"annual_average": "Jahresdurchschnitt",
|
|
||||||
"3_months_average": "Drei-Monats-Durchschnitt",
|
|
||||||
"30_days_average": "Monatsdurchschnitt",
|
|
||||||
"14_days_average": "Vierzehntägiger Durchschnitt",
|
|
||||||
"7_days_average": "Wöchentlicher Durchschnitt",
|
|
||||||
"subjectavg": "Fächer Durchschnitt",
|
|
||||||
"classavg": "Klassendurchschnitt",
|
|
||||||
"fail_warning": "Ausfallwarnung",
|
|
||||||
"fail_warning_description": "Sie werden in %d des Fachs durchfallen",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
String get i18n => localize(this, _t);
|
|
||||||
String fill(List<Object> params) => localizeFill(this, params);
|
|
||||||
String plural(int value) => localizePlural(value, this, _t);
|
|
||||||
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
import 'package:refilc/api/providers/user_provider.dart';
|
|
||||||
import 'package:refilc/models/settings.dart';
|
|
||||||
import 'package:refilc/ui/date_widget.dart';
|
|
||||||
import 'package:refilc_mobile_ui/common/filter_bar.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:animated_list_plus/animated_list_plus.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:refilc/ui/filter/widgets.dart';
|
|
||||||
import 'package:refilc/ui/filter/sort.dart';
|
|
||||||
import 'home_page.i18n.dart';
|
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
|
||||||
const HomePage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<HomePage> createState() => _HomePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _HomePageState extends State<HomePage>
|
|
||||||
with SingleTickerProviderStateMixin {
|
|
||||||
late UserProvider user;
|
|
||||||
late SettingsProvider settings;
|
|
||||||
|
|
||||||
late TabController _tabController;
|
|
||||||
late PageController _pageController;
|
|
||||||
|
|
||||||
late String greeting;
|
|
||||||
late String firstName;
|
|
||||||
|
|
||||||
late List<String> listOrder;
|
|
||||||
static const pageCount = 4;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
_tabController = TabController(length: pageCount, vsync: this);
|
|
||||||
_pageController = PageController();
|
|
||||||
|
|
||||||
listOrder = List.generate(pageCount, (index) => "$index");
|
|
||||||
|
|
||||||
user = Provider.of<UserProvider>(context, listen: false);
|
|
||||||
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
|
||||||
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
|
||||||
greeting = "goodrest";
|
|
||||||
} else if (now.month == user.student?.birth.month &&
|
|
||||||
now.day == user.student?.birth.day) {
|
|
||||||
greeting = "happybirthday";
|
|
||||||
} else if (now.month == DateTime.december &&
|
|
||||||
now.day >= 24 &&
|
|
||||||
now.day <= 26) {
|
|
||||||
greeting = "merryxmas";
|
|
||||||
} else if (now.month == DateTime.january && now.day == 1) {
|
|
||||||
greeting = "happynewyear";
|
|
||||||
} else if (now.hour >= 18) {
|
|
||||||
greeting = "goodevening";
|
|
||||||
} else if (now.hour >= 12) {
|
|
||||||
greeting = "goodafternoon";
|
|
||||||
} else if (now.hour >= 4) {
|
|
||||||
greeting = "goodmorning";
|
|
||||||
} else {
|
|
||||||
greeting = "goodevening";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
user = Provider.of<UserProvider>(context);
|
|
||||||
settings = Provider.of<SettingsProvider>(context);
|
|
||||||
|
|
||||||
List<String> nameParts = user.name?.split(" ") ?? ["?"];
|
|
||||||
if (!settings.presentationMode) {
|
|
||||||
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
|
||||||
} else {
|
|
||||||
firstName = "Béla";
|
|
||||||
}
|
|
||||||
|
|
||||||
return SafeArea(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// Greeting
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 32.0, top: 24.0, bottom: 12.0),
|
|
||||||
child: Text(
|
|
||||||
greeting.i18n.fill([firstName]),
|
|
||||||
overflow: TextOverflow.fade,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 24.0,
|
|
||||||
color: Theme.of(context).textTheme.bodyMedium?.color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 12.0),
|
|
||||||
child: FilterBar(
|
|
||||||
items: [
|
|
||||||
Tab(text: "All".i18n),
|
|
||||||
Tab(text: "Grades".i18n),
|
|
||||||
Tab(text: "Messages".i18n),
|
|
||||||
Tab(text: "Absences".i18n),
|
|
||||||
],
|
|
||||||
controller: _tabController,
|
|
||||||
onTap: (i) async {
|
|
||||||
int selectedPage = _pageController.page!.round();
|
|
||||||
|
|
||||||
if (i == selectedPage) return;
|
|
||||||
if (_pageController.page?.roundToDouble() !=
|
|
||||||
_pageController.page) {
|
|
||||||
_pageController.animateToPage(i,
|
|
||||||
curve: Curves.easeIn, duration: kTabScrollDuration);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// swap current page with target page
|
|
||||||
setState(() {
|
|
||||||
_pageController.jumpToPage(i);
|
|
||||||
String currentList = listOrder[selectedPage];
|
|
||||||
listOrder[selectedPage] = listOrder[i];
|
|
||||||
listOrder[i] = currentList;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
disableFading: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Data filters
|
|
||||||
Expanded(
|
|
||||||
child: PageView.custom(
|
|
||||||
controller: _pageController,
|
|
||||||
childrenDelegate: SliverChildBuilderDelegate(
|
|
||||||
(BuildContext context, int index) {
|
|
||||||
return FutureBuilder<List<DateWidget>>(
|
|
||||||
key: ValueKey<String>(listOrder[index]),
|
|
||||||
future: getFilterWidgets(homeFilters[index],
|
|
||||||
context: context),
|
|
||||||
builder: (context, dateWidgets) => dateWidgets.data !=
|
|
||||||
null
|
|
||||||
? ImplicitlyAnimatedList<Widget>(
|
|
||||||
items: sortDateWidgets(context,
|
|
||||||
dateWidgets: dateWidgets.data!),
|
|
||||||
itemBuilder: filterItemBuilder,
|
|
||||||
spawnIsolate: false,
|
|
||||||
areItemsTheSame: (a, b) => a.key == b.key,
|
|
||||||
physics: const BouncingScrollPhysics(
|
|
||||||
parent: AlwaysScrollableScrollPhysics()),
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 24.0),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: 4,
|
|
||||||
findChildIndexCallback: (Key key) {
|
|
||||||
final ValueKey<String> valueKey =
|
|
||||||
key as ValueKey<String>;
|
|
||||||
final String data = valueKey.value;
|
|
||||||
return listOrder.indexOf(data);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
physics: const PageScrollPhysics()
|
|
||||||
.applyTo(const BouncingScrollPhysics()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import 'package:i18n_extension/i18n_extension.dart';
|
|
||||||
|
|
||||||
extension Localization on String {
|
|
||||||
static final _t = Translations.byLocale("hu_hu") +
|
|
||||||
{
|
|
||||||
"en_en": {
|
|
||||||
"goodmorning": "Good morning, %s!",
|
|
||||||
"goodafternoon": "Good afternoon, %s!",
|
|
||||||
"goodevening": "Good evening, %s!",
|
|
||||||
"goodrest": "⛱️ Have a nice holiday, %s!",
|
|
||||||
"happybirthday": "🎂 Happy birthday, %s!",
|
|
||||||
"merryxmas": "🎄 Merry Christmas, %s!",
|
|
||||||
"happynewyear": "🎉 Happy New Year, %s!",
|
|
||||||
"empty": "Nothing to see here.",
|
|
||||||
"All": "All",
|
|
||||||
"Grades": "Grades",
|
|
||||||
"Messages": "Messages",
|
|
||||||
"Absences": "Absences",
|
|
||||||
"update_available": "Update Available",
|
|
||||||
"missed_exams": "You missed %s exams this week.".one("You missed an exam this week."),
|
|
||||||
"missed_exam_contact": "Contact %s, to resolve it!",
|
|
||||||
},
|
|
||||||
"hu_hu": {
|
|
||||||
"goodmorning": "Jó reggelt, %s!",
|
|
||||||
"goodafternoon": "Szép napot, %s!",
|
|
||||||
"goodevening": "Szép estét, %s!",
|
|
||||||
"goodrest": "⛱️ Jó szünetet, %s!",
|
|
||||||
"happybirthday": "🎂 Boldog születésnapot, %s!",
|
|
||||||
"merryxmas": "🎄 Boldog Karácsonyt, %s!",
|
|
||||||
"happynewyear": "🎉 Boldog új évet, %s!",
|
|
||||||
"empty": "Nincs itt semmi látnivaló.",
|
|
||||||
"All": "Összes",
|
|
||||||
"Grades": "Jegyek",
|
|
||||||
"Messages": "Üzenetek",
|
|
||||||
"Absences": "Hiányok",
|
|
||||||
"update_available": "Frissítés elérhető",
|
|
||||||
"missed_exams": "Ezen a héten hiányoztál %s dolgozatról.".one("Ezen a héten hiányoztál egy dolgozatról."),
|
|
||||||
"missed_exam_contact": "Keresd %s-t, ha pótolni szeretnéd!",
|
|
||||||
},
|
|
||||||
"de_de": {
|
|
||||||
"goodmorning": "Guten morgen, %s!",
|
|
||||||
"goodafternoon": "Guten Tag, %s!",
|
|
||||||
"goodevening": "Guten Abend, %s!",
|
|
||||||
"goodrest": "⛱️ Schöne Ferien, %s!",
|
|
||||||
"happybirthday": "🎂 Alles Gute zum Geburtstag, %s!",
|
|
||||||
"merryxmas": "🎄 Frohe Weihnachten, %s!",
|
|
||||||
"happynewyear": "🎉 Frohes neues Jahr, %s!",
|
|
||||||
"empty": "Hier gibt es nichts zu sehen.",
|
|
||||||
"All": "Alles",
|
|
||||||
"Grades": "Noten",
|
|
||||||
"Messages": "Nachrichten",
|
|
||||||
"Absences": "Fehlen",
|
|
||||||
"update_available": "Update verfügbar",
|
|
||||||
"missed_exams": "Diese Woche haben Sie %s Prüfungen verpasst.".one("Diese Woche haben Sie eine Prüfung verpasst."),
|
|
||||||
"missed_exam_contact": "Wenden Sie sich an %s, um sie zu erneuern!",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
String get i18n => localize(this, _t);
|
|
||||||
String fill(List<Object> params) => localizeFill(this, params);
|
|
||||||
String plural(int value) => localizePlural(value, this, _t);
|
|
||||||
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
|
||||||
}
|
|
||||||