Compare commits
136 Commits
Author | SHA1 | Date | |
---|---|---|---|
26267507eb | |||
24d0c5057b | |||
b05026a6e6 | |||
8036f3d7f7 | |||
23e309d38e | |||
bf92c6b2e9 | |||
c00b5edaf7 | |||
cb09ca13dc | |||
3d68b8e629 | |||
b3173581e5 | |||
ddac1d0f98 | |||
db6a359bea | |||
e7221e6a32 | |||
db9c2640c7 | |||
ca67e144e4 | |||
da2346ed83 | |||
a87818f3d0 | |||
5092f8c0bf | |||
af0787c0b1 | |||
721b4ac797 | |||
26a69092cc | |||
2bd0c75055 | |||
d6f3c57293 | |||
518387e7bb | |||
ca6dfbf2d0 | |||
da6d8a74fd | |||
e35e4ef152 | |||
40fc6ec2e0 | |||
b91973aec3 | |||
047e70ad46 | |||
112c1eb793 | |||
c479b31670 | |||
43ed8c8fce | |||
613fa44c27 | |||
f21216286d | |||
7298d0d75a | |||
ee0fbcdfd6 | |||
c362ad12c7 | |||
8a1a712d6d | |||
1f0f6b3e51 | |||
11487e77ca | |||
fd0fd4df55 | |||
d95a33787b | |||
e5661098d9 | |||
d020b01794 | |||
d8b1264024 | |||
cddd17650b | |||
a0f9c70036 | |||
2e05416fb5 | |||
d32ebd66de | |||
c6a99f1000 | |||
bafe52e310 | |||
e08abc1fc2 | |||
2a74b11cce | |||
b0b3ccfd53 | |||
6c68456f7a | |||
3e8e9b4ecc | |||
d6ebc343d5 | |||
73be416807 | |||
0cb65a29ba | |||
13198f2ab4 | |||
cd92f37435 | |||
5d8fb376ab | |||
47150364d8 | |||
792b123598 | |||
acf5c8e9ba | |||
53561668fc | |||
7cfe58d311 | |||
cd51fac621 | |||
adde5541e2 | |||
6e56d3ff06 | |||
ec761f6329 | |||
6363c90e37 | |||
c30f105be5 | |||
9f85b2206a | |||
42515fd084 | |||
9a7c04fe7b | |||
debb21f5f9 | |||
18b9bf42e1 | |||
6ded83d132 | |||
71d37a1c6c | |||
3975d06cde | |||
ee168bafe0 | |||
42ed7e0ae1 | |||
0e92447974 | |||
40492e6c01 | |||
69a1193154 | |||
0f65af8958 | |||
2ad1d086e0 | |||
f8b7baef24 | |||
90be9d1add | |||
20f931c5cc | |||
9997b1adbb | |||
eb616eedc7 | |||
a5de39a366 | |||
57bc2b2533 | |||
d1ce16d2b1 | |||
54fb01cd0d | |||
370cfbf22a | |||
d198a2ba21 | |||
580ad58dd6 | |||
b5f7c5f318 | |||
7e2de594a4 | |||
36984e08b5 | |||
f8031e1eca | |||
5bc49b2e74 | |||
ba81b4b465 | |||
5cc31a7c5e | |||
de70719d38 | |||
9f315b3af1 | |||
d5187d1808 | |||
ca7d977342 | |||
062985c5a0 | |||
8922d7d48d | |||
3ba16f2903 | |||
6a1a347579 | |||
6c4f27aff5 | |||
f6dce0fbda | |||
1ac42bb56d | |||
b0a674b471 | |||
1c1a90c12f | |||
d4ee1f8b98 | |||
152382a0c9 | |||
776972514a | |||
e072bf9fe3 | |||
927415f9a3 | |||
76b2ab1f25 | |||
c9a0bbda01 | |||
cbabe44461 | |||
5c313f986c | |||
f2682c6d30 | |||
3571f8bd04 | |||
dfcd5fc4d0 | |||
b8ea0ab0f9 | |||
4434d6f024 | |||
8cee882c08 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -113,3 +113,6 @@ Thumbs.db
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
.idea/jarRepositories.xml
|
||||
|
||||
|
||||
app/src/release/agconnect-services.json
|
||||
|
11
.idea/codeStyles/Project.xml
generated
11
.idea/codeStyles/Project.xml
generated
@ -4,7 +4,16 @@
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||
|
30
.travis.yml
30
.travis.yml
@ -3,8 +3,8 @@ jdk: oraclejdk8
|
||||
|
||||
env:
|
||||
global:
|
||||
- ANDROID_API_LEVEL=29
|
||||
- ANDROID_BUILD_TOOLS_VERSION=29.0.3
|
||||
- ANDROID_API_LEVEL=30
|
||||
- ANDROID_BUILD_TOOLS_VERSION=30.0.2
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@ -14,7 +14,7 @@ cache:
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 0.19.0
|
||||
- 0.22.1
|
||||
|
||||
android:
|
||||
licenses:
|
||||
@ -28,28 +28,32 @@ android:
|
||||
- build-tools-$ANDROID_BUILD_TOOLS_VERSION
|
||||
# The SDK version used to compile your project
|
||||
- android-$ANDROID_API_LEVEL
|
||||
# Additional components
|
||||
# Additional components
|
||||
- extra-google-google_play_services
|
||||
- extra-google-m2repository
|
||||
- extra-android-m2repository
|
||||
- addon-google_apis-google-$ANDROID_API_LEVEL
|
||||
# Android emulator
|
||||
# Android emulator
|
||||
- android-22
|
||||
- sys-img-armeabi-v7a-android-22
|
||||
|
||||
before_install:
|
||||
- yes | sdkmanager "platforms;android-30"
|
||||
- yes | sdkmanager "build-tools;30.0.2"
|
||||
|
||||
before_script:
|
||||
# Launch emulator before the execution
|
||||
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
|
||||
- emulator -avd test -no-audio -no-window &
|
||||
- android-wait-for-emulator
|
||||
- adb shell input keyevent 82 &
|
||||
- "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
|
||||
# Launch emulator before the execution
|
||||
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
|
||||
- emulator -avd test -no-audio -no-window &
|
||||
- android-wait-for-emulator
|
||||
- adb shell input keyevent 82 &
|
||||
- "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
|
||||
|
||||
script:
|
||||
- ./gradlew dependencies --stacktrace --daemon
|
||||
- fossa --no-ansi || true
|
||||
- ./gradlew -Pcoverage testPlayDebugUnitTest --stacktrace --daemon
|
||||
- ./gradlew -Pcoverage createFdroidDebugCoverageReport --stacktrace --daemon
|
||||
- ./gradlew -Pcoverage testFdroidDebugUnitTest --stacktrace --daemon
|
||||
- ./gradlew -Pcoverage connectedFdroidDebugAndroidTest --stacktrace --daemon
|
||||
- ./gradlew -Pcoverage jacocoTestReport --stacktrace --daemon
|
||||
- |
|
||||
if [ $TRAVIS_TAG ]; then
|
||||
|
10
README.en.md
10
README.en.md
@ -32,14 +32,17 @@ Unofficial android VULCAN UONET+ register client for both students and their par
|
||||
|
||||
## Download
|
||||
|
||||
You can download the current beta version from the Google Play or the F-Droid store
|
||||
You can download the current beta version from the Google Play, F-Droid or Huawei AppGallery store
|
||||
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
||||
alt="Get it on Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
||||
alt="Get it on Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
[<img src="appgallery_badge.png"
|
||||
alt="Explore it on AppGallery"
|
||||
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
||||
|
||||
You can also download a [development version](https://wulkanowy.github.io/#download) that includes new features being prepared for the next release
|
||||
|
||||
@ -47,7 +50,6 @@ You can also download a [development version](https://wulkanowy.github.io/#downl
|
||||
|
||||
|
||||
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
|
||||
* [RxJava 2](https://github.com/ReactiveX/RxJava)
|
||||
* [Dagger 2](https://github.com/google/dagger)
|
||||
* [Room](https://developer.android.com/topic/libraries/architecture/room)
|
||||
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
|
||||
|
10
README.md
10
README.md
@ -32,14 +32,17 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||
|
||||
## Pobierz
|
||||
|
||||
Aktualną wersję beta możesz pobrać ze sklepu Google Play lub F-Droid
|
||||
Aktualną wersję beta możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery
|
||||
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
||||
alt="Pobierz z Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
||||
alt="Pobierz z Google Play"
|
||||
height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Pobierz z F-Droid"
|
||||
height="80">](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
[<img src="appgallery_badge.png"
|
||||
alt="Odkrywaj w AppGallery"
|
||||
height="80">](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
|
||||
|
||||
|
||||
Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#download), która zawiera nowe funkcje przygotowywane do następnego wydania
|
||||
@ -48,7 +51,6 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa
|
||||
## Zbudowana za pomocą
|
||||
|
||||
* [Wulkanowy SDK](https://github.com/wulkanowy/SDK)
|
||||
* [RxJava 2](https://github.com/ReactiveX/RxJava)
|
||||
* [Dagger 2](https://github.com/google/dagger)
|
||||
* [Room](https://developer.android.com/topic/libraries/architecture/room)
|
||||
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
|
||||
|
107
app/build.gradle
107
app/build.gradle
@ -1,6 +1,7 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'dagger.hilt.android.plugin'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
|
||||
@ -9,16 +10,16 @@ apply from: 'sonarqube.gradle'
|
||||
apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.2'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 29
|
||||
versionCode 63
|
||||
versionName "0.19.0"
|
||||
targetSdkVersion 30
|
||||
versionCode 74
|
||||
versionName "0.22.1"
|
||||
multiDexEnabled true
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
@ -28,7 +29,7 @@ android {
|
||||
]
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [
|
||||
arguments += [
|
||||
"room.schemaLocation": "$projectDir/schemas".toString(),
|
||||
"room.incremental" : "true"
|
||||
]
|
||||
@ -68,12 +69,26 @@ android {
|
||||
flavorDimensions "platform"
|
||||
|
||||
productFlavors {
|
||||
hms {
|
||||
dimension "platform"
|
||||
minSdkVersion 19
|
||||
manifestPlaceholders = [
|
||||
install_channel: "AppGallery"
|
||||
]
|
||||
}
|
||||
|
||||
play {
|
||||
dimension "platform"
|
||||
manifestPlaceholders = [
|
||||
install_channel: "Google Play"
|
||||
]
|
||||
}
|
||||
|
||||
fdroid {
|
||||
dimension "platform"
|
||||
manifestPlaceholders = [
|
||||
install_channel: "F-Droid"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,12 +101,14 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"]
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
@ -109,14 +126,15 @@ play {
|
||||
serviceAccountCredentials = file('key.p12')
|
||||
defaultToAppBundles = false
|
||||
track = 'alpha'
|
||||
updatePriority = 1
|
||||
}
|
||||
|
||||
ext {
|
||||
work_manager = "2.3.4"
|
||||
work_manager = "2.4.0"
|
||||
room = "2.2.5"
|
||||
dagger = "2.28"
|
||||
chucker = "3.2.0"
|
||||
mockk = "1.9.2"
|
||||
chucker = "3.3.0"
|
||||
mockk = "1.10.2"
|
||||
moshi = "1.11.0"
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
@ -124,13 +142,17 @@ configurations.all {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "io.github.wulkanowy:sdk:0.19.0"
|
||||
implementation "io.github.wulkanowy:sdk:0.22.1"
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
|
||||
|
||||
implementation "androidx.core:core-ktx:1.3.2"
|
||||
implementation "androidx.activity:activity-ktx:1.1.0"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0-rc01"
|
||||
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||
implementation "androidx.appcompat:appcompat-resources:1.2.0"
|
||||
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
||||
implementation "androidx.annotation:annotation:1.1.0"
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
@ -138,74 +160,71 @@ dependencies {
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-rc01"
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.1"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||
implementation "com.google.android.material:material:1.1.0"
|
||||
implementation "com.google.android.material:material:1.2.1"
|
||||
implementation "com.github.wulkanowy:material-chips-input:2.1.1"
|
||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
||||
implementation "androidx.work:work-rxjava2:$work_manager"
|
||||
implementation "androidx.work:work-gcm:$work_manager"
|
||||
|
||||
implementation 'com.github.PaulinaSadowska:RxWorkManagerObservers:1.0.0'
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
|
||||
|
||||
implementation "androidx.room:room-runtime:$room"
|
||||
implementation "androidx.room:room-rxjava2:$room"
|
||||
implementation "androidx.room:room-ktx:$room"
|
||||
kapt "androidx.room:room-compiler:$room"
|
||||
|
||||
implementation "com.google.dagger:dagger-android-support:$dagger"
|
||||
kapt "com.google.dagger:dagger-compiler:$dagger"
|
||||
kapt "com.google.dagger:dagger-android-processor:$dagger"
|
||||
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2"
|
||||
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.2"
|
||||
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||
implementation 'androidx.hilt:hilt-work:1.0.0-alpha02'
|
||||
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
|
||||
|
||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
||||
implementation "com.ncapdevi:frag-nav:3.3.0"
|
||||
implementation "com.github.YarikSOffice:lingver:1.2.2"
|
||||
|
||||
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.8"
|
||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.19"
|
||||
|
||||
implementation "com.google.code.gson:gson:2.8.6"
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.4"
|
||||
implementation "com.squareup.moshi:moshi:$moshi"
|
||||
implementation "com.squareup.moshi:moshi-adapters:$moshi"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi"
|
||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation "fr.bipi.treessence:treessence:0.3.2"
|
||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
|
||||
implementation "io.coil-kt:coil:0.11.0"
|
||||
implementation "io.coil-kt:coil:1.0.0-rc3"
|
||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
||||
|
||||
playImplementation 'com.google.firebase:firebase-analytics:17.4.3'
|
||||
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.0.7'
|
||||
playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.0.7"
|
||||
playImplementation 'com.google.firebase:firebase-messaging:20.2.0'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:17.0.1'
|
||||
playImplementation 'com.google.firebase:firebase-analytics:17.6.0'
|
||||
playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1'
|
||||
playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1"
|
||||
playImplementation 'com.google.firebase:firebase-messaging:20.3.0'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2'
|
||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:5.0.4.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.1.300'
|
||||
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||
|
||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
|
||||
|
||||
testImplementation "junit:junit:4.13"
|
||||
testImplementation "junit:junit:4.13.1"
|
||||
testImplementation "io.mockk:mockk:$mockk"
|
||||
testImplementation "org.threeten:threetenbp:1.4.4"
|
||||
testImplementation "org.mockito:mockito-inline:3.3.3"
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9'
|
||||
|
||||
androidTestImplementation "androidx.test:core:1.2.0"
|
||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.1"
|
||||
androidTestImplementation "androidx.test:core:1.3.0"
|
||||
androidTestImplementation "androidx.test:runner:1.3.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||
androidTestImplementation "androidx.room:room-testing:$room"
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
androidTestImplementation "org.mockito:mockito-android:3.3.3"
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.huawei.agconnect'
|
||||
|
@ -35,13 +35,13 @@ task jacocoTestReport(type: JacocoReport) {
|
||||
dir: "$buildDir/intermediates/classes/debug",
|
||||
excludes: excludes
|
||||
) + fileTree(
|
||||
dir: "$buildDir/tmp/kotlin-classes/playDebug",
|
||||
dir: "$buildDir/tmp/kotlin-classes/fdroidDebug",
|
||||
excludes: excludes
|
||||
))
|
||||
|
||||
sourceDirectories.setFrom(files([
|
||||
"src/main/java",
|
||||
"src/play/java"
|
||||
"src/fdroid/java"
|
||||
]))
|
||||
executionData.setFrom(fileTree(
|
||||
dir: project.projectDir,
|
||||
|
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
@ -30,13 +30,6 @@
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
|
||||
#Config for ReactiveNetwork
|
||||
-dontwarn com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
-dontwarn io.reactivex.functions.Function
|
||||
-dontwarn rx.internal.util.**
|
||||
-dontwarn sun.misc.Unsafe
|
||||
|
||||
|
||||
#Config for MPAndroidChart
|
||||
-keep class com.github.mikephil.charting.** { *; }
|
||||
|
||||
|
1774
app/schemas/io.github.wulkanowy.data.db.AppDatabase/27.json
Normal file
1774
app/schemas/io.github.wulkanowy.data.db.AppDatabase/27.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.data
|
||||
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
class TestDispatchersProvider : DispatchersProvider() {
|
||||
|
||||
override val backgroundThread: CoroutineDispatcher
|
||||
get() = Dispatchers.Unconfined
|
||||
}
|
@ -4,6 +4,7 @@ import android.content.ContentValues
|
||||
import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.test.assertEquals
|
||||
@ -29,7 +30,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll().blockingGet()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(2, students.size)
|
||||
|
||||
@ -58,7 +59,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll().blockingGet()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(1, students.size)
|
||||
|
||||
@ -84,7 +85,7 @@ class Migration12Test : AbstractMigrationTest() {
|
||||
helper.runMigrationsAndValidate(dbName, 12, true, Migration12())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll().blockingGet()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(3, students.size)
|
||||
|
||||
|
@ -5,10 +5,11 @@ import android.database.sqlite.SQLiteDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import io.github.wulkanowy.data.db.Converters
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import java.time.LocalDate.of
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@ -26,7 +27,7 @@ class Migration13Test : AbstractMigrationTest() {
|
||||
helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll().blockingGet()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(3, students.size)
|
||||
|
||||
@ -60,7 +61,7 @@ class Migration13Test : AbstractMigrationTest() {
|
||||
helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = db.studentDao.loadAll().blockingGet()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(2, students.size)
|
||||
|
||||
|
@ -0,0 +1,124 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import kotlin.random.Random
|
||||
|
||||
class Migration27Test : AbstractMigrationTest() {
|
||||
|
||||
@Test
|
||||
fun userWithoutCorrespondingUnit() {
|
||||
with(helper.createDatabase(dbName, 26)) {
|
||||
createStudent(this, 321, 123, "Jan Student")
|
||||
createUnit(this, 9999, "Unit Jan")
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(1, students.size)
|
||||
|
||||
with(students[0]) {
|
||||
assertEquals(321, id)
|
||||
assertEquals(123, userLoginId)
|
||||
assertEquals("Student Jan", userName)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun userWithCorrespondingUnit() {
|
||||
with(helper.createDatabase(dbName, 26)) {
|
||||
createStudent(this, 1, 2, "Jan Kowalski Student")
|
||||
createUnit(this, 2, "Unit Jan")
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(1, students.size)
|
||||
|
||||
with(students[0]) {
|
||||
assertEquals(1, id)
|
||||
assertEquals(2, userLoginId)
|
||||
assertEquals("Unit Jan", userName)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun studentAccountAndParentAccountWithCorrespondingUnits() {
|
||||
with(helper.createDatabase(dbName, 26)) {
|
||||
createStudent(this, 1, 222, "Jan Student")
|
||||
createStudent(this, 2, 333, "Jan Parent")
|
||||
createUnit(this, 222, "Unit Jan")
|
||||
createUnit(this, 333, "Unit Tomasz")
|
||||
close()
|
||||
}
|
||||
|
||||
helper.runMigrationsAndValidate(dbName, 27, true, Migration27())
|
||||
|
||||
val db = getMigratedRoomDatabase()
|
||||
val students = runBlocking { db.studentDao.loadAll() }
|
||||
|
||||
assertEquals(2, students.size)
|
||||
|
||||
with(students[0]) {
|
||||
assertEquals(1, id)
|
||||
assertEquals(222, userLoginId)
|
||||
assertEquals("Unit Jan", userName)
|
||||
}
|
||||
with(students[1]) {
|
||||
assertEquals(2, id)
|
||||
assertEquals(333, userLoginId)
|
||||
assertEquals("Unit Tomasz", userName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createStudent(db: SupportSQLiteDatabase, id: Long, userLoginId: Int, studentName: String) {
|
||||
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||
put("id", id)
|
||||
put("scrapper_base_url", "https://fakelog.cf")
|
||||
put("mobile_base_url", "")
|
||||
put("login_mode", "SCRAPPER")
|
||||
put("login_type", "STANDARD")
|
||||
put("certificate_key", "")
|
||||
put("private_key", "")
|
||||
put("is_parent", false)
|
||||
put("email", "jan@fakelog.cf")
|
||||
put("password", "******")
|
||||
put("symbol", "Default")
|
||||
put("school_short", "")
|
||||
put("class_name", "")
|
||||
put("student_id", Random.nextInt())
|
||||
put("class_id", Random.nextInt())
|
||||
put("school_id", "123")
|
||||
put("school_name", "Wulkan first class school")
|
||||
put("is_current", false)
|
||||
put("registration_date", "0")
|
||||
|
||||
put("user_login_id", userLoginId)
|
||||
put("student_name", studentName)
|
||||
})
|
||||
}
|
||||
|
||||
private fun createUnit(db: SupportSQLiteDatabase, senderId: Int, senderName: String) {
|
||||
db.insert("ReportingUnits", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||
put("student_id", Random.nextInt())
|
||||
put("real_id", Random.nextInt())
|
||||
put("short", "SHORT")
|
||||
put("roles", "[0]")
|
||||
|
||||
put("sender_id", senderId)
|
||||
put("sender_name", senderName)
|
||||
})
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.time.LocalDate.now
|
||||
import java.time.LocalDateTime
|
||||
|
||||
fun getStudent(): Student {
|
||||
return Student(
|
||||
@ -11,6 +13,7 @@ fun getStudent(): Student {
|
||||
scrapperBaseUrl = "fakelog.cf",
|
||||
loginType = "AUTO",
|
||||
isCurrent = true,
|
||||
userName = "",
|
||||
studentName = "",
|
||||
schoolShortName = "",
|
||||
schoolName = "",
|
||||
@ -27,3 +30,16 @@ fun getStudent(): Student {
|
||||
isParent = false
|
||||
)
|
||||
}
|
||||
|
||||
fun getSemester() = Semester(
|
||||
semesterId = 1,
|
||||
studentId = 1,
|
||||
classId = 1,
|
||||
diaryId = 2,
|
||||
diaryName = "",
|
||||
end = now(),
|
||||
schoolYear = 2019,
|
||||
semesterName = 1,
|
||||
start = now(),
|
||||
unitId = 1
|
||||
)
|
||||
|
@ -1,19 +0,0 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.error.ErrorHandler
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class TestInternetObservingStrategy : InternetObservingStrategy {
|
||||
|
||||
override fun checkInternetConnectivity(host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Single<Boolean> {
|
||||
return Single.just(true)
|
||||
}
|
||||
|
||||
override fun observeInternetConnectivity(initialIntervalInMs: Int, intervalInMs: Int, host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Observable<Boolean> {
|
||||
return Observable.just(true)
|
||||
}
|
||||
|
||||
override fun getDefaultPingHost() = "localhost"
|
||||
}
|
@ -6,13 +6,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDate.now
|
||||
import java.time.LocalDate.of
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -35,7 +37,7 @@ class AttendanceLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
attendanceLocal.saveAttendance(listOf(
|
||||
val list = listOf(
|
||||
getAttendanceEntity(
|
||||
of(2018, 9, 10),
|
||||
SentExcuseStatus.ACCEPTED
|
||||
@ -48,14 +50,11 @@ class AttendanceLocalTest {
|
||||
of(2018, 9, 17),
|
||||
SentExcuseStatus.ACCEPTED
|
||||
)
|
||||
))
|
||||
)
|
||||
runBlocking { attendanceLocal.saveAttendance(list) }
|
||||
|
||||
val attendance = attendanceLocal
|
||||
.getAttendance(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1),
|
||||
of(2018, 9, 10),
|
||||
of(2018, 9, 14)
|
||||
)
|
||||
.blockingGet()
|
||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||
val attendance = runBlocking { attendanceLocal.getAttendance(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||
assertEquals(2, attendance.size)
|
||||
assertEquals(attendance[0].date, of(2018, 9, 10))
|
||||
assertEquals(attendance[1].date, of(2018, 9, 14))
|
||||
|
@ -6,13 +6,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDate.now
|
||||
import java.time.LocalDate.of
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -24,7 +26,8 @@ class CompletedLessonsLocalTest {
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
testDb = Room
|
||||
.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
.build()
|
||||
completedLessonsLocal = CompletedLessonsLocal(testDb.completedLessonsDao)
|
||||
}
|
||||
@ -36,18 +39,15 @@ class CompletedLessonsLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
completedLessonsLocal.saveCompletedLessons(listOf(
|
||||
val list = listOf(
|
||||
getCompletedLesson(of(2018, 9, 10), 1),
|
||||
getCompletedLesson(of(2018, 9, 14), 2),
|
||||
getCompletedLesson(of(2018, 9, 17), 3)
|
||||
))
|
||||
)
|
||||
runBlocking { completedLessonsLocal.saveCompletedLessons(list) }
|
||||
|
||||
val completed = completedLessonsLocal
|
||||
.getCompletedLessons(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1),
|
||||
of(2018, 9, 10),
|
||||
of(2018, 9, 14)
|
||||
)
|
||||
.blockingGet()
|
||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||
val completed = runBlocking { completedLessonsLocal.getCompletedLessons(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||
assertEquals(2, completed.size)
|
||||
assertEquals(completed[0].date, of(2018, 9, 10))
|
||||
assertEquals(completed[1].date, of(2018, 9, 14))
|
||||
|
@ -6,12 +6,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import java.time.LocalDate.now
|
||||
import java.time.LocalDate.of
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -34,18 +36,15 @@ class ExamLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
examLocal.saveExams(listOf(
|
||||
val list = listOf(
|
||||
Exam(1, 2, of(2018, 9, 10), now(), "", "", "", "", "", ""),
|
||||
Exam(1, 2, of(2018, 9, 14), now(), "", "", "", "", "", ""),
|
||||
Exam(1, 2, of(2018, 9, 17), now(), "", "", "", "", "", "")
|
||||
))
|
||||
)
|
||||
runBlocking { examLocal.saveExams(list) }
|
||||
|
||||
val exams = examLocal
|
||||
.getExams(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1),
|
||||
of(2018, 9, 10),
|
||||
of(2018, 9, 14)
|
||||
)
|
||||
.blockingGet()
|
||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||
val exams = runBlocking { examLocal.getExams(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||
assertEquals(2, exams.size)
|
||||
assertEquals(exams[0].date, of(2018, 9, 10))
|
||||
assertEquals(exams[1].date, of(2018, 9, 14))
|
||||
|
@ -5,12 +5,14 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDate.now
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -22,7 +24,8 @@ class GradeLocalTest {
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
testDb = Room
|
||||
.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
.build()
|
||||
gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
|
||||
}
|
||||
@ -34,17 +37,16 @@ class GradeLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
val list = listOf(
|
||||
createGradeLocal(5, 3.0, LocalDate.of(2018, 9, 10), "", 1),
|
||||
createGradeLocal(4, 4.0, LocalDate.of(2019, 2, 27), "", 2),
|
||||
createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2)
|
||||
))
|
||||
)
|
||||
runBlocking { gradeLocal.saveGrades(list) }
|
||||
|
||||
val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1)
|
||||
|
||||
val grades = gradeLocal
|
||||
.getGradesDetails(semester)
|
||||
.blockingGet()
|
||||
val grades = runBlocking { gradeLocal.getGradesDetails(semester).first() }
|
||||
|
||||
assertEquals(2, grades.size)
|
||||
assertEquals(grades[0].date, LocalDate.of(2019, 2, 27))
|
||||
|
@ -5,23 +5,25 @@ import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Grade
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.time.LocalDate.of
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
@ -30,19 +32,12 @@ import kotlin.test.assertTrue
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class GradeRepositoryTest {
|
||||
|
||||
@MockK
|
||||
private lateinit var mockSdk: Sdk
|
||||
|
||||
private val settings = InternetObservingSettings.builder()
|
||||
.strategy(TestInternetObservingStrategy())
|
||||
.build()
|
||||
|
||||
@MockK
|
||||
private lateinit var semesterMock: Semester
|
||||
|
||||
@MockK
|
||||
private lateinit var studentMock: Student
|
||||
|
||||
@MockK
|
||||
private lateinit var gradeRemote: GradeRemote
|
||||
|
||||
private lateinit var gradeLocal: GradeLocal
|
||||
@ -54,14 +49,12 @@ class GradeRepositoryTest {
|
||||
MockKAnnotations.init(this)
|
||||
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
||||
gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
|
||||
gradeRemote = GradeRemote(mockSdk)
|
||||
studentMock = getStudentMock()
|
||||
|
||||
every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0)
|
||||
every { semesterMock.studentId } returns 1
|
||||
every { semesterMock.diaryId } returns 1
|
||||
every { semesterMock.schoolYear } returns 2019
|
||||
every { semesterMock.semesterId } returns 1
|
||||
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
|
||||
}
|
||||
|
||||
@After
|
||||
@ -71,15 +64,18 @@ class GradeRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun markOlderThanRegisterDateAsRead() {
|
||||
every { mockSdk.getGrades(1) } returns Single.just(listOf(
|
||||
createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
|
||||
createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
|
||||
createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
|
||||
createGradeApi(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||
createGradeLocal(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
|
||||
createGradeLocal(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
|
||||
createGradeLocal(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
|
||||
createGradeLocal(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
|
||||
) to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet().first.sortedByDescending { it.date }
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
|
||||
}
|
||||
|
||||
assertFalse { grades[0].isRead }
|
||||
assertFalse { grades[1].isRead }
|
||||
@ -89,21 +85,25 @@ class GradeRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun mitigateOldGradesNotifications() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
val list = listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Jedna ocena"),
|
||||
createGradeLocal(4, 4.0, of(2019, 2, 26), "Druga"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia")
|
||||
))
|
||||
)
|
||||
runBlocking { gradeLocal.saveGrades(list) }
|
||||
|
||||
every { mockSdk.getGrades(1) } returns Single.just(listOf(
|
||||
createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
|
||||
createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
|
||||
createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
|
||||
createGradeApi(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||
createGradeLocal(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
|
||||
createGradeLocal(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
|
||||
createGradeLocal(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
|
||||
createGradeLocal(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
|
||||
) to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet().first.sortedByDescending { it.date }
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
|
||||
}
|
||||
|
||||
assertFalse { grades[0].isRead }
|
||||
assertFalse { grades[1].isRead }
|
||||
@ -113,70 +113,109 @@ class GradeRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun subtractLocaleDuplicateGrades() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
val list = listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
))
|
||||
)
|
||||
runBlocking { gradeLocal.saveGrades(list) }
|
||||
|
||||
every { mockSdk.getGrades(1) } returns Single.just(listOf(
|
||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
) to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||
}
|
||||
|
||||
assertEquals(2, grades.first.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun subtractRemoteDuplicateGrades() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
val list = listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
))
|
||||
)
|
||||
runBlocking { gradeLocal.saveGrades(list) }
|
||||
|
||||
every { mockSdk.getGrades(1) } returns Single.just(listOf(
|
||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
) to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||
}
|
||||
|
||||
assertEquals(3, grades.first.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyLocal() {
|
||||
gradeLocal.saveGrades(listOf())
|
||||
runBlocking { gradeLocal.saveGrades(listOf()) }
|
||||
|
||||
every { mockSdk.getGrades(1) } returns Single.just(listOf(
|
||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
) to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||
}
|
||||
|
||||
assertEquals(3, grades.first.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyRemote() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
val list = listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
))
|
||||
)
|
||||
runBlocking { gradeLocal.saveGrades(list) }
|
||||
|
||||
every { mockSdk.getGrades(1) } returns Single.just(emptyList<Grade>() to emptyList())
|
||||
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (emptyList<Grade>() to emptyList())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
val grades = runBlocking {
|
||||
GradeRepository(gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true)
|
||||
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||
}
|
||||
|
||||
assertEquals(0, grades.first.size)
|
||||
}
|
||||
|
||||
private fun getStudentMock() = Student(
|
||||
scrapperBaseUrl = "http://fakelog.cf",
|
||||
email = "jan@fakelog.cf",
|
||||
certificateKey = "",
|
||||
classId = 0,
|
||||
className = "",
|
||||
isCurrent = false,
|
||||
isParent = false,
|
||||
loginMode = Sdk.Mode.SCRAPPER.name,
|
||||
loginType = "STANDARD",
|
||||
mobileBaseUrl = "",
|
||||
password = "",
|
||||
privateKey = "",
|
||||
registrationDate = LocalDateTime.of(2019, 2, 27, 12, 0),
|
||||
schoolName = "",
|
||||
schoolShortName = "test",
|
||||
schoolSymbol = "",
|
||||
studentId = 0,
|
||||
studentName = "",
|
||||
symbol = "",
|
||||
userLoginId = 0,
|
||||
userName = ""
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package io.github.wulkanowy.data.repositories.grade
|
||||
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.time.LocalDate
|
||||
import io.github.wulkanowy.sdk.pojo.Grade as GradeRemote
|
||||
import io.github.wulkanowy.data.db.entities.Grade as GradeLocal
|
||||
|
||||
|
@ -7,11 +7,13 @@ 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.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import java.time.LocalDate.now
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -35,40 +37,44 @@ class GradeStatisticsLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndRead_subject() {
|
||||
gradeStatisticsLocal.saveGradesStatistics(listOf(
|
||||
val list = listOf(
|
||||
getGradeStatistics("Matematyka", 2, 1),
|
||||
getGradeStatistics("Fizyka", 1, 2)
|
||||
))
|
||||
)
|
||||
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Matematyka").blockingGet()
|
||||
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
|
||||
assertEquals(1, stats.size)
|
||||
assertEquals(stats[0].subject, "Matematyka")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndRead_all() {
|
||||
gradeStatisticsLocal.saveGradesStatistics(listOf(
|
||||
val list = listOf(
|
||||
getGradeStatistics("Matematyka", 2, 1),
|
||||
getGradeStatistics("Chemia", 2, 1),
|
||||
getGradeStatistics("Fizyka", 1, 2)
|
||||
))
|
||||
)
|
||||
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Wszystkie").blockingGet()
|
||||
assertEquals(3, stats.size)
|
||||
assertEquals(stats[0].subject, "Wszystkie")
|
||||
assertEquals(stats[1].subject, "Matematyka")
|
||||
assertEquals(stats[2].subject, "Chemia")
|
||||
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
|
||||
assertEquals(2, stats.size)
|
||||
// assertEquals(3, stats.size)
|
||||
// assertEquals(stats[0].subject, "Wszystkie") // now in main repo
|
||||
assertEquals(stats[0].subject, "Matematyka")
|
||||
assertEquals(stats[1].subject, "Chemia")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndRead_points() {
|
||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf(
|
||||
val list = listOf(
|
||||
getGradePointsStatistics("Matematyka", 2, 1),
|
||||
getGradePointsStatistics("Chemia", 2, 1),
|
||||
getGradePointsStatistics("Fizyka", 1, 2)
|
||||
))
|
||||
)
|
||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) }
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka").blockingGet()
|
||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||
with(stats[0]) {
|
||||
assertEquals(subject, "Matematyka")
|
||||
assertEquals(others, 5.0)
|
||||
@ -78,18 +84,18 @@ class GradeStatisticsLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndRead_subjectEmpty() {
|
||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka").blockingGet()
|
||||
assertEquals(null, stats)
|
||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||
assertEquals(emptyList(), stats)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndRead_allEmpty() {
|
||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
||||
|
||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Wszystkie").blockingGet()
|
||||
assertEquals(null, stats)
|
||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||
assertEquals(emptyList(), stats)
|
||||
}
|
||||
|
||||
private fun getSemester(): Semester {
|
||||
|
@ -6,12 +6,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime.now
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime.now
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -23,7 +25,8 @@ class LuckyNumberLocalTest {
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
testDb = Room
|
||||
.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||
.build()
|
||||
luckyNumberLocal = LuckyNumberLocal(testDb.luckyNumberDao)
|
||||
}
|
||||
@ -35,14 +38,14 @@ class LuckyNumberLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14))
|
||||
val number = LuckyNumber(1, LocalDate.of(2019, 1, 20), 14)
|
||||
runBlocking { luckyNumberLocal.saveLuckyNumber(number) }
|
||||
|
||||
val luckyNumber = luckyNumberLocal.getLuckyNumber(Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", 1, false, now()),
|
||||
LocalDate.of(2019, 1, 20)
|
||||
).blockingGet()
|
||||
val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", "", 1, false, now())
|
||||
val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() }
|
||||
|
||||
assertEquals(1, luckyNumber.studentId)
|
||||
assertEquals(LocalDate.of(2019, 1, 20), luckyNumber.date)
|
||||
assertEquals(14, luckyNumber.luckyNumber)
|
||||
assertEquals(1, luckyNumber?.studentId)
|
||||
assertEquals(LocalDate.of(2019, 1, 20), luckyNumber?.date)
|
||||
assertEquals(14, luckyNumber?.luckyNumber)
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,12 @@ import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -35,17 +36,21 @@ class RecipientLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
recipientLocal.saveRecipients(listOf(
|
||||
val list = listOf(
|
||||
Recipient(1, "2rPracownik", "Kowalski Jan", "Kowalski Jan [KJ] - Pracownik (Fake123456)", 3, 4, 2, "hash"),
|
||||
Recipient(1, "3rPracownik", "Kowalska Karolina", "Kowalska Karolina [KK] - Pracownik (Fake123456)", 4, 4, 2, "hash"),
|
||||
Recipient(1, "4rPracownik", "Krupa Stanisław", "Krupa Stanisław [KS] - Uczeń (Fake123456)", 5, 4, 1, "hash")
|
||||
))
|
||||
)
|
||||
runBlocking { recipientLocal.saveRecipients(list) }
|
||||
|
||||
val recipients = recipientLocal.getRecipients(
|
||||
Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", 1, true, LocalDateTime.now()),
|
||||
2,
|
||||
ReportingUnit(1, 4, "", 0, "", emptyList())
|
||||
).blockingGet()
|
||||
val student = Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", "", 1, true, LocalDateTime.now())
|
||||
val recipients = runBlocking {
|
||||
recipientLocal.getRecipients(
|
||||
student = student,
|
||||
role = 2,
|
||||
unit = ReportingUnit(1, 4, "", 0, "", emptyList())
|
||||
)
|
||||
}
|
||||
|
||||
assertEquals(2, recipients.size)
|
||||
assertEquals(1, recipients[0].studentId)
|
||||
|
@ -4,8 +4,10 @@ import android.content.Context
|
||||
import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.TestDispatchersProvider
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.repositories.getStudent
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -26,7 +28,7 @@ class StudentLocalTest {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
||||
.build()
|
||||
studentLocal = StudentLocal(testDb.studentDao, context)
|
||||
studentLocal = StudentLocal(testDb.studentDao, TestDispatchersProvider(), context)
|
||||
}
|
||||
|
||||
@After
|
||||
@ -36,9 +38,9 @@ class StudentLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
studentLocal.saveStudents(listOf(student)).blockingGet()
|
||||
runBlocking { studentLocal.saveStudents(listOf(student)) }
|
||||
|
||||
val student = studentLocal.getCurrentStudent(true).blockingGet()
|
||||
assertEquals("23", student.schoolSymbol)
|
||||
val student = runBlocking { studentLocal.getCurrentStudent(true) }
|
||||
assertEquals("23", student?.schoolSymbol)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.github.wulkanowy.data.repositories.timetable
|
||||
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import org.threeten.bp.LocalDateTime.now
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalDateTime.now
|
||||
import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
|
||||
import io.github.wulkanowy.sdk.pojo.Timetable as TimetableRemote
|
||||
|
||||
|
@ -5,12 +5,14 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime.of
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime.of
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@ -34,17 +36,21 @@ class TimetableLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
timetableDb.saveTimetable(listOf(
|
||||
val list = listOf(
|
||||
createTimetableLocal(of(2018, 9, 10, 0, 0, 0), 1),
|
||||
createTimetableLocal(of(2018, 9, 14, 0, 0, 0), 1),
|
||||
createTimetableLocal(of(2018, 9, 17, 0, 0, 0), 1)
|
||||
))
|
||||
)
|
||||
runBlocking { timetableDb.saveTimetable(list) }
|
||||
|
||||
val exams = timetableDb.getTimetable(
|
||||
Semester(1, 2, "", 1, 1, 2019, LocalDate.now(), LocalDate.now(), 1, 1),
|
||||
LocalDate.of(2018, 9, 10),
|
||||
LocalDate.of(2018, 9, 14)
|
||||
).blockingGet()
|
||||
val semester = Semester(1, 2, "", 1, 1, 2019, LocalDate.now(), LocalDate.now(), 1, 1)
|
||||
val exams = runBlocking {
|
||||
timetableDb.getTimetable(
|
||||
semester = semester,
|
||||
startDate = LocalDate.of(2018, 9, 10),
|
||||
endDate = LocalDate.of(2018, 9, 14)
|
||||
).first()
|
||||
}
|
||||
|
||||
assertEquals(2, exams.size)
|
||||
assertEquals(exams[0].date, LocalDate.of(2018, 9, 10))
|
||||
|
@ -5,74 +5,48 @@ import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy
|
||||
import io.github.wulkanowy.data.repositories.getSemester
|
||||
import io.github.wulkanowy.data.repositories.getStudent
|
||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.every
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.mockk
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime.of
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime.of
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@SdkSuppress(minSdkVersion = P)
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TimetableRepositoryTest {
|
||||
|
||||
@MockK
|
||||
private lateinit var mockSdk: Sdk
|
||||
|
||||
private val settings = InternetObservingSettings.builder()
|
||||
.strategy(TestInternetObservingStrategy())
|
||||
.build()
|
||||
|
||||
@MockK
|
||||
private lateinit var studentMock: Student
|
||||
|
||||
private val student = getStudent()
|
||||
|
||||
@MockK
|
||||
private lateinit var semesterMock: Semester
|
||||
|
||||
@MockK
|
||||
@MockK(relaxed = true)
|
||||
private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper
|
||||
|
||||
@MockK
|
||||
private lateinit var timetableRemote: TimetableRemote
|
||||
|
||||
private lateinit var timetableLocal: TimetableLocal
|
||||
|
||||
private lateinit var testDb: AppDatabase
|
||||
|
||||
private val student = getStudent()
|
||||
|
||||
private val semester = getSemester()
|
||||
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockKAnnotations.init(this)
|
||||
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
||||
timetableLocal = TimetableLocal(testDb.timetableDao)
|
||||
timetableRemote = TimetableRemote(mockSdk)
|
||||
|
||||
every { timetableNotificationSchedulerHelper.scheduleNotifications(any(), any()) } returns mockk()
|
||||
every { timetableNotificationSchedulerHelper.cancelScheduled(any(), any()) } returns mockk()
|
||||
|
||||
every { studentMock.studentId } returns 1
|
||||
every { studentMock.studentName } returns "Jan Kowalski"
|
||||
|
||||
every { semesterMock.studentId } returns 1
|
||||
every { semesterMock.diaryId } returns 2
|
||||
every { semesterMock.schoolYear } returns 2019
|
||||
every { semesterMock.semesterId } returns 1
|
||||
|
||||
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
|
||||
}
|
||||
|
||||
@After
|
||||
@ -82,23 +56,31 @@ class TimetableRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun copyRoomToCompletedFromPrevious() {
|
||||
timetableLocal.saveTimetable(listOf(
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "123", "Przyroda"),
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "321", "Religia"),
|
||||
createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "213", "W-F"),
|
||||
createTimetableLocal(of(2019, 3, 5, 10, 30),3, "213", "W-F", "Jan Kowalski")
|
||||
))
|
||||
runBlocking {
|
||||
timetableLocal.saveTimetable(listOf(
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "123", "Przyroda"),
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "321", "Religia"),
|
||||
createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "213", "W-F"),
|
||||
createTimetableLocal(of(2019, 3, 5, 10, 30), 3, "213", "W-F", "Jan Kowalski")
|
||||
))
|
||||
}
|
||||
|
||||
every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf(
|
||||
createTimetableRemote(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
|
||||
createTimetableRemote(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
|
||||
createTimetableRemote(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
|
||||
createTimetableRemote(of(2019, 3, 5, 10, 30), 4, "", "W-F")
|
||||
))
|
||||
coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
|
||||
createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
|
||||
createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
|
||||
createTimetableLocal(of(2019, 3, 5, 10, 30), 4, "", "W-F")
|
||||
)
|
||||
|
||||
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote, timetableNotificationSchedulerHelper)
|
||||
.getTimetable(student, semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true)
|
||||
.blockingGet()
|
||||
val lessons = runBlocking {
|
||||
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = LocalDate.of(2019, 3, 5),
|
||||
end = LocalDate.of(2019, 3, 5),
|
||||
forceRefresh = true
|
||||
).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
|
||||
}
|
||||
|
||||
assertEquals(4, lessons.size)
|
||||
assertEquals("123", lessons[0].room)
|
||||
@ -108,7 +90,7 @@ class TimetableRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun copyTeacherToCompletedFromPrevious() {
|
||||
timetableLocal.saveTimetable(listOf(
|
||||
val list = listOf(
|
||||
createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
|
||||
createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Paweł Poniedziałkowski", false),
|
||||
createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Wtorkowska", true),
|
||||
@ -123,28 +105,35 @@ class TimetableRepositoryTest {
|
||||
createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "", false),
|
||||
createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "", true),
|
||||
createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "", true)
|
||||
))
|
||||
)
|
||||
runBlocking { timetableLocal.saveTimetable(list) }
|
||||
|
||||
every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf(
|
||||
createTimetableRemote(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
|
||||
createTimetableRemote(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
|
||||
createTimetableRemote(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
|
||||
createTimetableRemote(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
|
||||
coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
|
||||
createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
|
||||
createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
|
||||
createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
|
||||
createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
|
||||
|
||||
createTimetableRemote(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
|
||||
createTimetableRemote(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
|
||||
createTimetableRemote(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
|
||||
createTimetableRemote(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
|
||||
createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
|
||||
createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
|
||||
createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
|
||||
createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
|
||||
|
||||
createTimetableRemote(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
|
||||
createTimetableRemote(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
|
||||
createTimetableRemote(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
|
||||
createTimetableRemote(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
|
||||
))
|
||||
createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
|
||||
createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
|
||||
createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
|
||||
createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
|
||||
)
|
||||
|
||||
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote, timetableNotificationSchedulerHelper)
|
||||
.getTimetable(student, semesterMock, LocalDate.of(2019, 12, 23), LocalDate.of(2019, 12, 25), true)
|
||||
.blockingGet()
|
||||
val lessons = runBlocking {
|
||||
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = LocalDate.of(2019, 12, 23),
|
||||
end = LocalDate.of(2019, 12, 25),
|
||||
forceRefresh = true
|
||||
).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
|
||||
}
|
||||
|
||||
assertEquals(12, lessons.size)
|
||||
|
||||
|
33
app/src/debug/agconnect-services.json
Normal file
33
app/src/debug/agconnect-services.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"agcgw":{
|
||||
"backurl":"connect-dre.dbankcloud.cn",
|
||||
"url":"connect-dre.hispace.hicloud.com"
|
||||
},
|
||||
"client":{
|
||||
"cp_id":"890048000024105546",
|
||||
"product_id":"",
|
||||
"client_id":"",
|
||||
"client_secret":"",
|
||||
"app_id":"101440411",
|
||||
"package_name":"io.github.wulkanowy.dev",
|
||||
"api_key":""
|
||||
},
|
||||
"service":{
|
||||
"analytics":{
|
||||
"collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||
"resource_id":"p1",
|
||||
"channel_id":""
|
||||
},
|
||||
"search":{
|
||||
"url":"https://search-dre.cloud.huawei.com"
|
||||
},
|
||||
"cloudstorage":{
|
||||
"storage_url":"https://ops-dre.agcstorage.link"
|
||||
},
|
||||
"ml":{
|
||||
"mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
|
||||
}
|
||||
},
|
||||
"region":"DE",
|
||||
"configuration_version":"1.0"
|
||||
}
|
@ -6,7 +6,7 @@ import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class FirebaseAnalyticsHelper @Inject constructor() {
|
||||
class AnalyticsHelper @Inject constructor() {
|
||||
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||
// do nothing
|
@ -8,6 +8,6 @@ open class TimberTreeNoOp : Timber.Tree() {
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {}
|
||||
}
|
||||
|
||||
class CrashlyticsTree : TimberTreeNoOp()
|
||||
class CrashLogTree : TimberTreeNoOp()
|
||||
|
||||
class CrashlyticsExceptionTree : TimberTreeNoOp()
|
||||
class CrashLogExceptionTree : TimberTreeNoOp()
|
@ -0,0 +1,17 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class UpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates(activity: Activity) {}
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||
|
||||
fun onResume(activity: Activity) {}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import com.huawei.hms.analytics.HiAnalytics
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AnalyticsHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
|
||||
private val analytics by lazy { HiAnalytics.getInstance(context) }
|
||||
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||
Bundle().apply {
|
||||
params.forEach {
|
||||
if (it.second == null) return@forEach
|
||||
when (it.second) {
|
||||
is String, is String? -> putString(it.first, it.second as String)
|
||||
is Int, is Int? -> putInt(it.first, it.second as Int)
|
||||
is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
|
||||
}
|
||||
}
|
||||
analytics.onEvent(name, this)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentScreen(activity: Activity, name: String?) {
|
||||
analytics.onEvent("screen_view", Bundle().apply {
|
||||
putString("screen_name", name)
|
||||
putString("screen_class", activity::class.simpleName)
|
||||
})
|
||||
}
|
||||
}
|
52
app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
Normal file
52
app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
Normal file
@ -0,0 +1,52 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.util.Log
|
||||
import com.huawei.agconnect.crash.AGConnectCrash
|
||||
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||
import fr.bipi.tressence.common.StackTraceRecorder
|
||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
||||
import java.io.InterruptedIOException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
|
||||
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||
|
||||
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
if (skipLog(priority, tag, message, t)) return
|
||||
|
||||
connectCrash.log(format(priority, tag, message))
|
||||
}
|
||||
}
|
||||
|
||||
class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
|
||||
|
||||
private val connectCrash by lazy { AGConnectCrash.getInstance() }
|
||||
|
||||
override fun skipLog(priority: Int, tag: String?, message: String, t: Throwable?): Boolean {
|
||||
return when (t) {
|
||||
is FeatureDisabledException,
|
||||
is FeatureNotAvailableException,
|
||||
is UnknownHostException,
|
||||
is SocketTimeoutException,
|
||||
is InterruptedIOException -> true
|
||||
else -> super.skipLog(priority, tag, message, t)
|
||||
}
|
||||
}
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
if (skipLog(priority, tag, message, t)) return
|
||||
|
||||
connectCrash.setCustomKey("priority", priority)
|
||||
connectCrash.setCustomKey("tag", tag.orEmpty())
|
||||
connectCrash.setCustomKey("message", message)
|
||||
connectCrash.log(priority, t?.stackTraceToString())
|
||||
if (t != null) {
|
||||
connectCrash.log(priority, t.stackTraceToString())
|
||||
} else {
|
||||
connectCrash.log(priority, StackTraceRecorder(format(priority, tag, message)).stackTraceToString())
|
||||
}
|
||||
}
|
||||
}
|
17
app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
Normal file
17
app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class UpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates(activity: Activity) {}
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||
|
||||
fun onResume(activity: Activity) {}
|
||||
}
|
@ -18,8 +18,7 @@
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"
|
||||
tools:replace="android:supportsRtl,android:allowBackup">
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
<activity
|
||||
android:name=".ui.modules.splash.SplashActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -111,6 +110,11 @@
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<meta-data
|
||||
android:name="install_channel"
|
||||
android:value="${install_channel}">
|
||||
</meta-data>
|
||||
|
||||
<!-- workaround for https://github.com/firebase/firebase-android-sdk/issues/473 enabled:false -->
|
||||
<!-- https://firebase.googleblog.com/2017/03/take-control-of-your-firebase-init-on.html -->
|
||||
<provider
|
||||
|
@ -1,34 +1,30 @@
|
||||
package io.github.wulkanowy
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log.DEBUG
|
||||
import android.util.Log.INFO
|
||||
import android.util.Log.VERBOSE
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.multidex.MultiDex
|
||||
import androidx.work.Configuration
|
||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||
import com.yariksoffice.lingver.Lingver
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.support.DaggerApplication
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import fr.bipi.tressence.file.FileLoggerTree
|
||||
import io.github.wulkanowy.di.DaggerAppComponent
|
||||
import io.github.wulkanowy.services.sync.SyncWorkerFactory
|
||||
import io.github.wulkanowy.ui.base.ThemeManager
|
||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.CrashlyticsExceptionTree
|
||||
import io.github.wulkanowy.utils.CrashlyticsTree
|
||||
import io.github.wulkanowy.utils.CrashLogExceptionTree
|
||||
import io.github.wulkanowy.utils.CrashLogTree
|
||||
import io.github.wulkanowy.utils.DebugLogTree
|
||||
import io.reactivex.exceptions.UndeliverableException
|
||||
import io.reactivex.plugins.RxJavaPlugins
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
|
||||
class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
||||
@HiltAndroidApp
|
||||
class WulkanowyApp : Application(), Configuration.Provider {
|
||||
|
||||
@Inject
|
||||
lateinit var workerFactory: SyncWorkerFactory
|
||||
lateinit var workerFactory: HiltWorkerFactory
|
||||
|
||||
@Inject
|
||||
lateinit var themeManager: ThemeManager
|
||||
@ -43,8 +39,6 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AndroidThreeTen.init(this)
|
||||
RxJavaPlugins.setErrorHandler(::onError)
|
||||
Lingver.init(this)
|
||||
themeManager.applyDefaultTheme()
|
||||
|
||||
@ -62,24 +56,12 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
|
||||
.build()
|
||||
)
|
||||
} else {
|
||||
Timber.plant(CrashlyticsExceptionTree())
|
||||
Timber.plant(CrashlyticsTree())
|
||||
Timber.plant(CrashLogExceptionTree())
|
||||
Timber.plant(CrashLogTree())
|
||||
}
|
||||
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
|
||||
}
|
||||
|
||||
private fun onError(error: Throwable) {
|
||||
//RxJava's too deep stack traces may cause SOE on older android devices
|
||||
val cause = error.cause
|
||||
if (error is UndeliverableException && cause is IOException || cause is InterruptedException || cause is StackOverflowError) {
|
||||
Timber.e(cause, "An undeliverable error occurred")
|
||||
} else throw error
|
||||
}
|
||||
|
||||
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
|
||||
return DaggerAppComponent.factory().create(this)
|
||||
}
|
||||
|
||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
|
@ -8,10 +8,11 @@ import androidx.preference.PreferenceManager
|
||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||
import com.chuckerteam.chucker.api.ChuckerInterceptor
|
||||
import com.chuckerteam.chucker.api.RetentionManager
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ApplicationComponent
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
@ -20,32 +21,29 @@ import timber.log.Timber
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(ApplicationComponent::class)
|
||||
internal class RepositoryModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideInternetObservingSettings(): InternetObservingSettings {
|
||||
return InternetObservingSettings.builder()
|
||||
.strategy(WalledGardenInternetObservingStrategy())
|
||||
.build()
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSdk(chuckerCollector: ChuckerCollector, context: Context): Sdk {
|
||||
fun provideSdk(chuckerCollector: ChuckerCollector, @ApplicationContext context: Context): Sdk {
|
||||
return Sdk().apply {
|
||||
androidVersion = android.os.Build.VERSION.RELEASE
|
||||
buildTag = android.os.Build.MODEL
|
||||
setSimpleHttpLogger { Timber.d(it) }
|
||||
|
||||
// for debug only
|
||||
addInterceptor(ChuckerInterceptor(context, chuckerCollector), true)
|
||||
addInterceptor(ChuckerInterceptor(
|
||||
context = context,
|
||||
collector = chuckerCollector,
|
||||
alwaysReadResponseBody = true
|
||||
), true)
|
||||
}
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideChuckerCollector(context: Context, prefRepository: PreferencesRepository): ChuckerCollector {
|
||||
fun provideChuckerCollector(@ApplicationContext context: Context, prefRepository: PreferencesRepository): ChuckerCollector {
|
||||
return ChuckerCollector(
|
||||
context = context,
|
||||
showNotification = prefRepository.isDebugNotificationEnable,
|
||||
@ -55,19 +53,19 @@ internal class RepositoryModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideDatabase(context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider)
|
||||
fun provideDatabase(@ApplicationContext context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider)
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideResources(context: Context): Resources = context.resources
|
||||
fun provideResources(@ApplicationContext context: Context): Resources = context.resources
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAssets(context: Context): AssetManager = context.assets
|
||||
fun provideAssets(@ApplicationContext context: Context): AssetManager = context.assets
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
|
23
app/src/main/java/io/github/wulkanowy/data/Resource.kt
Normal file
23
app/src/main/java/io/github/wulkanowy/data/Resource.kt
Normal file
@ -0,0 +1,23 @@
|
||||
package io.github.wulkanowy.data
|
||||
|
||||
data class Resource<T>(val status: Status, val data: T?, val error: Throwable?) {
|
||||
companion object {
|
||||
fun <T> success(data: T?): Resource<T> {
|
||||
return Resource(Status.SUCCESS, data, null)
|
||||
}
|
||||
|
||||
fun <T> error(error: Throwable?, data: T? = null): Resource<T> {
|
||||
return Resource(Status.ERROR, data, error)
|
||||
}
|
||||
|
||||
fun <T> loading(data: T? = null): Resource<T> {
|
||||
return Resource(Status.LOADING, data, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Status {
|
||||
LOADING,
|
||||
SUCCESS,
|
||||
ERROR
|
||||
}
|
@ -69,6 +69,7 @@ import io.github.wulkanowy.data.db.migrations.Migration23
|
||||
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||
import io.github.wulkanowy.data.db.migrations.Migration27
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -111,7 +112,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 26
|
||||
const val VERSION_SCHEMA = 27
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -139,7 +140,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration23(),
|
||||
Migration24(),
|
||||
Migration25(),
|
||||
Migration26()
|
||||
Migration26(),
|
||||
Migration27(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,31 @@
|
||||
package io.github.wulkanowy.data.db
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import org.threeten.bp.DateTimeUtils
|
||||
import org.threeten.bp.Instant
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import org.threeten.bp.Month
|
||||
import org.threeten.bp.ZoneOffset
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import io.github.wulkanowy.data.db.adapters.PairAdapterFactory
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.Month
|
||||
import java.time.ZoneOffset
|
||||
import java.util.Date
|
||||
|
||||
class Converters {
|
||||
|
||||
private val moshi by lazy { Moshi.Builder().add(PairAdapterFactory).build() }
|
||||
|
||||
private val integerListAdapter by lazy {
|
||||
moshi.adapter<List<Int>>(Types.newParameterizedType(List::class.java, Integer::class.java))
|
||||
}
|
||||
|
||||
private val stringListPairAdapter by lazy {
|
||||
moshi.adapter<List<Pair<String, String>>>(Types.newParameterizedType(List::class.java, Pair::class.java, String::class.java, String::class.java))
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
||||
DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate()
|
||||
Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@ -40,22 +50,22 @@ class Converters {
|
||||
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
|
||||
|
||||
@TypeConverter
|
||||
fun intListToGson(list: List<Int>): String {
|
||||
return Gson().toJson(list)
|
||||
fun intListToJson(list: List<Int>): String {
|
||||
return integerListAdapter.toJson(list)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun gsonToIntList(value: String): List<Int> {
|
||||
return Gson().fromJson(value, object : TypeToken<List<Int>>() {}.type)
|
||||
fun jsonToIntList(value: String): List<Int> {
|
||||
return integerListAdapter.fromJson(value).orEmpty()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun stringPairListToGson(list: List<Pair<String, String>>): String {
|
||||
return Gson().toJson(list)
|
||||
fun stringPairListToJson(list: List<Pair<String, String>>): String {
|
||||
return stringListPairAdapter.toJson(list)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun gsonToStringPairList(value: String): List<Pair<String, String>> {
|
||||
return Gson().fromJson(value, object : TypeToken<List<Pair<String, String>>>() {}.type)
|
||||
fun jsonToStringPairList(value: String): List<Pair<String, String>> {
|
||||
return stringListPairAdapter.fromJson(value).orEmpty()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
package io.github.wulkanowy.data.db.adapters
|
||||
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.JsonReader
|
||||
import com.squareup.moshi.JsonWriter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object PairAdapterFactory : JsonAdapter.Factory {
|
||||
|
||||
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
|
||||
if (type !is ParameterizedType || List::class.java != type.rawType) return null
|
||||
if (type.actualTypeArguments[0] != Pair::class.java) return null
|
||||
|
||||
val listType = Types.newParameterizedType(List::class.java, Map::class.java, String::class.java)
|
||||
val listAdapter = moshi.adapter<List<Map<String, String>>>(listType)
|
||||
|
||||
val mapType = Types.newParameterizedType(MutableMap::class.java, String::class.java, String::class.java)
|
||||
val mapAdapter = moshi.adapter<Map<String, String>>(mapType)
|
||||
|
||||
return PairAdapter(listAdapter, mapAdapter)
|
||||
}
|
||||
|
||||
private class PairAdapter(
|
||||
private val listAdapter: JsonAdapter<List<Map<String, String>>>,
|
||||
private val mapAdapter: JsonAdapter<Map<String, String>>,
|
||||
) : JsonAdapter<List<Pair<String, String>>>() {
|
||||
|
||||
override fun toJson(writer: JsonWriter, value: List<Pair<String, String>>?) {
|
||||
writer.beginArray()
|
||||
value?.forEach {
|
||||
writer.beginObject()
|
||||
writer.name("first").value(it.first)
|
||||
writer.name("second").value(it.second)
|
||||
writer.endObject()
|
||||
}
|
||||
writer.endArray()
|
||||
}
|
||||
|
||||
override fun fromJson(reader: JsonReader): List<Pair<String, String>>? {
|
||||
return if (reader.peek() == JsonReader.Token.BEGIN_OBJECT) deserializeMoshiMap(reader)
|
||||
else deserializeGsonPair(reader)
|
||||
}
|
||||
|
||||
// for compatibility with 0.21.0
|
||||
private fun deserializeMoshiMap(reader: JsonReader): List<Pair<String, String>>? {
|
||||
val map = mapAdapter.fromJson(reader) ?: return null
|
||||
|
||||
return map.entries.map {
|
||||
it.key to it.value
|
||||
}
|
||||
}
|
||||
|
||||
private fun deserializeGsonPair(reader: JsonReader): List<Pair<String, String>>? {
|
||||
val list = listAdapter.fromJson(reader) ?: return null
|
||||
|
||||
return list.map {
|
||||
require(it.size == 2) {
|
||||
"pair with more or less than two elements: $list"
|
||||
}
|
||||
|
||||
it["first"].orEmpty() to it["second"].orEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface AttendanceDao : BaseDao<Attendance> {
|
||||
|
||||
@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): Flow<List<Attendance>>
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
|
||||
|
||||
@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): Flow<List<AttendanceSummary>>
|
||||
}
|
||||
|
@ -7,11 +7,11 @@ import androidx.room.Update
|
||||
interface BaseDao<T> {
|
||||
|
||||
@Insert
|
||||
fun insertAll(items: List<T>): List<Long>
|
||||
suspend fun insertAll(items: List<T>): List<Long>
|
||||
|
||||
@Update
|
||||
fun updateAll(items: List<T>)
|
||||
suspend fun updateAll(items: List<T>)
|
||||
|
||||
@Delete
|
||||
fun deleteAll(items: List<T>)
|
||||
suspend fun deleteAll(items: List<T>)
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface CompletedLessonsDao : BaseDao<CompletedLesson> {
|
||||
|
||||
@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): Flow<List<CompletedLesson>>
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface ExamDao : BaseDao<Exam> {
|
||||
|
||||
@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): Flow<List<Exam>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,6 +11,5 @@ import javax.inject.Singleton
|
||||
interface GradeDao : BaseDao<Grade> {
|
||||
|
||||
@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): Flow<List<Grade>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ 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 kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,8 +11,8 @@ import javax.inject.Singleton
|
||||
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<List<GradePointsStatistics>>
|
||||
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Flow<List<GradePointsStatistics>>
|
||||
|
||||
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradePointsStatistics>>
|
||||
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradePointsStatistics>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,8 +11,8 @@ import javax.inject.Singleton
|
||||
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
|
||||
|
||||
@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): Flow<List<GradeStatistics>>
|
||||
|
||||
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
|
||||
fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Maybe<List<GradeStatistics>>
|
||||
fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Flow<List<GradeStatistics>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface GradeSummaryDao : BaseDao<GradeSummary> {
|
||||
|
||||
@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): Flow<List<GradeSummary>>
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface HomeworkDao : BaseDao<Homework> {
|
||||
|
||||
@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): Flow<List<Homework>>
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface LuckyNumberDao : BaseDao<LuckyNumber> {
|
||||
|
||||
@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): Flow<LuckyNumber?>
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||
interface MessageAttachmentDao : BaseDao<MessageAttachment> {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAttachments(items: List<MessageAttachment>): List<Long>
|
||||
suspend fun insertAttachments(items: List<MessageAttachment>): List<Long>
|
||||
}
|
||||
|
@ -5,19 +5,15 @@ import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface MessagesDao : BaseDao<Message> {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
||||
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Single<MessageWithAttachment>
|
||||
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment?>
|
||||
|
||||
@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>>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
|
||||
fun loadDeleted(studentId: Int): Maybe<List<Message>>
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int, folder: Int): Flow<List<Message>>
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||
|
||||
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int): Maybe<List<MobileDevice>>
|
||||
fun loadAll(studentId: Int): Flow<List<MobileDevice>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface NoteDao : BaseDao<Note> {
|
||||
|
||||
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
|
||||
fun loadAll(studentId: Int): Maybe<List<Note>>
|
||||
fun loadAll(studentId: Int): Flow<List<Note>>
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.reactivex.Maybe
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,5 +10,5 @@ import javax.inject.Singleton
|
||||
interface RecipientDao : BaseDao<Recipient> {
|
||||
|
||||
@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>>
|
||||
suspend fun load(studentId: Int, role: Int, unitId: Int): List<Recipient>
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
import io.reactivex.Maybe
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,8 +10,8 @@ import javax.inject.Singleton
|
||||
interface ReportingUnitDao : BaseDao<ReportingUnit> {
|
||||
|
||||
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
|
||||
fun load(studentId: Int): Maybe<List<ReportingUnit>>
|
||||
suspend fun load(studentId: Int): List<ReportingUnit>
|
||||
|
||||
@Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
|
||||
fun loadOne(studentId: Int, unitId: Int): Maybe<ReportingUnit>
|
||||
suspend fun loadOne(studentId: Int, unitId: Int): ReportingUnit?
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ 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 kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface SchoolDao : BaseDao<School> {
|
||||
|
||||
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
|
||||
fun load(studentId: Int, classId: Int): Maybe<School>
|
||||
fun load(studentId: Int, classId: Int): Flow<School?>
|
||||
}
|
||||
|
@ -1,15 +1,19 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Dao
|
||||
interface SemesterDao : BaseDao<Semester> {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertSemesters(items: List<Semester>): List<Long>
|
||||
|
||||
@Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
|
||||
fun loadAll(studentId: Int, classId: Int): Maybe<List<Semester>>
|
||||
suspend fun loadAll(studentId: Int, classId: Int): List<Semester>
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy.ABORT
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.reactivex.Maybe
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -14,23 +15,27 @@ import javax.inject.Singleton
|
||||
interface StudentDao {
|
||||
|
||||
@Insert(onConflict = ABORT)
|
||||
fun insertAll(student: List<Student>): List<Long>
|
||||
suspend fun insertAll(student: List<Student>): List<Long>
|
||||
|
||||
@Delete
|
||||
fun delete(student: Student)
|
||||
suspend fun delete(student: Student)
|
||||
|
||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||
fun loadCurrent(): Maybe<Student>
|
||||
suspend fun loadCurrent(): Student?
|
||||
|
||||
@Query("SELECT * FROM Students WHERE id = :id")
|
||||
fun loadById(id: Int): Maybe<Student>
|
||||
suspend fun loadById(id: Int): Student?
|
||||
|
||||
@Query("SELECT * FROM Students")
|
||||
fun loadAll(): Maybe<List<Student>>
|
||||
suspend fun loadAll(): List<Student>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Students")
|
||||
suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||
|
||||
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
||||
fun updateCurrent(id: Long)
|
||||
suspend fun updateCurrent(id: Long)
|
||||
|
||||
@Query("UPDATE Students SET is_current = 0")
|
||||
fun resetCurrent()
|
||||
suspend fun resetCurrent()
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SubjectDao : BaseDao<Subject> {
|
||||
|
||||
@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): Flow<List<Subject>>
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ 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 kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -11,5 +11,5 @@ import javax.inject.Singleton
|
||||
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>>
|
||||
fun loadAll(studentId: Int, classId: Int): Flow<List<Teacher>>
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface TimetableDao : BaseDao<Timetable> {
|
||||
|
||||
@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): Flow<List<Timetable>>
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Attendance")
|
||||
data class Attendance(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.Month
|
||||
import java.io.Serializable
|
||||
import java.time.Month
|
||||
|
||||
@Entity(tableName = "AttendanceSummary")
|
||||
data class AttendanceSummary(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "CompletedLesson")
|
||||
data class CompletedLesson(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Exams")
|
||||
data class Exam(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Grades")
|
||||
data class Grade(
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "GradesSummary")
|
||||
data class GradeSummary(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Homework")
|
||||
data class Homework(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "LuckyNumbers")
|
||||
data class LuckyNumber (
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "Messages")
|
||||
data class Message(
|
||||
@ -29,8 +29,6 @@ data class Message(
|
||||
|
||||
val subject: String,
|
||||
|
||||
var content: String,
|
||||
|
||||
val date: LocalDateTime,
|
||||
|
||||
@ColumnInfo(name = "folder_id")
|
||||
@ -38,12 +36,6 @@ data class Message(
|
||||
|
||||
var unread: Boolean,
|
||||
|
||||
@ColumnInfo(name = "unread_by")
|
||||
val unreadBy: Int,
|
||||
|
||||
@ColumnInfo(name = "read_by")
|
||||
val readBy: Int,
|
||||
|
||||
val removed: Boolean,
|
||||
|
||||
@ColumnInfo(name = "has_attachments")
|
||||
@ -55,4 +47,12 @@ data class Message(
|
||||
|
||||
@ColumnInfo(name = "is_notified")
|
||||
var isNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "unread_by")
|
||||
var unreadBy: Int = 0
|
||||
|
||||
@ColumnInfo(name = "read_by")
|
||||
var readBy: Int = 0
|
||||
|
||||
var content: String = ""
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "MobileDevices")
|
||||
data class MobileDevice(
|
||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Notes")
|
||||
data class Note(
|
||||
|
@ -4,7 +4,8 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)])
|
||||
data class Semester(
|
||||
@ -36,7 +37,7 @@ data class Semester(
|
||||
|
||||
@ColumnInfo(name = "unit_id")
|
||||
val unitId: Int
|
||||
) {
|
||||
): Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
@ -4,8 +4,8 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)])
|
||||
data class Student(
|
||||
@ -43,6 +43,9 @@ data class Student(
|
||||
@ColumnInfo(name = "user_login_id")
|
||||
val userLoginId: Int,
|
||||
|
||||
@ColumnInfo(name = "user_name")
|
||||
val userName: String,
|
||||
|
||||
@ColumnInfo(name = "student_name")
|
||||
val studentName: String,
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Relation
|
||||
import java.io.Serializable
|
||||
|
||||
data class StudentWithSemesters(
|
||||
@Embedded
|
||||
val student: Student,
|
||||
|
||||
@Relation(parentColumn = "student_id", entityColumn = "student_id")
|
||||
val semesters: List<Semester>
|
||||
) : Serializable
|
@ -3,9 +3,9 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "Timetable")
|
||||
data class Timetable(
|
||||
|
@ -0,0 +1,45 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration27 : Migration(26, 27) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"")
|
||||
|
||||
val students = getStudentsIdsAndNames(database)
|
||||
val units = getReportingUnits(database)
|
||||
|
||||
students.forEach { (id, userLoginId, studentName) ->
|
||||
val userNameFromUnits = units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second
|
||||
val normalizedStudentName = studentName.split(" ").asReversed().joinToString(" ")
|
||||
|
||||
val userName = userNameFromUnits ?: normalizedStudentName
|
||||
database.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||
val studentsCursor = database.query("SELECT id, user_login_id, student_name FROM Students")
|
||||
if (studentsCursor.moveToFirst()) {
|
||||
do {
|
||||
students.add(Triple(studentsCursor.getLong(0), studentsCursor.getInt(1), studentsCursor.getString(2)))
|
||||
} while (studentsCursor.moveToNext())
|
||||
}
|
||||
return students
|
||||
}
|
||||
|
||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val units = mutableListOf<Pair<Int, String>>()
|
||||
val unitsCursor = database.query("SELECT sender_id, sender_name FROM ReportingUnits")
|
||||
if (unitsCursor.moveToFirst()) {
|
||||
do {
|
||||
units.add(unitsCursor.getInt(0) to unitsCursor.getString(1))
|
||||
} while (unitsCursor.moveToNext())
|
||||
}
|
||||
|
||||
return units
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@ package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import org.threeten.bp.LocalDateTime.now
|
||||
import org.threeten.bp.ZoneOffset
|
||||
import java.time.LocalDateTime.now
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class Migration5 : Migration(4, 5) {
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.sdk.pojo.Semester as SdkSemester
|
||||
|
||||
fun List<SdkSemester>.mapToEntities(studentId: Int) = map {
|
||||
Semester(
|
||||
studentId = studentId,
|
||||
diaryId = it.diaryId,
|
||||
diaryName = it.diaryName,
|
||||
schoolYear = it.schoolYear,
|
||||
semesterId = it.semesterId,
|
||||
semesterName = it.semesterNumber,
|
||||
start = it.start,
|
||||
end = it.end,
|
||||
classId = it.classId,
|
||||
unitId = it.unitId
|
||||
)
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.github.wulkanowy.data.mappers
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import java.time.LocalDateTime
|
||||
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
||||
|
||||
fun List<SdkStudent>.mapToEntities(password: String = "") = map {
|
||||
StudentWithSemesters(
|
||||
student = Student(
|
||||
email = it.email,
|
||||
password = password,
|
||||
isParent = it.isParent,
|
||||
symbol = it.symbol,
|
||||
studentId = it.studentId,
|
||||
userLoginId = it.userLoginId,
|
||||
userName = it.userName,
|
||||
studentName = it.studentName + " " + it.studentSurname,
|
||||
schoolSymbol = it.schoolSymbol,
|
||||
schoolShortName = it.schoolShortName,
|
||||
schoolName = it.schoolName,
|
||||
className = it.className,
|
||||
classId = it.classId,
|
||||
scrapperBaseUrl = it.scrapperBaseUrl,
|
||||
loginType = it.loginType.name,
|
||||
isCurrent = false,
|
||||
registrationDate = LocalDateTime.now(),
|
||||
mobileBaseUrl = it.mobileBaseUrl,
|
||||
privateKey = it.privateKey,
|
||||
certificateKey = it.certificateKey,
|
||||
loginMode = it.loginMode.name
|
||||
),
|
||||
semesters = it.semesters.mapToEntities(it.studentId)
|
||||
)
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
package io.github.wulkanowy.data.pojos
|
||||
|
||||
class Contributor(val displayName: String, val githubUsername: String)
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
class Contributor(
|
||||
val displayName: String,
|
||||
val githubUsername: String
|
||||
)
|
||||
|
@ -1,20 +1,24 @@
|
||||
package io.github.wulkanowy.data.repositories.appcreator
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import com.google.gson.Gson
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import io.github.wulkanowy.data.pojos.Contributor
|
||||
import io.reactivex.Single
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AppCreatorRepository @Inject constructor(private val assets: AssetManager) {
|
||||
fun getAppCreators(): Single<List<Contributor>> {
|
||||
return Single.fromCallable {
|
||||
Gson().fromJson(
|
||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||
Array<Contributor>::class.java
|
||||
).toList()
|
||||
}
|
||||
class AppCreatorRepository @Inject constructor(
|
||||
private val assets: AssetManager,
|
||||
private val dispatchers: DispatchersProvider
|
||||
) {
|
||||
|
||||
suspend fun getAppCreators() = withContext(dispatchers.backgroundThread) {
|
||||
val moshi = Moshi.Builder().build()
|
||||
val type = Types.newParameterizedType(List::class.java, Contributor::class.java)
|
||||
val adapter = moshi.adapter<List<Contributor>>(type)
|
||||
adapter.fromJson(assets.open("contributors.json").bufferedReader().use { it.readText() })
|
||||
}
|
||||
}
|
||||
|
@ -3,23 +3,23 @@ package io.github.wulkanowy.data.repositories.attendance
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) {
|
||||
|
||||
fun saveAttendance(attendance: List<Attendance>) {
|
||||
suspend fun saveAttendance(attendance: List<Attendance>) {
|
||||
attendanceDb.insertAll(attendance)
|
||||
}
|
||||
|
||||
fun deleteAttendance(attendance: List<Attendance>) {
|
||||
suspend fun deleteAttendance(attendance: List<Attendance>) {
|
||||
attendanceDb.deleteAll(attendance)
|
||||
}
|
||||
|
||||
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Attendance>> {
|
||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate).filter { it.isNotEmpty() }
|
||||
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Attendance>> {
|
||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||
}
|
||||
}
|
||||
|
@ -6,43 +6,40 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Absent
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import org.threeten.bp.LocalTime
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getAttendance(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Attendance>> {
|
||||
suspend fun getAttendance(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Attendance> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getAttendance(startDate, endDate, semester.semesterId)
|
||||
.map { attendance ->
|
||||
attendance.map {
|
||||
Attendance(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
timeId = it.timeId,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
name = it.name,
|
||||
presence = it.presence,
|
||||
absence = it.absence,
|
||||
exemption = it.exemption,
|
||||
lateness = it.lateness,
|
||||
excused = it.excused,
|
||||
deleted = it.deleted,
|
||||
excusable = it.excusable,
|
||||
excuseStatus = it.excuseStatus?.name
|
||||
)
|
||||
}
|
||||
.map {
|
||||
Attendance(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
timeId = it.timeId,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
name = it.name,
|
||||
presence = it.presence,
|
||||
absence = it.absence,
|
||||
exemption = it.exemption,
|
||||
lateness = it.lateness,
|
||||
excused = it.excused,
|
||||
deleted = it.deleted,
|
||||
excusable = it.excusable,
|
||||
excuseStatus = it.excuseStatus?.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun excuseAbsence(student: Student, semester: Semester, absenceList: List<Attendance>, reason: String?): Single<Boolean> {
|
||||
suspend fun excuseAbsence(student: Student, semester: Semester, absenceList: List<Attendance>, reason: String?): Boolean {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance ->
|
||||
Absent(
|
||||
date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)),
|
||||
|
@ -1,45 +1,34 @@
|
||||
package io.github.wulkanowy.data.repositories.attendance
|
||||
|
||||
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.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: AttendanceLocal,
|
||||
private val remote: AttendanceRemote
|
||||
) {
|
||||
|
||||
fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean): Single<List<Attendance>> {
|
||||
return local.getAttendance(semester, start.monday, end.sunday).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||
if (it) remote.getAttendance(student, semester, start.monday, end.sunday)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newAttendance ->
|
||||
local.getAttendance(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { oldAttendance ->
|
||||
local.deleteAttendance(oldAttendance.uniqueSubtract(newAttendance))
|
||||
local.saveAttendance(newAttendance.uniqueSubtract(oldAttendance))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getAttendance(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
}).map { list -> list.filter { it.date in start..end } }
|
||||
}
|
||||
fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getAttendance(semester, start.monday, end.sunday) },
|
||||
fetch = { remote.getAttendance(student, semester, start.monday, end.sunday) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteAttendance(old uniqueSubtract new)
|
||||
local.saveAttendance(new uniqueSubtract old)
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
|
||||
fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List<Attendance>, reason: String? = null): Single<Boolean> {
|
||||
return remote.excuseAbsence(student, semester, attendanceList, reason)
|
||||
suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List<Attendance>, reason: String? = null) {
|
||||
remote.excuseAbsence(student, semester, attendanceList, reason)
|
||||
}
|
||||
}
|
||||
|
@ -3,22 +3,22 @@ package io.github.wulkanowy.data.repositories.attendancesummary
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: AttendanceSummaryDao) {
|
||||
|
||||
fun saveAttendanceSummary(attendance: List<AttendanceSummary>) {
|
||||
suspend fun saveAttendanceSummary(attendance: List<AttendanceSummary>) {
|
||||
attendanceDb.insertAll(attendance)
|
||||
}
|
||||
|
||||
fun deleteAttendanceSummary(attendance: List<AttendanceSummary>) {
|
||||
suspend fun deleteAttendanceSummary(attendance: List<AttendanceSummary>) {
|
||||
attendanceDb.deleteAll(attendance)
|
||||
}
|
||||
|
||||
fun getAttendanceSummary(semester: Semester, subjectId: Int): Maybe<List<AttendanceSummary>> {
|
||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId).filter { it.isNotEmpty() }
|
||||
fun getAttendanceSummary(semester: Semester, subjectId: Int): Flow<List<AttendanceSummary>> {
|
||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId)
|
||||
}
|
||||
}
|
||||
|
@ -5,32 +5,29 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceSummaryRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int): Single<List<AttendanceSummary>> {
|
||||
suspend fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int): List<AttendanceSummary> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getAttendanceSummary(subjectId)
|
||||
.map { attendance ->
|
||||
attendance.map {
|
||||
AttendanceSummary(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
subjectId = subjectId,
|
||||
month = it.month,
|
||||
presence = it.presence,
|
||||
absence = it.absence,
|
||||
absenceExcused = it.absenceExcused,
|
||||
absenceForSchoolReasons = it.absenceForSchoolReasons,
|
||||
lateness = it.lateness,
|
||||
latenessExcused = it.latenessExcused,
|
||||
exemption = it.exemption
|
||||
)
|
||||
}
|
||||
.map {
|
||||
AttendanceSummary(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
subjectId = subjectId,
|
||||
month = it.month,
|
||||
presence = it.presence,
|
||||
absence = it.absence,
|
||||
absenceExcused = it.absenceExcused,
|
||||
absenceForSchoolReasons = it.absenceForSchoolReasons,
|
||||
lateness = it.lateness,
|
||||
latenessExcused = it.latenessExcused,
|
||||
exemption = it.exemption
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,25 @@
|
||||
package io.github.wulkanowy.data.repositories.attendancesummary
|
||||
|
||||
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.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class AttendanceSummaryRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: AttendanceSummaryLocal,
|
||||
private val remote: AttendanceSummaryRemote
|
||||
) {
|
||||
|
||||
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean = false): Single<List<AttendanceSummary>> {
|
||||
return local.getAttendanceSummary(semester, subjectId).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getAttendanceSummary(student, semester, subjectId)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { new ->
|
||||
local.getAttendanceSummary(semester, subjectId).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteAttendanceSummary(old.uniqueSubtract(new))
|
||||
local.saveAttendanceSummary(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) })
|
||||
}
|
||||
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getAttendanceSummary(semester, subjectId) },
|
||||
fetch = { remote.getAttendanceSummary(student, semester, subjectId) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteAttendanceSummary(old uniqueSubtract new)
|
||||
local.saveAttendanceSummary(new uniqueSubtract old)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -3,23 +3,23 @@ package io.github.wulkanowy.data.repositories.completedlessons
|
||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb: CompletedLessonsDao) {
|
||||
|
||||
fun saveCompletedLessons(completedLessons: List<CompletedLesson>) {
|
||||
suspend fun saveCompletedLessons(completedLessons: List<CompletedLesson>) {
|
||||
completedLessonsDb.insertAll(completedLessons)
|
||||
}
|
||||
|
||||
fun deleteCompleteLessons(completedLessons: List<CompletedLesson>) {
|
||||
suspend fun deleteCompleteLessons(completedLessons: List<CompletedLesson>) {
|
||||
completedLessonsDb.deleteAll(completedLessons)
|
||||
}
|
||||
|
||||
fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Maybe<List<CompletedLesson>> {
|
||||
return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end).filter { it.isNotEmpty() }
|
||||
fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Flow<List<CompletedLesson>> {
|
||||
return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end)
|
||||
}
|
||||
}
|
||||
|
@ -5,34 +5,31 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class CompletedLessonsRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getCompletedLessons(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<CompletedLesson>> {
|
||||
suspend fun getCompletedLessons(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<CompletedLesson> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getCompletedLessons(startDate, endDate)
|
||||
.map { lessons ->
|
||||
lessons.map {
|
||||
it.absence
|
||||
CompletedLesson(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
topic = it.topic,
|
||||
teacher = it.teacher,
|
||||
teacherSymbol = it.teacherSymbol,
|
||||
substitution = it.substitution,
|
||||
absence = it.absence,
|
||||
resources = it.resources
|
||||
)
|
||||
}
|
||||
.map {
|
||||
it.absence
|
||||
CompletedLesson(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
topic = it.topic,
|
||||
teacher = it.teacher,
|
||||
teacherSymbol = it.teacherSymbol,
|
||||
substitution = it.substitution,
|
||||
absence = it.absence,
|
||||
resources = it.resources
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,29 @@
|
||||
package io.github.wulkanowy.data.repositories.completedlessons
|
||||
|
||||
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.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class CompletedLessonsRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: CompletedLessonsLocal,
|
||||
private val remote: CompletedLessonsRemote
|
||||
) {
|
||||
|
||||
fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single<List<CompletedLesson>> {
|
||||
return local.getCompletedLessons(semester, start.monday, end.sunday).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getCompletedLessons(student, semester, start.monday, end.sunday)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { new ->
|
||||
local.getCompletedLessons(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteCompleteLessons(old.uniqueSubtract(new))
|
||||
local.saveCompletedLessons(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getCompletedLessons(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
}).map { list -> list.filter { it.date in start..end } }
|
||||
}
|
||||
fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getCompletedLessons(semester, start.monday, end.sunday) },
|
||||
fetch = { remote.getCompletedLessons(student, semester, start.monday, end.sunday) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteCompleteLessons(old uniqueSubtract new)
|
||||
local.saveCompletedLessons(new uniqueSubtract old)
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
}
|
||||
|
@ -3,24 +3,23 @@ package io.github.wulkanowy.data.repositories.exam
|
||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.LocalDate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
||||
|
||||
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Exam>> {
|
||||
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Exam>> {
|
||||
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||
.filter { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
fun saveExams(exams: List<Exam>) {
|
||||
suspend fun saveExams(exams: List<Exam>) {
|
||||
examDb.insertAll(exams)
|
||||
}
|
||||
|
||||
fun deleteExams(exams: List<Exam>) {
|
||||
suspend fun deleteExams(exams: List<Exam>) {
|
||||
examDb.deleteAll(exams)
|
||||
}
|
||||
}
|
||||
|
@ -5,32 +5,29 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ExamRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getExams(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Exam>> {
|
||||
suspend fun getExams(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Exam> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getExams(startDate, endDate, semester.semesterId)
|
||||
.map { exams ->
|
||||
exams.map {
|
||||
Exam(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
entryDate = it.entryDate,
|
||||
subject = it.subject,
|
||||
group = it.group,
|
||||
type = it.type,
|
||||
description = it.description,
|
||||
teacher = it.teacher,
|
||||
teacherSymbol = it.teacherSymbol
|
||||
)
|
||||
}
|
||||
.map {
|
||||
Exam(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
entryDate = it.entryDate,
|
||||
subject = it.subject,
|
||||
group = it.group,
|
||||
type = it.type,
|
||||
description = it.description,
|
||||
teacher = it.teacher,
|
||||
teacherSymbol = it.teacherSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,29 @@
|
||||
package io.github.wulkanowy.data.repositories.exam
|
||||
|
||||
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.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.endExamsDay
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.startExamsDay
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ExamRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: ExamLocal,
|
||||
private val remote: ExamRemote
|
||||
) {
|
||||
|
||||
fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
||||
return local.getExams(semester, start.monday, end.sunday).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getExams(student, semester, start.monday, end.sunday)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { new ->
|
||||
local.getExams(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteExams(old.uniqueSubtract(new))
|
||||
local.saveExams(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getExams(semester, start.monday, end.sunday)
|
||||
.toSingle(emptyList())
|
||||
}).map { list -> list.filter { it.date in start..end } }
|
||||
}
|
||||
fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getExams(semester, start.startExamsDay, start.endExamsDay) },
|
||||
fetch = { remote.getExams(student, semester, start.startExamsDay, start.endExamsDay) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteExams(old uniqueSubtract new)
|
||||
local.saveExams(new uniqueSubtract old)
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -15,35 +15,35 @@ class GradeLocal @Inject constructor(
|
||||
private val gradeSummaryDb: GradeSummaryDao
|
||||
) {
|
||||
|
||||
fun saveGrades(grades: List<Grade>) {
|
||||
suspend fun saveGrades(grades: List<Grade>) {
|
||||
gradeDb.insertAll(grades)
|
||||
}
|
||||
|
||||
fun deleteGrades(grades: List<Grade>) {
|
||||
suspend fun deleteGrades(grades: List<Grade>) {
|
||||
gradeDb.deleteAll(grades)
|
||||
}
|
||||
|
||||
fun updateGrades(grades: List<Grade>) {
|
||||
suspend fun updateGrades(grades: List<Grade>) {
|
||||
gradeDb.updateAll(grades)
|
||||
}
|
||||
|
||||
fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
suspend fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
gradeSummaryDb.updateAll(gradesSummary)
|
||||
}
|
||||
|
||||
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
||||
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
||||
fun getGradesDetails(semester: Semester): Flow<List<Grade>> {
|
||||
return gradeDb.loadAll(semester.semesterId, semester.studentId)
|
||||
}
|
||||
|
||||
fun saveGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
suspend fun saveGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
gradeSummaryDb.insertAll(gradesSummary)
|
||||
}
|
||||
|
||||
fun deleteGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
suspend fun deleteGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
gradeSummaryDb.deleteAll(gradesSummary)
|
||||
}
|
||||
|
||||
fun getGradesSummary(semester: Semester): Maybe<List<GradeSummary>> {
|
||||
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
||||
fun getGradesSummary(semester: Semester): Flow<List<GradeSummary>> {
|
||||
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
|
||||
}
|
||||
}
|
||||
|
@ -6,48 +6,48 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class GradeRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
fun getGrades(student: Student, semester: Semester): Single<Pair<List<Grade>, List<GradeSummary>>> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
suspend fun getGrades(student: Student, semester: Semester): Pair<List<Grade>, List<GradeSummary>> {
|
||||
val (details, summary) = sdk
|
||||
.init(student)
|
||||
.switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getGrades(semester.semesterId)
|
||||
.map { (details, summary) ->
|
||||
details.map {
|
||||
Grade(
|
||||
studentId = semester.studentId,
|
||||
semesterId = semester.semesterId,
|
||||
subject = it.subject,
|
||||
entry = it.entry,
|
||||
value = it.value,
|
||||
modifier = it.modifier,
|
||||
comment = it.comment,
|
||||
color = it.color,
|
||||
gradeSymbol = it.symbol,
|
||||
description = it.description,
|
||||
weight = it.weight,
|
||||
weightValue = it.weightValue,
|
||||
date = it.date,
|
||||
teacher = it.teacher
|
||||
)
|
||||
} to summary.map {
|
||||
GradeSummary(
|
||||
semesterId = semester.semesterId,
|
||||
studentId = semester.studentId,
|
||||
position = 0,
|
||||
subject = it.name,
|
||||
predictedGrade = it.predicted,
|
||||
finalGrade = it.final,
|
||||
pointsSum = it.pointsSum,
|
||||
proposedPoints = it.proposedPoints,
|
||||
finalPoints = it.finalPoints,
|
||||
average = it.average
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return details.map {
|
||||
Grade(
|
||||
studentId = semester.studentId,
|
||||
semesterId = semester.semesterId,
|
||||
subject = it.subject,
|
||||
entry = it.entry,
|
||||
value = it.value,
|
||||
modifier = it.modifier,
|
||||
comment = it.comment,
|
||||
color = it.color,
|
||||
gradeSymbol = it.symbol,
|
||||
description = it.description,
|
||||
weight = it.weight,
|
||||
weightValue = it.weightValue,
|
||||
date = it.date,
|
||||
teacher = it.teacher
|
||||
)
|
||||
} to summary.map {
|
||||
GradeSummary(
|
||||
semesterId = semester.semesterId,
|
||||
studentId = semester.studentId,
|
||||
position = 0,
|
||||
subject = it.name,
|
||||
predictedGrade = it.predicted,
|
||||
finalGrade = it.final,
|
||||
pointsSum = it.pointsSum,
|
||||
proposedPoints = it.proposedPoints,
|
||||
finalPoints = it.finalPoints,
|
||||
average = it.average
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user