Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
0bccbc6011 | |||
ed6a0f8cd0 | |||
58d5e4da0e | |||
ba6fb1a4b9 | |||
b6b862d4c3 | |||
9b044a19fe | |||
7485cb2a39 | |||
75122d0dcd | |||
39af56484b | |||
05f7e1d115 | |||
9cd5377438 | |||
7a61b233f0 | |||
83dbd9874e | |||
1d9a49d552 | |||
6175081b88 | |||
116e551186 | |||
713500d892 | |||
dfdbe374c2 | |||
b1e3bab5e7 | |||
0b2ef367da | |||
28f27db2b5 | |||
5c70cd8b8c | |||
0f75ff3206 | |||
383cab4dae | |||
e1b0db76c2 | |||
f10684097c | |||
35d4342bec | |||
068aee215a | |||
033074c66b | |||
0de534cb66 | |||
26e4619dde | |||
cf08d1ff24 | |||
96c400a0bd | |||
e238f65dde | |||
ba7966125b | |||
1536208e45 | |||
24cc07264a | |||
1ad5232520 | |||
07f3333029 | |||
214afb82a6 | |||
7a69710261 | |||
64d3afbdb3 | |||
387e46f72d | |||
89acc2f384 | |||
4ef1439878 | |||
6efd170e03 | |||
82cd39329a | |||
b38e0d04e7 | |||
90b2ffe250 | |||
33951dff54 | |||
9ced00c4d7 | |||
2ac1638911 | |||
463a7e2744 | |||
d14382f3b4 | |||
efa0b19cc1 | |||
7cb893a254 | |||
f7371f7b73 | |||
9c626ad517 | |||
9c4c6b0192 | |||
8efc4d750d | |||
e4a6caa13e | |||
209e75160a | |||
153e026a8d | |||
8731c2e1f2 | |||
0977282a4b | |||
667c4b6af7 | |||
1f5088cfc9 | |||
bf6b857a3e | |||
80cb94c434 | |||
0cb4eda32b | |||
d169f964f2 | |||
103ab95c80 | |||
a191f03cdf | |||
63404b8576 | |||
1b7760ff88 | |||
24f58835e7 | |||
b032c459d1 |
@ -7,7 +7,7 @@ references:
|
||||
|
||||
container_config: &container_config
|
||||
docker:
|
||||
- image: circleci/android:api-28
|
||||
- image: circleci/android@sha256:5cdc8626cc6f13efe5ed982cdcdb432b0472f8740fed8743a6461e025ad6cdfc
|
||||
working_directory: *workspace_root
|
||||
environment:
|
||||
environment:
|
||||
@ -35,7 +35,7 @@ jobs:
|
||||
command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true
|
||||
- run:
|
||||
name: Initial build
|
||||
command: ./gradlew build -x test -x lint -x fabricGenerateResourcesRelease -x packageRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
command: ./gradlew build -x test -x lint -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease -x packageRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
- run:
|
||||
name: Run FOSSA
|
||||
command: fossa --no-ansi || true
|
||||
@ -56,7 +56,7 @@ jobs:
|
||||
<<: *general_cache_key
|
||||
- run:
|
||||
name: Run lint
|
||||
command: ./gradlew lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
command: ./gradlew lint -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
- store_artifacts:
|
||||
path: ./app/build/reports/
|
||||
destination: lint_reports/app/
|
||||
@ -75,7 +75,7 @@ jobs:
|
||||
<<: *general_cache_key
|
||||
- run:
|
||||
name: Run app tests
|
||||
command: ./gradlew :app:test :app:jacocoTestReport -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
command: ./gradlew :app:test :app:jacocoTestReport -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
- run:
|
||||
name: Upload unit code coverage to codecov
|
||||
command: bash <(curl -s https://codecov.io/bash) -F app
|
||||
@ -93,6 +93,9 @@ jobs:
|
||||
<<: *container_config
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- run:
|
||||
name: Accept licenses
|
||||
command: yes | sdkmanager --licenses && yes | sdkmanager --update
|
||||
- run:
|
||||
name: Setup emulator
|
||||
command: sdkmanager "system-images;android-19;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;default;armeabi-v7a"
|
||||
@ -113,7 +116,7 @@ jobs:
|
||||
adb shell input keyevent 82
|
||||
- run:
|
||||
name: Run instrumented tests
|
||||
command: ./gradlew clean createDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
command: ./gradlew clean createPlayDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||
- run:
|
||||
name: Collect logs from emulator
|
||||
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
|
||||
@ -159,7 +162,7 @@ jobs:
|
||||
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
|
||||
- run:
|
||||
name: Publish release
|
||||
command: ./gradlew publish --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
|
||||
command: ./gradlew publishPlayRelease --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -48,3 +48,4 @@ app/key.p12
|
||||
app/upload-key.jks
|
||||
*.log
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/uiDesigner.xml
|
||||
|
@ -12,7 +12,7 @@ build:
|
||||
script:
|
||||
- ./gradlew --no-daemon --stacktrace dependencies || true
|
||||
- ./gradlew --no-daemon --stacktrace assembleDebug
|
||||
- mv app/build/outputs/apk/debug/app-debug.apk .
|
||||
- mv app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk .
|
||||
artifacts:
|
||||
name: "${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}-${CI_BUILD_ID}"
|
||||
paths:
|
||||
@ -26,7 +26,7 @@ tests:
|
||||
- .gradle
|
||||
policy: pull
|
||||
script:
|
||||
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesRelease test
|
||||
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease test
|
||||
artifacts:
|
||||
paths:
|
||||
- app/build/reports/tests
|
||||
@ -39,7 +39,7 @@ lint:
|
||||
- .gradle
|
||||
policy: pull
|
||||
script:
|
||||
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesRelease lint
|
||||
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease lint
|
||||
artifacts:
|
||||
paths:
|
||||
- app/build/reports
|
||||
|
12
.idea/runConfigurations.xml
generated
12
.idea/runConfigurations.xml
generated
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
18
.travis.yml
18
.travis.yml
@ -11,10 +11,10 @@ cache:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
#branches:
|
||||
# only:
|
||||
# - master
|
||||
# - 0.7.x
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 0.9.2
|
||||
|
||||
android:
|
||||
licenses:
|
||||
@ -48,20 +48,20 @@ before_script:
|
||||
script:
|
||||
- ./gradlew dependencies --stacktrace --daemon
|
||||
- fossa --no-ansi || true
|
||||
- ./gradlew lint -x fabricGenerateResourcesRelease --stacktrace --daemon
|
||||
- ./gradlew test -x fabricGenerateResourcesRelease --stacktrace --daemon
|
||||
- ./gradlew createDebugCoverageReport --stacktrace --daemon
|
||||
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
|
||||
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
|
||||
- ./gradlew createPlayDebugCoverageReport --stacktrace --daemon
|
||||
- ./gradlew jacocoTestReport --stacktrace --daemon
|
||||
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
|
||||
git fetch --unshallow;
|
||||
./gradlew sonarqube -x test -x lint -x fabricGenerateResourcesRelease -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} --stacktrace --daemon;
|
||||
./gradlew sonarqube -x test -x lint -x fabricGenerateResourcesPlayRelease -x fabricGenerateResourcesFdroidRelease -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} --stacktrace --daemon;
|
||||
fi
|
||||
- |
|
||||
if [ $TRAVIS_TAG ]; then
|
||||
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg;
|
||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg;
|
||||
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg;
|
||||
./gradlew publish -PenableCrashlytics --stacktrace;
|
||||
./gradlew publishPlayRelease -PenableCrashlytics --stacktrace;
|
||||
fi
|
||||
|
||||
after_success:
|
||||
|
@ -1,6 +1,5 @@
|
||||
# Wulkanowy
|
||||
|
||||
[](https://circleci.com/gh/wulkanowy/wulkanowy)
|
||||
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
||||
[](https://www.bitrise.io/app/daeff1893f3c8128)
|
||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||
@ -8,6 +7,8 @@
|
||||
[](https://sonarcloud.io/dashboard?id=io.github.wulkanowy%3Aapp)
|
||||
[](https://app.fossa.com/projects/custom%2B5644%2Fgithub.com%2Fwulkanowy%2Fwulkanowy?ref=badge_shield)
|
||||
[](https://discord.gg/vccAQBr)
|
||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||
|
||||
[Pobierz wersję beta z Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy&utm_source=vcs)
|
||||
|
||||
|
100
app/build.gradle
100
app/build.gradle
@ -6,6 +6,7 @@ apply plugin: 'io.fabric'
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
apply from: 'jacoco.gradle'
|
||||
apply from: 'sonarqube.gradle'
|
||||
apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
@ -16,8 +17,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 28
|
||||
versionCode 33
|
||||
versionName "0.8.0"
|
||||
versionCode 40
|
||||
versionName "0.9.2"
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@ -63,6 +64,18 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "platform"
|
||||
productFlavors {
|
||||
play {
|
||||
dimension "platform"
|
||||
}
|
||||
|
||||
fdroid {
|
||||
buildConfigField "boolean", "CRASHLYTICS_ENABLED", "false"
|
||||
dimension "platform"
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'HardwareIds'
|
||||
}
|
||||
@ -80,75 +93,86 @@ androidExtensions {
|
||||
play {
|
||||
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf"
|
||||
serviceAccountCredentials = file('key.p12')
|
||||
defaultToAppBundles = true
|
||||
defaultToAppBundles = false
|
||||
track = 'alpha'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'io.github.wulkanowy:api:0.8.0'
|
||||
implementation "io.github.wulkanowy:api:0.9.2"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
implementation "androidx.core:core:1.0.2"
|
||||
implementation "androidx.appcompat:appcompat:1.0.2"
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation "androidx.fragment:fragment:1.0.0"
|
||||
implementation "androidx.annotation:annotation:1.1.0"
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation "com.google.android.material:material:1.1.0-alpha05"
|
||||
implementation 'com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
implementation "androidx.recyclerview:recyclerview:1.0.0"
|
||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.0.0"
|
||||
implementation "com.google.android.material:material:1.1.0-alpha07"
|
||||
implementation "com.github.wulkanowy:MaterialChipsInput:b72fd0ee6f"
|
||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||
|
||||
implementation "androidx.work:work-runtime:2.0.1"
|
||||
implementation "androidx.work:work-rxjava2:2.0.1"
|
||||
|
||||
implementation "androidx.room:room-runtime:2.1.0-alpha07"
|
||||
implementation "androidx.room:room-rxjava2:2.1.0-alpha07"
|
||||
kapt "androidx.room:room-compiler:2.1.0-alpha07"
|
||||
implementation "androidx.room:room-runtime:2.1.0-rc01"
|
||||
implementation "androidx.room:room-rxjava2:2.1.0-rc01"
|
||||
kapt "androidx.room:room-compiler:2.1.0-rc01"
|
||||
|
||||
implementation "com.google.dagger:dagger-android-support:2.22.1"
|
||||
kapt "com.google.dagger:dagger-compiler:2.22.1"
|
||||
kapt "com.google.dagger:dagger-android-processor:2.22.1"
|
||||
implementation 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
|
||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
|
||||
implementation "com.google.dagger:dagger-android-support:2.23.1"
|
||||
kapt "com.google.dagger:dagger-compiler:2.23.1"
|
||||
kapt "com.google.dagger:dagger-android-processor:2.23.1"
|
||||
implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0"
|
||||
kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.4.0"
|
||||
|
||||
implementation "eu.davidea:flexible-adapter:5.1.0"
|
||||
implementation "eu.davidea:flexible-adapter-ui:1.0.0"
|
||||
implementation "com.aurelhubert:ahbottomnavigation:2.3.4"
|
||||
implementation 'com.ncapdevi:frag-nav:3.2.0'
|
||||
implementation "com.ncapdevi:frag-nav:3.2.0"
|
||||
|
||||
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.2'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.8"
|
||||
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.3"
|
||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.9"
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.0"
|
||||
implementation "com.google.code.gson:gson:2.8.5"
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.1"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.3"
|
||||
|
||||
implementation "com.mikepenz:aboutlibraries:6.2.3"
|
||||
implementation 'com.takisoft.preferencex:preferencex:1.0.0'
|
||||
implementation "com.takisoft.preferencex:preferencex:1.0.0"
|
||||
|
||||
implementation 'com.google.firebase:firebase-core:16.0.8'
|
||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'
|
||||
playImplementation "com.google.firebase:firebase-core:16.0.9"
|
||||
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||
|
||||
releaseImplementation 'fr.o80.chucker:library-no-op:2.0.4'
|
||||
releaseImplementation "fr.o80.chucker:library-no-op:2.0.4"
|
||||
|
||||
debugImplementation 'fr.o80.chucker:library:2.0.4'
|
||||
debugImplementation "fr.o80.chucker:library:2.0.4"
|
||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
|
||||
|
||||
testImplementation "junit:junit:4.12"
|
||||
testImplementation "io.mockk:mockk:1.9.2"
|
||||
testImplementation "org.mockito:mockito-inline:2.27.0"
|
||||
testImplementation 'org.threeten:threetenbp:1.3.8'
|
||||
testImplementation "org.threeten:threetenbp:1.4.0"
|
||||
testImplementation "org.mockito:mockito-core:2.28.2"
|
||||
testImplementation("org.mockito:mockito-inline:2.28.2") {
|
||||
exclude group: "org.mockito", module: "mockito-core"
|
||||
}
|
||||
|
||||
androidTestImplementation 'androidx.test:core:1.1.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||
androidTestImplementation "androidx.test:core:1.2.0"
|
||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.1"
|
||||
androidTestImplementation "io.mockk:mockk-android:1.9.2"
|
||||
androidTestImplementation 'org.mockito:mockito-android:2.27.0'
|
||||
androidTestImplementation "androidx.room:room-testing:2.1.0-alpha07"
|
||||
androidTestImplementation "androidx.room:room-testing:2.1.0-rc01"
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
androidTestImplementation "org.mockito:mockito-core:2.28.2"
|
||||
androidTestImplementation("org.mockito:mockito-android:2.28.2") {
|
||||
exclude group: 'org.mockito', module: 'mockito-core'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
10
app/hooks.gradle
Normal file
10
app/hooks.gradle
Normal file
@ -0,0 +1,10 @@
|
||||
apply plugin: "com.star-zero.gradle.githook"
|
||||
|
||||
githook {
|
||||
failOnMissingHooksDir = false
|
||||
hooks {
|
||||
"pre-push" {
|
||||
shell = "./app/play-publish-lint.sh"
|
||||
}
|
||||
}
|
||||
}
|
@ -35,11 +35,14 @@ task jacocoTestReport(type: JacocoReport) {
|
||||
dir: "$buildDir/intermediates/classes/debug",
|
||||
excludes: excludes
|
||||
) + fileTree(
|
||||
dir: "$buildDir/tmp/kotlin-classes/debug",
|
||||
dir: "$buildDir/tmp/kotlin-classes/playDebug",
|
||||
excludes: excludes
|
||||
))
|
||||
|
||||
sourceDirectories.setFrom(files("$project.projectDir/src/main/java"))
|
||||
sourceDirectories.setFrom(files([
|
||||
"src/main/java",
|
||||
"src/play/java"
|
||||
]))
|
||||
executionData.setFrom(fileTree(
|
||||
dir: project.projectDir,
|
||||
includes: ["**/*.exec", "**/*.ec"]
|
||||
|
7
app/play-publish-lint.sh
Executable file
7
app/play-publish-lint.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash -
|
||||
|
||||
content=$(cat < "app/src/main/play/release-notes/pl-PL/default.txt") || exit
|
||||
if [[ "${#content}" -gt 500 ]]; then
|
||||
echo >&2 "Release notes content has reached the limit of 500 characters"
|
||||
exit 1
|
||||
fi
|
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@ -37,3 +37,6 @@
|
||||
|
||||
#Config for API
|
||||
-keep class io.github.wulkanowy.api.** {*;}
|
||||
|
||||
#Config for Material Components
|
||||
-keep class com.google.android.material.tabs.** {*;}
|
||||
|
1386
app/schemas/io.github.wulkanowy.data.db.AppDatabase/14.json
Normal file
1386
app/schemas/io.github.wulkanowy.data.db.AppDatabase/14.json
Normal file
File diff suppressed because it is too large
Load Diff
1430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/15.json
Normal file
1430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/15.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,5 +29,6 @@ sonarqube {
|
||||
property "sonar.java.coveragePlugin", "jacoco"
|
||||
property "sonar.android.lint.report", "build/reports/lint-results.xml"
|
||||
property "sonar.jacoco.reportPaths", fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec'])
|
||||
property "sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacocoTestReport/jacocoTestReport.xml"
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,12 @@ abstract class AbstractMigrationTest {
|
||||
fun getMigratedRoomDatabase(): AppDatabase {
|
||||
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
||||
AppDatabase::class.java, dbName)
|
||||
.addMigrations(Migration12(), Migration13())
|
||||
.addMigrations(
|
||||
Migration12(),
|
||||
Migration13(),
|
||||
Migration14(),
|
||||
Migration15()
|
||||
)
|
||||
.build()
|
||||
// close the database and release any stream resources when the test finishes
|
||||
helper.closeWhenFinished(database)
|
||||
|
@ -22,6 +22,7 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.threeten.bp.LocalDate.of
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import io.github.wulkanowy.api.grades.Grade as GradeApi
|
||||
@ -109,4 +110,73 @@ class GradeRepositoryTest {
|
||||
assertTrue { grades[2].isRead }
|
||||
assertTrue { grades[3].isRead }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun subtractLocaleDuplicateGrades() {
|
||||
gradeLocal.saveGrades(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")
|
||||
))
|
||||
|
||||
every { mockApi.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")
|
||||
))
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
|
||||
assertEquals(2, grades.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun subtractRemoteDuplicateGrades() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
))
|
||||
|
||||
every { mockApi.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")
|
||||
))
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
|
||||
assertEquals(3, grades.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyLocal() {
|
||||
gradeLocal.saveGrades(listOf())
|
||||
|
||||
every { mockApi.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")
|
||||
))
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
|
||||
assertEquals(3, grades.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyRemote() {
|
||||
gradeLocal.saveGrades(listOf(
|
||||
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||
))
|
||||
|
||||
every { mockApi.getGrades(1) } returns Single.just(listOf())
|
||||
|
||||
val grades = GradeRepository(settings, gradeLocal, gradeRemote)
|
||||
.getGrades(studentMock, semesterMock, true).blockingGet()
|
||||
|
||||
assertEquals(0, grades.size)
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import org.threeten.bp.LocalDateTime.now
|
||||
import io.github.wulkanowy.api.timetable.Timetable as TimetableRemote
|
||||
import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
|
||||
|
||||
fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = ""): TimetableLocal {
|
||||
fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", subject: String = "", teacher: String = ""): TimetableLocal {
|
||||
return TimetableLocal(
|
||||
studentId = 1,
|
||||
diaryId = 2,
|
||||
@ -20,7 +20,7 @@ fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", s
|
||||
group = "",
|
||||
room = room,
|
||||
roomOld = "",
|
||||
teacher = "",
|
||||
teacher = teacher,
|
||||
teacherOld = "",
|
||||
info = "",
|
||||
changes = false,
|
||||
@ -28,7 +28,7 @@ fun createTimetableLocal(number: Int, start: LocalDateTime, room: String = "", s
|
||||
)
|
||||
}
|
||||
|
||||
fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = ""): TimetableRemote {
|
||||
fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subject: String = "", teacher: String = ""): TimetableRemote {
|
||||
return TimetableRemote(
|
||||
number = number,
|
||||
start = start.toDate(),
|
||||
@ -37,7 +37,7 @@ fun createTimetableRemote(number: Int, start: LocalDateTime, room: String, subje
|
||||
subject = subject,
|
||||
group = "",
|
||||
room = room,
|
||||
teacher = "",
|
||||
teacher = teacher,
|
||||
info = "",
|
||||
changes = false,
|
||||
canceled = false
|
||||
|
@ -63,23 +63,27 @@ class TimetableRepositoryTest {
|
||||
fun copyDetailsToCompletedFromPrevious() {
|
||||
timetableLocal.saveTimetable(listOf(
|
||||
createTimetableLocal(1, of(2019, 3, 5, 8, 0), "123", "Przyroda"),
|
||||
createTimetableLocal(1, of(2019, 3, 5, 8, 50), "321", "Religia"),
|
||||
createTimetableLocal(1, of(2019, 3, 5, 9, 40), "213", "W-F")
|
||||
createTimetableLocal(2, of(2019, 3, 5, 8, 50), "321", "Religia"),
|
||||
createTimetableLocal(3, of(2019, 3, 5, 9, 40), "213", "W-F"),
|
||||
createTimetableLocal(4, of(2019, 3, 5, 10, 30), "213", "W-F", "Jan Kowalski")
|
||||
))
|
||||
|
||||
every { mockApi.getTimetable(any(), any()) } returns Single.just(listOf(
|
||||
createTimetableRemote(1, of(2019, 3, 5, 8, 0), "", "Przyroda"),
|
||||
createTimetableRemote(1, of(2019, 3, 5, 8, 50), "", "Religia"),
|
||||
createTimetableRemote(1, of(2019, 3, 5, 9, 40), "", "W-F")
|
||||
createTimetableRemote(2, of(2019, 3, 5, 8, 50), "", "Religia"),
|
||||
createTimetableRemote(3, of(2019, 3, 5, 9, 40), "", "W-F"),
|
||||
createTimetableRemote(4, of(2019, 3, 5, 10, 30), "", "W-F")
|
||||
))
|
||||
|
||||
val lessons = TimetableRepository(settings, timetableLocal, timetableRemote)
|
||||
.getTimetable(semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true)
|
||||
.blockingGet()
|
||||
|
||||
assertEquals(3, lessons.size)
|
||||
assertEquals(4, lessons.size)
|
||||
assertEquals("123", lessons[0].room)
|
||||
assertEquals("321", lessons[1].room)
|
||||
assertEquals("213", lessons[2].room)
|
||||
|
||||
assertEquals("", lessons[3].teacher)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
@file:Suppress("UNUSED_PARAMETER")
|
||||
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Context
|
||||
import timber.log.Timber
|
||||
|
||||
fun initCrashlytics(context: Context, appInfo: AppInfo) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
class CrashlyticsTree : Timber.Tree() {
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class FirebaseAnalyticsHelper @Inject constructor() {
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun logEvent(name: String, vararg params: Pair<String, Any?>) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
@ -48,8 +48,8 @@
|
||||
android:theme="@style/WulkanowyTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||
android:noHistory="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
@ -57,8 +57,8 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity"
|
||||
android:noHistory="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/WulkanowyTheme.WidgetAccountSwitcher">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
@ -80,7 +80,6 @@
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/provider_widget_timetable" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"
|
||||
android:label="@string/lucky_number_title">
|
||||
|
@ -1,24 +1,23 @@
|
||||
package io.github.wulkanowy
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log.INFO
|
||||
import android.util.Log.VERBOSE
|
||||
import androidx.multidex.MultiDex
|
||||
import androidx.work.Configuration
|
||||
import androidx.work.WorkManager
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.crashlytics.android.core.CrashlyticsCore
|
||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.support.DaggerApplication
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.utils.Log
|
||||
import io.fabric.sdk.android.Fabric
|
||||
import io.github.wulkanowy.BuildConfig.CRASHLYTICS_ENABLED
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.di.DaggerAppComponent
|
||||
import io.github.wulkanowy.services.sync.SyncWorkerFactory
|
||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.CrashlyticsTree
|
||||
import io.github.wulkanowy.utils.DebugLogTree
|
||||
import io.github.wulkanowy.utils.initCrashlytics
|
||||
import io.reactivex.exceptions.UndeliverableException
|
||||
import io.reactivex.plugins.RxJavaPlugins
|
||||
import timber.log.Timber
|
||||
@ -30,6 +29,9 @@ class WulkanowyApp : DaggerApplication() {
|
||||
@Inject
|
||||
lateinit var workerFactory: SyncWorkerFactory
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
super.attachBaseContext(base)
|
||||
MultiDex.install(this)
|
||||
@ -38,15 +40,23 @@ class WulkanowyApp : DaggerApplication() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
AndroidThreeTen.init(this)
|
||||
WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(workerFactory).build())
|
||||
RxJavaPlugins.setErrorHandler(::onError)
|
||||
|
||||
initCrashlytics()
|
||||
initWorkManager()
|
||||
initLogging()
|
||||
initCrashlytics(this, appInfo)
|
||||
}
|
||||
|
||||
private fun initWorkManager() {
|
||||
WorkManager.initialize(this,
|
||||
Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
.build())
|
||||
}
|
||||
|
||||
private fun initLogging() {
|
||||
if (DEBUG) {
|
||||
if (appInfo.isDebug) {
|
||||
Timber.plant(DebugLogTree())
|
||||
FlexibleAdapter.enableLogs(Log.Level.DEBUG)
|
||||
} else {
|
||||
@ -55,15 +65,11 @@ class WulkanowyApp : DaggerApplication() {
|
||||
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
|
||||
}
|
||||
|
||||
private fun initCrashlytics() {
|
||||
Fabric.with(Fabric.Builder(this).kits(
|
||||
Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(!CRASHLYTICS_ENABLED).build()).build()
|
||||
).debuggable(DEBUG).build())
|
||||
}
|
||||
|
||||
private fun onError(error: Throwable) {
|
||||
if (error is UndeliverableException && error.cause is IOException || error.cause is InterruptedException) {
|
||||
Timber.e(error.cause, "An undeliverable error occurred")
|
||||
//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
|
||||
}
|
||||
|
||||
|
@ -132,4 +132,8 @@ internal class RepositoryModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideRecipientDao(database: AppDatabase) = database.recipientDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||
import io.github.wulkanowy.data.db.dao.MessagesDao
|
||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||
@ -33,6 +34,7 @@ import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
@ -44,6 +46,8 @@ import io.github.wulkanowy.data.db.migrations.Migration10
|
||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||
import io.github.wulkanowy.data.db.migrations.Migration12
|
||||
import io.github.wulkanowy.data.db.migrations.Migration13
|
||||
import io.github.wulkanowy.data.db.migrations.Migration14
|
||||
import io.github.wulkanowy.data.db.migrations.Migration15
|
||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
@ -73,7 +77,8 @@ import javax.inject.Singleton
|
||||
LuckyNumber::class,
|
||||
CompletedLesson::class,
|
||||
ReportingUnit::class,
|
||||
Recipient::class
|
||||
Recipient::class,
|
||||
MobileDevice::class
|
||||
],
|
||||
version = AppDatabase.VERSION_SCHEMA,
|
||||
exportSchema = true
|
||||
@ -82,7 +87,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 13
|
||||
const val VERSION_SCHEMA = 15
|
||||
|
||||
fun newInstance(context: Context): AppDatabase {
|
||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||
@ -101,7 +106,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration10(),
|
||||
Migration11(),
|
||||
Migration12(),
|
||||
Migration13()
|
||||
Migration13(),
|
||||
Migration14(),
|
||||
Migration15()
|
||||
)
|
||||
.build()
|
||||
}
|
||||
@ -140,4 +147,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val reportingUnitDao: ReportingUnitDao
|
||||
|
||||
abstract val recipientDao: RecipientDao
|
||||
|
||||
abstract val mobileDeviceDao: MobileDeviceDao
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ interface MessagesDao {
|
||||
@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 real_id = :id")
|
||||
fun load(studentId: Int, id: Int): Maybe<Message>
|
||||
@Query("SELECT * FROM Messages WHERE id = :id")
|
||||
fun load(id: Long): Maybe<Message>
|
||||
|
||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
|
||||
fun loadDeleted(studentId: Int): Maybe<List<Message>>
|
||||
|
@ -0,0 +1,21 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.reactivex.Maybe
|
||||
|
||||
@Dao
|
||||
interface MobileDeviceDao {
|
||||
|
||||
@Insert
|
||||
fun insertAll(devices: List<MobileDevice>)
|
||||
|
||||
@Delete
|
||||
fun deleteAll(devices: List<MobileDevice>)
|
||||
|
||||
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
||||
fun loadAll(studentId: Int): Maybe<List<MobileDevice>>
|
||||
}
|
@ -13,11 +13,26 @@ data class GradeSummary(
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
|
||||
val position: Int,
|
||||
|
||||
val subject: String,
|
||||
|
||||
@ColumnInfo(name = "predicted_grade")
|
||||
val predictedGrade: String,
|
||||
|
||||
val finalGrade: String
|
||||
@ColumnInfo(name = "final_grade")
|
||||
val finalGrade: String,
|
||||
|
||||
@ColumnInfo(name = "proposed_points")
|
||||
val proposedPoints: String,
|
||||
|
||||
@ColumnInfo(name = "final_points")
|
||||
val finalPoints: String,
|
||||
|
||||
@ColumnInfo(name = "points_sum")
|
||||
val pointsSum: String,
|
||||
|
||||
val average: Double
|
||||
) {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
@ -0,0 +1,25 @@
|
||||
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
|
||||
|
||||
@Entity(tableName = "MobileDevices")
|
||||
data class MobileDevice(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
|
||||
@ColumnInfo(name = "device_id")
|
||||
val deviceId: Int,
|
||||
|
||||
val name: String,
|
||||
|
||||
val date: LocalDateTime
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration14 : Migration(13, 14) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS GradesSummary")
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS GradesSummary (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
semester_id INTEGER NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
predicted_grade TEXT NOT NULL,
|
||||
final_grade TEXT NOT NULL,
|
||||
proposed_points TEXT NOT NULL,
|
||||
final_points TEXT NOT NULL,
|
||||
points_sum TEXT NOT NULL,
|
||||
average REAL NOT NULL
|
||||
)
|
||||
""")
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration15 : Migration(14, 15) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS MobileDevices (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
device_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
date INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package io.github.wulkanowy.data.pojos
|
||||
|
||||
data class MobileDeviceToken(
|
||||
|
||||
val token: String,
|
||||
|
||||
val symbol: String,
|
||||
|
||||
val pin: String,
|
||||
|
||||
val qr: String
|
||||
)
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.friday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
@ -31,8 +32,8 @@ class AttendanceRepository @Inject constructor(
|
||||
local.getAttendance(semester, dates.first, dates.second)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { oldAttendance ->
|
||||
local.deleteAttendance(oldAttendance - newAttendance)
|
||||
local.saveAttendance(newAttendance - oldAttendance)
|
||||
local.deleteAttendance(oldAttendance.uniqueSubtract(newAttendance))
|
||||
local.saveAttendance(newAttendance.uniqueSubtract(oldAttendance))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getAttendance(semester, dates.first, dates.second)
|
||||
|
@ -4,6 +4,7 @@ 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.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
@ -25,8 +26,8 @@ class AttendanceSummaryRepository @Inject constructor(
|
||||
}.flatMap { new ->
|
||||
local.getAttendanceSummary(semester, subjectId).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteAttendanceSummary(old - new)
|
||||
local.saveAttendanceSummary(new - old)
|
||||
local.deleteAttendanceSummary(old.uniqueSubtract(new))
|
||||
local.saveAttendanceSummary(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) })
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.friday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
@ -31,8 +32,8 @@ class CompletedLessonsRepository @Inject constructor(
|
||||
local.getCompletedLessons(semester, dates.first, dates.second)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteCompleteLessons(old - new)
|
||||
local.saveCompletedLessons(new - old)
|
||||
local.deleteCompleteLessons(old.uniqueSubtract(new))
|
||||
local.saveCompletedLessons(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getCompletedLessons(semester, dates.first, dates.second)
|
||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.friday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
@ -27,12 +28,12 @@ class ExamRepository @Inject constructor(
|
||||
.flatMap {
|
||||
if (it) remote.getExams(semester, dates.first, dates.second)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newExams ->
|
||||
}.flatMap { new ->
|
||||
local.getExams(semester, dates.first, dates.second)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { oldExams ->
|
||||
local.deleteExams(oldExams - newExams)
|
||||
local.saveExams(newExams - oldExams)
|
||||
.doOnSuccess { old ->
|
||||
local.deleteExams(old.uniqueSubtract(new))
|
||||
local.saveExams(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getExams(semester, dates.first, dates.second)
|
||||
|
@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
|
||||
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.utils.uniqueSubtract
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
@ -24,13 +25,12 @@ class GradeRepository @Inject constructor(
|
||||
.flatMap {
|
||||
if (it) remote.getGrades(semester)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newGrades ->
|
||||
}.flatMap { new ->
|
||||
local.getGrades(semester).toSingle(emptyList())
|
||||
.doOnSuccess { oldGrades ->
|
||||
val notifyBreakDate = oldGrades.maxBy { it.date }?.date
|
||||
?: student.registrationDate.toLocalDate()
|
||||
local.deleteGrades(oldGrades - newGrades)
|
||||
local.saveGrades((newGrades - oldGrades)
|
||||
.doOnSuccess { old ->
|
||||
val notifyBreakDate = old.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
|
||||
local.deleteGrades(old.uniqueSubtract(new))
|
||||
local.saveGrades(new.uniqueSubtract(old)
|
||||
.onEach {
|
||||
if (it.date >= notifyBreakDate) it.apply {
|
||||
isRead = false
|
||||
|
@ -18,9 +18,14 @@ class GradeSummaryRemote @Inject constructor(private val api: Api) {
|
||||
GradeSummary(
|
||||
semesterId = semester.semesterId,
|
||||
studentId = semester.studentId,
|
||||
position = it.order,
|
||||
subject = it.name,
|
||||
predictedGrade = it.predicted,
|
||||
finalGrade = it.final
|
||||
finalGrade = it.final,
|
||||
pointsSum = it.pointsSum,
|
||||
proposedPoints = it.proposedPoints,
|
||||
finalPoints = it.finalPoints,
|
||||
average = it.average
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ 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.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
@ -22,11 +23,11 @@ class GradeSummaryRepository @Inject constructor(
|
||||
.flatMap {
|
||||
if (it) remote.getGradeSummary(semester)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newGradesSummary ->
|
||||
}.flatMap { new ->
|
||||
local.getGradesSummary(semester).toSingle(emptyList())
|
||||
.doOnSuccess { oldGradesSummary ->
|
||||
local.deleteGradesSummary(oldGradesSummary - newGradesSummary)
|
||||
local.saveGradesSummary(newGradesSummary - oldGradesSummary)
|
||||
.doOnSuccess { old ->
|
||||
local.deleteGradesSummary(old.uniqueSubtract(new))
|
||||
local.saveGradesSummary(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getGradesSummary(semester).toSingle(emptyList()) })
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ 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.GradeStatistics
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
@ -22,11 +23,11 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
.flatMap {
|
||||
if (it) remote.getGradeStatistics(semester, isSemester)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newGradesStats ->
|
||||
}.flatMap { new ->
|
||||
local.getGradesStatistics(semester, isSemester).toSingle(emptyList())
|
||||
.doOnSuccess { oldGradesStats ->
|
||||
local.deleteGradesStatistics(oldGradesStats - newGradesStats)
|
||||
local.saveGradesStatistics(newGradesStats - oldGradesStats)
|
||||
.doOnSuccess { old ->
|
||||
local.deleteGradesStatistics(old.uniqueSubtract(new))
|
||||
local.saveGradesStatistics(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.friday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
@ -26,11 +27,11 @@ class HomeworkRepository @Inject constructor(
|
||||
.flatMap {
|
||||
if (it) remote.getHomework(semester, monday, friday)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newGrades ->
|
||||
}.flatMap { new ->
|
||||
local.getHomework(semester, monday, friday).toSingle(emptyList())
|
||||
.doOnSuccess { oldGrades ->
|
||||
local.deleteHomework(oldGrades - newGrades)
|
||||
local.saveHomework(newGrades - oldGrades)
|
||||
.doOnSuccess { old ->
|
||||
local.deleteHomework(old.uniqueSubtract(new))
|
||||
local.saveHomework(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getHomework(semester, monday, friday).toSingle(emptyList()) })
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ class MessageLocal @Inject constructor(private val messagesDb: MessagesDao) {
|
||||
messagesDb.deleteAll(messages)
|
||||
}
|
||||
|
||||
fun getMessage(student: Student, id: Int): Maybe<Message> {
|
||||
return messagesDb.load(student.id.toInt(), id)
|
||||
fun getMessage(id: Long): Maybe<Message> {
|
||||
return messagesDb.load(id)
|
||||
}
|
||||
|
||||
fun getMessages(student: Student, folder: MessageFolder): Maybe<List<Message>> {
|
||||
|
@ -8,6 +8,7 @@ import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.Recipient
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
@ -34,8 +35,8 @@ class MessageRepository @Inject constructor(
|
||||
}.flatMap { new ->
|
||||
local.getMessages(student, folder).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteMessages(old - new)
|
||||
local.saveMessages((new - old)
|
||||
local.deleteMessages(old.uniqueSubtract(new))
|
||||
local.saveMessages(new.uniqueSubtract(old)
|
||||
.onEach {
|
||||
it.isNotified = !notify
|
||||
})
|
||||
@ -45,14 +46,14 @@ class MessageRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun getMessage(student: Student, messageId: Int, markAsRead: Boolean = false): Single<Message> {
|
||||
fun getMessage(student: Student, messageDbId: Long, markAsRead: Boolean = false): Single<Message> {
|
||||
return Single.just(apiHelper.initApi(student))
|
||||
.flatMap { _ ->
|
||||
local.getMessage(student, messageId)
|
||||
local.getMessage(messageDbId)
|
||||
.filter { !it.content.isNullOrEmpty() }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) local.getMessage(student, messageId).toSingle()
|
||||
if (it) local.getMessage(messageDbId).toSingle()
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
.flatMap { dbMessage ->
|
||||
@ -63,7 +64,7 @@ class MessageRepository @Inject constructor(
|
||||
}))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getMessage(student, messageId).toSingle()
|
||||
local.getMessage(messageDbId).toSingle()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package io.github.wulkanowy.data.repositories.mobiledevice
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.reactivex.Maybe
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDao) {
|
||||
|
||||
fun saveDevices(devices: List<MobileDevice>) {
|
||||
mobileDb.insertAll(devices)
|
||||
}
|
||||
|
||||
fun deleteDevices(devices: List<MobileDevice>) {
|
||||
mobileDb.deleteAll(devices)
|
||||
}
|
||||
|
||||
fun getDevices(semester: Semester): Maybe<List<MobileDevice>> {
|
||||
return mobileDb.loadAll(semester.studentId).filter { it.isNotEmpty() }
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package io.github.wulkanowy.data.repositories.mobiledevice
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||
import io.github.wulkanowy.utils.toLocalDateTime
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MobileDeviceRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getDevices(semester: Semester): Single<List<MobileDevice>> {
|
||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||
.flatMap { api.getRegisteredDevices() }
|
||||
.map { devices ->
|
||||
devices.map {
|
||||
MobileDevice(
|
||||
studentId = semester.studentId,
|
||||
date = it.date.toLocalDateTime(),
|
||||
deviceId = it.id,
|
||||
name = it.name
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun unregisterDevice(semester: Semester, device: MobileDevice): Single<Boolean> {
|
||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||
.flatMap { api.unregisterDevice(device.deviceId) }
|
||||
}
|
||||
|
||||
fun getToken(semester: Semester): Single<MobileDeviceToken> {
|
||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||
.flatMap { api.getToken() }
|
||||
.map {
|
||||
MobileDeviceToken(
|
||||
token = it.token,
|
||||
symbol = it.symbol,
|
||||
pin = it.pin,
|
||||
qr = it.qrCodeImage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.github.wulkanowy.data.repositories.mobiledevice
|
||||
|
||||
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.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MobileDeviceRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: MobileDeviceLocal,
|
||||
private val remote: MobileDeviceRemote
|
||||
) {
|
||||
|
||||
fun getDevices(semester: Semester, forceRefresh: Boolean = false): Single<List<MobileDevice>> {
|
||||
return local.getDevices(semester).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getDevices(semester)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { new ->
|
||||
local.getDevices(semester).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteDevices(old uniqueSubtract new)
|
||||
local.saveDevices(new uniqueSubtract old)
|
||||
}
|
||||
}
|
||||
).flatMap { local.getDevices(semester).toSingle(emptyList()) }
|
||||
}
|
||||
|
||||
fun unregisterDevice(semester: Semester, device: MobileDevice): Single<Boolean> {
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.unregisterDevice(semester, device)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
|
||||
fun getToken(semester: Semester): Single<MobileDeviceToken> {
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getToken(semester)
|
||||
else Single.error(UnknownHostException())
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
@ -27,8 +28,8 @@ class NoteRepository @Inject constructor(
|
||||
}.flatMap { new ->
|
||||
local.getNotes(student).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteNotes(old - new)
|
||||
local.saveNotes((new - old)
|
||||
local.deleteNotes(old.uniqueSubtract(new))
|
||||
local.saveNotes(new.uniqueSubtract(old)
|
||||
.onEach {
|
||||
if (it.date >= student.registrationDate.toLocalDate()) it.apply {
|
||||
isRead = false
|
||||
|
@ -20,6 +20,9 @@ class PreferencesRepository @Inject constructor(
|
||||
val gradeAverageMode: String
|
||||
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester"
|
||||
|
||||
val gradeAverageForceCalc: Boolean
|
||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false)
|
||||
|
||||
val isGradeExpandable: Boolean
|
||||
get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false)
|
||||
|
||||
@ -40,7 +43,7 @@ class PreferencesRepository @Inject constructor(
|
||||
|
||||
val servicesOnlyWifiKey: String = context.getString(R.string.pref_key_services_wifi_only)
|
||||
val isServicesOnlyWifi: Boolean
|
||||
get() = sharedPref.getBoolean(servicesOnlyWifiKey, true)
|
||||
get() = sharedPref.getBoolean(servicesOnlyWifiKey, false)
|
||||
|
||||
val isNotificationsEnable: Boolean
|
||||
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_notifications_enable), true)
|
||||
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.data.db.entities.Message
|
||||
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 io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
@ -31,8 +32,8 @@ class RecipientRepository @Inject constructor(
|
||||
}.flatMap { new ->
|
||||
local.getRecipients(student, role, unit).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteRecipients(old - new)
|
||||
local.saveRecipients(new - old)
|
||||
local.deleteRecipients(old.uniqueSubtract(new))
|
||||
local.saveRecipients(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getRecipients(student, role, unit).toSingle(emptyList())
|
||||
|
@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
|
||||
import io.github.wulkanowy.data.ApiHelper
|
||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
@ -30,8 +31,8 @@ class ReportingUnitRepository @Inject constructor(
|
||||
}.flatMap { new ->
|
||||
local.getReportingUnits(student).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteReportingUnits(old - new)
|
||||
local.saveReportingUnits(new - old)
|
||||
local.deleteReportingUnits(old.uniqueSubtract(new))
|
||||
local.saveReportingUnits(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap { local.getReportingUnits(student).toSingle(emptyList()) }
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
|
||||
import io.github.wulkanowy.data.ApiHelper
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
import timber.log.Timber
|
||||
@ -31,8 +32,8 @@ class SemesterRepository @Inject constructor(
|
||||
if (currentSemesters.size == 1) {
|
||||
local.getSemesters(student).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteSemesters(old - new)
|
||||
local.saveSemesters(new - old)
|
||||
local.deleteSemesters(old.uniqueSubtract(new))
|
||||
local.saveSemesters(new.uniqueSubtract(old))
|
||||
}
|
||||
} else {
|
||||
Timber.i("Current semesters list:\n${currentSemesters.joinToString(separator = "\n")}")
|
||||
|
@ -22,6 +22,8 @@ class StudentRepository @Inject constructor(
|
||||
|
||||
fun isStudentSaved(): Single<Boolean> = local.getStudents(false).isEmpty.map { !it }
|
||||
|
||||
fun isCurrentStudentSet(): Single<Boolean> = local.getCurrentStudent(false).isEmpty.map { !it }
|
||||
|
||||
fun getStudents(email: String, password: String, endpoint: String, symbol: String = ""): Single<List<Student>> {
|
||||
return ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
|
@ -4,6 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
@ -26,8 +27,8 @@ class SubjectRepository @Inject constructor(
|
||||
local.getSubjects(semester)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteSubjects(old - new)
|
||||
local.saveSubjects(new - old)
|
||||
local.deleteSubjects(old.uniqueSubtract(new))
|
||||
local.saveSubjects(new.uniqueSubtract(old))
|
||||
}
|
||||
}.flatMap {
|
||||
local.getSubjects(semester).toSingle(emptyList())
|
||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.utils.friday
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
@ -25,17 +26,16 @@ class TimetableRepository @Inject constructor(
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||
if (it) remote.getTimetable(semester, monday, friday)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newTimetable ->
|
||||
}.flatMap { new ->
|
||||
local.getTimetable(semester, monday, friday)
|
||||
.toSingle(emptyList())
|
||||
.doOnSuccess { oldTimetable ->
|
||||
local.deleteTimetable(oldTimetable - newTimetable)
|
||||
local.saveTimetable((newTimetable - oldTimetable).map { item ->
|
||||
.doOnSuccess { old ->
|
||||
local.deleteTimetable(old.uniqueSubtract(new))
|
||||
local.saveTimetable(new.uniqueSubtract(old).map { item ->
|
||||
item.apply {
|
||||
oldTimetable.singleOrNull { this.start == it.start }?.let {
|
||||
old.singleOrNull { this.start == it.start }?.let {
|
||||
return@map copy(
|
||||
room = if (room.isEmpty()) it.room else room,
|
||||
teacher = if (teacher.isEmpty()) it.teacher else teacher
|
||||
room = if (room.isEmpty()) it.room else room
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,13 @@ package io.github.wulkanowy.di
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.BuildConfig.DEBUG
|
||||
import io.github.wulkanowy.WulkanowyApp
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@ -27,16 +25,11 @@ internal class AppModule {
|
||||
@Provides
|
||||
fun provideFlexibleAdapter() = FlexibleAdapter<AbstractFlexibleItem<*>>(null, null, true)
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideFirebaseAnalytics(context: Context) = FirebaseAnalytics.getInstance(context)
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAppWidgetManager(context: Context): AppWidgetManager = AppWidgetManager.getInstance(context)
|
||||
|
||||
@Singleton
|
||||
@Named("isDebug")
|
||||
@Provides
|
||||
fun provideIsDebug() = DEBUG
|
||||
fun provideAppInfo() = AppInfo()
|
||||
}
|
||||
|
@ -6,34 +6,50 @@ import androidx.work.BackoffPolicy.EXPONENTIAL
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingPeriodicWorkPolicy.KEEP
|
||||
import androidx.work.ExistingPeriodicWorkPolicy.REPLACE
|
||||
import androidx.work.NetworkType.METERED
|
||||
import androidx.work.NetworkType.CONNECTED
|
||||
import androidx.work.NetworkType.UNMETERED
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import io.github.wulkanowy.data.db.SharedPrefHelper
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.DebugChannel
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.isHolidays
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MINUTES
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SyncManager @Inject constructor(
|
||||
private val workManager: WorkManager,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
sharedPrefHelper: SharedPrefHelper,
|
||||
newEntriesChannel: NewEntriesChannel,
|
||||
debugChannel: DebugChannel,
|
||||
@Named("isDebug") isDebug: Boolean
|
||||
appInfo: AppInfo
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val APP_VERSION_CODE_KEY = "app_version_code"
|
||||
}
|
||||
|
||||
init {
|
||||
if (SDK_INT >= O) newEntriesChannel.create()
|
||||
if (SDK_INT >= O && isDebug) debugChannel.create()
|
||||
if (now().isHolidays) stopSyncWorker()
|
||||
|
||||
if (SDK_INT > O) {
|
||||
newEntriesChannel.create()
|
||||
if (appInfo.isDebug) debugChannel.create()
|
||||
}
|
||||
|
||||
if (sharedPrefHelper.getLong(APP_VERSION_CODE_KEY, -1L) != appInfo.versionCode.toLong()) {
|
||||
startSyncWorker(true)
|
||||
sharedPrefHelper.putLong(APP_VERSION_CODE_KEY, appInfo.versionCode.toLong(), true)
|
||||
}
|
||||
|
||||
Timber.i("SyncManager was initialized")
|
||||
}
|
||||
|
||||
@ -43,7 +59,7 @@ class SyncManager @Inject constructor(
|
||||
PeriodicWorkRequest.Builder(SyncWorker::class.java, preferencesRepository.servicesInterval, MINUTES, 10, MINUTES)
|
||||
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
||||
.setConstraints(Constraints.Builder()
|
||||
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) METERED else UNMETERED)
|
||||
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED)
|
||||
.build())
|
||||
.build())
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class SyncWorker @AssistedInject constructor(
|
||||
|
||||
override fun createWork(): Single<Result> {
|
||||
Timber.i("SyncWorker is starting")
|
||||
return studentRepository.isStudentSaved()
|
||||
return studentRepository.isCurrentStudentSet()
|
||||
.filter { true }
|
||||
.flatMap { studentRepository.getCurrentStudent().toMaybe() }
|
||||
.flatMapCompletable { student ->
|
||||
|
@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.main.MainView.MenuView
|
||||
import io.github.wulkanowy.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import javax.inject.Inject
|
||||
@ -48,8 +47,8 @@ class GradeWork @Inject constructor(
|
||||
.setDefaults(DEFAULT_ALL)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, 0,
|
||||
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.GRADE), FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getActivity(context, MenuView.GRADE.id,
|
||||
MainActivity.getStartIntent(context, MenuView.GRADE, true), FLAG_UPDATE_CURRENT))
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
||||
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
||||
|
@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.main.MainView.MenuView
|
||||
import io.github.wulkanowy.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import javax.inject.Inject
|
||||
@ -48,9 +47,8 @@ class LuckyNumberWork @Inject constructor(
|
||||
.setPriority(PRIORITY_HIGH)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, MainView.MenuView.MESSAGE.id,
|
||||
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.LUCKY_NUMBER)
|
||||
, FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getActivity(context, MenuView.MESSAGE.id,
|
||||
MainActivity.getStartIntent(context, MenuView.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
|
||||
.build())
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.main.MainView.MenuView
|
||||
import io.github.wulkanowy.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import javax.inject.Inject
|
||||
@ -49,8 +48,8 @@ class MessageWork @Inject constructor(
|
||||
.setPriority(PRIORITY_HIGH)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, MainView.MenuView.MESSAGE.id, MainActivity.getStartIntent(context)
|
||||
.putExtra(EXTRA_START_MENU, MainView.MenuView.MESSAGE), FLAG_UPDATE_CURRENT)
|
||||
PendingIntent.getActivity(context, MenuView.MESSAGE.id,
|
||||
MainActivity.getStartIntent(context, MenuView.MESSAGE, true), FLAG_UPDATE_CURRENT)
|
||||
)
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size))
|
||||
|
@ -15,8 +15,7 @@ import io.github.wulkanowy.data.repositories.note.NoteRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.NewEntriesChannel
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity.Companion.EXTRA_START_MENU
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.main.MainView.MenuView
|
||||
import io.github.wulkanowy.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import javax.inject.Inject
|
||||
@ -48,9 +47,8 @@ class NoteWork @Inject constructor(
|
||||
.setPriority(PRIORITY_HIGH)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, MainView.MenuView.NOTE.id,
|
||||
MainActivity.getStartIntent(context).putExtra(EXTRA_START_MENU, MainView.MenuView.NOTE)
|
||||
, FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getActivity(context, MenuView.NOTE.id,
|
||||
MainActivity.getStartIntent(context, MenuView.NOTE, true), FLAG_UPDATE_CURRENT))
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size))
|
||||
notes.forEach { addLine("${it.teacher}: ${it.category}") }
|
||||
|
@ -1,7 +1,11 @@
|
||||
package io.github.wulkanowy.ui.base
|
||||
|
||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -11,10 +15,12 @@ import dagger.android.AndroidInjection
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.support.HasSupportFragmentInjector
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.utils.FragmentLifecycleLogger
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentInjector {
|
||||
abstract class BaseActivity<T : BasePresenter<out BaseView>> : AppCompatActivity(), BaseView,
|
||||
HasSupportFragmentInjector {
|
||||
|
||||
@Inject
|
||||
lateinit var supportFragmentInjector: DispatchingAndroidInjector<Fragment>
|
||||
@ -25,7 +31,9 @@ abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentI
|
||||
@Inject
|
||||
lateinit var themeManager: ThemeManager
|
||||
|
||||
protected lateinit var messageContainer: View
|
||||
protected var messageContainer: View? = null
|
||||
|
||||
abstract var presenter: T
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
AndroidInjection.inject(this)
|
||||
@ -36,18 +44,38 @@ abstract class BaseActivity : AppCompatActivity(), BaseView, HasSupportFragmentI
|
||||
}
|
||||
|
||||
override fun showError(text: String, error: Throwable) {
|
||||
Snackbar.make(messageContainer, text, LENGTH_LONG).setAction(R.string.all_details) {
|
||||
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
|
||||
}.show()
|
||||
if (messageContainer != null) {
|
||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
||||
.setAction(R.string.all_details) {
|
||||
ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString())
|
||||
}
|
||||
.show()
|
||||
} else showMessage(text)
|
||||
}
|
||||
|
||||
override fun showMessage(text: String) {
|
||||
Snackbar.make(messageContainer, text, LENGTH_LONG).show()
|
||||
if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
||||
else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.main_session_expired)
|
||||
.setMessage(R.string.main_session_relogin)
|
||||
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun openClearLoginView() {
|
||||
startActivity(LoginActivity.getStartIntent(this)
|
||||
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
invalidateOptionsMenu()
|
||||
presenter.onDetachView()
|
||||
}
|
||||
|
||||
override fun supportFragmentInjector() = supportFragmentInjector
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.base
|
||||
|
||||
import android.view.View
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
|
||||
import dagger.android.support.DaggerFragment
|
||||
import io.github.wulkanowy.R
|
||||
|
||||
@ -10,16 +11,30 @@ abstract class BaseFragment : DaggerFragment(), BaseView {
|
||||
protected var messageContainer: View? = null
|
||||
|
||||
override fun showError(text: String, error: Throwable) {
|
||||
if (messageContainer == null) (activity as? BaseActivity)?.showError(text, error)
|
||||
else messageContainer?.also {
|
||||
Snackbar.make(it, text, Snackbar.LENGTH_LONG).setAction(R.string.all_details) {
|
||||
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||
}.show()
|
||||
if (messageContainer != null) {
|
||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG)
|
||||
.setAction(R.string.all_details) {
|
||||
if (isAdded) ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
(activity as? BaseActivity<*>)?.showError(text, error)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showMessage(text: String) {
|
||||
if (messageContainer == null) (activity as? BaseActivity)?.showMessage(text)
|
||||
else messageContainer?.also { Snackbar.make(it, text, Snackbar.LENGTH_LONG).show() }
|
||||
if (messageContainer != null) {
|
||||
Snackbar.make(messageContainer!!, text, LENGTH_LONG).show()
|
||||
} else {
|
||||
(activity as? BaseActivity<*>)?.showMessage(text)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
(activity as? BaseActivity<*>)?.showExpiredDialog()
|
||||
}
|
||||
|
||||
override fun openClearLoginView() {
|
||||
(activity as? BaseActivity<*>)?.openClearLoginView()
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,16 @@
|
||||
package io.github.wulkanowy.ui.base
|
||||
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import timber.log.Timber
|
||||
|
||||
open class BasePresenter<T : BaseView>(private val errorHandler: ErrorHandler) {
|
||||
open class BasePresenter<T : BaseView>(
|
||||
protected val errorHandler: ErrorHandler,
|
||||
protected val studentRepository: StudentRepository,
|
||||
protected val schedulers: SchedulersProvider
|
||||
) {
|
||||
|
||||
val disposable = CompositeDisposable()
|
||||
|
||||
@ -10,7 +18,33 @@ open class BasePresenter<T : BaseView>(private val errorHandler: ErrorHandler) {
|
||||
|
||||
open fun onAttachView(view: T) {
|
||||
this.view = view
|
||||
errorHandler.showErrorMessage = { text, error -> view.showError(text, error) }
|
||||
errorHandler.apply {
|
||||
showErrorMessage = view::showError
|
||||
onSessionExpired = view::showExpiredDialog
|
||||
onNoCurrentStudent = view::openClearLoginView
|
||||
}
|
||||
}
|
||||
|
||||
fun onExpiredLoginSelected() {
|
||||
Timber.i("Attempt to switch the student after the session expires")
|
||||
disposable.add(studentRepository.getCurrentStudent(false)
|
||||
.flatMapCompletable { studentRepository.logoutStudent(it) }
|
||||
.andThen(studentRepository.getSavedStudents(false))
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) {
|
||||
Timber.i("Switching current student")
|
||||
studentRepository.switchStudent(it[0])
|
||||
} else Completable.complete()
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Switch student result: Open login view")
|
||||
view?.openClearLoginView()
|
||||
}, {
|
||||
Timber.i("Switch student result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
}
|
||||
|
||||
open fun onDetachView() {
|
||||
|
@ -5,4 +5,8 @@ interface BaseView {
|
||||
fun showError(text: String, error: Throwable)
|
||||
|
||||
fun showMessage(text: String)
|
||||
|
||||
fun showExpiredDialog()
|
||||
|
||||
fun openClearLoginView()
|
||||
}
|
||||
|
@ -5,7 +5,10 @@ import com.readystatesoftware.chuck.api.ChuckCollector
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.api.interceptor.FeatureDisabledException
|
||||
import io.github.wulkanowy.api.interceptor.ServiceUnavailableException
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException
|
||||
import io.github.wulkanowy.api.login.NotLoggedInException
|
||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||
import io.github.wulkanowy.utils.security.ScramblerException
|
||||
import timber.log.Timber
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
@ -15,6 +18,10 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources,
|
||||
|
||||
var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> }
|
||||
|
||||
var onSessionExpired: () -> Unit = {}
|
||||
|
||||
var onNoCurrentStudent: () -> Unit = {}
|
||||
|
||||
fun dispatch(error: Throwable) {
|
||||
chuckCollector.onError(error.javaClass.simpleName, error)
|
||||
Timber.e(error, "An exception occurred while the Wulkanowy was running")
|
||||
@ -22,17 +29,23 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources,
|
||||
}
|
||||
|
||||
protected open fun proceed(error: Throwable) {
|
||||
showErrorMessage((when (error) {
|
||||
is UnknownHostException -> resources.getString(R.string.error_no_internet)
|
||||
is SocketTimeoutException -> resources.getString(R.string.error_timeout)
|
||||
is NotLoggedInException -> resources.getString(R.string.error_login_failed)
|
||||
is ServiceUnavailableException -> resources.getString(R.string.error_service_unavailable)
|
||||
is FeatureDisabledException -> resources.getString(R.string.error_feature_disabled)
|
||||
else -> resources.getString(R.string.error_unknown)
|
||||
}), error)
|
||||
resources.run {
|
||||
when (error) {
|
||||
is UnknownHostException -> showErrorMessage(getString(R.string.error_no_internet), error)
|
||||
is SocketTimeoutException -> showErrorMessage(getString(R.string.error_timeout), error)
|
||||
is NotLoggedInException -> showErrorMessage(getString(R.string.error_login_failed), error)
|
||||
is ServiceUnavailableException -> showErrorMessage(getString(R.string.error_service_unavailable), error)
|
||||
is FeatureDisabledException -> showErrorMessage(getString(R.string.error_feature_disabled), error)
|
||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||
else -> showErrorMessage(getString(R.string.error_unknown), error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun clear() {
|
||||
showErrorMessage = { _, _ -> }
|
||||
onSessionExpired = {}
|
||||
onNoCurrentStudent = {}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
|
||||
|
||||
private fun isThemeApplicable(activity: AppCompatActivity): Boolean {
|
||||
return activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES)
|
||||
.activities.singleOrNull { it.name == activity.localClassName }?.theme
|
||||
.activities.singleOrNull { it.name == activity::class.java.canonicalName }?.theme
|
||||
.let { it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar }
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
package io.github.wulkanowy.ui.base.session
|
||||
|
||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
|
||||
open class BaseSessionFragment : BaseFragment(), BaseSessionView {
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
(activity as? MainActivity)?.showExpiredDialog()
|
||||
}
|
||||
|
||||
override fun openLoginView() {
|
||||
activity?.also {
|
||||
startActivity(LoginActivity.getStartIntent(it)
|
||||
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package io.github.wulkanowy.ui.base.session
|
||||
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
|
||||
open class BaseSessionPresenter<T : BaseSessionView>(private val errorHandler: SessionErrorHandler) :
|
||||
BasePresenter<T>(errorHandler) {
|
||||
|
||||
override fun onAttachView(view: T) {
|
||||
super.onAttachView(view)
|
||||
errorHandler.apply {
|
||||
onDecryptionFail = { view.showExpiredDialog() }
|
||||
onNoCurrentStudent = { view.openLoginView() }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package io.github.wulkanowy.ui.base.session
|
||||
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface BaseSessionView : BaseView {
|
||||
|
||||
fun showExpiredDialog()
|
||||
|
||||
fun openLoginView()
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package io.github.wulkanowy.ui.base.session
|
||||
|
||||
import android.content.res.Resources
|
||||
import com.readystatesoftware.chuck.api.ChuckCollector
|
||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.security.ScramblerException
|
||||
import javax.inject.Inject
|
||||
|
||||
open class SessionErrorHandler @Inject constructor(
|
||||
resources: Resources,
|
||||
chuckCollector: ChuckCollector
|
||||
) : ErrorHandler(resources, chuckCollector) {
|
||||
|
||||
var onDecryptionFail: () -> Unit = {}
|
||||
|
||||
var onNoCurrentStudent: () -> Unit = {}
|
||||
|
||||
override fun proceed(error: Throwable) {
|
||||
when (error) {
|
||||
is ScramblerException -> onDecryptionFail()
|
||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||
else -> super.proceed(error)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
super.clear()
|
||||
onDecryptionFail = {}
|
||||
onNoCurrentStudent = {}
|
||||
}
|
||||
}
|
@ -8,10 +8,11 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||
import com.mikepenz.aboutlibraries.LibsFragmentCompat
|
||||
import io.github.wulkanowy.BuildConfig
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.withOnExtraListener
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -23,6 +24,9 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
@Inject
|
||||
lateinit var fragmentCompat: LibsFragmentCompat
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
companion object {
|
||||
fun newInstance() = AboutFragment()
|
||||
}
|
||||
@ -57,11 +61,11 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
}
|
||||
|
||||
override fun openDiscordInviteView() {
|
||||
startActivity(Intent.parseUri("https://discord.gg/vccAQBr", 0))
|
||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
||||
}
|
||||
|
||||
override fun openHomepageWebView() {
|
||||
startActivity(Intent.parseUri("https://wulkanowy.github.io/", 0))
|
||||
context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage)
|
||||
}
|
||||
|
||||
override fun openEmailClientView() {
|
||||
@ -70,9 +74,9 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
putExtra(Intent.EXTRA_EMAIL, Array(1) { "wulkanowyinc@gmail.com" })
|
||||
putExtra(Intent.EXTRA_SUBJECT, "Zgłoszenie błędu")
|
||||
putExtra(Intent.EXTRA_TEXT, "Tu umieść treść zgłoszenia\n\n" + "-".repeat(40) + "\n" + """
|
||||
Build: ${BuildConfig.VERSION_CODE}
|
||||
SDK: ${android.os.Build.VERSION.SDK_INT}
|
||||
Device: ${android.os.Build.MANUFACTURER} ${android.os.Build.MODEL}
|
||||
Build: ${appInfo.versionCode}
|
||||
SDK: ${appInfo.systemVersion}
|
||||
Device: ${appInfo.systemManufacturer} ${appInfo.systemModel}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@ -80,7 +84,7 @@ class AboutFragment : BaseFragment(), AboutView, MainView.TitledView {
|
||||
if (intent.resolveActivity(it.packageManager) != null) {
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.about_feedback)))
|
||||
} else {
|
||||
startActivity(Intent.parseUri("https://github.com/wulkanowy/wulkanowy/issues", 0))
|
||||
it.openInternetBrowser("https://github.com/wulkanowy/wulkanowy/issues", ::showMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,20 @@ import com.mikepenz.aboutlibraries.Libs
|
||||
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL1
|
||||
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL2
|
||||
import com.mikepenz.aboutlibraries.Libs.SpecialButton.SPECIAL3
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class AboutPresenter @Inject constructor(
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BasePresenter<AboutView>(errorHandler) {
|
||||
) : BasePresenter<AboutView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
override fun onAttachView(view: AboutView) {
|
||||
super.onAttachView(view)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package io.github.wulkanowy.ui.modules.account
|
||||
|
||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -14,8 +12,8 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.dialog_account.*
|
||||
import javax.inject.Inject
|
||||
@ -74,16 +72,17 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
|
||||
}
|
||||
|
||||
override fun openLoginView() {
|
||||
activity?.also {
|
||||
activity?.let {
|
||||
startActivity(LoginActivity.getStartIntent(it))
|
||||
}
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
(activity as? BaseActivity<*>)?.showExpiredDialog()
|
||||
}
|
||||
|
||||
override fun openClearLoginView() {
|
||||
activity?.also {
|
||||
startActivity(LoginActivity.getStartIntent(it)
|
||||
.apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) })
|
||||
}
|
||||
(activity as? BaseActivity<*>)?.openClearLoginView()
|
||||
}
|
||||
|
||||
override fun showConfirmDialog() {
|
||||
@ -97,11 +96,8 @@ class AccountDialog : DaggerAppCompatDialogFragment(), AccountView {
|
||||
}
|
||||
}
|
||||
|
||||
override fun recreateView() {
|
||||
activity?.also {
|
||||
startActivity(MainActivity.getStartIntent(it))
|
||||
it.finish()
|
||||
}
|
||||
override fun recreateMainView() {
|
||||
activity?.recreate()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -11,11 +11,11 @@ import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class AccountPresenter @Inject constructor(
|
||||
private val errorHandler: ErrorHandler,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val syncManager: SyncManager,
|
||||
private val schedulers: SchedulersProvider
|
||||
) : BasePresenter<AccountView>(errorHandler) {
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val syncManager: SyncManager
|
||||
) : BasePresenter<AccountView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
override fun onAttachView(view: AccountView) {
|
||||
super.onAttachView(view)
|
||||
@ -54,7 +54,7 @@ class AccountPresenter @Inject constructor(
|
||||
openClearLoginView()
|
||||
} else {
|
||||
Timber.i("Logout result: Switch to another student")
|
||||
recreateView()
|
||||
recreateMainView()
|
||||
}
|
||||
}
|
||||
}, {
|
||||
@ -73,9 +73,10 @@ class AccountPresenter @Inject constructor(
|
||||
disposable.add(studentRepository.switchStudent(item.student)
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally { view?.dismissView() }
|
||||
.subscribe({
|
||||
Timber.i("Change a student result: Success")
|
||||
view?.recreateView()
|
||||
view?.recreateMainView()
|
||||
}, {
|
||||
Timber.i("Change a student result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
|
@ -14,8 +14,6 @@ interface AccountView : BaseView {
|
||||
|
||||
fun openLoginView()
|
||||
|
||||
fun openClearLoginView()
|
||||
|
||||
fun recreateView()
|
||||
fun recreateMainView()
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
@ -21,7 +21,7 @@ import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttendanceFragment : BaseSessionFragment(), AttendanceView, MainView.MainChildView, MainView.TitledView {
|
||||
class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: AttendancePresenter
|
||||
@ -103,7 +103,7 @@ class AttendanceFragment : BaseSessionFragment(), AttendanceView, MainView.MainC
|
||||
}
|
||||
|
||||
override fun onFragmentReselected() {
|
||||
presenter.onViewReselected()
|
||||
if (::presenter.isInitialized) presenter.onViewReselected()
|
||||
}
|
||||
|
||||
override fun popView() {
|
||||
|
@ -1,20 +1,14 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.isHolidays
|
||||
import io.github.wulkanowy.utils.nextSchoolDay
|
||||
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.previousSchoolDay
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import io.github.wulkanowy.utils.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import org.threeten.bp.LocalDate.ofEpochDay
|
||||
@ -23,14 +17,14 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttendancePresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val schedulers: SchedulersProvider,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val attendanceRepository: AttendanceRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val prefRepository: PreferencesRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<AttendanceView>(errorHandler) {
|
||||
) : BasePresenter<AttendanceView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
lateinit var currentDate: LocalDate
|
||||
private set
|
||||
@ -115,7 +109,7 @@ class AttendancePresenter @Inject constructor(
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
}
|
||||
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd"))
|
||||
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh)
|
||||
}) {
|
||||
Timber.i("Loading attendance result: An exception occurred")
|
||||
view?.run { showEmpty(isViewEmpty) }
|
||||
|
@ -1,9 +1,9 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface AttendanceView : BaseSessionView {
|
||||
interface AttendanceView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -13,13 +13,13 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.setOnItemSelectedListener
|
||||
import kotlinx.android.synthetic.main.fragment_attendance_summary.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttendanceSummaryFragment : BaseSessionFragment(), AttendanceSummaryView, MainView.TitledView {
|
||||
class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: AttendanceSummaryPresenter
|
||||
|
@ -6,8 +6,8 @@ import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummary
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.subject.SubjectRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.calculatePercentage
|
||||
@ -19,14 +19,14 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttendanceSummaryPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val attendanceSummaryRepository: AttendanceSummaryRepository,
|
||||
private val subjectRepository: SubjectRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val schedulers: SchedulersProvider,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<AttendanceSummaryView>(errorHandler) {
|
||||
) : BasePresenter<AttendanceSummaryView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
private var subjects = emptyList<Subject>()
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance.summary
|
||||
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface AttendanceSummaryView : BaseSessionView {
|
||||
interface AttendanceSummaryView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -13,14 +13,14 @@ import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_exam.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamFragment : BaseSessionFragment(), ExamView, MainView.MainChildView, MainView.TitledView {
|
||||
class ExamFragment : BaseFragment(), ExamView, MainView.MainChildView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: ExamPresenter
|
||||
@ -88,7 +88,7 @@ class ExamFragment : BaseSessionFragment(), ExamView, MainView.MainChildView, Ma
|
||||
}
|
||||
|
||||
override fun onFragmentReselected() {
|
||||
presenter.onViewReselected()
|
||||
if (::presenter.isInitialized) presenter.onViewReselected()
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
|
@ -1,13 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.exam
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.repositories.exam.ExamRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.friday
|
||||
@ -23,13 +22,13 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val schedulers: SchedulersProvider,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val examRepository: ExamRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<ExamView>(errorHandler) {
|
||||
) : BasePresenter<ExamView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
lateinit var currentDate: LocalDate
|
||||
private set
|
||||
@ -102,7 +101,7 @@ class ExamPresenter @Inject constructor(
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
}
|
||||
analytics.logEvent("load_exam", "items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd"))
|
||||
analytics.logEvent("load_exam", "items" to it.size, "force_refresh" to forceRefresh)
|
||||
}) {
|
||||
Timber.i("Loading exam result: An exception occurred")
|
||||
view?.run { showEmpty(isViewEmpty) }
|
||||
|
@ -1,9 +1,9 @@
|
||||
package io.github.wulkanowy.ui.modules.exam
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface ExamView : BaseSessionView {
|
||||
interface ExamView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -3,16 +3,20 @@ package io.github.wulkanowy.ui.modules.grade
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.gradessummary.GradeSummaryRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.utils.calcAverage
|
||||
import io.github.wulkanowy.utils.changeModifier
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeAverageProvider @Inject constructor(
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
private val gradeRepository: GradeRepository
|
||||
private val gradeRepository: GradeRepository,
|
||||
private val gradeSummaryRepository: GradeSummaryRepository
|
||||
) {
|
||||
|
||||
fun getGradeAverage(student: Student, semesters: List<Semester>, selectedSemesterId: Int, forceRefresh: Boolean): Single<Map<String, Double>> {
|
||||
return when (preferencesRepository.gradeAverageMode) {
|
||||
"all_year" -> getAllYearAverage(student, semesters, selectedSemesterId, forceRefresh)
|
||||
@ -27,16 +31,19 @@ class GradeAverageProvider @Inject constructor(
|
||||
val plusModifier = preferencesRepository.gradePlusModifier
|
||||
val minusModifier = preferencesRepository.gradeMinusModifier
|
||||
|
||||
return gradeRepository.getGrades(student, selectedSemester, forceRefresh)
|
||||
.flatMap { firstGrades ->
|
||||
if (selectedSemester == firstSemester) Single.just(firstGrades)
|
||||
else gradeRepository.getGrades(student, firstSemester)
|
||||
.map { secondGrades -> secondGrades + firstGrades }
|
||||
}.map { grades ->
|
||||
grades.map { it.changeModifier(plusModifier, minusModifier) }
|
||||
.groupBy { it.subject }
|
||||
.mapValues { it.value.calcAverage() }
|
||||
}
|
||||
return getAverageFromGradeSummary(selectedSemester, forceRefresh)
|
||||
.switchIfEmpty(gradeRepository.getGrades(student, selectedSemester, forceRefresh)
|
||||
.flatMap { firstGrades ->
|
||||
if (selectedSemester == firstSemester) Single.just(firstGrades)
|
||||
else {
|
||||
gradeRepository.getGrades(student, firstSemester)
|
||||
.map { secondGrades -> secondGrades + firstGrades }
|
||||
}
|
||||
}.map { grades ->
|
||||
grades.map { it.changeModifier(plusModifier, minusModifier) }
|
||||
.groupBy { it.subject }
|
||||
.mapValues { it.value.calcAverage() }
|
||||
})
|
||||
}
|
||||
|
||||
private fun getOnlyOneSemesterAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Single<Map<String, Double>> {
|
||||
@ -44,11 +51,22 @@ class GradeAverageProvider @Inject constructor(
|
||||
val plusModifier = preferencesRepository.gradePlusModifier
|
||||
val minusModifier = preferencesRepository.gradeMinusModifier
|
||||
|
||||
return gradeRepository.getGrades(student, selectedSemester, forceRefresh)
|
||||
.map { grades ->
|
||||
grades.map { it.changeModifier(plusModifier, minusModifier) }
|
||||
.groupBy { it.subject }
|
||||
.mapValues { it.value.calcAverage() }
|
||||
}
|
||||
return getAverageFromGradeSummary(selectedSemester, forceRefresh)
|
||||
.switchIfEmpty(gradeRepository.getGrades(student, selectedSemester, forceRefresh)
|
||||
.map { grades ->
|
||||
grades.map { it.changeModifier(plusModifier, minusModifier) }
|
||||
.groupBy { it.subject }
|
||||
.mapValues { it.value.calcAverage() }
|
||||
})
|
||||
}
|
||||
|
||||
private fun getAverageFromGradeSummary(selectedSemester: Semester, forceRefresh: Boolean): Maybe<Map<String, Double>> {
|
||||
return gradeSummaryRepository.getGradesSummary(selectedSemester, forceRefresh)
|
||||
.toMaybe()
|
||||
.flatMap {
|
||||
if (it.any { summary -> summary.average != .0 }) {
|
||||
Maybe.just(it.map { summary -> summary.subject to summary.average }.toMap())
|
||||
} else Maybe.empty()
|
||||
}.filter { !preferencesRepository.gradeAverageForceCalc }
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
||||
@ -21,7 +21,7 @@ import io.github.wulkanowy.utils.setOnSelectPageListener
|
||||
import kotlinx.android.synthetic.main.fragment_grade.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView, MainView.TitledView {
|
||||
class GradeFragment : BaseFragment(), GradeView, MainView.MainChildView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: GradePresenter
|
||||
@ -88,7 +88,7 @@ class GradeFragment : BaseSessionFragment(), GradeView, MainView.MainChildView,
|
||||
}
|
||||
|
||||
override fun onFragmentReselected() {
|
||||
presenter.onViewReselected()
|
||||
if (::presenter.isInitialized) presenter.onViewReselected()
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
|
@ -3,20 +3,20 @@ package io.github.wulkanowy.ui.modules.grade
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradePresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val schedulers: SchedulersProvider,
|
||||
private val studentRepository: StudentRepository,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<GradeView>(errorHandler) {
|
||||
) : BasePresenter<GradeView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
var selectedIndex = 0
|
||||
private set
|
||||
|
@ -1,8 +1,8 @@
|
||||
package io.github.wulkanowy.ui.modules.grade
|
||||
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface GradeView : BaseSessionView {
|
||||
interface GradeView : BaseView {
|
||||
|
||||
val currentPageIndex: Int
|
||||
|
||||
|
@ -17,7 +17,7 @@ import eu.davidea.flexibleadapter.items.IExpandable
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
@ -25,7 +25,7 @@ import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_grade_details.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeDetailsFragment : BaseSessionFragment(), GradeDetailsView, GradeView.GradeChildView {
|
||||
class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeChildView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: GradeDetailsPresenter
|
||||
|
@ -6,8 +6,8 @@ import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
@ -16,15 +16,15 @@ import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeDetailsPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val schedulers: SchedulersProvider,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val gradeRepository: GradeRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
private val averageProvider: GradeAverageProvider,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<GradeDetailsView>(errorHandler) {
|
||||
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
private var currentSemesterId = 0
|
||||
|
||||
@ -113,7 +113,7 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
.flatMap { (student, semesters) ->
|
||||
averageProvider.getGradeAverage(student, semesters, semesterId, forceRefresh)
|
||||
.flatMap { averages ->
|
||||
gradeRepository.getGrades(student, semesters.first { semester -> semester.semesterId == semesterId })
|
||||
gradeRepository.getGrades(student, semesters.first { it.semesterId == semesterId }, forceRefresh)
|
||||
.map { it.sortedByDescending { grade -> grade.date } }
|
||||
.map { it.groupBy { grade -> grade.subject }.toSortedMap() }
|
||||
.map { createGradeItems(it, averages) }
|
||||
|
@ -4,9 +4,9 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IExpandable
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface GradeDetailsView : BaseSessionView {
|
||||
interface GradeDetailsView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -16,7 +16,7 @@ import com.github.mikephil.charting.data.PieEntry
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
@ -24,7 +24,7 @@ import io.github.wulkanowy.utils.setOnItemSelectedListener
|
||||
import kotlinx.android.synthetic.main.fragment_grade_statistics.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeStatisticsFragment : BaseSessionFragment(), GradeStatisticsView, GradeView.GradeChildView {
|
||||
class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.GradeChildView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: GradeStatisticsPresenter
|
||||
|
@ -6,23 +6,23 @@ import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.subject.SubjectRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeStatisticsPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val gradeStatisticsRepository: GradeStatisticsRepository,
|
||||
private val subjectRepository: SubjectRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
private val schedulers: SchedulersProvider,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<GradeStatisticsView>(errorHandler) {
|
||||
) : BasePresenter<GradeStatisticsView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
private var subjects = emptyList<Subject>()
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface GradeStatisticsView : BaseSessionView {
|
||||
interface GradeStatisticsView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -11,13 +11,13 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeView
|
||||
import kotlinx.android.synthetic.main.fragment_grade_summary.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeSummaryFragment : BaseSessionFragment(), GradeSummaryView, GradeView.GradeChildView {
|
||||
class GradeSummaryFragment : BaseFragment(), GradeSummaryView, GradeView.GradeChildView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: GradeSummaryPresenter
|
||||
|
@ -1,19 +1,21 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.item_grade_summary.*
|
||||
|
||||
class GradeSummaryItem(
|
||||
private val title: String,
|
||||
private val average: String,
|
||||
private val predictedGrade: String,
|
||||
private val finalGrade: String
|
||||
val summary: GradeSummary,
|
||||
private val average: String
|
||||
) : AbstractFlexibleItem<GradeSummaryItem.ViewHolder>() {
|
||||
|
||||
override fun getLayoutRes() = R.layout.item_grade_summary
|
||||
@ -22,12 +24,16 @@ class GradeSummaryItem(
|
||||
return ViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>?) {
|
||||
holder.run {
|
||||
gradeSummaryItemTitle.text = title
|
||||
gradeSummaryItemTitle.text = summary.subject
|
||||
gradeSummaryItemPoints.text = summary.pointsSum
|
||||
gradeSummaryItemAverage.text = average
|
||||
gradeSummaryItemPredicted.text = predictedGrade
|
||||
gradeSummaryItemFinal.text = finalGrade
|
||||
gradeSummaryItemPredicted.text = "${summary.predictedGrade} ${summary.proposedPoints}".trim()
|
||||
gradeSummaryItemFinal.text = "${summary.finalGrade} ${summary.finalPoints}".trim()
|
||||
|
||||
gradeSummaryItemPointsContainer.visibility = if (summary.pointsSum.isBlank()) GONE else VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,18 +44,16 @@ class GradeSummaryItem(
|
||||
other as GradeSummaryItem
|
||||
|
||||
if (average != other.average) return false
|
||||
if (title != other.title) return false
|
||||
if (predictedGrade != other.predictedGrade) return false
|
||||
if (finalGrade != other.finalGrade) return false
|
||||
if (summary != other.summary) return false
|
||||
if (summary.id != other.summary.id) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = title.hashCode()
|
||||
var result = summary.hashCode()
|
||||
result = 31 * result + summary.id.hashCode()
|
||||
result = 31 * result + average.hashCode()
|
||||
result = 31 * result + predictedGrade.hashCode()
|
||||
result = 31 * result + finalGrade.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.repositories.gradessummary.GradeSummaryRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
@ -16,14 +16,14 @@ import java.util.Locale.FRANCE
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradeSummaryPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val gradeSummaryRepository: GradeSummaryRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val averageProvider: GradeAverageProvider,
|
||||
private val schedulers: SchedulersProvider,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<GradeSummaryView>(errorHandler) {
|
||||
) : BasePresenter<GradeSummaryView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
override fun onAttachView(view: GradeSummaryView) {
|
||||
super.onAttachView(view)
|
||||
@ -96,10 +96,8 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
gradesSummary.filter { !checkEmpty(it, filteredAverages) }
|
||||
.map {
|
||||
GradeSummaryItem(
|
||||
title = it.subject,
|
||||
average = formatAverage(filteredAverages.getOrElse(it.subject) { 0.0 }, ""),
|
||||
predictedGrade = it.predictedGrade,
|
||||
finalGrade = it.finalGrade
|
||||
summary = it,
|
||||
average = formatAverage(filteredAverages.getOrElse(it.subject) { 0.0 }, "")
|
||||
)
|
||||
}.let {
|
||||
it to GradeSummaryScrollableHeader(
|
||||
|
@ -1,8 +1,8 @@
|
||||
package io.github.wulkanowy.ui.modules.grade.summary
|
||||
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionView
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface GradeSummaryView : BaseSessionView {
|
||||
interface GradeSummaryView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
|
@ -10,14 +10,14 @@ import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionFragment
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_homework.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class HomeworkFragment : BaseSessionFragment(), HomeworkView, MainView.TitledView {
|
||||
class HomeworkFragment : BaseFragment(), HomeworkView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: HomeworkPresenter
|
||||
|
@ -1,13 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.homework
|
||||
|
||||
import com.google.firebase.analytics.FirebaseAnalytics.Param.START_DATE
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.session.BaseSessionPresenter
|
||||
import io.github.wulkanowy.ui.base.session.SessionErrorHandler
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.friday
|
||||
@ -21,13 +20,13 @@ import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class HomeworkPresenter @Inject constructor(
|
||||
private val errorHandler: SessionErrorHandler,
|
||||
private val schedulers: SchedulersProvider,
|
||||
schedulers: SchedulersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val homeworkRepository: HomeworkRepository,
|
||||
private val studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val analytics: FirebaseAnalyticsHelper
|
||||
) : BaseSessionPresenter<HomeworkView>(errorHandler) {
|
||||
) : BasePresenter<HomeworkView>(errorHandler, studentRepository, schedulers) {
|
||||
|
||||
lateinit var currentDate: LocalDate
|
||||
private set
|
||||
@ -89,7 +88,7 @@ class HomeworkPresenter @Inject constructor(
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
}
|
||||
analytics.logEvent("load_homework", "items" to it.size, "force_refresh" to forceRefresh, START_DATE to currentDate.toFormattedString("yyyy-MM-dd"))
|
||||
analytics.logEvent("load_homework", "items" to it.size, "force_refresh" to forceRefresh)
|
||||
}) {
|
||||
Timber.i("Loading homework result: An exception occurred")
|
||||
view?.run { showEmpty(isViewEmpty()) }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user