Compare commits
116 Commits
Author | SHA1 | Date | |
---|---|---|---|
ff1e794820 | |||
ceba5f7fe8 | |||
f570acbed6 | |||
2a7a472d90 | |||
138fbe5bf5 | |||
ad99cc75eb | |||
f6606e7a4f | |||
3690deef1e | |||
cd1438587d | |||
8193a57227 | |||
8467f39ad9 | |||
0fc293f47a | |||
9b063edb0b | |||
5d852eee87 | |||
54ab408135 | |||
41aa326f42 | |||
24f605c71c | |||
5c52dcc74f | |||
667659fbe6 | |||
d467bf096f | |||
98d556bcd5 | |||
8c730be635 | |||
377d24fbb4 | |||
bde810e031 | |||
2f18d42c86 | |||
c708b0c20e | |||
ff8d55d4f8 | |||
49bf911c84 | |||
9e33ef419f | |||
40e95eac1e | |||
19e76a0b5d | |||
5feafe3907 | |||
b7206ed714 | |||
38370d647d | |||
323bc188b1 | |||
b17356591a | |||
a02c444cf5 | |||
87a133beb9 | |||
1f4a208857 | |||
a7c472989c | |||
747696e386 | |||
a71a183160 | |||
125a010f03 | |||
5c5993cc2a | |||
f234b71932 | |||
497a3391d4 | |||
a72c743c6f | |||
98fdfd001a | |||
994b162ae3 | |||
90c60f399b | |||
b16b225a1a | |||
7a4cf694ca | |||
1b492d50fe | |||
d9b5e000f8 | |||
7e30524876 | |||
ce9b12eb93 | |||
b602657d55 | |||
360dfbcdb5 | |||
f466497970 | |||
184a7ab200 | |||
2e5ef7dfa2 | |||
8f617f4ca1 | |||
fe5f96a394 | |||
cb9c35d772 | |||
7cf7977cc6 | |||
1de747fa35 | |||
93750829d7 | |||
798688e7dd | |||
6ab9c1d737 | |||
b074ce99b7 | |||
b03fd86be5 | |||
3de2f5ff88 | |||
35adf83154 | |||
0162c8bbee | |||
736d570f26 | |||
5b0901e311 | |||
f9474af39e | |||
d411d86355 | |||
a50c6707cb | |||
6991c68d3a | |||
8b1e6f7bd6 | |||
943fd9c622 | |||
838e2781c0 | |||
66cfd7b52c | |||
a45bc0eef6 | |||
ed7996299e | |||
d4b73fb73e | |||
d6ece78eff | |||
2f44f3c4ba | |||
23b49e4b8c | |||
5d33cefe1d | |||
6089df9462 | |||
3ee98e2bd0 | |||
53a5d02051 | |||
e332fd9cf9 | |||
7232938c12 | |||
fd02f2253b | |||
12046ef0a0 | |||
dfc84b4208 | |||
f5f11d5130 | |||
81ce328abd | |||
867951136a | |||
8b41ab27bd | |||
e542ef003c | |||
a5f212e6be | |||
385a320536 | |||
e65000ec2c | |||
c87de7b3c2 | |||
bb6023709f | |||
e998e54d3e | |||
e269886eae | |||
dabb83c522 | |||
6350b72e23 | |||
e4100d940a | |||
6575674169 | |||
a13aad984c |
@ -98,7 +98,7 @@ jobs:
|
|||||||
command: yes | sdkmanager --licenses && yes | sdkmanager --update
|
command: yes | sdkmanager --licenses && yes | sdkmanager --update
|
||||||
- run:
|
- run:
|
||||||
name: Setup emulator
|
name: Setup emulator
|
||||||
command: sdkmanager "system-images;android-19;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;default;armeabi-v7a"
|
command: sdkmanager "system-images;android-22;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-22;default;armeabi-v7a"
|
||||||
- run:
|
- run:
|
||||||
name: Launch emulator
|
name: Launch emulator
|
||||||
command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on
|
command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on
|
||||||
@ -116,7 +116,7 @@ jobs:
|
|||||||
adb shell input keyevent 82
|
adb shell input keyevent 82
|
||||||
- run:
|
- run:
|
||||||
name: Run instrumented tests
|
name: Run instrumented tests
|
||||||
command: ./gradlew clean createPlayDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
command: ./gradlew clean createFdroidDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||||
- run:
|
- run:
|
||||||
name: Collect logs from emulator
|
name: Collect logs from emulator
|
||||||
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
|
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -111,3 +111,4 @@ Thumbs.db
|
|||||||
### AndroidStudio Patch ###
|
### AndroidStudio Patch ###
|
||||||
|
|
||||||
!/gradle/wrapper/gradle-wrapper.jar
|
!/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
3
.idea/codeStyles/Project.xml
generated
3
.idea/codeStyles/Project.xml
generated
@ -1,6 +1,9 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
|
<AndroidXmlCodeStyleSettings>
|
||||||
|
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
||||||
|
</AndroidXmlCodeStyleSettings>
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
<value>
|
<value>
|
||||||
|
14
.travis.yml
14
.travis.yml
@ -3,8 +3,8 @@ jdk: oraclejdk8
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- ANDROID_API_LEVEL=28
|
- ANDROID_API_LEVEL=29
|
||||||
- ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
- ANDROID_BUILD_TOOLS_VERSION=29.0.2
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
@ -14,7 +14,7 @@ cache:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- develop
|
- develop
|
||||||
- 0.10.0
|
- 0.13.0
|
||||||
|
|
||||||
android:
|
android:
|
||||||
licenses:
|
licenses:
|
||||||
@ -34,12 +34,12 @@ android:
|
|||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- addon-google_apis-google-$ANDROID_API_LEVEL
|
- addon-google_apis-google-$ANDROID_API_LEVEL
|
||||||
# Android emulator
|
# Android emulator
|
||||||
- android-19
|
- android-22
|
||||||
- sys-img-armeabi-v7a-android-19
|
- sys-img-armeabi-v7a-android-22
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
# Launch emulator before the execution
|
# Launch emulator before the execution
|
||||||
- echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a
|
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
|
||||||
- emulator -avd test -no-audio -no-window &
|
- emulator -avd test -no-audio -no-window &
|
||||||
- android-wait-for-emulator
|
- android-wait-for-emulator
|
||||||
- adb shell input keyevent 82 &
|
- adb shell input keyevent 82 &
|
||||||
@ -50,7 +50,7 @@ script:
|
|||||||
- fossa --no-ansi || true
|
- fossa --no-ansi || true
|
||||||
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
|
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
|
||||||
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
|
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
|
||||||
- ./gradlew createPlayDebugCoverageReport --stacktrace --daemon
|
- ./gradlew createFdroidDebugCoverageReport --stacktrace --daemon
|
||||||
- ./gradlew jacocoTestReport --stacktrace --daemon
|
- ./gradlew jacocoTestReport --stacktrace --daemon
|
||||||
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
|
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
|
||||||
git fetch --unshallow;
|
git fetch --unshallow;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
|
||||||
Unofficial android VULCAN UONET+ register client for student and parent
|
Unofficial android VULCAN UONET+ register client for student and parent
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
|
||||||
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
|
|
||||||
|
@ -9,16 +9,16 @@ apply from: 'sonarqube.gradle'
|
|||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 29
|
||||||
buildToolsVersion '28.0.3'
|
buildToolsVersion '29.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 29
|
||||||
versionCode 43
|
versionCode 48
|
||||||
versionName "0.10.0"
|
versionName "0.13.0"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@ -28,8 +28,10 @@ android {
|
|||||||
]
|
]
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions {
|
annotationProcessorOptions {
|
||||||
arguments = ["room.schemaLocation": "$projectDir/schemas".toString(),
|
arguments = [
|
||||||
"room.incremental" : "true"]
|
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||||
|
"room.incremental" : "true"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +63,6 @@ android {
|
|||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
testCoverageEnabled = true
|
testCoverageEnabled = true
|
||||||
ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
|
ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
|
||||||
multiDexKeepProguard file('proguard-multidex-rules.pro')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,38 +110,36 @@ play {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.2.0"
|
work_manager = "2.3.0-beta01"
|
||||||
room = "2.2.0-beta01"
|
room = "2.2.2"
|
||||||
dagger = "2.24"
|
dagger = "2.25.2"
|
||||||
chucker = "2.0.4"
|
chucker = "2.0.4"
|
||||||
mockk = "1.9.2"
|
mockk = "1.9.2"
|
||||||
mockito_core = "3.0.6"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
|
resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||||
resolutionStrategy.force "com.google.android.material:material:1.1.0-alpha07"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:api:0.10.0"
|
implementation "io.github.wulkanowy:api:0.13.0"
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "androidx.core:core-ktx:1.1.0-rc03"
|
implementation "androidx.core:core-ktx:1.2.0-rc01"
|
||||||
implementation "androidx.activity:activity-ktx:1.0.0-rc01"
|
implementation "androidx.activity:activity-ktx:1.1.0-rc03"
|
||||||
implementation "androidx.appcompat:appcompat:1.1.0-rc01"
|
implementation "androidx.appcompat:appcompat:1.1.0"
|
||||||
implementation "androidx.appcompat:appcompat-resources:1.1.0-rc01"
|
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.1.0-rc04"
|
implementation "androidx.fragment:fragment-ktx:1.2.0-rc03"
|
||||||
implementation "androidx.annotation:annotation:1.1.0"
|
implementation "androidx.annotation:annotation:1.1.0"
|
||||||
implementation "androidx.multidex:multidex:2.0.1"
|
implementation "androidx.multidex:multidex:2.0.1"
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.1.0-rc01"
|
implementation "androidx.preference:preference-ktx:1.1.0"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0-beta03"
|
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-beta01"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "com.google.android.material:material:1.1.0-alpha07"
|
implementation "com.google.android.material:material:1.1.0-beta02"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
|
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
||||||
@ -157,26 +156,28 @@ dependencies {
|
|||||||
implementation "com.google.dagger:dagger-android-support:$dagger"
|
implementation "com.google.dagger:dagger-android-support:$dagger"
|
||||||
kapt "com.google.dagger:dagger-compiler:$dagger"
|
kapt "com.google.dagger:dagger-compiler:$dagger"
|
||||||
kapt "com.google.dagger:dagger-android-processor:$dagger"
|
kapt "com.google.dagger:dagger-android-processor:$dagger"
|
||||||
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0"
|
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2"
|
||||||
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.0"
|
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.2"
|
||||||
|
|
||||||
implementation "eu.davidea:flexible-adapter:5.1.0"
|
implementation "eu.davidea:flexible-adapter:5.1.0"
|
||||||
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
|
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
|
||||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
||||||
implementation "com.ncapdevi:frag-nav:3.3.0"
|
implementation "com.ncapdevi:frag-nav:3.3.0"
|
||||||
|
implementation "com.github.YarikSOffice:lingver:1.1.0"
|
||||||
|
|
||||||
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
|
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
|
||||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||||
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
|
implementation "io.reactivex.rxjava2:rxjava:2.2.15"
|
||||||
|
|
||||||
implementation "com.google.code.gson:gson:2.8.5"
|
implementation "com.google.code.gson:gson:2.8.6"
|
||||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
||||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.3"
|
implementation "com.squareup.okhttp3:logging-interceptor:3.12.6"
|
||||||
implementation "com.mikepenz:aboutlibraries:7.0.3"
|
implementation "com.mikepenz:aboutlibraries:7.0.4"
|
||||||
|
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||||
|
|
||||||
playImplementation "com.google.firebase:firebase-core:17.2.0"
|
playImplementation "com.google.firebase:firebase-core:17.2.1"
|
||||||
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||||
|
|
||||||
releaseImplementation "fr.o80.chucker:library-no-op:$chucker"
|
releaseImplementation "fr.o80.chucker:library-no-op:$chucker"
|
||||||
@ -187,10 +188,7 @@ dependencies {
|
|||||||
testImplementation "junit:junit:4.12"
|
testImplementation "junit:junit:4.12"
|
||||||
testImplementation "io.mockk:mockk:$mockk"
|
testImplementation "io.mockk:mockk:$mockk"
|
||||||
testImplementation "org.threeten:threetenbp:1.4.0"
|
testImplementation "org.threeten:threetenbp:1.4.0"
|
||||||
testImplementation "org.mockito:mockito-core:$mockito_core"
|
testImplementation "org.mockito:mockito-inline:3.2.0"
|
||||||
testImplementation("org.mockito:mockito-inline:3.0.6") {
|
|
||||||
exclude group: "org.mockito", module: "mockito-core"
|
|
||||||
}
|
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.2.0"
|
androidTestImplementation "androidx.test:core:1.2.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||||
@ -198,10 +196,7 @@ dependencies {
|
|||||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||||
androidTestImplementation "androidx.room:room-testing:$room"
|
androidTestImplementation "androidx.room:room-testing:$room"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
androidTestImplementation "org.mockito:mockito-core:$mockito_core"
|
androidTestImplementation "org.mockito:mockito-android:3.2.0"
|
||||||
androidTestImplementation("org.mockito:mockito-android:3.0.6") {
|
|
||||||
exclude group: 'org.mockito', module: 'mockito-core'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
-keep class android.support.test.internal** { *; }
|
|
||||||
-keep class org.junit.** { *; }
|
|
||||||
-keep public class io.github.wulkanowy** { *; }
|
|
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@ -42,4 +42,4 @@
|
|||||||
|
|
||||||
|
|
||||||
#Config for Material Components
|
#Config for Material Components
|
||||||
-keep class com.google.android.material.tabs.**
|
-keep class com.google.android.material.tabs.** { *; }
|
||||||
|
1480
app/schemas/io.github.wulkanowy.data.db.AppDatabase/16.json
Normal file
1480
app/schemas/io.github.wulkanowy.data.db.AppDatabase/16.json
Normal file
File diff suppressed because it is too large
Load Diff
1530
app/schemas/io.github.wulkanowy.data.db.AppDatabase/17.json
Normal file
1530
app/schemas/io.github.wulkanowy.data.db.AppDatabase/17.json
Normal file
File diff suppressed because it is too large
Load Diff
1592
app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json
Normal file
1592
app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -22,12 +22,7 @@ abstract class AbstractMigrationTest {
|
|||||||
fun getMigratedRoomDatabase(): AppDatabase {
|
fun getMigratedRoomDatabase(): AppDatabase {
|
||||||
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
||||||
AppDatabase::class.java, dbName)
|
AppDatabase::class.java, dbName)
|
||||||
.addMigrations(
|
.addMigrations(*AppDatabase.getMigrations())
|
||||||
Migration12(),
|
|
||||||
Migration13(),
|
|
||||||
Migration14(),
|
|
||||||
Migration15()
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
// close the database and release any stream resources when the test finishes
|
// close the database and release any stream resources when the test finishes
|
||||||
helper.closeWhenFinished(database)
|
helper.closeWhenFinished(database)
|
||||||
|
@ -3,10 +3,14 @@ package io.github.wulkanowy.data.db.migrations
|
|||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import io.github.wulkanowy.data.db.Converters
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDate.of
|
import org.threeten.bp.LocalDate.of
|
||||||
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class Migration13Test : AbstractMigrationTest() {
|
class Migration13Test : AbstractMigrationTest() {
|
||||||
@ -97,11 +101,9 @@ class Migration13Test : AbstractMigrationTest() {
|
|||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
val db = helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
||||||
|
|
||||||
val db = getMigratedRoomDatabase()
|
val semesters1 = getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 1 AND class_id = 5")
|
||||||
|
|
||||||
val semesters1 = db.semesterDao.loadAll(1, 5).blockingGet()
|
|
||||||
assertTrue { semesters1.single { it.isCurrent }.isCurrent }
|
assertTrue { semesters1.single { it.isCurrent }.isCurrent }
|
||||||
semesters1[0].run {
|
semesters1[0].run {
|
||||||
assertFalse(isCurrent)
|
assertFalse(isCurrent)
|
||||||
@ -119,7 +121,7 @@ class Migration13Test : AbstractMigrationTest() {
|
|||||||
assertEquals(2, diaryId)
|
assertEquals(2, diaryId)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.semesterDao.loadAll(2, 5).blockingGet().let {
|
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
||||||
assertTrue { it.single { it.isCurrent }.isCurrent }
|
assertTrue { it.single { it.isCurrent }.isCurrent }
|
||||||
assertEquals(1970, it[0].schoolYear)
|
assertEquals(1970, it[0].schoolYear)
|
||||||
assertEquals(of(1970, 1, 1), it[0].end)
|
assertEquals(of(1970, 1, 1), it[0].end)
|
||||||
@ -130,7 +132,7 @@ class Migration13Test : AbstractMigrationTest() {
|
|||||||
assertTrue(it[3].isCurrent)
|
assertTrue(it[3].isCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.semesterDao.loadAll(2, 5).blockingGet().let {
|
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
||||||
assertTrue { it.single { it.isCurrent }.isCurrent }
|
assertTrue { it.single { it.isCurrent }.isCurrent }
|
||||||
assertFalse(it[0].isCurrent)
|
assertFalse(it[0].isCurrent)
|
||||||
assertFalse(it[1].isCurrent)
|
assertFalse(it[1].isCurrent)
|
||||||
@ -139,6 +141,30 @@ class Migration13Test : AbstractMigrationTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Semester> {
|
||||||
|
val semesters = mutableListOf<Semester>()
|
||||||
|
|
||||||
|
val cursor = db.query(query)
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
semesters.add(Semester(
|
||||||
|
studentId = cursor.getInt(1),
|
||||||
|
diaryId = cursor.getInt(2),
|
||||||
|
diaryName = cursor.getString(3),
|
||||||
|
semesterId = cursor.getInt(4),
|
||||||
|
semesterName = cursor.getInt(5),
|
||||||
|
isCurrent = cursor.getInt(6) == 1,
|
||||||
|
classId = cursor.getInt(7),
|
||||||
|
unitId = cursor.getInt(8),
|
||||||
|
schoolYear = cursor.getInt(9),
|
||||||
|
start = Converters().timestampToDate(cursor.getLong(10))!!,
|
||||||
|
end = Converters().timestampToDate(cursor.getLong(11))!!
|
||||||
|
))
|
||||||
|
} while (cursor.moveToNext())
|
||||||
|
}
|
||||||
|
return semesters.toList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) {
|
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) {
|
||||||
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||||
put("endpoint", "https://fakelog.cf")
|
put("endpoint", "https://fakelog.cf")
|
||||||
|
@ -4,6 +4,7 @@ import androidx.room.Room
|
|||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@ -24,7 +25,7 @@ class GradeStatisticsLocalTest {
|
|||||||
fun createDb() {
|
fun createDb() {
|
||||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||||
.build()
|
.build()
|
||||||
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics)
|
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -63,7 +64,52 @@ class GradeStatisticsLocalTest {
|
|||||||
assertEquals(stats[0].subject, "Wszystkie")
|
assertEquals(stats[0].subject, "Wszystkie")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun saveAndRead_points() {
|
||||||
|
gradeStatisticsLocal.saveGradesPointsStatistics(listOf(
|
||||||
|
getGradePointsStatistics("Matematyka", 2, 1),
|
||||||
|
getGradePointsStatistics("Chemia", 2, 1),
|
||||||
|
getGradePointsStatistics("Fizyka", 1, 2)
|
||||||
|
))
|
||||||
|
|
||||||
|
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
||||||
|
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
||||||
|
"Matematyka"
|
||||||
|
).blockingGet()
|
||||||
|
with(stats) {
|
||||||
|
assertEquals(subject, "Matematyka")
|
||||||
|
assertEquals(others, 5.0)
|
||||||
|
assertEquals(student, 5.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun saveAndRead_subjectEmpty() {
|
||||||
|
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
||||||
|
|
||||||
|
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
||||||
|
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
||||||
|
"Matematyka"
|
||||||
|
).blockingGet()
|
||||||
|
assertEquals(null, stats)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun saveAndRead_allEmpty() {
|
||||||
|
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
||||||
|
|
||||||
|
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
||||||
|
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
||||||
|
"Wszystkie"
|
||||||
|
).blockingGet()
|
||||||
|
assertEquals(null, stats)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
|
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
|
||||||
return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
|
return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics {
|
||||||
|
return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">Wulkanowy DEV</string>
|
|
||||||
</resources>
|
|
@ -6,10 +6,13 @@ import android.util.Log.VERBOSE
|
|||||||
import androidx.multidex.MultiDex
|
import androidx.multidex.MultiDex
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||||
|
import com.yariksoffice.lingver.Lingver
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.support.DaggerApplication
|
import dagger.android.support.DaggerApplication
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.utils.Log
|
import eu.davidea.flexibleadapter.utils.Log
|
||||||
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
|
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
|
||||||
import io.github.wulkanowy.di.DaggerAppComponent
|
import io.github.wulkanowy.di.DaggerAppComponent
|
||||||
import io.github.wulkanowy.services.sync.SyncWorkerFactory
|
import io.github.wulkanowy.services.sync.SyncWorkerFactory
|
||||||
import io.github.wulkanowy.ui.base.ThemeManager
|
import io.github.wulkanowy.ui.base.ThemeManager
|
||||||
@ -32,6 +35,9 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var themeManager: ThemeManager
|
lateinit var themeManager: ThemeManager
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var sharedPrefProvider: SharedPrefProvider
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appInfo: AppInfo
|
lateinit var appInfo: AppInfo
|
||||||
|
|
||||||
@ -44,7 +50,9 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
AndroidThreeTen.init(this)
|
AndroidThreeTen.init(this)
|
||||||
RxJavaPlugins.setErrorHandler(::onError)
|
RxJavaPlugins.setErrorHandler(::onError)
|
||||||
|
Lingver.init(this)
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
|
migrateSharedPreferences()
|
||||||
|
|
||||||
initLogging()
|
initLogging()
|
||||||
initCrashlytics(this, appInfo)
|
initCrashlytics(this, appInfo)
|
||||||
@ -60,6 +68,13 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
|||||||
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
|
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun migrateSharedPreferences() {
|
||||||
|
if (sharedPrefProvider.getLong(APP_VERSION_CODE_KEY, -1) < 48) { // #596
|
||||||
|
sharedPrefProvider.delete(getString(R.string.pref_key_grade_modifier_plus))
|
||||||
|
sharedPrefProvider.delete(getString(R.string.pref_key_grade_modifier_minus))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onError(error: Throwable) {
|
private fun onError(error: Throwable) {
|
||||||
//RxJava's too deep stack traces may cause SOE on older android devices
|
//RxJava's too deep stack traces may cause SOE on older android devices
|
||||||
val cause = error.cause
|
val cause = error.cause
|
||||||
|
@ -85,6 +85,10 @@ internal class RepositoryModule {
|
|||||||
@Provides
|
@Provides
|
||||||
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
|
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMessagesDao(database: AppDatabase) = database.messagesDao
|
fun provideMessagesDao(database: AppDatabase) = database.messagesDao
|
||||||
@ -136,4 +140,12 @@ internal class RepositoryModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
|
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideTeacherDao(database: AppDatabase) = database.teacherDao
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,13 @@ import androidx.room.Room
|
|||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
|
import androidx.room.migration.Migration
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeDao
|
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||||
@ -20,15 +22,18 @@ import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
|||||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||||
import io.github.wulkanowy.data.db.dao.RecipientDao
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.dao.SubjectDao
|
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
|
import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
@ -38,9 +43,11 @@ import io.github.wulkanowy.data.db.entities.MobileDevice
|
|||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
import io.github.wulkanowy.data.db.migrations.Migration10
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||||
@ -48,6 +55,9 @@ import io.github.wulkanowy.data.db.migrations.Migration12
|
|||||||
import io.github.wulkanowy.data.db.migrations.Migration13
|
import io.github.wulkanowy.data.db.migrations.Migration13
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration14
|
import io.github.wulkanowy.data.db.migrations.Migration14
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration15
|
import io.github.wulkanowy.data.db.migrations.Migration15
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration16
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration17
|
||||||
|
import io.github.wulkanowy.data.db.migrations.Migration18
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
@ -70,6 +80,7 @@ import javax.inject.Singleton
|
|||||||
Grade::class,
|
Grade::class,
|
||||||
GradeSummary::class,
|
GradeSummary::class,
|
||||||
GradeStatistics::class,
|
GradeStatistics::class,
|
||||||
|
GradePointsStatistics::class,
|
||||||
Message::class,
|
Message::class,
|
||||||
Note::class,
|
Note::class,
|
||||||
Homework::class,
|
Homework::class,
|
||||||
@ -78,7 +89,9 @@ import javax.inject.Singleton
|
|||||||
CompletedLesson::class,
|
CompletedLesson::class,
|
||||||
ReportingUnit::class,
|
ReportingUnit::class,
|
||||||
Recipient::class,
|
Recipient::class,
|
||||||
MobileDevice::class
|
MobileDevice::class,
|
||||||
|
Teacher::class,
|
||||||
|
School::class
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
@ -87,14 +100,10 @@ import javax.inject.Singleton
|
|||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 15
|
const val VERSION_SCHEMA = 18
|
||||||
|
|
||||||
fun newInstance(context: Context): AppDatabase {
|
fun getMigrations(): Array<Migration> {
|
||||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
return arrayOf(
|
||||||
.setJournalMode(TRUNCATE)
|
|
||||||
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
|
|
||||||
.fallbackToDestructiveMigrationOnDowngrade()
|
|
||||||
.addMigrations(
|
|
||||||
Migration2(),
|
Migration2(),
|
||||||
Migration3(),
|
Migration3(),
|
||||||
Migration4(),
|
Migration4(),
|
||||||
@ -108,8 +117,19 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration12(),
|
Migration12(),
|
||||||
Migration13(),
|
Migration13(),
|
||||||
Migration14(),
|
Migration14(),
|
||||||
Migration15()
|
Migration15(),
|
||||||
|
Migration16(),
|
||||||
|
Migration17(),
|
||||||
|
Migration18()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun newInstance(context: Context): AppDatabase {
|
||||||
|
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||||
|
.setJournalMode(TRUNCATE)
|
||||||
|
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
|
||||||
|
.fallbackToDestructiveMigrationOnDowngrade()
|
||||||
|
.addMigrations(*getMigrations())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,6 +152,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
|
|
||||||
abstract val gradeStatistics: GradeStatisticsDao
|
abstract val gradeStatistics: GradeStatisticsDao
|
||||||
|
|
||||||
|
abstract val gradePointsStatistics: GradePointsStatisticsDao
|
||||||
|
|
||||||
abstract val messagesDao: MessagesDao
|
abstract val messagesDao: MessagesDao
|
||||||
|
|
||||||
abstract val noteDao: NoteDao
|
abstract val noteDao: NoteDao
|
||||||
@ -149,4 +171,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract val recipientDao: RecipientDao
|
abstract val recipientDao: RecipientDao
|
||||||
|
|
||||||
abstract val mobileDeviceDao: MobileDeviceDao
|
abstract val mobileDeviceDao: MobileDeviceDao
|
||||||
|
|
||||||
|
abstract val teacherDao: TeacherDao
|
||||||
|
|
||||||
|
abstract val schoolDao: SchoolDao
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@ import javax.inject.Singleton
|
|||||||
@Singleton
|
@Singleton
|
||||||
class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
|
class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val APP_VERSION_CODE_KEY = "app_version_code"
|
||||||
|
}
|
||||||
|
|
||||||
fun putLong(key: String, value: Long, sync: Boolean = false) {
|
fun putLong(key: String, value: Long, sync: Boolean = false) {
|
||||||
sharedPref.edit(sync) { putLong(key, value) }
|
sharedPref.edit(sync) { putLong(key, value) }
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -11,13 +9,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface AttendanceDao {
|
interface AttendanceDao : BaseDao<Attendance> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(exams: List<Attendance>): List<Long>
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(exams: List<Attendance>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Attendance>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Attendance>>
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface AttendanceSummaryDao {
|
interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(exams: List<AttendanceSummary>): List<Long>
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(exams: List<AttendanceSummary>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
|
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe<List<AttendanceSummary>>
|
fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe<List<AttendanceSummary>>
|
||||||
|
17
app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
Normal file
17
app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Update
|
||||||
|
|
||||||
|
interface BaseDao<T> {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAll(items: List<T>): List<Long>
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun updateAll(items: List<T>)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteAll(items: List<T>)
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -11,13 +9,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface CompletedLessonsDao {
|
interface CompletedLessonsDao : BaseDao<CompletedLesson> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(exams: List<CompletedLesson>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(exams: List<CompletedLesson>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>>
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -11,13 +9,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface ExamDao {
|
interface ExamDao : BaseDao<Exam> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(exams: List<Exam>): List<Long>
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(exams: List<Exam>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Exam>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Exam>>
|
||||||
|
@ -1,26 +1,14 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface GradeDao {
|
interface GradeDao : BaseDao<Grade> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(grades: List<Grade>)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun updateAll(grade: List<Grade>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(grades: List<Grade>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
|
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
|
||||||
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Grade>>
|
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<Grade>>
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface GradePointsStatisticsDao : BaseDao<GradePointsStatistics> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
|
||||||
|
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe<GradePointsStatistics>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||||
|
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradePointsStatistics>>
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -10,13 +8,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface GradeStatisticsDao {
|
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(gradesStatistics: List<GradeStatistics>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(gradesStatistics: List<GradeStatistics>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
|
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
|
||||||
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe<List<GradeStatistics>>
|
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe<List<GradeStatistics>>
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -10,13 +8,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface GradeSummaryDao {
|
interface GradeSummaryDao : BaseDao<GradeSummary> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(gradesSummary: List<GradeSummary>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(gradesSummary: List<GradeSummary>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
|
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||||
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradeSummary>>
|
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradeSummary>>
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -11,13 +9,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface HomeworkDao {
|
interface HomeworkDao : BaseDao<Homework> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(homework: List<Homework>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(homework: List<Homework>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Homework>>
|
fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Homework>>
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -12,18 +9,8 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface LuckyNumberDao {
|
interface LuckyNumberDao : BaseDao<LuckyNumber> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insert(luckyNumber: LuckyNumber)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun update(luckyNumber: LuckyNumber)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun delete(luckyNumber: LuckyNumber)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
|
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
|
||||||
fun load(studentId: Int, date: LocalDate): Maybe<LuckyNumber>
|
fun load(studentId: Int, date: LocalDate): Maybe<LuckyNumber>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,12 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface MessagesDao {
|
interface MessagesDao : BaseDao<Message> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(messages: List<Message>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(messages: List<Message>)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun updateAll(messages: List<Message>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
||||||
fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>>
|
fun loadAll(studentId: Int, folder: Int): Maybe<List<Message>>
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface MobileDeviceDao {
|
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(devices: List<MobileDevice>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(devices: List<MobileDevice>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
||||||
fun loadAll(studentId: Int): Maybe<List<MobileDevice>>
|
fun loadAll(studentId: Int): Maybe<List<MobileDevice>>
|
||||||
|
@ -1,28 +1,15 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface NoteDao {
|
interface NoteDao : BaseDao<Note> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(notes: List<Note>)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun updateAll(notes: List<Note>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(notes: List<Note>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
|
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
|
||||||
fun loadAll(studentId: Int): Maybe<List<Note>>
|
fun loadAll(studentId: Int): Maybe<List<Note>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -10,13 +8,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface RecipientDao {
|
interface RecipientDao : BaseDao<Recipient> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(messages: List<Recipient>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(messages: List<Recipient>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
|
@Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
|
||||||
fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>>
|
fun load(studentId: Int, role: Int, unitId: Int): Maybe<List<Recipient>>
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -10,13 +8,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface ReportingUnitDao {
|
interface ReportingUnitDao : BaseDao<ReportingUnit> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(reportingUnits: List<ReportingUnit>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(reportingUnits: List<ReportingUnit>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
|
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
|
||||||
fun load(studentId: Int): Maybe<List<ReportingUnit>>
|
fun load(studentId: Int): Maybe<List<ReportingUnit>>
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface SchoolDao : BaseDao<School> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
|
||||||
|
fun load(studentId: Int, classId: Int): Maybe<School>
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -10,13 +8,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface SemesterDao {
|
interface SemesterDao : BaseDao<Semester> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(semester: List<Semester>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(semester: List<Semester>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
|
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
|
||||||
fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>>
|
fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>>
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface SubjectDao {
|
interface SubjectDao : BaseDao<Subject> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(subjects: List<Subject>): List<Long>
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(subjects: List<Subject>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
|
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
|
||||||
fun loadAll(diaryId: Int, studentId: Int): Maybe<List<Subject>>
|
fun loadAll(diaryId: Int, studentId: Int): Maybe<List<Subject>>
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Dao
|
||||||
|
interface TeacherDao : BaseDao<Teacher> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
|
||||||
|
fun loadAll(studentId: Int, classId: Int): Maybe<List<Teacher>>
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -11,13 +9,7 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface TimetableDao {
|
interface TimetableDao : BaseDao<Timetable> {
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(exams: List<Timetable>): List<Long>
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(exams: List<Timetable>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Timetable>>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe<List<Timetable>>
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "GradesPointsStatistics")
|
||||||
|
data class GradePointsStatistics(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "semester_id")
|
||||||
|
val semesterId: Int,
|
||||||
|
|
||||||
|
val subject: String,
|
||||||
|
|
||||||
|
val others: Double,
|
||||||
|
|
||||||
|
val student: Double
|
||||||
|
) {
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "School")
|
||||||
|
data class School(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "class_id")
|
||||||
|
val classId: Int,
|
||||||
|
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
val address: String,
|
||||||
|
|
||||||
|
val contact: String,
|
||||||
|
|
||||||
|
val headmaster: String,
|
||||||
|
|
||||||
|
val pedagogue: String
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "Teachers")
|
||||||
|
data class Teacher(
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
val studentId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "class_id")
|
||||||
|
val classId: Int,
|
||||||
|
|
||||||
|
val subject: String,
|
||||||
|
|
||||||
|
val name: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "short_name")
|
||||||
|
val shortName: String
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration16 : Migration(15, 16) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("""
|
||||||
|
CREATE TABLE IF NOT EXISTS Teachers (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
student_id INTEGER NOT NULL,
|
||||||
|
class_id INTEGER NOT NULL,
|
||||||
|
subject TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
short_name TEXT NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration17 : Migration(16, 17) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
createGradesPointsStatisticsTable(database)
|
||||||
|
truncateSemestersTable(database)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("""
|
||||||
|
CREATE TABLE IF NOT EXISTS GradesPointsStatistics(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
student_id INTEGER NOT NULL,
|
||||||
|
semester_id INTEGER NOT NULL,
|
||||||
|
subject TEXT NOT NULL,
|
||||||
|
others REAL NOT NULL,
|
||||||
|
student REAL NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun truncateSemestersTable(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("DELETE FROM Semesters")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.wulkanowy.data.db.migrations
|
||||||
|
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
|
||||||
|
class Migration18 : Migration(17, 18) {
|
||||||
|
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("""
|
||||||
|
CREATE TABLE IF NOT EXISTS School (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
student_id INTEGER NOT NULL,
|
||||||
|
class_id INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
address TEXT NOT NULL,
|
||||||
|
contact TEXT NOT NULL,
|
||||||
|
headmaster TEXT NOT NULL,
|
||||||
|
pedagogue TEXT NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package io.github.wulkanowy.data.repositories.gradestatistics
|
package io.github.wulkanowy.data.repositories.gradestatistics
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
@ -8,27 +10,57 @@ import javax.inject.Inject
|
|||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class GradeStatisticsLocal @Inject constructor(private val gradeStatisticsDb: GradeStatisticsDao) {
|
class GradeStatisticsLocal @Inject constructor(
|
||||||
|
private val gradeStatisticsDb: GradeStatisticsDao,
|
||||||
|
private val gradePointsStatisticsDb: GradePointsStatisticsDao
|
||||||
|
) {
|
||||||
|
|
||||||
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
|
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
|
||||||
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
|
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).filter { it.isNotEmpty() }
|
||||||
.filter { !it.isEmpty() }
|
}
|
||||||
|
|
||||||
|
fun getGradesPointsStatistics(semester: Semester): Maybe<List<GradePointsStatistics>> {
|
||||||
|
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
|
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
|
||||||
return (if ("Wszystkie" == subjectName) gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
|
return when (subjectName) {
|
||||||
|
"Wszystkie" -> gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
|
||||||
list.groupBy { it.grade }.map {
|
list.groupBy { it.grade }.map {
|
||||||
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
|
||||||
|
it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)).filter { !it.isEmpty() }
|
else -> gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)
|
||||||
|
}.filter { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGradesPointsStatistics(semester: Semester, subjectName: String): Maybe<GradePointsStatistics> {
|
||||||
|
return when (subjectName) {
|
||||||
|
"Wszystkie" -> gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).flatMap { list ->
|
||||||
|
if (list.isEmpty()) return@flatMap Maybe.empty<GradePointsStatistics>()
|
||||||
|
Maybe.just(GradePointsStatistics(semester.studentId, semester.semesterId, subjectName,
|
||||||
|
list.fold(.0) { acc, e -> acc + e.others },
|
||||||
|
list.fold(.0) { acc, e -> acc + e.student })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> gradePointsStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
||||||
gradeStatisticsDb.insertAll(gradesStatistics)
|
gradeStatisticsDb.insertAll(gradesStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveGradesPointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) {
|
||||||
|
gradePointsStatisticsDb.insertAll(gradePointsStatistics)
|
||||||
|
}
|
||||||
|
|
||||||
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
||||||
gradeStatisticsDb.deleteAll(gradesStatistics)
|
gradeStatisticsDb.deleteAll(gradesStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteGradesPointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) {
|
||||||
|
gradePointsStatisticsDb.deleteAll(gradesPointsStatistics)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.repositories.gradestatistics
|
package io.github.wulkanowy.data.repositories.gradestatistics
|
||||||
|
|
||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
@ -12,7 +13,10 @@ class GradeStatisticsRemote @Inject constructor(private val api: Api) {
|
|||||||
|
|
||||||
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
|
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
|
||||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||||
.flatMap { it.getGradesStatistics(semester.semesterId, isSemester) }
|
.flatMap {
|
||||||
|
if (isSemester) it.getGradesAnnualStatistics(semester.semesterId)
|
||||||
|
else it.getGradesPartialStatistics(semester.semesterId)
|
||||||
|
}
|
||||||
.map { gradeStatistics ->
|
.map { gradeStatistics ->
|
||||||
gradeStatistics.map {
|
gradeStatistics.map {
|
||||||
GradeStatistics(
|
GradeStatistics(
|
||||||
@ -26,4 +30,20 @@ class GradeStatisticsRemote @Inject constructor(private val api: Api) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getGradePointsStatistics(semester: Semester): Single<List<GradePointsStatistics>> {
|
||||||
|
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||||
|
.flatMap { it.getGradesPointsStatistics(semester.semesterId) }
|
||||||
|
.map { gradePointsStatistics ->
|
||||||
|
gradePointsStatistics.map {
|
||||||
|
GradePointsStatistics(
|
||||||
|
semesterId = semester.semesterId,
|
||||||
|
studentId = semester.studentId,
|
||||||
|
subject = it.subject,
|
||||||
|
others = it.others,
|
||||||
|
student = it.student
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ package io.github.wulkanowy.data.repositories.gradestatistics
|
|||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -31,4 +33,19 @@ class GradeStatisticsRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
|
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getGradesPointsStatistics(semester: Semester, subjectName: String, forceRefresh: Boolean): Maybe<GradePointsStatistics> {
|
||||||
|
return local.getGradesPointsStatistics(semester, subjectName).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMapMaybe {
|
||||||
|
if (it) remote.getGradePointsStatistics(semester).toMaybe()
|
||||||
|
else Maybe.error(UnknownHostException())
|
||||||
|
}.flatMap { new ->
|
||||||
|
local.getGradesPointsStatistics(semester).defaultIfEmpty(emptyList())
|
||||||
|
.doOnSuccess { old ->
|
||||||
|
local.deleteGradesPointsStatistics(old.uniqueSubtract(new))
|
||||||
|
local.saveGradesPointsStatistics(new.uniqueSubtract(old))
|
||||||
|
}
|
||||||
|
}.flatMap { local.getGradesPointsStatistics(semester, subjectName) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,15 @@ import javax.inject.Singleton
|
|||||||
class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
|
class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
|
||||||
|
|
||||||
fun saveLuckyNumber(luckyNumber: LuckyNumber) {
|
fun saveLuckyNumber(luckyNumber: LuckyNumber) {
|
||||||
luckyNumberDb.insert(luckyNumber)
|
luckyNumberDb.insertAll(listOf(luckyNumber))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateLuckyNumber(luckyNumber: LuckyNumber) {
|
fun updateLuckyNumber(luckyNumber: LuckyNumber) {
|
||||||
luckyNumberDb.update(luckyNumber)
|
luckyNumberDb.updateAll(listOf(luckyNumber))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteLuckyNumber(luckyNumber: LuckyNumber) {
|
fun deleteLuckyNumber(luckyNumber: LuckyNumber) {
|
||||||
luckyNumberDb.delete(luckyNumber)
|
luckyNumberDb.deleteAll(listOf(luckyNumber))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe<LuckyNumber> {
|
fun getLuckyNumber(semester: Semester, date: LocalDate): Maybe<LuckyNumber> {
|
||||||
|
@ -11,7 +11,6 @@ import io.reactivex.Single
|
|||||||
import org.threeten.bp.LocalDateTime.now
|
import org.threeten.bp.LocalDateTime.now
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import io.github.wulkanowy.api.messages.Message as ApiMessage
|
|
||||||
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
|
import io.github.wulkanowy.api.messages.Recipient as ApiRecipient
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.data.repositories.mobiledevice
|
|||||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -12,52 +12,64 @@ class PreferencesRepository @Inject constructor(
|
|||||||
val context: Context
|
val context: Context
|
||||||
) {
|
) {
|
||||||
val startMenuIndex: Int
|
val startMenuIndex: Int
|
||||||
get() = sharedPref.getString(context.getString(R.string.pref_key_start_menu), "0")?.toIntOrNull() ?: 0
|
get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt()
|
||||||
|
|
||||||
val isShowPresent: Boolean
|
val isShowPresent: Boolean
|
||||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_attendance_present), true)
|
get() = getBoolean(R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present)
|
||||||
|
|
||||||
val gradeAverageMode: String
|
val gradeAverageMode: String
|
||||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester"
|
get() = getString(R.string.pref_key_grade_average_mode, R.string.pref_default_grade_average_mode)
|
||||||
|
|
||||||
val gradeAverageForceCalc: Boolean
|
val gradeAverageForceCalc: Boolean
|
||||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false)
|
get() = getBoolean(R.string.pref_key_grade_average_force_calc, R.bool.pref_default_grade_average_force_calc)
|
||||||
|
|
||||||
val isGradeExpandable: Boolean
|
val isGradeExpandable: Boolean
|
||||||
get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false)
|
get() = !getBoolean(R.string.pref_key_expand_grade, R.bool.pref_default_expand_grade)
|
||||||
|
|
||||||
val appThemeKey: String = context.getString(R.string.pref_key_app_theme)
|
val appThemeKey = context.getString(R.string.pref_key_app_theme)
|
||||||
val appTheme: String
|
val appTheme: String
|
||||||
get() = sharedPref.getString(appThemeKey, "light") ?: "light"
|
get() = getString(appThemeKey, R.string.pref_default_app_theme)
|
||||||
|
|
||||||
val gradeColorTheme: String
|
val gradeColorTheme: String
|
||||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan"
|
get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme)
|
||||||
|
|
||||||
val serviceEnableKey: String = context.getString(R.string.pref_key_services_enable)
|
val appLanguageKey = context.getString(R.string.pref_key_app_language)
|
||||||
|
val appLanguage
|
||||||
|
get() = getString(appLanguageKey, R.string.pref_default_app_language)
|
||||||
|
|
||||||
|
val serviceEnableKey = context.getString(R.string.pref_key_services_enable)
|
||||||
val isServiceEnabled: Boolean
|
val isServiceEnabled: Boolean
|
||||||
get() = sharedPref.getBoolean(serviceEnableKey, true)
|
get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable)
|
||||||
|
|
||||||
val servicesIntervalKey: String = context.getString(R.string.pref_key_services_interval)
|
val servicesIntervalKey = context.getString(R.string.pref_key_services_interval)
|
||||||
val servicesInterval: Long
|
val servicesInterval: Long
|
||||||
get() = sharedPref.getString(servicesIntervalKey, "60")?.toLongOrNull() ?: 60
|
get() = getString(servicesIntervalKey, R.string.pref_default_services_interval).toLong()
|
||||||
|
|
||||||
val servicesOnlyWifiKey: String = context.getString(R.string.pref_key_services_wifi_only)
|
val servicesOnlyWifiKey = context.getString(R.string.pref_key_services_wifi_only)
|
||||||
val isServicesOnlyWifi: Boolean
|
val isServicesOnlyWifi: Boolean
|
||||||
get() = sharedPref.getBoolean(servicesOnlyWifiKey, false)
|
get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only)
|
||||||
|
|
||||||
val isNotificationsEnable: Boolean
|
val isNotificationsEnable: Boolean
|
||||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_notifications_enable), true)
|
get() = getBoolean(R.string.pref_key_notifications_enable, R.bool.pref_default_notifications_enable)
|
||||||
|
|
||||||
val isDebugNotificationEnableKey: String = context.getString(R.string.pref_key_notification_debug)
|
val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
|
||||||
val isDebugNotificationEnable: Boolean
|
val isDebugNotificationEnable: Boolean
|
||||||
get() = sharedPref.getBoolean(isDebugNotificationEnableKey, false)
|
get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
|
||||||
|
|
||||||
val gradePlusModifier: Double
|
val gradePlusModifier: Double
|
||||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDouble() ?: 0.0
|
get() = getString(R.string.pref_key_grade_modifier_plus, R.string.pref_default_grade_modifier_plus).toDouble()
|
||||||
|
|
||||||
val gradeMinusModifier: Double
|
val gradeMinusModifier: Double
|
||||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDouble() ?: 0.0
|
get() = getString(R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus).toDouble()
|
||||||
|
|
||||||
val fillMessageContent: Boolean
|
val fillMessageContent: Boolean
|
||||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_fill_message_content), true)
|
get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content)
|
||||||
|
|
||||||
|
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
|
||||||
|
|
||||||
|
private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default)
|
||||||
|
|
||||||
|
private fun getBoolean(id: Int, default: Int) = getBoolean(context.getString(id), default)
|
||||||
|
|
||||||
|
private fun getBoolean(id: String, default: Int) = sharedPref.getBoolean(id, context.resources.getBoolean(default))
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao)
|
|||||||
return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() }
|
return recipientDb.load(student.studentId, role, unit.realId).filter { !it.isEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveRecipients(recipients: List<Recipient>) {
|
fun saveRecipients(recipients: List<Recipient>): List<Long> {
|
||||||
return recipientDb.insertAll(recipients)
|
return recipientDb.insertAll(recipients)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: Report
|
|||||||
return reportingUnitDb.loadOne(student.studentId, unitId)
|
return reportingUnitDb.loadOne(student.studentId, unitId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveReportingUnits(reportingUnits: List<ReportingUnit>) {
|
fun saveReportingUnits(reportingUnits: List<ReportingUnit>): List<Long> {
|
||||||
return reportingUnitDb.insertAll(reportingUnits)
|
return reportingUnitDb.insertAll(reportingUnits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.school
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
||||||
|
|
||||||
|
fun saveSchool(school: School) {
|
||||||
|
schoolDb.insertAll(listOf(school))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteSchool(school: School) {
|
||||||
|
schoolDb.deleteAll(listOf(school))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSchool(semester: Semester): Maybe<School> {
|
||||||
|
return schoolDb.load(semester.studentId, semester.classId)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.school
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SchoolRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getSchoolInfo(semester: Semester): Single<School> {
|
||||||
|
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||||
|
.flatMap { it.getSchool() }
|
||||||
|
.map {
|
||||||
|
School(
|
||||||
|
studentId = semester.studentId,
|
||||||
|
classId = semester.classId,
|
||||||
|
name = it.name,
|
||||||
|
address = it.address,
|
||||||
|
contact = it.contact,
|
||||||
|
headmaster = it.headmaster,
|
||||||
|
pedagogue = it.pedagogue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.school
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class SchoolRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: SchoolLocal,
|
||||||
|
private val remote: SchoolRemote
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getSchoolInfo(semester: Semester, forceRefresh: Boolean = false): Maybe<School> {
|
||||||
|
return local.getSchool(semester).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getSchoolInfo(semester)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMapMaybe { new ->
|
||||||
|
local.getSchool(semester)
|
||||||
|
.doOnSuccess { old ->
|
||||||
|
if (new != old) {
|
||||||
|
local.deleteSchool(old)
|
||||||
|
local.saveSchool(new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.doOnComplete {
|
||||||
|
local.saveSchool(new)
|
||||||
|
}
|
||||||
|
}.flatMap({ local.getSchool(semester) }, { Maybe.error(it) },
|
||||||
|
{ local.getSchool(semester) })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ class StudentLocal @Inject constructor(
|
|||||||
fun getStudents(decryptPass: Boolean): Maybe<List<Student>> {
|
fun getStudents(decryptPass: Boolean): Maybe<List<Student>> {
|
||||||
return studentDb.loadAll()
|
return studentDb.loadAll()
|
||||||
.map { list -> list.map { it.apply { if (decryptPass) password = decrypt(password) } } }
|
.map { list -> list.map { it.apply { if (decryptPass) password = decrypt(password) } } }
|
||||||
.filter { !it.isEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentStudent(decryptPass: Boolean): Maybe<Student> {
|
fun getCurrentStudent(decryptPass: Boolean): Maybe<Student> {
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.teacher
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
||||||
|
|
||||||
|
fun saveTeachers(teachers: List<Teacher>) {
|
||||||
|
teacherDb.insertAll(teachers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteTeachers(teachers: List<Teacher>) {
|
||||||
|
teacherDb.deleteAll(teachers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTeachers(semester: Semester): Maybe<List<Teacher>> {
|
||||||
|
return teacherDb.loadAll(semester.studentId, semester.classId).filter { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.teacher
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import io.reactivex.Single
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class TeacherRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getTeachers(semester: Semester): Single<List<Teacher>> {
|
||||||
|
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||||
|
.flatMap { it.getTeachers() }
|
||||||
|
.map { teachers ->
|
||||||
|
teachers.map {
|
||||||
|
Teacher(
|
||||||
|
studentId = semester.studentId,
|
||||||
|
name = it.name,
|
||||||
|
subject = it.subject,
|
||||||
|
shortName = it.short,
|
||||||
|
classId = semester.classId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.teacher
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import io.reactivex.Single
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class TeacherRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: TeacherLocal,
|
||||||
|
private val remote: TeacherRemote
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getTeachers(semester: Semester, forceRefresh: Boolean = false): Single<List<Teacher>> {
|
||||||
|
return local.getTeachers(semester).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||||
|
.flatMap {
|
||||||
|
if (it) remote.getTeachers(semester)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMap { new ->
|
||||||
|
local.getTeachers(semester).toSingle(emptyList())
|
||||||
|
.doOnSuccess { old ->
|
||||||
|
local.deleteTeachers(old.uniqueSubtract(new))
|
||||||
|
local.saveTeachers(new.uniqueSubtract(old))
|
||||||
|
}
|
||||||
|
}.flatMap { local.getTeachers(semester).toSingle(emptyList()) })
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.di
|
|||||||
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.yariksoffice.lingver.Lingver
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
@ -32,4 +33,8 @@ internal class AppModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideAppInfo() = AppInfo()
|
fun provideAppInfo() = AppInfo()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideLingver() = Lingver.getInstance()
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import io.github.wulkanowy.services.sync.works.LuckyNumberWork
|
|||||||
import io.github.wulkanowy.services.sync.works.MessageWork
|
import io.github.wulkanowy.services.sync.works.MessageWork
|
||||||
import io.github.wulkanowy.services.sync.works.NoteWork
|
import io.github.wulkanowy.services.sync.works.NoteWork
|
||||||
import io.github.wulkanowy.services.sync.works.RecipientWork
|
import io.github.wulkanowy.services.sync.works.RecipientWork
|
||||||
|
import io.github.wulkanowy.services.sync.works.TeacherWork
|
||||||
import io.github.wulkanowy.services.sync.works.TimetableWork
|
import io.github.wulkanowy.services.sync.works.TimetableWork
|
||||||
import io.github.wulkanowy.services.sync.works.Work
|
import io.github.wulkanowy.services.sync.works.Work
|
||||||
import io.github.wulkanowy.services.widgets.TimetableWidgetService
|
import io.github.wulkanowy.services.widgets.TimetableWidgetService
|
||||||
@ -28,17 +29,15 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@AssistedModule
|
@AssistedModule
|
||||||
@Module(includes = [AssistedInject_ServicesModule::class])
|
@Module(includes = [AssistedInject_ServicesModule::class, ServicesModule.Static::class])
|
||||||
abstract class ServicesModule {
|
abstract class ServicesModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
companion object {
|
object Static {
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideWorkManager(context: Context) = WorkManager.getInstance(context)
|
fun provideWorkManager(context: Context) = WorkManager.getInstance(context)
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context)
|
fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context)
|
||||||
@ -75,6 +74,10 @@ abstract class ServicesModule {
|
|||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun provideTimetableWork(work: TimetableWork): Work
|
abstract fun provideTimetableWork(work: TimetableWork): Work
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
abstract fun provideTeacherWork(work: TeacherWork): Work
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work
|
abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work
|
||||||
|
@ -11,6 +11,7 @@ import androidx.work.NetworkType.UNMETERED
|
|||||||
import androidx.work.PeriodicWorkRequestBuilder
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
|
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
import io.github.wulkanowy.services.sync.channels.DebugChannel
|
import io.github.wulkanowy.services.sync.channels.DebugChannel
|
||||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||||
@ -32,10 +33,6 @@ class SyncManager @Inject constructor(
|
|||||||
appInfo: AppInfo
|
appInfo: AppInfo
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val APP_VERSION_CODE_KEY = "app_version_code"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (now().isHolidays) stopSyncWorker()
|
if (now().isHolidays) stopSyncWorker()
|
||||||
|
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package io.github.wulkanowy.services.sync.works
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.repositories.teacher.TeacherRepository
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
||||||
|
|
||||||
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
|
return teacherRepository.getTeachers(semester, true).ignoreElement()
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,8 @@ import io.github.wulkanowy.utils.FragmentLifecycleLogger
|
|||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity(), BaseView, HasAndroidInjector {
|
abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity(), BaseView,
|
||||||
|
HasAndroidInjector {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
||||||
@ -53,13 +54,15 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity
|
|||||||
override fun showError(text: String, error: Throwable) {
|
override fun showError(text: String, error: Throwable) {
|
||||||
if (messageContainer != null) {
|
if (messageContainer != null) {
|
||||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
||||||
.setAction(R.string.all_details) {
|
.setAction(R.string.all_details) { showErrorDetailsDialog(error) }
|
||||||
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
|
|
||||||
}
|
|
||||||
.show()
|
.show()
|
||||||
} else showMessage(text)
|
} else showMessage(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorDetailsDialog(error: Throwable) {
|
||||||
|
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
|
||||||
|
}
|
||||||
|
|
||||||
override fun showMessage(text: String) {
|
override fun showMessage(text: String) {
|
||||||
if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
||||||
else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import dagger.android.support.DaggerAppCompatDialogFragment
|
||||||
|
|
||||||
|
abstract class BaseDialogFragment : DaggerAppCompatDialogFragment(), BaseView {
|
||||||
|
|
||||||
|
override fun showError(text: String, error: Throwable) {
|
||||||
|
showMessage(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showMessage(text: String) {
|
||||||
|
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showExpiredDialog() {
|
||||||
|
(activity as? BaseActivity<*>)?.showExpiredDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openClearLoginView() {
|
||||||
|
(activity as? BaseActivity<*>)?.openClearLoginView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showErrorDetailsDialog(error: Throwable) {
|
||||||
|
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||||
|
}
|
||||||
|
}
|
@ -13,15 +13,17 @@ abstract class BaseFragment : DaggerFragment(), BaseView {
|
|||||||
override fun showError(text: String, error: Throwable) {
|
override fun showError(text: String, error: Throwable) {
|
||||||
if (messageContainer != null) {
|
if (messageContainer != null) {
|
||||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
||||||
.setAction(R.string.all_details) {
|
.setAction(R.string.all_details) { if (isAdded) showErrorDetailsDialog(error) }
|
||||||
if (isAdded) ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
|
||||||
}
|
|
||||||
.show()
|
.show()
|
||||||
} else {
|
} else {
|
||||||
(activity as? BaseActivity<*>)?.showError(text, error)
|
(activity as? BaseActivity<*>)?.showError(text, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorDetailsDialog(error: Throwable) {
|
||||||
|
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||||
|
}
|
||||||
|
|
||||||
override fun showMessage(text: String) {
|
override fun showMessage(text: String) {
|
||||||
if (messageContainer != null) {
|
if (messageContainer != null) {
|
||||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
||||||
|
@ -9,4 +9,6 @@ interface BaseView {
|
|||||||
fun showExpiredDialog()
|
fun showExpiredDialog()
|
||||||
|
|
||||||
fun openClearLoginView()
|
fun openClearLoginView()
|
||||||
|
|
||||||
|
fun showErrorDetailsDialog(error: Throwable)
|
||||||
}
|
}
|
||||||
|
@ -43,17 +43,18 @@ class ErrorDialog : DialogFragment() {
|
|||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
StringWriter().let { writer ->
|
|
||||||
error.printStackTrace(PrintWriter(writer))
|
|
||||||
|
|
||||||
errorDialogContent.text = writer.toString()
|
val stringWriter = StringWriter().apply {
|
||||||
|
error.printStackTrace(PrintWriter(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
errorDialogContent.text = stringWriter.toString()
|
||||||
errorDialogCopy.setOnClickListener {
|
errorDialogCopy.setOnClickListener {
|
||||||
ClipData.newPlainText("wulkanowyError", writer.toString()).let { clip ->
|
val clip = ClipData.newPlainText("wulkanowy", stringWriter.toString())
|
||||||
activity?.getSystemService<ClipboardManager>()?.primaryClip = clip
|
activity?.getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
||||||
}
|
|
||||||
Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show()
|
Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
errorDialogCancel.setOnClickListener { dismiss() }
|
errorDialogCancel.setOnClickListener { dismiss() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.base
|
|||||||
import android.content.pm.PackageManager.GET_ACTIVITIES
|
import android.content.pm.PackageManager.GET_ACTIVITIES
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
@ -22,8 +23,12 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
|
|||||||
|
|
||||||
fun applyDefaultTheme() {
|
fun applyDefaultTheme() {
|
||||||
AppCompatDelegate.setDefaultNightMode(
|
AppCompatDelegate.setDefaultNightMode(
|
||||||
if (preferencesRepository.appTheme == "light") MODE_NIGHT_NO
|
when (val theme = preferencesRepository.appTheme) {
|
||||||
else MODE_NIGHT_YES
|
"light" -> MODE_NIGHT_NO
|
||||||
|
"dark", "black" -> MODE_NIGHT_YES
|
||||||
|
"system" -> MODE_NIGHT_FOLLOW_SYSTEM
|
||||||
|
else -> throw IllegalArgumentException("Wrong theme: $theme")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,11 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
|||||||
Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback))
|
Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val faqRes: Triple<String, String, Drawable?>?
|
||||||
|
get() = context?.run {
|
||||||
|
Triple(getString(R.string.about_faq), getString(R.string.about_faq_summary), getCompatDrawable(R.drawable.ic_about_faq))
|
||||||
|
}
|
||||||
|
|
||||||
override val discordRes: Triple<String, String, Drawable?>?
|
override val discordRes: Triple<String, String, Drawable?>?
|
||||||
get() = context?.run {
|
get() = context?.run {
|
||||||
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
|
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
|
||||||
@ -130,6 +135,10 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openFaqPage() {
|
||||||
|
context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania", ::showMessage)
|
||||||
|
}
|
||||||
|
|
||||||
override fun openLicenses() {
|
override fun openLicenses() {
|
||||||
(activity as? MainActivity)?.pushView(LicenseFragment.newInstance())
|
(activity as? MainActivity)?.pushView(LicenseFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,15 @@ class AboutPresenter @Inject constructor(
|
|||||||
view?.run {
|
view?.run {
|
||||||
when (item.title) {
|
when (item.title) {
|
||||||
feedbackRes?.first -> {
|
feedbackRes?.first -> {
|
||||||
Timber.i("Opening email client ")
|
Timber.i("Opening email client")
|
||||||
openEmailClient()
|
openEmailClient()
|
||||||
analytics.logEvent("about_open", "name" to "feedback")
|
analytics.logEvent("about_open", "name" to "feedback")
|
||||||
}
|
}
|
||||||
|
faqRes?.first -> {
|
||||||
|
Timber.i("Opening faq page")
|
||||||
|
openFaqPage()
|
||||||
|
analytics.logEvent("about_open", "name" to "faq")
|
||||||
|
}
|
||||||
discordRes?.first -> {
|
discordRes?.first -> {
|
||||||
Timber.i("Opening discord")
|
Timber.i("Opening discord")
|
||||||
openDiscordInvite()
|
openDiscordInvite()
|
||||||
@ -61,6 +66,7 @@ class AboutPresenter @Inject constructor(
|
|||||||
updateData(AboutScrollableHeader(), listOfNotNull(
|
updateData(AboutScrollableHeader(), listOfNotNull(
|
||||||
versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
versionRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
feedbackRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
|
faqRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
discordRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
homepageRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
homepageRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
licensesRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
licensesRes?.let { (title, summary, image) -> AboutItem(title, summary, image) },
|
||||||
|
@ -9,6 +9,8 @@ interface AboutView : BaseView {
|
|||||||
|
|
||||||
val feedbackRes: Triple<String, String, Drawable?>?
|
val feedbackRes: Triple<String, String, Drawable?>?
|
||||||
|
|
||||||
|
val faqRes: Triple<String, String, Drawable?>?
|
||||||
|
|
||||||
val discordRes: Triple<String, String, Drawable?>?
|
val discordRes: Triple<String, String, Drawable?>?
|
||||||
|
|
||||||
val homepageRes: Triple<String, String, Drawable?>?
|
val homepageRes: Triple<String, String, Drawable?>?
|
||||||
@ -25,6 +27,8 @@ interface AboutView : BaseView {
|
|||||||
|
|
||||||
fun openEmailClient()
|
fun openEmailClient()
|
||||||
|
|
||||||
|
fun openFaqPage()
|
||||||
|
|
||||||
fun openHomepage()
|
fun openHomepage()
|
||||||
|
|
||||||
fun openLicenses()
|
fun openLicenses()
|
||||||
|
@ -7,18 +7,17 @@ import android.view.ViewGroup
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import android.widget.Toast.LENGTH_LONG
|
import android.widget.Toast.LENGTH_LONG
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import dagger.android.support.DaggerAppCompatDialogFragment
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.dialog_account.*
|
import kotlinx.android.synthetic.main.dialog_account.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
|
class AccountDialog : BaseDialogFragment(), AccountView {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: AccountPresenter
|
lateinit var presenter: AccountPresenter
|
||||||
@ -77,14 +76,6 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showExpiredDialog() {
|
|
||||||
(activity as? BaseActivity<*>)?.showExpiredDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openClearLoginView() {
|
|
||||||
(activity as? BaseActivity<*>)?.openClearLoginView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showConfirmDialog() {
|
override fun showConfirmDialog() {
|
||||||
context?.let {
|
context?.let {
|
||||||
AlertDialog.Builder(it)
|
AlertDialog.Builder(it)
|
||||||
@ -105,4 +96,3 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,11 @@ import android.view.Menu
|
|||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.INVISIBLE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
@ -17,9 +21,11 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
|||||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
|
import io.github.wulkanowy.utils.SchooldaysRangeLimiter
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
import io.github.wulkanowy.utils.dpToPx
|
||||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_attendance.*
|
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView,
|
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView,
|
||||||
@ -70,7 +76,11 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||||
|
attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
|
|
||||||
attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
||||||
|
attendanceNavDate.setOnClickListener { presenter.onPickDate() }
|
||||||
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
||||||
|
|
||||||
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||||
@ -110,11 +120,19 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
override fun showEmpty(show: Boolean) {
|
||||||
attendanceEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
attendanceEmpty.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
attendanceError.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
attendanceErrorMessage.text = message
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
attendanceProgress.visibility = if (show) View.VISIBLE else View.GONE
|
attendanceProgress.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableSwipe(enable: Boolean) {
|
override fun enableSwipe(enable: Boolean) {
|
||||||
@ -122,7 +140,7 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
override fun showContent(show: Boolean) {
|
||||||
attendanceRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
attendanceRecycler.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hideRefresh() {
|
override fun hideRefresh() {
|
||||||
@ -130,17 +148,32 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showPreButton(show: Boolean) {
|
override fun showPreButton(show: Boolean) {
|
||||||
attendancePreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
attendancePreviousButton.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showNextButton(show: Boolean) {
|
override fun showNextButton(show: Boolean) {
|
||||||
attendanceNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
attendanceNextButton.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showAttendanceDialog(lesson: Attendance) {
|
override fun showAttendanceDialog(lesson: Attendance) {
|
||||||
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showDatePickerDialog(currentDate: LocalDate) {
|
||||||
|
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth ->
|
||||||
|
presenter.onDateSet(year, month + 1, dayOfMonth)
|
||||||
|
}
|
||||||
|
val datePickerDialog = DatePickerDialog.newInstance(dateSetListener,
|
||||||
|
currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth)
|
||||||
|
|
||||||
|
with(datePickerDialog) {
|
||||||
|
setDateRangeLimiter(SchooldaysRangeLimiter())
|
||||||
|
version = DatePickerDialog.Version.VERSION_2
|
||||||
|
scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL
|
||||||
|
show(this@AttendanceFragment.parentFragmentManager, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun openSummaryView() {
|
override fun openSummaryView() {
|
||||||
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
|
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.attendance
|
package io.github.wulkanowy.ui.modules.attendance
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
@ -37,10 +38,13 @@ class AttendancePresenter @Inject constructor(
|
|||||||
lateinit var currentDate: LocalDate
|
lateinit var currentDate: LocalDate
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
fun onAttachView(view: AttendanceView, date: Long?) {
|
fun onAttachView(view: AttendanceView, date: Long?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
Timber.i("Attendance view was initialized")
|
Timber.i("Attendance view was initialized")
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||||
reloadView()
|
reloadView()
|
||||||
@ -56,11 +60,32 @@ class AttendancePresenter @Inject constructor(
|
|||||||
reloadView()
|
reloadView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onPickDate() {
|
||||||
|
view?.showDatePickerDialog(currentDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||||
|
loadData(LocalDate.of(year, month, day))
|
||||||
|
reloadView()
|
||||||
|
}
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
fun onSwipeRefresh() {
|
||||||
Timber.i("Force refreshing the attendance")
|
Timber.i("Force refreshing the attendance")
|
||||||
loadData(currentDate, true)
|
loadData(currentDate, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
loadData(currentDate, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onViewReselected() {
|
fun onViewReselected() {
|
||||||
Timber.i("Attendance view is reselected")
|
Timber.i("Attendance view is reselected")
|
||||||
view?.also { view ->
|
view?.also { view ->
|
||||||
@ -130,18 +155,29 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
updateData(it)
|
updateData(it)
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading attendance result: An exception occurred")
|
Timber.i("Loading attendance result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun reloadView() {
|
private fun reloadView() {
|
||||||
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
|
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
|
||||||
view?.apply {
|
view?.apply {
|
||||||
@ -149,16 +185,18 @@ class AttendancePresenter @Inject constructor(
|
|||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
|
showErrorView(false)
|
||||||
clearData()
|
clearData()
|
||||||
reloadNavigation()
|
reloadNavigation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
private fun reloadNavigation() {
|
private fun reloadNavigation() {
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize())
|
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.attendance
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
|
||||||
interface AttendanceView : BaseView {
|
interface AttendanceView : BaseView {
|
||||||
|
|
||||||
@ -23,6 +24,10 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
fun enableSwipe(enable: Boolean)
|
||||||
@ -35,6 +40,8 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun showAttendanceDialog(lesson: Attendance)
|
fun showAttendanceDialog(lesson: Attendance)
|
||||||
|
|
||||||
|
fun showDatePickerDialog(currentDate: LocalDate)
|
||||||
|
|
||||||
fun openSummaryView()
|
fun openSummaryView()
|
||||||
|
|
||||||
fun popView()
|
fun popView()
|
||||||
|
@ -57,6 +57,8 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
attendanceSummarySwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
attendanceSummarySwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||||
|
attendanceSummaryErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
attendanceSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
|
|
||||||
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
||||||
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
||||||
@ -80,7 +82,7 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
|
|||||||
override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) {
|
override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) {
|
||||||
with(attendanceSummaryAdapter) {
|
with(attendanceSummaryAdapter) {
|
||||||
updateDataSet(data, true)
|
updateDataSet(data, true)
|
||||||
removeAllScrollableFooters()
|
removeAllScrollableHeaders()
|
||||||
addScrollableHeader(header)
|
addScrollableHeader(header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,6 +95,14 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
|
|||||||
attendanceSummaryEmpty.visibility = if (show) VISIBLE else GONE
|
attendanceSummaryEmpty.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
attendanceSummaryError.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
attendanceSummaryErrorMessage.text = message
|
||||||
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
attendanceSummaryProgress.visibility = if (show) VISIBLE else GONE
|
attendanceSummaryProgress.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,13 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
var currentSubjectId = -1
|
var currentSubjectId = -1
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
fun onAttachView(view: AttendanceSummaryView, subjectId: Int?) {
|
fun onAttachView(view: AttendanceSummaryView, subjectId: Int?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
Timber.i("Attendance summary view was initialized with subject id ${subjectId ?: -1}")
|
Timber.i("Attendance summary view was initialized with subject id ${subjectId ?: -1}")
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
loadData(subjectId ?: -1)
|
loadData(subjectId ?: -1)
|
||||||
loadSubjects()
|
loadSubjects()
|
||||||
}
|
}
|
||||||
@ -46,12 +49,26 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
loadData(currentSubjectId, true)
|
loadData(currentSubjectId, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
loadData(currentSubjectId, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onSubjectSelected(name: String?) {
|
fun onSubjectSelected(name: String?) {
|
||||||
Timber.i("Select attendance summary subject $name")
|
Timber.i("Select attendance summary subject $name")
|
||||||
view?.run {
|
view?.run {
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
|
showEmpty(false)
|
||||||
|
showErrorView(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
(subjects.singleOrNull { it.name == name }?.realId ?: -1).let {
|
(subjects.singleOrNull { it.name == name }?.realId ?: -1).let {
|
||||||
@ -88,13 +105,23 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
analytics.logEvent("load_attendance_summary", "items" to it.first.size, "force_refresh" to forceRefresh, "item_id" to subjectId)
|
analytics.logEvent("load_attendance_summary", "items" to it.first.size, "force_refresh" to forceRefresh, "item_id" to subjectId)
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading attendance summary result: An exception occurred")
|
Timber.i("Loading attendance summary result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadSubjects() {
|
private fun loadSubjects() {
|
||||||
Timber.i("Loading attendance summary subjects started")
|
Timber.i("Loading attendance summary subjects started")
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
|
@ -18,6 +18,10 @@ interface AttendanceSummaryView : BaseView {
|
|||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader)
|
fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader)
|
||||||
|
|
||||||
fun updateSubjects(data: ArrayList<String>)
|
fun updateSubjects(data: ArrayList<String>)
|
||||||
|
@ -61,6 +61,9 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
|
|||||||
}
|
}
|
||||||
|
|
||||||
examSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
examSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||||
|
examErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
examErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
|
|
||||||
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
|
examPreviousButton.setOnClickListener { presenter.onPreviousWeek() }
|
||||||
examNextButton.setOnClickListener { presenter.onNextWeek() }
|
examNextButton.setOnClickListener { presenter.onNextWeek() }
|
||||||
|
|
||||||
@ -95,6 +98,14 @@ class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.
|
|||||||
examEmpty.visibility = if (show) VISIBLE else GONE
|
examEmpty.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
examError.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
examErrorMessage.text = message
|
||||||
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
examProgress.visibility = if (show) VISIBLE else GONE
|
examProgress.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,13 @@ class ExamPresenter @Inject constructor(
|
|||||||
lateinit var currentDate: LocalDate
|
lateinit var currentDate: LocalDate
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
fun onAttachView(view: ExamView, date: Long?) {
|
fun onAttachView(view: ExamView, date: Long?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
Timber.i("Exam view was initialized")
|
Timber.i("Exam view was initialized")
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||||
reloadView()
|
reloadView()
|
||||||
@ -60,6 +63,18 @@ class ExamPresenter @Inject constructor(
|
|||||||
loadData(currentDate, true)
|
loadData(currentDate, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
loadData(currentDate, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onExamItemSelected(item: AbstractFlexibleItem<*>?) {
|
fun onExamItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||||
if (item is ExamItem) {
|
if (item is ExamItem) {
|
||||||
Timber.i("Select exam item ${item.exam.id}")
|
Timber.i("Select exam item ${item.exam.id}")
|
||||||
@ -116,17 +131,28 @@ class ExamPresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
updateData(it)
|
updateData(it)
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_exam", "items" to it.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_exam", "items" to it.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading exam result: An exception occurred")
|
Timber.i("Loading exam result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createExamItems(items: Map<LocalDate, List<Exam>>): List<ExamItem> {
|
private fun createExamItems(items: Map<LocalDate, List<Exam>>): List<ExamItem> {
|
||||||
return items.flatMap {
|
return items.flatMap {
|
||||||
ExamHeader(it.key).let { header ->
|
ExamHeader(it.key).let { header ->
|
||||||
@ -142,6 +168,7 @@ class ExamPresenter @Inject constructor(
|
|||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
|
showErrorView(false)
|
||||||
clearData()
|
clearData()
|
||||||
reloadNavigation()
|
reloadNavigation()
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ interface ExamView : BaseView {
|
|||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
fun enableSwipe(enable: Boolean)
|
||||||
|
@ -13,6 +13,7 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||||
|
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||||
import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
|
import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
|
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
||||||
@ -83,7 +84,8 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
|
|||||||
setElevationCompat(context.dpToPx(4f))
|
setElevationCompat(context.dpToPx(4f))
|
||||||
}
|
}
|
||||||
|
|
||||||
gradeSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
gradeErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
gradeErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
@ -104,22 +106,18 @@ class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainVie
|
|||||||
gradeProgress.visibility = if (show) VISIBLE else INVISIBLE
|
gradeProgress.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
override fun showErrorView(show: Boolean) {
|
||||||
gradeEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
gradeError.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showRefresh(show: Boolean) {
|
override fun setErrorDetails(message: String) {
|
||||||
gradeSwipe.isRefreshing = show
|
gradeErrorMessage.text = message
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showSemesterSwitch(show: Boolean) {
|
override fun showSemesterSwitch(show: Boolean) {
|
||||||
semesterSwitchMenu?.isVisible = show
|
semesterSwitchMenu?.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableSwipe(enable: Boolean) {
|
|
||||||
gradeSwipe.isEnabled = enable
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showSemesterDialog(selectedIndex: Int) {
|
override fun showSemesterDialog(selectedIndex: Int) {
|
||||||
val choices = arrayOf(
|
val choices = arrayOf(
|
||||||
getString(R.string.grade_semester, 1),
|
getString(R.string.grade_semester, 1),
|
||||||
|
@ -11,13 +11,12 @@ import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
|
|||||||
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module
|
@Module(includes = [GradeModule.Static::class])
|
||||||
abstract class GradeModule {
|
abstract class GradeModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
companion object {
|
object Static {
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@Provides
|
@Provides
|
||||||
fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
||||||
|
@ -25,14 +25,14 @@ class GradePresenter @Inject constructor(
|
|||||||
|
|
||||||
private val loadedSemesterId = mutableMapOf<Int, Int>()
|
private val loadedSemesterId = mutableMapOf<Int, Int>()
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
fun onAttachView(view: GradeView, savedIndex: Int?) {
|
fun onAttachView(view: GradeView, savedIndex: Int?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
selectedIndex = savedIndex ?: 0
|
selectedIndex = savedIndex ?: 0
|
||||||
view.run {
|
view.initView()
|
||||||
initView()
|
|
||||||
enableSwipe(false)
|
|
||||||
}
|
|
||||||
Timber.i("Grade view was initialized with $selectedIndex index")
|
Timber.i("Grade view was initialized with $selectedIndex index")
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class GradePresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
showContent(true)
|
showContent(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showEmpty(false)
|
showErrorView(false)
|
||||||
loadedSemesterId[currentPageIndex] = semesterId
|
loadedSemesterId[currentPageIndex] = semesterId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,10 +80,18 @@ class GradePresenter @Inject constructor(
|
|||||||
if (semesters.isNotEmpty()) loadChild(index)
|
if (semesters.isNotEmpty()) loadChild(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
Timber.i("Loading grade data started")
|
Timber.i("Loading grade data started")
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
@ -96,25 +104,28 @@ class GradePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
.observeOn(schedulers.mainThread)
|
.observeOn(schedulers.mainThread)
|
||||||
.doFinally { view?.showRefresh(false) }
|
.doFinally { view?.showProgress(false) }
|
||||||
.subscribe({
|
.subscribe({
|
||||||
view?.run {
|
view?.run {
|
||||||
Timber.i("Loading grade result: Attempt load index $currentPageIndex")
|
Timber.i("Loading grade result: Attempt load index $currentPageIndex")
|
||||||
loadChild(currentPageIndex)
|
loadChild(currentPageIndex)
|
||||||
enableSwipe(false)
|
showErrorView(false)
|
||||||
showSemesterSwitch(true)
|
showSemesterSwitch(true)
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading grade result: An exception occurred")
|
Timber.i("Loading grade result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
view?.run {
|
|
||||||
showProgress(false)
|
|
||||||
showEmpty(true)
|
|
||||||
enableSwipe(true)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
lastError = error
|
||||||
|
view?.run {
|
||||||
|
showErrorView(true)
|
||||||
|
setErrorDetails(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadChild(index: Int, forceRefresh: Boolean = false) {
|
private fun loadChild(index: Int, forceRefresh: Boolean = false) {
|
||||||
semesters.first { it.semesterName == selectedIndex }.semesterId.also {
|
semesters.first { it.semesterName == selectedIndex }.semesterId.also {
|
||||||
if (forceRefresh || loadedSemesterId[index] != it) {
|
if (forceRefresh || loadedSemesterId[index] != it) {
|
||||||
|
@ -12,16 +12,14 @@ interface GradeView : BaseView {
|
|||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
fun showRefresh(show: Boolean)
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun showSemesterSwitch(show: Boolean)
|
fun showSemesterSwitch(show: Boolean)
|
||||||
|
|
||||||
fun showSemesterDialog(selectedIndex: Int)
|
fun showSemesterDialog(selectedIndex: Int)
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
|
||||||
|
|
||||||
fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean)
|
fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean)
|
||||||
|
|
||||||
fun notifyChildParentReselected(index: Int)
|
fun notifyChildParentReselected(index: Int)
|
||||||
|
@ -18,6 +18,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
|||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.ui.base.ErrorDialog
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
@ -33,6 +34,8 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var gradeDetailsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
lateinit var gradeDetailsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
|
private var gradeDetailsMenu: Menu? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = GradeDetailsFragment()
|
fun newInstance() = GradeDetailsFragment()
|
||||||
}
|
}
|
||||||
@ -69,6 +72,8 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
|||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.action_menu_grade_details, menu)
|
inflater.inflate(R.menu.action_menu_grade_details, menu)
|
||||||
|
gradeDetailsMenu = menu
|
||||||
|
presenter.updateMarkAsDoneButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
@ -86,6 +91,8 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||||
|
gradeDetailsErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
gradeDetailsErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
@ -137,6 +144,14 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
|||||||
gradeDetailsEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
gradeDetailsEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
gradeDetailsError.visibility = if (show) VISIBLE else GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
gradeDetailsErrorMessage.text = message
|
||||||
|
}
|
||||||
|
|
||||||
override fun showRefresh(show: Boolean) {
|
override fun showRefresh(show: Boolean) {
|
||||||
gradeDetailsSwipe.isRefreshing = show
|
gradeDetailsSwipe.isRefreshing = show
|
||||||
}
|
}
|
||||||
@ -165,6 +180,10 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
|||||||
(parentFragment as? GradeFragment)?.onChildRefresh()
|
(parentFragment as? GradeFragment)?.onChildRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun enableMarkAsDoneButton(enable: Boolean) {
|
||||||
|
gradeDetailsMenu?.findItem(R.id.gradeDetailsMenuRead)?.isEnabled = enable
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
|
@ -26,11 +26,16 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
private val analytics: FirebaseAnalyticsHelper
|
private val analytics: FirebaseAnalyticsHelper
|
||||||
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository, schedulers) {
|
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository, schedulers) {
|
||||||
|
|
||||||
|
private var newGradesAmount: Int = 0
|
||||||
|
|
||||||
private var currentSemesterId = 0
|
private var currentSemesterId = 0
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
override fun onAttachView(view: GradeDetailsView) {
|
override fun onAttachView(view: GradeDetailsView) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
@ -52,6 +57,8 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
updateItem(header)
|
updateItem(header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newGradesAmount--
|
||||||
|
updateMarkAsDoneButton()
|
||||||
updateGrade(item.grade)
|
updateGrade(item.grade)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,6 +92,18 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
view?.notifyParentRefresh()
|
view?.notifyParentRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
view?.notifyParentRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onParentViewReselected() {
|
fun onParentViewReselected() {
|
||||||
view?.run {
|
view?.run {
|
||||||
if (!isViewEmpty) {
|
if (!isViewEmpty) {
|
||||||
@ -106,6 +125,10 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateMarkAsDoneButton() {
|
||||||
|
view?.enableMarkAsDoneButton(newGradesAmount > 0)
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
Timber.i("Loading grade details data started")
|
Timber.i("Loading grade details data started")
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
@ -131,19 +154,32 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
.subscribe({
|
.subscribe({
|
||||||
Timber.i("Loading grade details result: Success")
|
Timber.i("Loading grade details result: Success")
|
||||||
|
newGradesAmount = it.sumBy { gradeDetailsHeader -> gradeDetailsHeader.newGrades }
|
||||||
|
updateMarkAsDoneButton()
|
||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
updateData(it)
|
updateData(it)
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_grade_details", "items" to it.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_grade_details", "items" to it.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading grade details result: An exception occurred")
|
Timber.i("Loading grade details result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createGradeItems(items: Map<String, List<Grade>>, averages: Map<String, Double>): List<GradeDetailsHeader> {
|
private fun createGradeItems(items: Map<String, List<Grade>>, averages: Map<String, Double>): List<GradeDetailsHeader> {
|
||||||
val isGradeExpandable = preferencesRepository.isGradeExpandable
|
val isGradeExpandable = preferencesRepository.isGradeExpandable
|
||||||
val gradeColorTheme = preferencesRepository.gradeColorTheme
|
val gradeColorTheme = preferencesRepository.gradeColorTheme
|
||||||
|
@ -38,6 +38,10 @@ interface GradeDetailsView : BaseView {
|
|||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
fun enableSwipe(enable: Boolean)
|
||||||
|
|
||||||
fun showRefresh(show: Boolean)
|
fun showRefresh(show: Boolean)
|
||||||
@ -46,6 +50,8 @@ interface GradeDetailsView : BaseView {
|
|||||||
|
|
||||||
fun notifyParentRefresh()
|
fun notifyParentRefresh()
|
||||||
|
|
||||||
|
fun enableMarkAsDoneButton(enable: Boolean)
|
||||||
|
|
||||||
fun getGradeNumberString(number: Int): String
|
fun getGradeNumberString(number: Int): String
|
||||||
|
|
||||||
fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>?
|
fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>?
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
import android.graphics.Color.WHITE
|
import android.graphics.Color.WHITE
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -10,11 +11,15 @@ import android.widget.TextView
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.github.mikephil.charting.components.Legend
|
import com.github.mikephil.charting.components.Legend
|
||||||
import com.github.mikephil.charting.components.LegendEntry
|
import com.github.mikephil.charting.components.LegendEntry
|
||||||
|
import com.github.mikephil.charting.data.BarData
|
||||||
|
import com.github.mikephil.charting.data.BarDataSet
|
||||||
|
import com.github.mikephil.charting.data.BarEntry
|
||||||
import com.github.mikephil.charting.data.PieData
|
import com.github.mikephil.charting.data.PieData
|
||||||
import com.github.mikephil.charting.data.PieDataSet
|
import com.github.mikephil.charting.data.PieDataSet
|
||||||
import com.github.mikephil.charting.data.PieEntry
|
import com.github.mikephil.charting.data.PieEntry
|
||||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
import com.github.mikephil.charting.formatter.ValueFormatter
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||||
@ -38,7 +43,9 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
fun newInstance() = GradeStatisticsFragment()
|
fun newInstance() = GradeStatisticsFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isViewEmpty get() = gradeStatisticsChart.isEmpty
|
override val isPieViewEmpty get() = gradeStatisticsChart.isEmpty
|
||||||
|
|
||||||
|
override val isBarViewEmpty get() = gradeStatisticsChartPoints.isEmpty
|
||||||
|
|
||||||
private lateinit var gradeColors: List<Pair<Int, Int>>
|
private lateinit var gradeColors: List<Pair<Int, Int>>
|
||||||
|
|
||||||
@ -60,6 +67,11 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
1 to R.color.grade_material_one
|
1 to R.color.grade_material_one
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val gradePointsColors = listOf(
|
||||||
|
Color.parseColor("#37c69c"),
|
||||||
|
Color.parseColor("#d8b12a")
|
||||||
|
)
|
||||||
|
|
||||||
private val gradeLabels = listOf(
|
private val gradeLabels = listOf(
|
||||||
"6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+"
|
"6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+"
|
||||||
)
|
)
|
||||||
@ -70,8 +82,8 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
messageContainer = gradeStatisticsChart
|
messageContainer = gradeStatisticsSwipe
|
||||||
presenter.onAttachView(this, savedInstanceState?.getBoolean(SAVED_CHART_TYPE))
|
presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? ViewType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
@ -84,6 +96,13 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(gradeStatisticsChartPoints) {
|
||||||
|
description.isEnabled = false
|
||||||
|
|
||||||
|
animateXY(1000, 1000)
|
||||||
|
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||||
|
}
|
||||||
|
|
||||||
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
||||||
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
||||||
|
|
||||||
@ -92,9 +111,11 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
setOnItemSelectedListener<TextView> { presenter.onSubjectSelected(it?.text?.toString()) }
|
setOnItemSelectedListener<TextView> { presenter.onSubjectSelected(it?.text?.toString()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
|
||||||
|
|
||||||
gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
|
gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f))
|
||||||
|
|
||||||
|
gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||||
|
gradeStatisticsErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
gradeStatisticsErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateSubjects(data: ArrayList<String>) {
|
override fun updateSubjects(data: ArrayList<String>) {
|
||||||
@ -105,14 +126,13 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(items: List<GradeStatistics>, theme: String) {
|
override fun updatePieData(items: List<GradeStatistics>, theme: String) {
|
||||||
gradeColors = when (theme) {
|
gradeColors = when (theme) {
|
||||||
"vulcan" -> vulcanGradeColors
|
"vulcan" -> vulcanGradeColors
|
||||||
else -> materialGradeColors
|
else -> materialGradeColors
|
||||||
}
|
}
|
||||||
|
|
||||||
gradeStatisticsChart.run {
|
val dataset = PieDataSet(items.map {
|
||||||
data = PieData(PieDataSet(items.map {
|
|
||||||
PieEntry(it.amount.toFloat(), it.grade.toString())
|
PieEntry(it.amount.toFloat(), it.grade.toString())
|
||||||
}, "Legenda").apply {
|
}, "Legenda").apply {
|
||||||
valueTextSize = 12f
|
valueTextSize = 12f
|
||||||
@ -121,7 +141,10 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
setColors(items.map {
|
setColors(items.map {
|
||||||
gradeColors.single { color -> color.first == it.grade }.second
|
gradeColors.single { color -> color.first == it.grade }.second
|
||||||
}.toIntArray(), context)
|
}.toIntArray(), context)
|
||||||
}).apply {
|
}
|
||||||
|
|
||||||
|
with(gradeStatisticsChart) {
|
||||||
|
data = PieData(dataset).apply {
|
||||||
setTouchEnabled(false)
|
setTouchEnabled(false)
|
||||||
setValueFormatter(object : ValueFormatter() {
|
setValueFormatter(object : ValueFormatter() {
|
||||||
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
|
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
|
||||||
@ -144,6 +167,47 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateBarData(item: GradePointsStatistics) {
|
||||||
|
val dataset = BarDataSet(listOf(
|
||||||
|
BarEntry(1f, item.others.toFloat()),
|
||||||
|
BarEntry(2f, item.student.toFloat())
|
||||||
|
), "Legenda").apply {
|
||||||
|
valueTextSize = 12f
|
||||||
|
valueTextColor = requireContext().getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||||
|
valueFormatter = object : ValueFormatter() {
|
||||||
|
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%"
|
||||||
|
}
|
||||||
|
colors = gradePointsColors
|
||||||
|
}
|
||||||
|
|
||||||
|
with(gradeStatisticsChartPoints) {
|
||||||
|
data = BarData(dataset).apply {
|
||||||
|
barWidth = 0.5f
|
||||||
|
setFitBars(true)
|
||||||
|
}
|
||||||
|
setTouchEnabled(false)
|
||||||
|
xAxis.setDrawLabels(false)
|
||||||
|
xAxis.setDrawGridLines(false)
|
||||||
|
requireContext().getThemeAttrColor(android.R.attr.textColorPrimary).let {
|
||||||
|
axisLeft.textColor = it
|
||||||
|
axisRight.textColor = it
|
||||||
|
}
|
||||||
|
legend.setCustom(listOf(
|
||||||
|
LegendEntry().apply {
|
||||||
|
label = "Średnia klasy"
|
||||||
|
formColor = gradePointsColors[0]
|
||||||
|
form = Legend.LegendForm.SQUARE
|
||||||
|
},
|
||||||
|
LegendEntry().apply {
|
||||||
|
label = "Uczeń"
|
||||||
|
formColor = gradePointsColors[1]
|
||||||
|
form = Legend.LegendForm.SQUARE
|
||||||
|
}
|
||||||
|
))
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun showSubjects(show: Boolean) {
|
override fun showSubjects(show: Boolean) {
|
||||||
gradeStatisticsSubjectsContainer.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsSubjectsContainer.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
gradeStatisticsTypeSwitch.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsTypeSwitch.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
@ -151,16 +215,29 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
|
|
||||||
override fun clearView() {
|
override fun clearView() {
|
||||||
gradeStatisticsChart.clear()
|
gradeStatisticsChart.clear()
|
||||||
|
gradeStatisticsChartPoints.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
override fun showPieContent(show: Boolean) {
|
||||||
gradeStatisticsChart.visibility = if (show) View.VISIBLE else View.GONE
|
gradeStatisticsChart.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showBarContent(show: Boolean) {
|
||||||
|
gradeStatisticsChartPoints.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
override fun showEmpty(show: Boolean) {
|
||||||
gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
gradeStatisticsError.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
gradeStatisticsErrorMessage.text = message
|
||||||
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
gradeStatisticsProgress.visibility = if (show) View.VISIBLE else View.GONE
|
gradeStatisticsProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
@ -196,13 +273,17 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
|
gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
|
||||||
presenter.onTypeChange(checkedId == R.id.gradeStatisticsTypeSemester)
|
presenter.onTypeChange(when (checkedId) {
|
||||||
|
R.id.gradeStatisticsTypeSemester -> ViewType.SEMESTER
|
||||||
|
R.id.gradeStatisticsTypePartial -> ViewType.PARTIAL
|
||||||
|
else -> ViewType.POINTS
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putBoolean(SAVED_CHART_TYPE, presenter.currentIsSemester)
|
outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -30,19 +30,22 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
|
|
||||||
private var currentSubjectName: String = "Wszystkie"
|
private var currentSubjectName: String = "Wszystkie"
|
||||||
|
|
||||||
var currentIsSemester = false
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
|
var currentType: ViewType = ViewType.PARTIAL
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun onAttachView(view: GradeStatisticsView, isSemester: Boolean?) {
|
fun onAttachView(view: GradeStatisticsView, type: ViewType?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
currentIsSemester = isSemester ?: false
|
currentType = type ?: ViewType.PARTIAL
|
||||||
view.initView()
|
view.initView()
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
currentSemesterId = semesterId
|
currentSemesterId = semesterId
|
||||||
loadSubjects()
|
loadSubjects()
|
||||||
loadData(semesterId, currentSubjectName, currentIsSemester, forceRefresh)
|
loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewChangeSemester() {
|
fun onParentViewChangeSemester() {
|
||||||
@ -50,7 +53,8 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showRefresh(false)
|
showRefresh(false)
|
||||||
showContent(false)
|
showBarContent(false)
|
||||||
|
showErrorView(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
@ -62,31 +66,47 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
view?.notifyParentRefresh()
|
view?.notifyParentRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
view?.notifyParentRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onSubjectSelected(name: String?) {
|
fun onSubjectSelected(name: String?) {
|
||||||
Timber.i("Select grade stats subject $name")
|
Timber.i("Select grade stats subject $name")
|
||||||
view?.run {
|
view?.run {
|
||||||
showContent(false)
|
showBarContent(false)
|
||||||
|
showPieContent(false)
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
|
showErrorView(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
(subjects.singleOrNull { it.name == name }?.name)?.let {
|
(subjects.singleOrNull { it.name == name }?.name)?.let {
|
||||||
if (it != currentSubjectName) loadData(currentSemesterId, it, currentIsSemester)
|
if (it != currentSubjectName) loadDataByType(currentSemesterId, it, currentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTypeChange(isSemester: Boolean) {
|
fun onTypeChange(type: ViewType) {
|
||||||
Timber.i("Select grade stats semester: $isSemester")
|
Timber.i("Select grade stats semester: $type")
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
view?.run {
|
view?.run {
|
||||||
showContent(false)
|
showBarContent(false)
|
||||||
|
showPieContent(false)
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
|
showErrorView(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
loadData(currentSemesterId, currentSubjectName, isSemester)
|
loadDataByType(currentSemesterId, currentSubjectName, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSubjects() {
|
private fun loadSubjects() {
|
||||||
@ -111,10 +131,18 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
||||||
|
currentSubjectName = subjectName
|
||||||
|
currentType = type
|
||||||
|
when (type) {
|
||||||
|
ViewType.SEMESTER -> loadData(semesterId, subjectName, true, forceRefresh)
|
||||||
|
ViewType.PARTIAL -> loadData(semesterId, subjectName, false, forceRefresh)
|
||||||
|
ViewType.POINTS -> loadPointsData(semesterId, subjectName, forceRefresh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadData(semesterId: Int, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false) {
|
private fun loadData(semesterId: Int, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading grade stats data started")
|
Timber.i("Loading grade stats data started")
|
||||||
currentSubjectName = subjectName
|
|
||||||
currentIsSemester = isSemester
|
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
.flatMap { semesterRepository.getSemesters(it) }
|
.flatMap { semesterRepository.getSemesters(it) }
|
||||||
.flatMap { gradeStatisticsRepository.getGradesStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, isSemester, forceRefresh) }
|
.flatMap { gradeStatisticsRepository.getGradesStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, isSemester, forceRefresh) }
|
||||||
@ -134,14 +162,64 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
Timber.i("Loading grade stats result: Success")
|
Timber.i("Loading grade stats result: Success")
|
||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
showContent(it.isNotEmpty())
|
showBarContent(false)
|
||||||
updateData(it, preferencesRepository.gradeColorTheme)
|
showPieContent(it.isNotEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
updatePieData(it, preferencesRepository.gradeColorTheme)
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_grade_statistics", "items" to it.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_grade_statistics", "items" to it.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.e("Loading grade stats result: An exception occurred")
|
Timber.e("Loading grade stats result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadPointsData(semesterId: Int, subjectName: String, forceRefresh: Boolean = false) {
|
||||||
|
Timber.i("Loading grade points stats data started")
|
||||||
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
|
.flatMap { semesterRepository.getSemesters(it) }
|
||||||
|
.flatMapMaybe { gradeStatisticsRepository.getGradesPointsStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, forceRefresh) }
|
||||||
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.observeOn(schedulers.mainThread)
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
enableSwipe(true)
|
||||||
|
notifyParentDataLoaded(semesterId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribe({
|
||||||
|
Timber.i("Loading grade points stats result: Success")
|
||||||
|
view?.run {
|
||||||
|
showEmpty(false)
|
||||||
|
showPieContent(false)
|
||||||
|
showBarContent(true)
|
||||||
|
showErrorView(false)
|
||||||
|
updateBarData(it)
|
||||||
|
}
|
||||||
|
analytics.logEvent("load_grade_points_statistics", "force_refresh" to forceRefresh)
|
||||||
|
}, {
|
||||||
|
Timber.e("Loading grade points stats result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it)
|
||||||
|
}, {
|
||||||
|
Timber.d("Loading grade points stats result: No point stats found")
|
||||||
|
view?.run {
|
||||||
|
showBarContent(false)
|
||||||
|
showEmpty(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isBarViewEmpty || isPieViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
interface GradeStatisticsView : BaseView {
|
interface GradeStatisticsView : BaseView {
|
||||||
|
|
||||||
val isViewEmpty: Boolean
|
val isPieViewEmpty: Boolean
|
||||||
|
|
||||||
|
val isBarViewEmpty: Boolean
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateSubjects(data: ArrayList<String>)
|
fun updateSubjects(data: ArrayList<String>)
|
||||||
|
|
||||||
fun updateData(items: List<GradeStatistics>, theme: String)
|
fun updatePieData(items: List<GradeStatistics>, theme: String)
|
||||||
|
|
||||||
|
fun updateBarData(item: GradePointsStatistics)
|
||||||
|
|
||||||
fun showSubjects(show: Boolean)
|
fun showSubjects(show: Boolean)
|
||||||
|
|
||||||
@ -21,10 +26,16 @@ interface GradeStatisticsView : BaseView {
|
|||||||
|
|
||||||
fun clearView()
|
fun clearView()
|
||||||
|
|
||||||
fun showContent(show: Boolean)
|
fun showPieContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showBarContent(show: Boolean)
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
fun enableSwipe(enable: Boolean)
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
|
enum class ViewType {
|
||||||
|
SEMESTER,
|
||||||
|
PARTIAL,
|
||||||
|
POINTS
|
||||||
|
}
|
@ -56,6 +56,8 @@ class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeCh
|
|||||||
adapter = gradeSummaryAdapter
|
adapter = gradeSummaryAdapter
|
||||||
}
|
}
|
||||||
gradeSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
gradeSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||||
|
gradeSummaryErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
|
gradeSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<GradeSummaryItem>, header: GradeSummaryScrollableHeader) {
|
override fun updateData(data: List<GradeSummaryItem>, header: GradeSummaryScrollableHeader) {
|
||||||
@ -82,6 +84,14 @@ class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeCh
|
|||||||
gradeSummaryEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
gradeSummaryEmpty.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showErrorView(show: Boolean) {
|
||||||
|
gradeSummaryError.visibility = if (show) VISIBLE else INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorDetails(message: String) {
|
||||||
|
gradeSummaryErrorMessage.text = message
|
||||||
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
gradeSummaryProgress.visibility = if (show) VISIBLE else GONE
|
gradeSummaryProgress.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,12 @@ class GradeSummaryPresenter @Inject constructor(
|
|||||||
private val analytics: FirebaseAnalyticsHelper
|
private val analytics: FirebaseAnalyticsHelper
|
||||||
) : BasePresenter<GradeSummaryView>(errorHandler, studentRepository, schedulers) {
|
) : BasePresenter<GradeSummaryView>(errorHandler, studentRepository, schedulers) {
|
||||||
|
|
||||||
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
override fun onAttachView(view: GradeSummaryView) {
|
override fun onAttachView(view: GradeSummaryView) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
@ -56,21 +59,44 @@ class GradeSummaryPresenter @Inject constructor(
|
|||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(gradeSummaryItems.isEmpty())
|
showEmpty(gradeSummaryItems.isEmpty())
|
||||||
showContent(gradeSummaryItems.isNotEmpty())
|
showContent(gradeSummaryItems.isNotEmpty())
|
||||||
|
showErrorView(false)
|
||||||
updateData(gradeSummaryItems, gradeSummaryHeader)
|
updateData(gradeSummaryItems, gradeSummaryHeader)
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_grade_summary", "items" to gradeSummaryItems.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_grade_summary", "items" to gradeSummaryItems.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.i("Loading grade summary result: An exception occurred")
|
Timber.i("Loading grade summary result: An exception occurred")
|
||||||
view?.run { showEmpty(isViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
view?.run {
|
||||||
|
if (isViewEmpty) {
|
||||||
|
lastError = error
|
||||||
|
setErrorDetails(message)
|
||||||
|
showErrorView(true)
|
||||||
|
showEmpty(false)
|
||||||
|
} else showError(message, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
fun onSwipeRefresh() {
|
||||||
Timber.i("Force refreshing the grade summary")
|
Timber.i("Force refreshing the grade summary")
|
||||||
view?.notifyParentRefresh()
|
view?.notifyParentRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRetry() {
|
||||||
|
view?.run {
|
||||||
|
showErrorView(false)
|
||||||
|
showProgress(true)
|
||||||
|
}
|
||||||
|
view?.notifyParentRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDetailsClick() {
|
||||||
|
view?.showErrorDetailsDialog(lastError)
|
||||||
|
}
|
||||||
|
|
||||||
fun onParentViewReselected() {
|
fun onParentViewReselected() {
|
||||||
view?.run {
|
view?.run {
|
||||||
if (!isViewEmpty) resetView()
|
if (!isViewEmpty) resetView()
|
||||||
|
@ -26,6 +26,10 @@ interface GradeSummaryView : BaseView {
|
|||||||
|
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
|
fun setErrorDetails(message: String)
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
fun notifyParentDataLoaded(semesterId: Int)
|
fun notifyParentDataLoaded(semesterId: Int)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user