Compare commits
No commits in common. "0.12.0" and "0.10.2" have entirely different histories.
155 changed files with 679 additions and 8407 deletions
|
@ -98,7 +98,7 @@ jobs:
|
||||||
command: yes | sdkmanager --licenses && yes | sdkmanager --update
|
command: yes | sdkmanager --licenses && yes | sdkmanager --update
|
||||||
- run:
|
- run:
|
||||||
name: Setup emulator
|
name: Setup emulator
|
||||||
command: sdkmanager "system-images;android-22;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-22;default;armeabi-v7a"
|
command: sdkmanager "system-images;android-19;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;default;armeabi-v7a"
|
||||||
- run:
|
- run:
|
||||||
name: Launch emulator
|
name: Launch emulator
|
||||||
command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on
|
command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on
|
||||||
|
@ -116,7 +116,7 @@ jobs:
|
||||||
adb shell input keyevent 82
|
adb shell input keyevent 82
|
||||||
- run:
|
- run:
|
||||||
name: Run instrumented tests
|
name: Run instrumented tests
|
||||||
command: ./gradlew clean createFdroidDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
command: ./gradlew clean createPlayDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
|
||||||
- run:
|
- run:
|
||||||
name: Collect logs from emulator
|
name: Collect logs from emulator
|
||||||
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
|
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -110,5 +110,4 @@ Thumbs.db
|
||||||
|
|
||||||
### AndroidStudio Patch ###
|
### AndroidStudio Patch ###
|
||||||
|
|
||||||
!/gradle/wrapper/gradle-wrapper.jar
|
!/gradle/wrapper/gradle-wrapper.jar
|
||||||
.idea/jarRepositories.xml
|
|
3
.idea/codeStyles/Project.xml
generated
3
.idea/codeStyles/Project.xml
generated
|
@ -1,9 +1,6 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
<AndroidXmlCodeStyleSettings>
|
|
||||||
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
|
||||||
</AndroidXmlCodeStyleSettings>
|
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
<value>
|
<value>
|
||||||
|
|
14
.travis.yml
14
.travis.yml
|
@ -3,8 +3,8 @@ jdk: oraclejdk8
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- ANDROID_API_LEVEL=29
|
- ANDROID_API_LEVEL=28
|
||||||
- ANDROID_BUILD_TOOLS_VERSION=29.0.2
|
- ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
@ -14,7 +14,7 @@ cache:
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- develop
|
- develop
|
||||||
- 0.12.0
|
- 0.10.2
|
||||||
|
|
||||||
android:
|
android:
|
||||||
licenses:
|
licenses:
|
||||||
|
@ -34,12 +34,12 @@ android:
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- addon-google_apis-google-$ANDROID_API_LEVEL
|
- addon-google_apis-google-$ANDROID_API_LEVEL
|
||||||
# Android emulator
|
# Android emulator
|
||||||
- android-22
|
- android-19
|
||||||
- sys-img-armeabi-v7a-android-22
|
- sys-img-armeabi-v7a-android-19
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
# Launch emulator before the execution
|
# Launch emulator before the execution
|
||||||
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
|
- echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a
|
||||||
- emulator -avd test -no-audio -no-window &
|
- emulator -avd test -no-audio -no-window &
|
||||||
- android-wait-for-emulator
|
- android-wait-for-emulator
|
||||||
- adb shell input keyevent 82 &
|
- adb shell input keyevent 82 &
|
||||||
|
@ -50,7 +50,7 @@ script:
|
||||||
- fossa --no-ansi || true
|
- fossa --no-ansi || true
|
||||||
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
|
#- ./gradlew lintPlayRelease -x fabricGenerateResourcesPlayRelease --stacktrace --daemon
|
||||||
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
|
- ./gradlew testPlayDebugUnitTest -x fabricGenerateResourcesPlay --stacktrace --daemon
|
||||||
- ./gradlew createFdroidDebugCoverageReport --stacktrace --daemon
|
- ./gradlew createPlayDebugCoverageReport --stacktrace --daemon
|
||||||
- ./gradlew jacocoTestReport --stacktrace --daemon
|
- ./gradlew jacocoTestReport --stacktrace --daemon
|
||||||
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
|
- if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else
|
||||||
git fetch --unshallow;
|
git fetch --unshallow;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
|
||||||
Unofficial android VULCAN UONET+ register client for student and parent
|
Unofficial android VULCAN UONET+ register client for student and parent
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
[](https://travis-ci.com/wulkanowy/wulkanowy)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://discord.gg/vccAQBr)
|
[](https://discord.gg/vccAQBr)
|
||||||
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
[](https://f-droid.org/packages/io.github.wulkanowy/)
|
||||||
[](https://github.com/wulkanowy/wulkanowy/releases)
|
[](https://github.com/wulkanowy/wulkanowy/releases)
|
||||||
|
|
||||||
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ apply from: 'sonarqube.gradle'
|
||||||
apply from: 'hooks.gradle'
|
apply from: 'hooks.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 28
|
||||||
buildToolsVersion '29.0.2'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 28
|
||||||
versionCode 47
|
versionCode 45
|
||||||
versionName "0.12.0"
|
versionName "0.10.2"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
@ -28,10 +28,8 @@ android {
|
||||||
]
|
]
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions {
|
annotationProcessorOptions {
|
||||||
arguments = [
|
arguments = ["room.schemaLocation": "$projectDir/schemas".toString(),
|
||||||
"room.schemaLocation": "$projectDir/schemas".toString(),
|
"room.incremental" : "true"]
|
||||||
"room.incremental" : "true"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +61,7 @@ android {
|
||||||
versionNameSuffix "-dev"
|
versionNameSuffix "-dev"
|
||||||
testCoverageEnabled = true
|
testCoverageEnabled = true
|
||||||
ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
|
ext.enableCrashlytics = project.hasProperty("enableCrashlytics")
|
||||||
|
multiDexKeepProguard file('proguard-multidex-rules.pro')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,11 +109,12 @@ play {
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.3.0-alpha03"
|
work_manager = "2.2.0"
|
||||||
room = "2.2.1"
|
room = "2.2.0-rc01"
|
||||||
dagger = "2.25.2"
|
dagger = "2.24"
|
||||||
chucker = "2.0.4"
|
chucker = "2.0.4"
|
||||||
mockk = "1.9.2"
|
mockk = "1.9.2"
|
||||||
|
mockito_core = "3.0.7"
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
|
@ -123,23 +123,23 @@ configurations.all {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:api:0.12.0"
|
implementation "io.github.wulkanowy:api:0.10.2"
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "androidx.core:core-ktx:1.2.0-beta01"
|
implementation "androidx.core:core-ktx:1.1.0"
|
||||||
implementation "androidx.activity:activity-ktx:1.1.0-rc01"
|
implementation "androidx.activity:activity-ktx:1.0.0"
|
||||||
implementation "androidx.appcompat:appcompat:1.1.0"
|
implementation "androidx.appcompat:appcompat:1.1.0"
|
||||||
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
implementation "androidx.appcompat:appcompat-resources:1.1.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.2.0-rc01"
|
implementation "androidx.fragment:fragment-ktx:1.1.0"
|
||||||
implementation "androidx.annotation:annotation:1.1.0"
|
implementation "androidx.annotation:annotation:1.1.0"
|
||||||
implementation "androidx.multidex:multidex:2.0.1"
|
implementation "androidx.multidex:multidex:2.0.1"
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.1.0"
|
implementation "androidx.preference:preference-ktx:1.1.0"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0-rc01"
|
implementation "androidx.recyclerview:recyclerview:1.1.0-beta04"
|
||||||
implementation "androidx.viewpager:viewpager:1.0.0"
|
implementation "androidx.viewpager:viewpager:1.0.0"
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-rc01"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0-beta01"
|
||||||
implementation "com.google.android.material:material:1.1.0-alpha07"
|
implementation "com.google.android.material:material:1.1.0-alpha07"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
|
implementation "com.github.wulkanowy:material-chips-input:2.0.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
|
@ -167,16 +167,16 @@ dependencies {
|
||||||
|
|
||||||
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
|
implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.6"
|
||||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||||
implementation "io.reactivex.rxjava2:rxjava:2.2.13"
|
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
|
||||||
|
|
||||||
implementation "com.google.code.gson:gson:2.8.6"
|
implementation "com.google.code.gson:gson:2.8.5"
|
||||||
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
implementation "com.jakewharton.threetenabp:threetenabp:1.2.1"
|
||||||
implementation "com.jakewharton.timber:timber:4.7.1"
|
implementation "com.jakewharton.timber:timber:4.7.1"
|
||||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:3.12.6"
|
implementation "com.squareup.okhttp3:logging-interceptor:3.12.4"
|
||||||
implementation "com.mikepenz:aboutlibraries:7.0.4"
|
implementation "com.mikepenz:aboutlibraries:7.0.3"
|
||||||
|
|
||||||
playImplementation "com.google.firebase:firebase-core:17.2.1"
|
playImplementation "com.google.firebase:firebase-core:17.2.0"
|
||||||
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
playImplementation "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||||
|
|
||||||
releaseImplementation "fr.o80.chucker:library-no-op:$chucker"
|
releaseImplementation "fr.o80.chucker:library-no-op:$chucker"
|
||||||
|
@ -187,7 +187,10 @@ dependencies {
|
||||||
testImplementation "junit:junit:4.12"
|
testImplementation "junit:junit:4.12"
|
||||||
testImplementation "io.mockk:mockk:$mockk"
|
testImplementation "io.mockk:mockk:$mockk"
|
||||||
testImplementation "org.threeten:threetenbp:1.4.0"
|
testImplementation "org.threeten:threetenbp:1.4.0"
|
||||||
testImplementation "org.mockito:mockito-inline:3.1.0"
|
testImplementation "org.mockito:mockito-core:$mockito_core"
|
||||||
|
testImplementation("org.mockito:mockito-inline:3.0.7") {
|
||||||
|
exclude group: "org.mockito", module: "mockito-core"
|
||||||
|
}
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.2.0"
|
androidTestImplementation "androidx.test:core:1.2.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||||
|
@ -195,7 +198,10 @@ dependencies {
|
||||||
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
androidTestImplementation "io.mockk:mockk-android:$mockk"
|
||||||
androidTestImplementation "androidx.room:room-testing:$room"
|
androidTestImplementation "androidx.room:room-testing:$room"
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||||
androidTestImplementation "org.mockito:mockito-android:3.1.0"
|
androidTestImplementation "org.mockito:mockito-core:$mockito_core"
|
||||||
|
androidTestImplementation("org.mockito:mockito-android:3.0.7") {
|
||||||
|
exclude group: 'org.mockito', module: 'mockito-core'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
3
app/proguard-multidex-rules.pro
Normal file
3
app/proguard-multidex-rules.pro
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
-keep class android.support.test.internal** { *; }
|
||||||
|
-keep class org.junit.** { *; }
|
||||||
|
-keep public class io.github.wulkanowy** { *; }
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,12 @@ abstract class AbstractMigrationTest {
|
||||||
fun getMigratedRoomDatabase(): AppDatabase {
|
fun getMigratedRoomDatabase(): AppDatabase {
|
||||||
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
||||||
AppDatabase::class.java, dbName)
|
AppDatabase::class.java, dbName)
|
||||||
.addMigrations(*AppDatabase.getMigrations())
|
.addMigrations(
|
||||||
|
Migration12(),
|
||||||
|
Migration13(),
|
||||||
|
Migration14(),
|
||||||
|
Migration15()
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
// close the database and release any stream resources when the test finishes
|
// close the database and release any stream resources when the test finishes
|
||||||
helper.closeWhenFinished(database)
|
helper.closeWhenFinished(database)
|
||||||
|
|
|
@ -3,14 +3,10 @@ package io.github.wulkanowy.data.db.migrations
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import io.github.wulkanowy.data.db.Converters
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.threeten.bp.LocalDate.now
|
|
||||||
import org.threeten.bp.LocalDate.of
|
import org.threeten.bp.LocalDate.of
|
||||||
import kotlin.test.assertFalse
|
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class Migration13Test : AbstractMigrationTest() {
|
class Migration13Test : AbstractMigrationTest() {
|
||||||
|
@ -101,9 +97,11 @@ class Migration13Test : AbstractMigrationTest() {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
val db = helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
helper.runMigrationsAndValidate(dbName, 13, true, Migration13())
|
||||||
|
|
||||||
val semesters1 = getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 1 AND class_id = 5")
|
val db = getMigratedRoomDatabase()
|
||||||
|
|
||||||
|
val semesters1 = db.semesterDao.loadAll(1, 5).blockingGet()
|
||||||
assertTrue { semesters1.single { it.isCurrent }.isCurrent }
|
assertTrue { semesters1.single { it.isCurrent }.isCurrent }
|
||||||
semesters1[0].run {
|
semesters1[0].run {
|
||||||
assertFalse(isCurrent)
|
assertFalse(isCurrent)
|
||||||
|
@ -121,7 +119,7 @@ class Migration13Test : AbstractMigrationTest() {
|
||||||
assertEquals(2, diaryId)
|
assertEquals(2, diaryId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
db.semesterDao.loadAll(2, 5).blockingGet().let {
|
||||||
assertTrue { it.single { it.isCurrent }.isCurrent }
|
assertTrue { it.single { it.isCurrent }.isCurrent }
|
||||||
assertEquals(1970, it[0].schoolYear)
|
assertEquals(1970, it[0].schoolYear)
|
||||||
assertEquals(of(1970, 1, 1), it[0].end)
|
assertEquals(of(1970, 1, 1), it[0].end)
|
||||||
|
@ -132,7 +130,7 @@ class Migration13Test : AbstractMigrationTest() {
|
||||||
assertTrue(it[3].isCurrent)
|
assertTrue(it[3].isCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let {
|
db.semesterDao.loadAll(2, 5).blockingGet().let {
|
||||||
assertTrue { it.single { it.isCurrent }.isCurrent }
|
assertTrue { it.single { it.isCurrent }.isCurrent }
|
||||||
assertFalse(it[0].isCurrent)
|
assertFalse(it[0].isCurrent)
|
||||||
assertFalse(it[1].isCurrent)
|
assertFalse(it[1].isCurrent)
|
||||||
|
@ -141,30 +139,6 @@ class Migration13Test : AbstractMigrationTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSemesters(db: SupportSQLiteDatabase, query: String): List<Semester> {
|
|
||||||
val semesters = mutableListOf<Semester>()
|
|
||||||
|
|
||||||
val cursor = db.query(query)
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
semesters.add(Semester(
|
|
||||||
studentId = cursor.getInt(1),
|
|
||||||
diaryId = cursor.getInt(2),
|
|
||||||
diaryName = cursor.getString(3),
|
|
||||||
semesterId = cursor.getInt(4),
|
|
||||||
semesterName = cursor.getInt(5),
|
|
||||||
isCurrent = cursor.getInt(6) == 1,
|
|
||||||
classId = cursor.getInt(7),
|
|
||||||
unitId = cursor.getInt(8),
|
|
||||||
schoolYear = cursor.getInt(9),
|
|
||||||
start = Converters().timestampToDate(cursor.getLong(10))!!,
|
|
||||||
end = Converters().timestampToDate(cursor.getLong(11))!!
|
|
||||||
))
|
|
||||||
} while (cursor.moveToNext())
|
|
||||||
}
|
|
||||||
return semesters.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) {
|
private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) {
|
||||||
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||||
put("endpoint", "https://fakelog.cf")
|
put("endpoint", "https://fakelog.cf")
|
||||||
|
|
|
@ -4,7 +4,6 @@ import androidx.room.Room
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
|
@ -25,7 +24,7 @@ class GradeStatisticsLocalTest {
|
||||||
fun createDb() {
|
fun createDb() {
|
||||||
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
|
||||||
.build()
|
.build()
|
||||||
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics)
|
gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -64,52 +63,7 @@ class GradeStatisticsLocalTest {
|
||||||
assertEquals(stats[0].subject, "Wszystkie")
|
assertEquals(stats[0].subject, "Wszystkie")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveAndRead_points() {
|
|
||||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf(
|
|
||||||
getGradePointsStatistics("Matematyka", 2, 1),
|
|
||||||
getGradePointsStatistics("Chemia", 2, 1),
|
|
||||||
getGradePointsStatistics("Fizyka", 1, 2)
|
|
||||||
))
|
|
||||||
|
|
||||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
|
||||||
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
|
||||||
"Matematyka"
|
|
||||||
).blockingGet()
|
|
||||||
with(stats) {
|
|
||||||
assertEquals(subject, "Matematyka")
|
|
||||||
assertEquals(others, 5.0)
|
|
||||||
assertEquals(student, 5.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveAndRead_subjectEmpty() {
|
|
||||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
|
||||||
|
|
||||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
|
||||||
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
|
||||||
"Matematyka"
|
|
||||||
).blockingGet()
|
|
||||||
assertEquals(null, stats)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveAndRead_allEmpty() {
|
|
||||||
gradeStatisticsLocal.saveGradesPointsStatistics(listOf())
|
|
||||||
|
|
||||||
val stats = gradeStatisticsLocal.getGradesPointsStatistics(
|
|
||||||
Semester(2, 2, "", 2019, 1, 2, true, LocalDate.now(), LocalDate.now(), 1, 1),
|
|
||||||
"Wszystkie"
|
|
||||||
).blockingGet()
|
|
||||||
assertEquals(null, stats)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
|
private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
|
||||||
return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
|
return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics {
|
|
||||||
return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,10 +85,6 @@ internal class RepositoryModule {
|
||||||
@Provides
|
@Provides
|
||||||
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
|
fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMessagesDao(database: AppDatabase) = database.messagesDao
|
fun provideMessagesDao(database: AppDatabase) = database.messagesDao
|
||||||
|
@ -140,12 +136,4 @@ internal class RepositoryModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
|
fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideTeacherDao(database: AppDatabase) = database.teacherDao
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,11 @@ import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeDao
|
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
||||||
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
||||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||||
|
@ -22,18 +20,15 @@ import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||||
import io.github.wulkanowy.data.db.dao.RecipientDao
|
import io.github.wulkanowy.data.db.dao.RecipientDao
|
||||||
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
import io.github.wulkanowy.data.db.dao.ReportingUnitDao
|
||||||
import io.github.wulkanowy.data.db.dao.SchoolDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.dao.SubjectDao
|
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
import io.github.wulkanowy.data.db.dao.TeacherDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
|
@ -43,11 +38,9 @@ import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
import io.github.wulkanowy.data.db.entities.ReportingUnit
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
import io.github.wulkanowy.data.db.migrations.Migration10
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
import io.github.wulkanowy.data.db.migrations.Migration11
|
||||||
|
@ -55,9 +48,6 @@ import io.github.wulkanowy.data.db.migrations.Migration12
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration13
|
import io.github.wulkanowy.data.db.migrations.Migration13
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration14
|
import io.github.wulkanowy.data.db.migrations.Migration14
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration15
|
import io.github.wulkanowy.data.db.migrations.Migration15
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration16
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration17
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration18
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
|
@ -80,7 +70,6 @@ import javax.inject.Singleton
|
||||||
Grade::class,
|
Grade::class,
|
||||||
GradeSummary::class,
|
GradeSummary::class,
|
||||||
GradeStatistics::class,
|
GradeStatistics::class,
|
||||||
GradePointsStatistics::class,
|
|
||||||
Message::class,
|
Message::class,
|
||||||
Note::class,
|
Note::class,
|
||||||
Homework::class,
|
Homework::class,
|
||||||
|
@ -89,9 +78,7 @@ import javax.inject.Singleton
|
||||||
CompletedLesson::class,
|
CompletedLesson::class,
|
||||||
ReportingUnit::class,
|
ReportingUnit::class,
|
||||||
Recipient::class,
|
Recipient::class,
|
||||||
MobileDevice::class,
|
MobileDevice::class
|
||||||
Teacher::class,
|
|
||||||
School::class
|
|
||||||
],
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
|
@ -100,36 +87,29 @@ import javax.inject.Singleton
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 18
|
const val VERSION_SCHEMA = 15
|
||||||
|
|
||||||
fun getMigrations(): Array<Migration> {
|
|
||||||
return arrayOf(
|
|
||||||
Migration2(),
|
|
||||||
Migration3(),
|
|
||||||
Migration4(),
|
|
||||||
Migration5(),
|
|
||||||
Migration6(),
|
|
||||||
Migration7(),
|
|
||||||
Migration8(),
|
|
||||||
Migration9(),
|
|
||||||
Migration10(),
|
|
||||||
Migration11(),
|
|
||||||
Migration12(),
|
|
||||||
Migration13(),
|
|
||||||
Migration14(),
|
|
||||||
Migration15(),
|
|
||||||
Migration16(),
|
|
||||||
Migration17(),
|
|
||||||
Migration18()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newInstance(context: Context): AppDatabase {
|
fun newInstance(context: Context): AppDatabase {
|
||||||
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
|
||||||
.setJournalMode(TRUNCATE)
|
.setJournalMode(TRUNCATE)
|
||||||
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
|
.fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
|
||||||
.fallbackToDestructiveMigrationOnDowngrade()
|
.fallbackToDestructiveMigrationOnDowngrade()
|
||||||
.addMigrations(*getMigrations())
|
.addMigrations(
|
||||||
|
Migration2(),
|
||||||
|
Migration3(),
|
||||||
|
Migration4(),
|
||||||
|
Migration5(),
|
||||||
|
Migration6(),
|
||||||
|
Migration7(),
|
||||||
|
Migration8(),
|
||||||
|
Migration9(),
|
||||||
|
Migration10(),
|
||||||
|
Migration11(),
|
||||||
|
Migration12(),
|
||||||
|
Migration13(),
|
||||||
|
Migration14(),
|
||||||
|
Migration15()
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,8 +132,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract val gradeStatistics: GradeStatisticsDao
|
abstract val gradeStatistics: GradeStatisticsDao
|
||||||
|
|
||||||
abstract val gradePointsStatistics: GradePointsStatisticsDao
|
|
||||||
|
|
||||||
abstract val messagesDao: MessagesDao
|
abstract val messagesDao: MessagesDao
|
||||||
|
|
||||||
abstract val noteDao: NoteDao
|
abstract val noteDao: NoteDao
|
||||||
|
@ -171,8 +149,4 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
abstract val recipientDao: RecipientDao
|
abstract val recipientDao: RecipientDao
|
||||||
|
|
||||||
abstract val mobileDeviceDao: MobileDeviceDao
|
abstract val mobileDeviceDao: MobileDeviceDao
|
||||||
|
|
||||||
abstract val teacherDao: TeacherDao
|
|
||||||
|
|
||||||
abstract val schoolDao: SchoolDao
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
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.GradePointsStatistics
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface GradePointsStatisticsDao {
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(gradesStatistics: List<GradePointsStatistics>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(gradesStatistics: List<GradePointsStatistics>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
|
|
||||||
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe<GradePointsStatistics>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
|
|
||||||
fun loadAll(semesterId: Int, studentId: Int): Maybe<List<GradePointsStatistics>>
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
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.School
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface SchoolDao {
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insert(school: School)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun delete(school: School)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
|
|
||||||
fun load(studentId: Int, classId: Int): Maybe<School>
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
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.Teacher
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Dao
|
|
||||||
interface TeacherDao {
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insertAll(teachers: List<Teacher>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteAll(teachers: List<Teacher>)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
|
|
||||||
fun loadAll(studentId: Int, classId: Int): Maybe<List<Teacher>>
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
@Entity(tableName = "GradesPointsStatistics")
|
|
||||||
data class GradePointsStatistics(
|
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
|
||||||
val studentId: Int,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "semester_id")
|
|
||||||
val semesterId: Int,
|
|
||||||
|
|
||||||
val subject: String,
|
|
||||||
|
|
||||||
val others: Double,
|
|
||||||
|
|
||||||
val student: Double
|
|
||||||
) {
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
@Entity(tableName = "School")
|
|
||||||
data class School(
|
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
|
||||||
val studentId: Int,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "class_id")
|
|
||||||
val classId: Int,
|
|
||||||
|
|
||||||
val name: String,
|
|
||||||
|
|
||||||
val address: String,
|
|
||||||
|
|
||||||
val contact: String,
|
|
||||||
|
|
||||||
val headmaster: String,
|
|
||||||
|
|
||||||
val pedagogue: String
|
|
||||||
) : Serializable {
|
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.entities
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
@Entity(tableName = "Teachers")
|
|
||||||
data class Teacher(
|
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
|
||||||
val studentId: Int,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "class_id")
|
|
||||||
val classId: Int,
|
|
||||||
|
|
||||||
val subject: String,
|
|
||||||
|
|
||||||
val name: String,
|
|
||||||
|
|
||||||
@ColumnInfo(name = "short_name")
|
|
||||||
val shortName: String
|
|
||||||
) : Serializable {
|
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration16 : Migration(15, 16) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("""
|
|
||||||
CREATE TABLE IF NOT EXISTS Teachers (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
student_id INTEGER NOT NULL,
|
|
||||||
class_id INTEGER NOT NULL,
|
|
||||||
subject TEXT NOT NULL,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
short_name TEXT NOT NULL
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration17 : Migration(16, 17) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
createGradesPointsStatisticsTable(database)
|
|
||||||
truncateSemestersTable(database)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("""
|
|
||||||
CREATE TABLE IF NOT EXISTS GradesPointsStatistics(
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
student_id INTEGER NOT NULL,
|
|
||||||
semester_id INTEGER NOT NULL,
|
|
||||||
subject TEXT NOT NULL,
|
|
||||||
others REAL NOT NULL,
|
|
||||||
student REAL NOT NULL
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun truncateSemestersTable(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("DELETE FROM Semesters")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package io.github.wulkanowy.data.db.migrations
|
|
||||||
|
|
||||||
import androidx.room.migration.Migration
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
|
||||||
|
|
||||||
class Migration18 : Migration(17, 18) {
|
|
||||||
|
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
|
||||||
database.execSQL("""
|
|
||||||
CREATE TABLE IF NOT EXISTS School (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
student_id INTEGER NOT NULL,
|
|
||||||
class_id INTEGER NOT NULL,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
address TEXT NOT NULL,
|
|
||||||
contact TEXT NOT NULL,
|
|
||||||
headmaster TEXT NOT NULL,
|
|
||||||
pedagogue TEXT NOT NULL
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
package io.github.wulkanowy.data.repositories.gradestatistics
|
package io.github.wulkanowy.data.repositories.gradestatistics
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
|
||||||
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
|
@ -10,57 +8,27 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class GradeStatisticsLocal @Inject constructor(
|
class GradeStatisticsLocal @Inject constructor(private val gradeStatisticsDb: GradeStatisticsDao) {
|
||||||
private val gradeStatisticsDb: GradeStatisticsDao,
|
|
||||||
private val gradePointsStatisticsDb: GradePointsStatisticsDao
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
|
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe<List<GradeStatistics>> {
|
||||||
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).filter { it.isNotEmpty() }
|
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
|
||||||
}
|
.filter { !it.isEmpty() }
|
||||||
|
|
||||||
fun getGradesPointsStatistics(semester: Semester): Maybe<List<GradePointsStatistics>> {
|
|
||||||
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
|
fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe<List<GradeStatistics>> {
|
||||||
return when (subjectName) {
|
return (if ("Wszystkie" == subjectName) gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
|
||||||
"Wszystkie" -> gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list ->
|
list.groupBy { it.grade }.map {
|
||||||
list.groupBy { it.grade }.map {
|
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
||||||
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
|
|
||||||
it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)
|
|
||||||
}.filter { it.isNotEmpty() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getGradesPointsStatistics(semester: Semester, subjectName: String): Maybe<GradePointsStatistics> {
|
|
||||||
return when (subjectName) {
|
|
||||||
"Wszystkie" -> gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).flatMap { list ->
|
|
||||||
if (list.isEmpty()) return@flatMap Maybe.empty<GradePointsStatistics>()
|
|
||||||
Maybe.just(GradePointsStatistics(semester.studentId, semester.semesterId, subjectName,
|
|
||||||
list.fold(.0) { acc, e -> acc + e.others },
|
|
||||||
list.fold(.0) { acc, e -> acc + e.student })
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> gradePointsStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName)
|
|
||||||
}
|
}
|
||||||
|
else gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)).filter { !it.isEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
||||||
gradeStatisticsDb.insertAll(gradesStatistics)
|
gradeStatisticsDb.insertAll(gradesStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveGradesPointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) {
|
|
||||||
gradePointsStatisticsDb.insertAll(gradePointsStatistics)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
||||||
gradeStatisticsDb.deleteAll(gradesStatistics)
|
gradeStatisticsDb.deleteAll(gradesStatistics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteGradesPointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) {
|
|
||||||
gradePointsStatisticsDb.deleteAll(gradesPointsStatistics)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.wulkanowy.data.repositories.gradestatistics
|
package io.github.wulkanowy.data.repositories.gradestatistics
|
||||||
|
|
||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
@ -13,10 +12,7 @@ class GradeStatisticsRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
|
fun getGradeStatistics(semester: Semester, isSemester: Boolean): Single<List<GradeStatistics>> {
|
||||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
return Single.just(api.apply { diaryId = semester.diaryId })
|
||||||
.flatMap {
|
.flatMap { it.getGradesStatistics(semester.semesterId, isSemester) }
|
||||||
if (isSemester) it.getGradesAnnualStatistics(semester.semesterId)
|
|
||||||
else it.getGradesPartialStatistics(semester.semesterId)
|
|
||||||
}
|
|
||||||
.map { gradeStatistics ->
|
.map { gradeStatistics ->
|
||||||
gradeStatistics.map {
|
gradeStatistics.map {
|
||||||
GradeStatistics(
|
GradeStatistics(
|
||||||
|
@ -30,20 +26,4 @@ class GradeStatisticsRemote @Inject constructor(private val api: Api) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradePointsStatistics(semester: Semester): Single<List<GradePointsStatistics>> {
|
|
||||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
|
||||||
.flatMap { it.getGradesPointsStatistics(semester.semesterId) }
|
|
||||||
.map { gradePointsStatistics ->
|
|
||||||
gradePointsStatistics.map {
|
|
||||||
GradePointsStatistics(
|
|
||||||
semesterId = semester.semesterId,
|
|
||||||
studentId = semester.studentId,
|
|
||||||
subject = it.subject,
|
|
||||||
others = it.others,
|
|
||||||
student = it.student
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@ package io.github.wulkanowy.data.repositories.gradestatistics
|
||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import io.reactivex.Maybe
|
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -33,19 +31,4 @@ class GradeStatisticsRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
|
}.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).toSingle(emptyList()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradesPointsStatistics(semester: Semester, subjectName: String, forceRefresh: Boolean): Maybe<GradePointsStatistics> {
|
|
||||||
return local.getGradesPointsStatistics(semester, subjectName).filter { !forceRefresh }
|
|
||||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
|
||||||
.flatMapMaybe {
|
|
||||||
if (it) remote.getGradePointsStatistics(semester).toMaybe()
|
|
||||||
else Maybe.error(UnknownHostException())
|
|
||||||
}.flatMap { new ->
|
|
||||||
local.getGradesPointsStatistics(semester).defaultIfEmpty(emptyList())
|
|
||||||
.doOnSuccess { old ->
|
|
||||||
local.deleteGradesPointsStatistics(old.uniqueSubtract(new))
|
|
||||||
local.saveGradesPointsStatistics(new.uniqueSubtract(old))
|
|
||||||
}
|
|
||||||
}.flatMap { local.getGradesPointsStatistics(semester, subjectName) })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,60 +12,52 @@ class PreferencesRepository @Inject constructor(
|
||||||
val context: Context
|
val context: Context
|
||||||
) {
|
) {
|
||||||
val startMenuIndex: Int
|
val startMenuIndex: Int
|
||||||
get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt()
|
get() = sharedPref.getString(context.getString(R.string.pref_key_start_menu), "0")?.toIntOrNull() ?: 0
|
||||||
|
|
||||||
val isShowPresent: Boolean
|
val isShowPresent: Boolean
|
||||||
get() = getBoolean(R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present)
|
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_attendance_present), true)
|
||||||
|
|
||||||
val gradeAverageMode: String
|
val gradeAverageMode: String
|
||||||
get() = getString(R.string.pref_key_grade_average_mode, R.string.pref_default_grade_average_mode)
|
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_average_mode), "only_one_semester") ?: "only_one_semester"
|
||||||
|
|
||||||
val gradeAverageForceCalc: Boolean
|
val gradeAverageForceCalc: Boolean
|
||||||
get() = getBoolean(R.string.pref_key_grade_average_force_calc, R.bool.pref_default_grade_average_force_calc)
|
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_grade_average_force_calc), false)
|
||||||
|
|
||||||
val isGradeExpandable: Boolean
|
val isGradeExpandable: Boolean
|
||||||
get() = !getBoolean(R.string.pref_key_expand_grade, R.bool.pref_default_expand_grade)
|
get() = !sharedPref.getBoolean(context.getString(R.string.pref_key_expand_grade), false)
|
||||||
|
|
||||||
val appThemeKey = context.getString(R.string.pref_key_app_theme)
|
val appThemeKey: String = context.getString(R.string.pref_key_app_theme)
|
||||||
val appTheme: String
|
val appTheme: String
|
||||||
get() = getString(appThemeKey, R.string.pref_default_app_theme)
|
get() = sharedPref.getString(appThemeKey, "light") ?: "light"
|
||||||
|
|
||||||
val gradeColorTheme: String
|
val gradeColorTheme: String
|
||||||
get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme)
|
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_color_scheme), "vulcan") ?: "vulcan"
|
||||||
|
|
||||||
val serviceEnableKey = context.getString(R.string.pref_key_services_enable)
|
val serviceEnableKey: String = context.getString(R.string.pref_key_services_enable)
|
||||||
val isServiceEnabled: Boolean
|
val isServiceEnabled: Boolean
|
||||||
get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable)
|
get() = sharedPref.getBoolean(serviceEnableKey, true)
|
||||||
|
|
||||||
val servicesIntervalKey = context.getString(R.string.pref_key_services_interval)
|
val servicesIntervalKey: String = context.getString(R.string.pref_key_services_interval)
|
||||||
val servicesInterval: Long
|
val servicesInterval: Long
|
||||||
get() = getString(servicesIntervalKey, R.string.pref_default_services_interval).toLong()
|
get() = sharedPref.getString(servicesIntervalKey, "60")?.toLongOrNull() ?: 60
|
||||||
|
|
||||||
val servicesOnlyWifiKey = context.getString(R.string.pref_key_services_wifi_only)
|
val servicesOnlyWifiKey: String = context.getString(R.string.pref_key_services_wifi_only)
|
||||||
val isServicesOnlyWifi: Boolean
|
val isServicesOnlyWifi: Boolean
|
||||||
get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only)
|
get() = sharedPref.getBoolean(servicesOnlyWifiKey, false)
|
||||||
|
|
||||||
val isNotificationsEnable: Boolean
|
val isNotificationsEnable: Boolean
|
||||||
get() = getBoolean(R.string.pref_key_notifications_enable, R.bool.pref_default_notifications_enable)
|
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_notifications_enable), true)
|
||||||
|
|
||||||
val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
|
val isDebugNotificationEnableKey: String = context.getString(R.string.pref_key_notification_debug)
|
||||||
val isDebugNotificationEnable: Boolean
|
val isDebugNotificationEnable: Boolean
|
||||||
get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
|
get() = sharedPref.getBoolean(isDebugNotificationEnableKey, false)
|
||||||
|
|
||||||
val gradePlusModifier: Double
|
val gradePlusModifier: Double
|
||||||
get() = getString(R.string.pref_key_grade_modifier_plus, R.string.pref_default_grade_modifier_plus).toDouble()
|
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_plus), "0.0")?.toDouble() ?: 0.0
|
||||||
|
|
||||||
val gradeMinusModifier: Double
|
val gradeMinusModifier: Double
|
||||||
get() = getString(R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus).toDouble()
|
get() = sharedPref.getString(context.getString(R.string.pref_key_grade_modifier_minus), "0.0")?.toDouble() ?: 0.0
|
||||||
|
|
||||||
val fillMessageContent: Boolean
|
val fillMessageContent: Boolean
|
||||||
get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content)
|
get() = sharedPref.getBoolean(context.getString(R.string.pref_key_fill_message_content), true)
|
||||||
|
|
||||||
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
|
|
||||||
|
|
||||||
private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default)
|
|
||||||
|
|
||||||
private fun getBoolean(id: Int, default: Int) = getBoolean(context.getString(id), default)
|
|
||||||
|
|
||||||
private fun getBoolean(id: String, default: Int) = sharedPref.getBoolean(id, context.resources.getBoolean(default))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.school
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.SchoolDao
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
|
||||||
|
|
||||||
fun saveSchool(school: School) {
|
|
||||||
schoolDb.insert(school)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteSchool(school: School) {
|
|
||||||
schoolDb.delete(school)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSchool(semester: Semester): Maybe<School> {
|
|
||||||
return schoolDb.load(semester.studentId, semester.classId)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.school
|
|
||||||
|
|
||||||
import io.github.wulkanowy.api.Api
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.reactivex.Single
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SchoolRemote @Inject constructor(private val api: Api) {
|
|
||||||
|
|
||||||
fun getSchoolInfo(semester: Semester): Single<School> {
|
|
||||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
|
||||||
.flatMap { it.getSchool() }
|
|
||||||
.map {
|
|
||||||
School(
|
|
||||||
studentId = semester.studentId,
|
|
||||||
classId = semester.classId,
|
|
||||||
name = it.name,
|
|
||||||
address = it.address,
|
|
||||||
contact = it.contact,
|
|
||||||
headmaster = it.headmaster,
|
|
||||||
pedagogue = it.pedagogue
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.school
|
|
||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import io.reactivex.Single
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class SchoolRepository @Inject constructor(
|
|
||||||
private val settings: InternetObservingSettings,
|
|
||||||
private val local: SchoolLocal,
|
|
||||||
private val remote: SchoolRemote
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun getSchoolInfo(semester: Semester, forceRefresh: Boolean = false): Maybe<School> {
|
|
||||||
return local.getSchool(semester).filter { !forceRefresh }
|
|
||||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
|
||||||
.flatMap {
|
|
||||||
if (it) remote.getSchoolInfo(semester)
|
|
||||||
else Single.error(UnknownHostException())
|
|
||||||
}.flatMapMaybe { new ->
|
|
||||||
local.getSchool(semester)
|
|
||||||
.doOnSuccess { old ->
|
|
||||||
if (new != old) {
|
|
||||||
local.deleteSchool(old)
|
|
||||||
local.saveSchool(new)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.doOnComplete {
|
|
||||||
local.saveSchool(new)
|
|
||||||
}
|
|
||||||
}.flatMap({ local.getSchool(semester) }, { Maybe.error(it) },
|
|
||||||
{ local.getSchool(semester) })
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.teacher
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.dao.TeacherDao
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
|
||||||
import io.reactivex.Maybe
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
|
||||||
|
|
||||||
fun saveTeachers(teachers: List<Teacher>) {
|
|
||||||
teacherDb.insertAll(teachers)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteTeachers(teachers: List<Teacher>) {
|
|
||||||
teacherDb.deleteAll(teachers)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTeachers(semester: Semester): Maybe<List<Teacher>> {
|
|
||||||
return teacherDb.loadAll(semester.studentId, semester.classId).filter { it.isNotEmpty() }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.teacher
|
|
||||||
|
|
||||||
import io.github.wulkanowy.api.Api
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
|
||||||
import io.reactivex.Single
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class TeacherRemote @Inject constructor(private val api: Api) {
|
|
||||||
|
|
||||||
fun getTeachers(semester: Semester): Single<List<Teacher>> {
|
|
||||||
return Single.just(api.apply { diaryId = semester.diaryId })
|
|
||||||
.flatMap { it.getTeachers() }
|
|
||||||
.map { teachers ->
|
|
||||||
teachers.map {
|
|
||||||
Teacher(
|
|
||||||
studentId = semester.studentId,
|
|
||||||
name = it.name,
|
|
||||||
subject = it.subject,
|
|
||||||
shortName = it.short,
|
|
||||||
classId = semester.classId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package io.github.wulkanowy.data.repositories.teacher
|
|
||||||
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import io.reactivex.Single
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class TeacherRepository @Inject constructor(
|
|
||||||
private val settings: InternetObservingSettings,
|
|
||||||
private val local: TeacherLocal,
|
|
||||||
private val remote: TeacherRemote
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun getTeachers(semester: Semester, forceRefresh: Boolean = false): Single<List<Teacher>> {
|
|
||||||
return local.getTeachers(semester).filter { !forceRefresh }
|
|
||||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
|
||||||
.flatMap {
|
|
||||||
if (it) remote.getTeachers(semester)
|
|
||||||
else Single.error(UnknownHostException())
|
|
||||||
}.flatMap { new ->
|
|
||||||
local.getTeachers(semester).toSingle(emptyList())
|
|
||||||
.doOnSuccess { old ->
|
|
||||||
local.deleteTeachers(old.uniqueSubtract(new))
|
|
||||||
local.saveTeachers(new.uniqueSubtract(old))
|
|
||||||
}
|
|
||||||
}.flatMap { local.getTeachers(semester).toSingle(emptyList()) })
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@ import io.github.wulkanowy.services.sync.works.LuckyNumberWork
|
||||||
import io.github.wulkanowy.services.sync.works.MessageWork
|
import io.github.wulkanowy.services.sync.works.MessageWork
|
||||||
import io.github.wulkanowy.services.sync.works.NoteWork
|
import io.github.wulkanowy.services.sync.works.NoteWork
|
||||||
import io.github.wulkanowy.services.sync.works.RecipientWork
|
import io.github.wulkanowy.services.sync.works.RecipientWork
|
||||||
import io.github.wulkanowy.services.sync.works.TeacherWork
|
|
||||||
import io.github.wulkanowy.services.sync.works.TimetableWork
|
import io.github.wulkanowy.services.sync.works.TimetableWork
|
||||||
import io.github.wulkanowy.services.sync.works.Work
|
import io.github.wulkanowy.services.sync.works.Work
|
||||||
import io.github.wulkanowy.services.widgets.TimetableWidgetService
|
import io.github.wulkanowy.services.widgets.TimetableWidgetService
|
||||||
|
@ -29,15 +28,17 @@ import javax.inject.Singleton
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@AssistedModule
|
@AssistedModule
|
||||||
@Module(includes = [AssistedInject_ServicesModule::class, ServicesModule.Static::class])
|
@Module(includes = [AssistedInject_ServicesModule::class])
|
||||||
abstract class ServicesModule {
|
abstract class ServicesModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object Static {
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
fun provideWorkManager(context: Context) = WorkManager.getInstance(context)
|
fun provideWorkManager(context: Context) = WorkManager.getInstance(context)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context)
|
fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context)
|
||||||
|
@ -74,10 +75,6 @@ abstract class ServicesModule {
|
||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun provideTimetableWork(work: TimetableWork): Work
|
abstract fun provideTimetableWork(work: TimetableWork): Work
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoSet
|
|
||||||
abstract fun provideTeacherWork(work: TeacherWork): Work
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work
|
abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package io.github.wulkanowy.services.sync.works
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.repositories.teacher.TeacherRepository
|
|
||||||
import io.reactivex.Completable
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
|
||||||
return teacherRepository.getTeachers(semester, true).ignoreElement()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,17 +43,16 @@ class ErrorDialog : DialogFragment() {
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
StringWriter().let { writer ->
|
||||||
|
error.printStackTrace(PrintWriter(writer))
|
||||||
|
|
||||||
val stringWriter = StringWriter().apply {
|
errorDialogContent.text = writer.toString()
|
||||||
error.printStackTrace(PrintWriter(this))
|
errorDialogCopy.setOnClickListener {
|
||||||
}
|
ClipData.newPlainText("wulkanowyError", writer.toString()).let { clip ->
|
||||||
|
activity?.getSystemService<ClipboardManager>()?.primaryClip = clip
|
||||||
errorDialogContent.text = stringWriter.toString()
|
}
|
||||||
errorDialogCopy.setOnClickListener {
|
Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show()
|
||||||
val clip = ClipData.newPlainText("wulkanowy", stringWriter.toString())
|
}
|
||||||
activity?.getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
|
||||||
|
|
||||||
Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show()
|
|
||||||
}
|
}
|
||||||
errorDialogCancel.setOnClickListener { dismiss() }
|
errorDialogCancel.setOnClickListener { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.base
|
||||||
import android.content.pm.PackageManager.GET_ACTIVITIES
|
import android.content.pm.PackageManager.GET_ACTIVITIES
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
|
@ -23,12 +22,8 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
|
||||||
|
|
||||||
fun applyDefaultTheme() {
|
fun applyDefaultTheme() {
|
||||||
AppCompatDelegate.setDefaultNightMode(
|
AppCompatDelegate.setDefaultNightMode(
|
||||||
when (val theme = preferencesRepository.appTheme) {
|
if (preferencesRepository.appTheme == "light") MODE_NIGHT_NO
|
||||||
"light" -> MODE_NIGHT_NO
|
else MODE_NIGHT_YES
|
||||||
"dark", "black" -> MODE_NIGHT_YES
|
|
||||||
"system" -> MODE_NIGHT_FOLLOW_SYSTEM
|
|
||||||
else -> throw IllegalArgumentException("Wrong theme: $theme")
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ class AttendancePresenter @Inject constructor(
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalize())
|
updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ class AttendanceSummaryFragment : BaseFragment(), AttendanceSummaryView, MainVie
|
||||||
override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) {
|
override fun updateDataSet(data: List<AttendanceSummaryItem>, header: AttendanceSummaryScrollableHeader) {
|
||||||
with(attendanceSummaryAdapter) {
|
with(attendanceSummaryAdapter) {
|
||||||
updateDataSet(data, true)
|
updateDataSet(data, true)
|
||||||
removeAllScrollableHeaders()
|
removeAllScrollableFooters()
|
||||||
addScrollableHeader(header)
|
addScrollableHeader(header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,13 @@ import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [GradeModule.Static::class])
|
@Module
|
||||||
abstract class GradeModule {
|
abstract class GradeModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object Static {
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@Provides
|
@Provides
|
||||||
fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
||||||
|
|
|
@ -33,8 +33,6 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var gradeDetailsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
lateinit var gradeDetailsAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
private var gradeDetailsMenu: Menu? = null
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = GradeDetailsFragment()
|
fun newInstance() = GradeDetailsFragment()
|
||||||
}
|
}
|
||||||
|
@ -71,8 +69,6 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.action_menu_grade_details, menu)
|
inflater.inflate(R.menu.action_menu_grade_details, menu)
|
||||||
gradeDetailsMenu = menu
|
|
||||||
presenter.updateMarkAsDoneButton()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
|
@ -169,10 +165,6 @@ class GradeDetailsFragment : BaseFragment(), GradeDetailsView, GradeView.GradeCh
|
||||||
(parentFragment as? GradeFragment)?.onChildRefresh()
|
(parentFragment as? GradeFragment)?.onChildRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableMarkAsDoneButton(enable: Boolean) {
|
|
||||||
gradeDetailsMenu?.findItem(R.id.gradeDetailsMenuRead)?.isEnabled = enable
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.github.wulkanowy.ui.modules.grade.details
|
package io.github.wulkanowy.ui.modules.grade.details
|
||||||
|
|
||||||
import android.widget.Toast
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||||
|
@ -27,8 +26,6 @@ class GradeDetailsPresenter @Inject constructor(
|
||||||
private val analytics: FirebaseAnalyticsHelper
|
private val analytics: FirebaseAnalyticsHelper
|
||||||
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository, schedulers) {
|
) : BasePresenter<GradeDetailsView>(errorHandler, studentRepository, schedulers) {
|
||||||
|
|
||||||
private var newGradesAmount: Int = 0
|
|
||||||
|
|
||||||
private var currentSemesterId = 0
|
private var currentSemesterId = 0
|
||||||
|
|
||||||
override fun onAttachView(view: GradeDetailsView) {
|
override fun onAttachView(view: GradeDetailsView) {
|
||||||
|
@ -55,8 +52,6 @@ class GradeDetailsPresenter @Inject constructor(
|
||||||
updateItem(header)
|
updateItem(header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newGradesAmount--
|
|
||||||
updateMarkAsDoneButton()
|
|
||||||
updateGrade(item.grade)
|
updateGrade(item.grade)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,10 +106,6 @@ class GradeDetailsPresenter @Inject constructor(
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateMarkAsDoneButton() {
|
|
||||||
view?.enableMarkAsDoneButton(newGradesAmount > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
Timber.i("Loading grade details data started")
|
Timber.i("Loading grade details data started")
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
|
@ -140,8 +131,6 @@ class GradeDetailsPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
.subscribe({
|
.subscribe({
|
||||||
Timber.i("Loading grade details result: Success")
|
Timber.i("Loading grade details result: Success")
|
||||||
newGradesAmount = it.sumBy { gradeDetailsHeader -> gradeDetailsHeader.newGrades }
|
|
||||||
updateMarkAsDoneButton()
|
|
||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
|
|
|
@ -46,8 +46,6 @@ interface GradeDetailsView : BaseView {
|
||||||
|
|
||||||
fun notifyParentRefresh()
|
fun notifyParentRefresh()
|
||||||
|
|
||||||
fun enableMarkAsDoneButton(enable: Boolean)
|
|
||||||
|
|
||||||
fun getGradeNumberString(number: Int): String
|
fun getGradeNumberString(number: Int): String
|
||||||
|
|
||||||
fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>?
|
fun getHeaderOfItem(item: AbstractFlexibleItem<*>): IExpandable<*, out IFlexible<*>>?
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Color.WHITE
|
import android.graphics.Color.WHITE
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -11,15 +10,11 @@ import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.github.mikephil.charting.components.Legend
|
import com.github.mikephil.charting.components.Legend
|
||||||
import com.github.mikephil.charting.components.LegendEntry
|
import com.github.mikephil.charting.components.LegendEntry
|
||||||
import com.github.mikephil.charting.data.BarData
|
|
||||||
import com.github.mikephil.charting.data.BarDataSet
|
|
||||||
import com.github.mikephil.charting.data.BarEntry
|
|
||||||
import com.github.mikephil.charting.data.PieData
|
import com.github.mikephil.charting.data.PieData
|
||||||
import com.github.mikephil.charting.data.PieDataSet
|
import com.github.mikephil.charting.data.PieDataSet
|
||||||
import com.github.mikephil.charting.data.PieEntry
|
import com.github.mikephil.charting.data.PieEntry
|
||||||
import com.github.mikephil.charting.formatter.ValueFormatter
|
import com.github.mikephil.charting.formatter.ValueFormatter
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||||
|
@ -43,9 +38,7 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
fun newInstance() = GradeStatisticsFragment()
|
fun newInstance() = GradeStatisticsFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isPieViewEmpty get() = gradeStatisticsChart.isEmpty
|
override val isViewEmpty get() = gradeStatisticsChart.isEmpty
|
||||||
|
|
||||||
override val isBarViewEmpty get() = gradeStatisticsChartPoints.isEmpty
|
|
||||||
|
|
||||||
private lateinit var gradeColors: List<Pair<Int, Int>>
|
private lateinit var gradeColors: List<Pair<Int, Int>>
|
||||||
|
|
||||||
|
@ -67,11 +60,6 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
1 to R.color.grade_material_one
|
1 to R.color.grade_material_one
|
||||||
)
|
)
|
||||||
|
|
||||||
private val gradePointsColors = listOf(
|
|
||||||
Color.parseColor("#37c69c"),
|
|
||||||
Color.parseColor("#d8b12a")
|
|
||||||
)
|
|
||||||
|
|
||||||
private val gradeLabels = listOf(
|
private val gradeLabels = listOf(
|
||||||
"6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+"
|
"6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+"
|
||||||
)
|
)
|
||||||
|
@ -82,8 +70,8 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
messageContainer = gradeStatisticsSwipe
|
messageContainer = gradeStatisticsChart
|
||||||
presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? ViewType)
|
presenter.onAttachView(this, savedInstanceState?.getBoolean(SAVED_CHART_TYPE))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
|
@ -96,13 +84,6 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||||
}
|
}
|
||||||
|
|
||||||
with(gradeStatisticsChartPoints) {
|
|
||||||
description.isEnabled = false
|
|
||||||
|
|
||||||
animateXY(1000, 1000)
|
|
||||||
legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
|
||||||
}
|
|
||||||
|
|
||||||
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
||||||
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
||||||
|
|
||||||
|
@ -124,25 +105,23 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updatePieData(items: List<GradeStatistics>, theme: String) {
|
override fun updateData(items: List<GradeStatistics>, theme: String) {
|
||||||
gradeColors = when (theme) {
|
gradeColors = when (theme) {
|
||||||
"vulcan" -> vulcanGradeColors
|
"vulcan" -> vulcanGradeColors
|
||||||
else -> materialGradeColors
|
else -> materialGradeColors
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataset = PieDataSet(items.map {
|
gradeStatisticsChart.run {
|
||||||
PieEntry(it.amount.toFloat(), it.grade.toString())
|
data = PieData(PieDataSet(items.map {
|
||||||
}, "Legenda").apply {
|
PieEntry(it.amount.toFloat(), it.grade.toString())
|
||||||
valueTextSize = 12f
|
}, "Legenda").apply {
|
||||||
sliceSpace = 1f
|
valueTextSize = 12f
|
||||||
valueTextColor = WHITE
|
sliceSpace = 1f
|
||||||
setColors(items.map {
|
valueTextColor = WHITE
|
||||||
gradeColors.single { color -> color.first == it.grade }.second
|
setColors(items.map {
|
||||||
}.toIntArray(), context)
|
gradeColors.single { color -> color.first == it.grade }.second
|
||||||
}
|
}.toIntArray(), context)
|
||||||
|
}).apply {
|
||||||
with(gradeStatisticsChart) {
|
|
||||||
data = PieData(dataset).apply {
|
|
||||||
setTouchEnabled(false)
|
setTouchEnabled(false)
|
||||||
setValueFormatter(object : ValueFormatter() {
|
setValueFormatter(object : ValueFormatter() {
|
||||||
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
|
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
|
||||||
|
@ -165,47 +144,6 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateBarData(item: GradePointsStatistics) {
|
|
||||||
val dataset = BarDataSet(listOf(
|
|
||||||
BarEntry(1f, item.others.toFloat()),
|
|
||||||
BarEntry(2f, item.student.toFloat())
|
|
||||||
), "Legenda").apply {
|
|
||||||
valueTextSize = 12f
|
|
||||||
valueTextColor = requireContext().getThemeAttrColor(android.R.attr.textColorPrimary)
|
|
||||||
valueFormatter = object : ValueFormatter() {
|
|
||||||
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%"
|
|
||||||
}
|
|
||||||
colors = gradePointsColors
|
|
||||||
}
|
|
||||||
|
|
||||||
with(gradeStatisticsChartPoints) {
|
|
||||||
data = BarData(dataset).apply {
|
|
||||||
barWidth = 0.5f
|
|
||||||
setFitBars(true)
|
|
||||||
}
|
|
||||||
setTouchEnabled(false)
|
|
||||||
xAxis.setDrawLabels(false)
|
|
||||||
xAxis.setDrawGridLines(false)
|
|
||||||
requireContext().getThemeAttrColor(android.R.attr.textColorPrimary).let {
|
|
||||||
axisLeft.textColor = it
|
|
||||||
axisRight.textColor = it
|
|
||||||
}
|
|
||||||
legend.setCustom(listOf(
|
|
||||||
LegendEntry().apply {
|
|
||||||
label = "Średnia klasy"
|
|
||||||
formColor = gradePointsColors[0]
|
|
||||||
form = Legend.LegendForm.SQUARE
|
|
||||||
},
|
|
||||||
LegendEntry().apply {
|
|
||||||
label = "Uczeń"
|
|
||||||
formColor = gradePointsColors[1]
|
|
||||||
form = Legend.LegendForm.SQUARE
|
|
||||||
}
|
|
||||||
))
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showSubjects(show: Boolean) {
|
override fun showSubjects(show: Boolean) {
|
||||||
gradeStatisticsSubjectsContainer.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsSubjectsContainer.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
gradeStatisticsTypeSwitch.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsTypeSwitch.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
|
@ -213,17 +151,12 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
|
|
||||||
override fun clearView() {
|
override fun clearView() {
|
||||||
gradeStatisticsChart.clear()
|
gradeStatisticsChart.clear()
|
||||||
gradeStatisticsChartPoints.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showPieContent(show: Boolean) {
|
override fun showContent(show: Boolean) {
|
||||||
gradeStatisticsChart.visibility = if (show) View.VISIBLE else View.GONE
|
gradeStatisticsChart.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showBarContent(show: Boolean) {
|
|
||||||
gradeStatisticsChartPoints.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
override fun showEmpty(show: Boolean) {
|
||||||
gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
@ -263,17 +196,13 @@ class GradeStatisticsFragment : BaseFragment(), GradeStatisticsView, GradeView.G
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
|
gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
|
||||||
presenter.onTypeChange(when (checkedId) {
|
presenter.onTypeChange(checkedId == R.id.gradeStatisticsTypeSemester)
|
||||||
R.id.gradeStatisticsTypeSemester -> ViewType.SEMESTER
|
|
||||||
R.id.gradeStatisticsTypePartial -> ViewType.PARTIAL
|
|
||||||
else -> ViewType.POINTS
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType)
|
outState.putBoolean(SAVED_CHART_TYPE, presenter.currentIsSemester)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -30,19 +30,19 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||||
|
|
||||||
private var currentSubjectName: String = "Wszystkie"
|
private var currentSubjectName: String = "Wszystkie"
|
||||||
|
|
||||||
var currentType: ViewType = ViewType.PARTIAL
|
var currentIsSemester = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun onAttachView(view: GradeStatisticsView, type: ViewType?) {
|
fun onAttachView(view: GradeStatisticsView, isSemester: Boolean?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
currentType = type ?: ViewType.PARTIAL
|
currentIsSemester = isSemester ?: false
|
||||||
view.initView()
|
view.initView()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
currentSemesterId = semesterId
|
currentSemesterId = semesterId
|
||||||
loadSubjects()
|
loadSubjects()
|
||||||
loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh)
|
loadData(semesterId, currentSubjectName, currentIsSemester, forceRefresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onParentViewChangeSemester() {
|
fun onParentViewChangeSemester() {
|
||||||
|
@ -50,7 +50,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showRefresh(false)
|
showRefresh(false)
|
||||||
showBarContent(false)
|
showContent(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
|
@ -65,30 +65,28 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||||
fun onSubjectSelected(name: String?) {
|
fun onSubjectSelected(name: String?) {
|
||||||
Timber.i("Select grade stats subject $name")
|
Timber.i("Select grade stats subject $name")
|
||||||
view?.run {
|
view?.run {
|
||||||
showBarContent(false)
|
showContent(false)
|
||||||
showPieContent(false)
|
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
(subjects.singleOrNull { it.name == name }?.name)?.let {
|
(subjects.singleOrNull { it.name == name }?.name)?.let {
|
||||||
if (it != currentSubjectName) loadDataByType(currentSemesterId, it, currentType)
|
if (it != currentSubjectName) loadData(currentSemesterId, it, currentIsSemester)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTypeChange(type: ViewType) {
|
fun onTypeChange(isSemester: Boolean) {
|
||||||
Timber.i("Select grade stats semester: $type")
|
Timber.i("Select grade stats semester: $isSemester")
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
view?.run {
|
view?.run {
|
||||||
showBarContent(false)
|
showContent(false)
|
||||||
showPieContent(false)
|
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
loadDataByType(currentSemesterId, currentSubjectName, type)
|
loadData(currentSemesterId, currentSubjectName, isSemester)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSubjects() {
|
private fun loadSubjects() {
|
||||||
|
@ -113,18 +111,10 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
|
||||||
currentSubjectName = subjectName
|
|
||||||
currentType = type
|
|
||||||
when (type) {
|
|
||||||
ViewType.SEMESTER -> loadData(semesterId, subjectName, true, forceRefresh)
|
|
||||||
ViewType.PARTIAL -> loadData(semesterId, subjectName, false, forceRefresh)
|
|
||||||
ViewType.POINTS -> loadPointsData(semesterId, subjectName, forceRefresh)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(semesterId: Int, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false) {
|
private fun loadData(semesterId: Int, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading grade stats data started")
|
Timber.i("Loading grade stats data started")
|
||||||
|
currentSubjectName = subjectName
|
||||||
|
currentIsSemester = isSemester
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
disposable.add(studentRepository.getCurrentStudent()
|
||||||
.flatMap { semesterRepository.getSemesters(it) }
|
.flatMap { semesterRepository.getSemesters(it) }
|
||||||
.flatMap { gradeStatisticsRepository.getGradesStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, isSemester, forceRefresh) }
|
.flatMap { gradeStatisticsRepository.getGradesStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, isSemester, forceRefresh) }
|
||||||
|
@ -144,53 +134,14 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||||
Timber.i("Loading grade stats result: Success")
|
Timber.i("Loading grade stats result: Success")
|
||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
showBarContent(false)
|
showContent(it.isNotEmpty())
|
||||||
showPieContent(it.isNotEmpty())
|
updateData(it, preferencesRepository.gradeColorTheme)
|
||||||
updatePieData(it, preferencesRepository.gradeColorTheme)
|
|
||||||
}
|
}
|
||||||
analytics.logEvent("load_grade_statistics", "items" to it.size, "force_refresh" to forceRefresh)
|
analytics.logEvent("load_grade_statistics", "items" to it.size, "force_refresh" to forceRefresh)
|
||||||
}) {
|
}) {
|
||||||
Timber.e("Loading grade stats result: An exception occurred")
|
Timber.e("Loading grade stats result: An exception occurred")
|
||||||
view?.run { showEmpty(isPieViewEmpty) }
|
view?.run { showEmpty(isViewEmpty) }
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadPointsData(semesterId: Int, subjectName: String, forceRefresh: Boolean = false) {
|
|
||||||
Timber.i("Loading grade points stats data started")
|
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
|
||||||
.flatMap { semesterRepository.getSemesters(it) }
|
|
||||||
.flatMapMaybe { gradeStatisticsRepository.getGradesPointsStatistics(it.first { item -> item.semesterId == semesterId }, subjectName, forceRefresh) }
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
|
||||||
showRefresh(false)
|
|
||||||
showProgress(false)
|
|
||||||
enableSwipe(true)
|
|
||||||
notifyParentDataLoaded(semesterId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading grade points stats result: Success")
|
|
||||||
view?.run {
|
|
||||||
showEmpty(false)
|
|
||||||
showPieContent(false)
|
|
||||||
showBarContent(true)
|
|
||||||
updateBarData(it)
|
|
||||||
}
|
|
||||||
analytics.logEvent("load_grade_points_statistics", "force_refresh" to forceRefresh)
|
|
||||||
}, {
|
|
||||||
Timber.e("Loading grade points stats result: An exception occurred")
|
|
||||||
view?.run { showEmpty(isBarViewEmpty) }
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
}, {
|
|
||||||
Timber.d("Loading grade points stats result: No point stats found")
|
|
||||||
view?.run {
|
|
||||||
showBarContent(false)
|
|
||||||
showEmpty(true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
interface GradeStatisticsView : BaseView {
|
interface GradeStatisticsView : BaseView {
|
||||||
|
|
||||||
val isPieViewEmpty: Boolean
|
val isViewEmpty: Boolean
|
||||||
|
|
||||||
val isBarViewEmpty: Boolean
|
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateSubjects(data: ArrayList<String>)
|
fun updateSubjects(data: ArrayList<String>)
|
||||||
|
|
||||||
fun updatePieData(items: List<GradeStatistics>, theme: String)
|
fun updateData(items: List<GradeStatistics>, theme: String)
|
||||||
|
|
||||||
fun updateBarData(item: GradePointsStatistics)
|
|
||||||
|
|
||||||
fun showSubjects(show: Boolean)
|
fun showSubjects(show: Boolean)
|
||||||
|
|
||||||
|
@ -26,9 +21,7 @@ interface GradeStatisticsView : BaseView {
|
||||||
|
|
||||||
fun clearView()
|
fun clearView()
|
||||||
|
|
||||||
fun showPieContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
fun showBarContent(show: Boolean)
|
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
|
||||||
|
|
||||||
enum class ViewType {
|
|
||||||
SEMESTER,
|
|
||||||
PARTIAL,
|
|
||||||
POINTS
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.modules.login
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity
|
import io.github.wulkanowy.ui.base.BaseActivity
|
||||||
|
@ -24,28 +23,22 @@ class LoginActivity : BaseActivity<LoginPresenter>(), LoginView {
|
||||||
lateinit var loginAdapter: BaseFragmentPagerAdapter
|
lateinit var loginAdapter: BaseFragmentPagerAdapter
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val currentViewIndex get() = loginViewpager.currentItem
|
override val currentViewIndex: Int
|
||||||
|
get() = loginViewpager.currentItem
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_login)
|
setContentView(R.layout.activity_login)
|
||||||
setSupportActionBar(loginToolbar)
|
|
||||||
messageContainer = loginContainer
|
messageContainer = loginContainer
|
||||||
|
|
||||||
presenter.onAttachView(this)
|
presenter.onAttachView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initAdapter() {
|
||||||
with(requireNotNull(supportActionBar)) {
|
loginAdapter.apply {
|
||||||
setDisplayHomeAsUpEnabled(true)
|
|
||||||
setDisplayShowTitleEnabled(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
with(loginAdapter) {
|
|
||||||
containerId = loginViewpager.id
|
containerId = loginViewpager.id
|
||||||
addFragments(listOf(
|
addFragments(listOf(
|
||||||
LoginFormFragment.newInstance(),
|
LoginFormFragment.newInstance(),
|
||||||
|
@ -54,24 +47,19 @@ class LoginActivity : BaseActivity<LoginPresenter>(), LoginView {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
with(loginViewpager) {
|
loginViewpager.run {
|
||||||
offscreenPageLimit = 2
|
offscreenPageLimit = 2
|
||||||
adapter = loginAdapter
|
adapter = loginAdapter
|
||||||
setOnSelectPageListener(presenter::onViewSelected)
|
setOnSelectPageListener { presenter.onViewSelected(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) onBackPressed()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun switchView(index: Int) {
|
override fun switchView(index: Int) {
|
||||||
loginViewpager.setCurrentItem(index, false)
|
loginViewpager.setCurrentItem(index, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showActionBar(show: Boolean) {
|
override fun showActionBar(show: Boolean) {
|
||||||
supportActionBar?.run { if (show) show() else hide() }
|
supportActionBar?.apply { if (show) show() else hide() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
|
|
|
@ -11,12 +11,13 @@ import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFrag
|
||||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [LoginModule.Static::class])
|
@Module
|
||||||
internal abstract class LoginModule {
|
internal abstract class LoginModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object Static {
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@PerActivity
|
@PerActivity
|
||||||
@Provides
|
@Provides
|
||||||
fun provideLoginAdapter(activity: LoginActivity) = BaseFragmentPagerAdapter(activity.supportFragmentManager)
|
fun provideLoginAdapter(activity: LoginActivity) = BaseFragmentPagerAdapter(activity.supportFragmentManager)
|
||||||
|
|
|
@ -16,8 +16,8 @@ class LoginPresenter @Inject constructor(
|
||||||
|
|
||||||
override fun onAttachView(view: LoginView) {
|
override fun onAttachView(view: LoginView) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
with(view) {
|
view.run {
|
||||||
initView()
|
initAdapter()
|
||||||
showActionBar(false)
|
showActionBar(false)
|
||||||
}
|
}
|
||||||
Timber.i("Login view was initialized")
|
Timber.i("Login view was initialized")
|
||||||
|
@ -48,8 +48,8 @@ class LoginPresenter @Inject constructor(
|
||||||
fun onViewSelected(index: Int) {
|
fun onViewSelected(index: Int) {
|
||||||
view?.apply {
|
view?.apply {
|
||||||
when (index) {
|
when (index) {
|
||||||
0 -> showActionBar(false)
|
0, 1 -> showActionBar(false)
|
||||||
1, 2 -> showActionBar(true)
|
2 -> showActionBar(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ interface LoginView : BaseView {
|
||||||
|
|
||||||
val currentViewIndex: Int
|
val currentViewIndex: Int
|
||||||
|
|
||||||
fun initView()
|
fun initAdapter()
|
||||||
|
|
||||||
fun switchView(index: Int)
|
fun switchView(index: Int)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
|
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
|
||||||
import android.view.inputmethod.EditorInfo.IME_NULL
|
import android.view.inputmethod.EditorInfo.IME_NULL
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
@ -16,7 +17,6 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.hideSoftInput
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
import io.github.wulkanowy.utils.openEmail
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
import io.github.wulkanowy.utils.openInternetBrowser
|
||||||
import io.github.wulkanowy.utils.showSoftInput
|
import io.github.wulkanowy.utils.showSoftInput
|
||||||
import kotlinx.android.synthetic.main.fragment_login_form.*
|
import kotlinx.android.synthetic.main.fragment_login_form.*
|
||||||
|
@ -38,7 +38,7 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||||
|
|
||||||
override val formPassValue get() = loginFormPass.text.toString()
|
override val formPassValue get() = loginFormPass.text.toString()
|
||||||
|
|
||||||
override val formHostValue get() = hostValues.getOrNull(hostKeys.indexOf(loginFormHost.text.toString()))
|
override val formHostValue get() = hostValues[(hostKeys.indexOf(loginFormHost.text.toString()))]
|
||||||
|
|
||||||
private lateinit var hostKeys: Array<String>
|
private lateinit var hostKeys: Array<String>
|
||||||
|
|
||||||
|
@ -54,24 +54,26 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
hostKeys = resources.getStringArray(R.array.hosts_keys)
|
hostKeys = resources.getStringArray(R.array.endpoints_keys)
|
||||||
hostValues = resources.getStringArray(R.array.hosts_values)
|
hostValues = resources.getStringArray(R.array.endpoints_values)
|
||||||
|
|
||||||
loginFormName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() }
|
loginFormName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() }
|
||||||
loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() }
|
loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() }
|
||||||
loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
|
loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() }
|
||||||
loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
|
loginFormSignIn.setOnClickListener { presenter.onSignInClick() }
|
||||||
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
|
loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() }
|
||||||
loginFormContactDiscord.setOnClickListener { presenter.onDiscordClick() }
|
|
||||||
loginFormContactEmail.setOnClickListener { presenter.onEmailClick() }
|
|
||||||
|
|
||||||
loginFormPass.setOnEditorActionListener { _, id, _ ->
|
loginFormPass.setOnEditorActionListener { _, id, _ ->
|
||||||
if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false
|
if (id == IME_ACTION_DONE || id == IME_NULL) loginFormSignIn.callOnClick() else false
|
||||||
}
|
}
|
||||||
|
|
||||||
with(loginFormHost) {
|
with(loginFormHost) {
|
||||||
|
//Bug with filter in ExposedDropdownMenu on restoring state
|
||||||
|
isSaveEnabled = false
|
||||||
|
|
||||||
setText(hostKeys.getOrElse(0) { "" })
|
setText(hostKeys.getOrElse(0) { "" })
|
||||||
setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
|
setAdapter(ArrayAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys))
|
||||||
|
keyListener = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,33 +146,21 @@ class LoginFormFragment : BaseFragment(), LoginFormView {
|
||||||
loginFormPrivacyLink.visibility = VISIBLE
|
loginFormPrivacyLink.visibility = VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun notifyParentAccountLogged(students: List<Student>, loginData: Triple<String, String, String>) {
|
override fun notifyParentAccountLogged(students: List<Student>) {
|
||||||
(activity as? LoginActivity)?.onFormFragmentAccountLogged(students, loginData)
|
(activity as? LoginActivity)?.onFormFragmentAccountLogged(students,
|
||||||
|
Triple(
|
||||||
|
loginFormName.text.toString(),
|
||||||
|
loginFormPass.text.toString(),
|
||||||
|
formHostValue
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openPrivacyPolicyPage() {
|
override fun openPrivacyPolicyPage() {
|
||||||
context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage)
|
context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContact(show: Boolean) {
|
|
||||||
loginFormContact.visibility = if (show) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openDiscordInvite() {
|
|
||||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openEmail() {
|
|
||||||
context?.openEmail(
|
|
||||||
requireContext().getString(R.string.login_email_intent_title),
|
|
||||||
"wulkanowyinc@gmail.com",
|
|
||||||
requireContext().getString(R.string.login_email_subject),
|
|
||||||
requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ class LoginFormPresenter @Inject constructor(
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.run {
|
view.run {
|
||||||
initView()
|
initView()
|
||||||
showContact(false)
|
|
||||||
if (appInfo.isDebug) showVersion() else showPrivacyPolicy()
|
if (appInfo.isDebug) showVersion() else showPrivacyPolicy()
|
||||||
|
|
||||||
loginErrorHandler.onBadCredentials = {
|
loginErrorHandler.onBadCredentials = {
|
||||||
|
@ -41,9 +40,7 @@ class LoginFormPresenter @Inject constructor(
|
||||||
view?.apply {
|
view?.apply {
|
||||||
clearPassError()
|
clearPassError()
|
||||||
clearNameError()
|
clearNameError()
|
||||||
if (formHostValue?.contains("fakelog") == true) {
|
if (formHostValue.contains("fakelog")) setCredentials("jan@fakelog.cf", "jan123")
|
||||||
setCredentials("jan@fakelog.cf", "jan123")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,23 +79,14 @@ class LoginFormPresenter @Inject constructor(
|
||||||
.subscribe({
|
.subscribe({
|
||||||
Timber.i("Login result: Success")
|
Timber.i("Login result: Success")
|
||||||
analytics.logEvent("registration_form", "success" to true, "students" to it.size, "endpoint" to endpoint, "error" to "No error")
|
analytics.logEvent("registration_form", "success" to true, "students" to it.size, "endpoint" to endpoint, "error" to "No error")
|
||||||
view?.notifyParentAccountLogged(it, Triple(email, password, endpoint))
|
view?.notifyParentAccountLogged(it)
|
||||||
}, {
|
}, {
|
||||||
Timber.i("Login result: An exception occurred")
|
Timber.i("Login result: An exception occurred")
|
||||||
analytics.logEvent("registration_form", "success" to false, "students" to -1, "endpoint" to endpoint, "error" to it.message.ifNullOrBlank { "No message" })
|
analytics.logEvent("registration_form", "success" to false, "students" to -1, "endpoint" to endpoint, "error" to it.message.ifNullOrBlank { "No message" })
|
||||||
loginErrorHandler.dispatch(it)
|
loginErrorHandler.dispatch(it)
|
||||||
view?.showContact(true)
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDiscordClick() {
|
|
||||||
view?.openDiscordInvite()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onEmailClick() {
|
|
||||||
view?.openEmail()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun validateCredentials(login: String, password: String): Boolean {
|
private fun validateCredentials(login: String, password: String): Boolean {
|
||||||
var isCorrect = true
|
var isCorrect = true
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ interface LoginFormView : BaseView {
|
||||||
|
|
||||||
val formPassValue: String
|
val formPassValue: String
|
||||||
|
|
||||||
val formHostValue: String?
|
val formHostValue: String
|
||||||
|
|
||||||
fun setCredentials(name: String, pass: String)
|
fun setCredentials(name: String, pass: String)
|
||||||
|
|
||||||
|
@ -39,13 +39,7 @@ interface LoginFormView : BaseView {
|
||||||
|
|
||||||
fun showPrivacyPolicy()
|
fun showPrivacyPolicy()
|
||||||
|
|
||||||
fun notifyParentAccountLogged(students: List<Student>, loginData: Triple<String, String, String>)
|
fun notifyParentAccountLogged(students: List<Student>)
|
||||||
|
|
||||||
fun openPrivacyPolicyPage()
|
fun openPrivacyPolicyPage()
|
||||||
|
|
||||||
fun showContact(show: Boolean)
|
|
||||||
|
|
||||||
fun openDiscordInvite()
|
|
||||||
|
|
||||||
fun openEmail()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.login.form
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.Filter
|
|
||||||
|
|
||||||
class LoginSymbolAdapter(context: Context, resource: Int, objects: Array<out String>) :
|
|
||||||
ArrayAdapter<String>(context, resource, objects) {
|
|
||||||
|
|
||||||
override fun getFilter() = object : Filter() {
|
|
||||||
|
|
||||||
override fun performFiltering(constraint: CharSequence?) = null
|
|
||||||
|
|
||||||
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,9 +13,6 @@ import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import io.github.wulkanowy.utils.openEmail
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_login_student_select.*
|
import kotlinx.android.synthetic.main.fragment_login_student_select.*
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
@ -29,9 +26,6 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var loginAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
lateinit var loginAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var appInfo: AppInfo
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SAVED_STUDENTS = "STUDENTS"
|
const val SAVED_STUDENTS = "STUDENTS"
|
||||||
|
|
||||||
|
@ -50,8 +44,6 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView {
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
|
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
|
||||||
loginAdapter.apply { setOnItemClickListener { presenter.onItemSelected(it) } }
|
loginAdapter.apply { setOnItemClickListener { presenter.onItemSelected(it) } }
|
||||||
loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() }
|
|
||||||
loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() }
|
|
||||||
|
|
||||||
loginStudentSelectRecycler.apply {
|
loginStudentSelectRecycler.apply {
|
||||||
adapter = loginAdapter
|
adapter = loginAdapter
|
||||||
|
@ -88,25 +80,8 @@ class LoginStudentSelectFragment : BaseFragment(), LoginStudentSelectView {
|
||||||
outState.putSerializable(SAVED_STUDENTS, presenter.students as Serializable)
|
outState.putSerializable(SAVED_STUDENTS, presenter.students as Serializable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContact(show: Boolean) {
|
|
||||||
loginStudentSelectContact.visibility = if (show) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openDiscordInvite() {
|
|
||||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openEmail() {
|
|
||||||
context?.openEmail(
|
|
||||||
requireContext().getString(R.string.login_email_intent_title),
|
|
||||||
"wulkanowyinc@gmail.com",
|
|
||||||
requireContext().getString(R.string.login_email_subject),
|
|
||||||
requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.run {
|
view.run {
|
||||||
initView()
|
initView()
|
||||||
showContact(false)
|
|
||||||
enableSignIn(false)
|
enableSignIn(false)
|
||||||
loginErrorHandler.onStudentDuplicate = {
|
loginErrorHandler.onStudentDuplicate = {
|
||||||
showMessage(it)
|
showMessage(it)
|
||||||
|
@ -89,16 +88,7 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
showContact(true)
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDiscordClick() {
|
|
||||||
view?.openDiscordInvite()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onEmailClick() {
|
|
||||||
view?.openEmail()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,4 @@ interface LoginStudentSelectView : BaseView {
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
fun enableSignIn(enable: Boolean)
|
fun enableSignIn(enable: Boolean)
|
||||||
|
|
||||||
fun showContact(show: Boolean)
|
|
||||||
|
|
||||||
fun openDiscordInvite()
|
|
||||||
|
|
||||||
fun openEmail()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@ import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import io.github.wulkanowy.utils.hideSoftInput
|
import io.github.wulkanowy.utils.hideSoftInput
|
||||||
import io.github.wulkanowy.utils.openEmail
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import io.github.wulkanowy.utils.showSoftInput
|
import io.github.wulkanowy.utils.showSoftInput
|
||||||
import kotlinx.android.synthetic.main.fragment_login_symbol.*
|
import kotlinx.android.synthetic.main.fragment_login_symbol.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -27,9 +24,6 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: LoginSymbolPresenter
|
lateinit var presenter: LoginSymbolPresenter
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var appInfo: AppInfo
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SAVED_LOGIN_DATA = "LOGIN_DATA"
|
private const val SAVED_LOGIN_DATA = "LOGIN_DATA"
|
||||||
|
|
||||||
|
@ -50,8 +44,6 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView {
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
|
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
|
||||||
loginSymbolContactDiscord.setOnClickListener { presenter.onDiscordClick() }
|
|
||||||
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
|
|
||||||
|
|
||||||
loginSymbolName.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() }
|
loginSymbolName.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() }
|
||||||
|
|
||||||
|
@ -117,25 +109,8 @@ class LoginSymbolFragment : BaseFragment(), LoginSymbolView {
|
||||||
outState.putSerializable(SAVED_LOGIN_DATA, presenter.loginData)
|
outState.putSerializable(SAVED_LOGIN_DATA, presenter.loginData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContact(show: Boolean) {
|
|
||||||
loginSymbolContact.visibility = if (show) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openDiscordInvite() {
|
|
||||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openEmail() {
|
|
||||||
context?.openEmail(
|
|
||||||
requireContext().getString(R.string.login_email_intent_title),
|
|
||||||
"wulkanowyinc@gmail.com",
|
|
||||||
requireContext().getString(R.string.login_email_subject),
|
|
||||||
requireContext().getString(R.string.login_email_text, appInfo.systemModel, appInfo.systemVersion.toString(), appInfo.versionName)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun onAttachView(view: LoginSymbolView, savedLoginData: Serializable?) {
|
fun onAttachView(view: LoginSymbolView, savedLoginData: Serializable?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.run {
|
view.initView()
|
||||||
initView()
|
|
||||||
showContact(false)
|
|
||||||
}
|
|
||||||
if (savedLoginData is Triple<*, *, *>) {
|
if (savedLoginData is Triple<*, *, *>) {
|
||||||
loginData = savedLoginData as Triple<String, String, String>
|
loginData = savedLoginData as Triple<String, String, String>
|
||||||
}
|
}
|
||||||
|
@ -67,7 +64,6 @@ class LoginSymbolPresenter @Inject constructor(
|
||||||
if (it.isEmpty()) {
|
if (it.isEmpty()) {
|
||||||
Timber.i("Login with symbol result: Empty student list")
|
Timber.i("Login with symbol result: Empty student list")
|
||||||
setErrorSymbolIncorrect()
|
setErrorSymbolIncorrect()
|
||||||
view?.showContact(true)
|
|
||||||
} else {
|
} else {
|
||||||
Timber.i("Login with symbol result: Success")
|
Timber.i("Login with symbol result: Success")
|
||||||
notifyParentAccountLogged(it)
|
notifyParentAccountLogged(it)
|
||||||
|
@ -77,7 +73,6 @@ class LoginSymbolPresenter @Inject constructor(
|
||||||
Timber.i("Login with symbol result: An exception occurred")
|
Timber.i("Login with symbol result: An exception occurred")
|
||||||
analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "endpoint" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" })
|
analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "endpoint" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" })
|
||||||
loginErrorHandler.dispatch(it)
|
loginErrorHandler.dispatch(it)
|
||||||
view?.showContact(true)
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,12 +83,4 @@ class LoginSymbolPresenter @Inject constructor(
|
||||||
showSoftKeyboard()
|
showSoftKeyboard()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDiscordClick() {
|
|
||||||
view?.openDiscordInvite()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onEmailClick() {
|
|
||||||
view?.openEmail()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,4 @@ interface LoginSymbolView : BaseView {
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
fun notifyParentAccountLogged(students: List<Student>)
|
fun notifyParentAccountLogged(students: List<Student>)
|
||||||
|
|
||||||
fun showContact(show: Boolean)
|
|
||||||
|
|
||||||
fun openDiscordInvite()
|
|
||||||
|
|
||||||
fun openEmail()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
@ -26,8 +25,6 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
|
||||||
@Inject
|
@Inject
|
||||||
override lateinit var presenter: LuckyNumberWidgetConfigurePresenter
|
override lateinit var presenter: LuckyNumberWidgetConfigurePresenter
|
||||||
|
|
||||||
private var dialog: AlertDialog? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
|
@ -39,27 +36,11 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
with(widgetConfigureRecycler) {
|
widgetConfigureRecycler.apply {
|
||||||
adapter = configureAdapter
|
adapter = configureAdapter
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||||
}
|
}
|
||||||
|
configureAdapter.setOnItemClickListener { presenter.onItemSelect(it) }
|
||||||
configureAdapter.setOnItemClickListener(presenter::onItemSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showThemeDialog() {
|
|
||||||
val items = arrayOf(
|
|
||||||
getString(R.string.widget_timetable_theme_light),
|
|
||||||
getString(R.string.widget_timetable_theme_dark)
|
|
||||||
)
|
|
||||||
|
|
||||||
dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher)
|
|
||||||
.setTitle(R.string.widget_timetable_theme_title)
|
|
||||||
.setOnDismissListener { presenter.onDismissThemeView() }
|
|
||||||
.setSingleChoiceItems(items, -1) { _, which ->
|
|
||||||
presenter.onThemeSelect(which)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<LuckyNumberWidgetConfigureItem>) {
|
override fun updateData(data: List<LuckyNumberWidgetConfigureItem>) {
|
||||||
|
@ -89,9 +70,4 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
|
||||||
override fun openLoginView() {
|
override fun openLoginView() {
|
||||||
startActivity(LoginActivity.getStartIntent(this))
|
startActivity(LoginActivity.getStartIntent(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
dialog?.dismiss()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
|
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
|
||||||
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey
|
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -20,8 +19,6 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
|
||||||
|
|
||||||
private var appWidgetId: Int? = null
|
private var appWidgetId: Int? = null
|
||||||
|
|
||||||
private var selectedStudent: Student? = null
|
|
||||||
|
|
||||||
fun onAttachView(view: LuckyNumberWidgetConfigureView, appWidgetId: Int?) {
|
fun onAttachView(view: LuckyNumberWidgetConfigureView, appWidgetId: Int?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
this.appWidgetId = appWidgetId
|
this.appWidgetId = appWidgetId
|
||||||
|
@ -31,22 +28,10 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
|
||||||
|
|
||||||
fun onItemSelect(item: AbstractFlexibleItem<*>) {
|
fun onItemSelect(item: AbstractFlexibleItem<*>) {
|
||||||
if (item is LuckyNumberWidgetConfigureItem) {
|
if (item is LuckyNumberWidgetConfigureItem) {
|
||||||
selectedStudent = item.student
|
registerStudent(item.student)
|
||||||
view?.showThemeDialog()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onThemeSelect(index: Int) {
|
|
||||||
appWidgetId?.let {
|
|
||||||
sharedPref.putLong(getThemeWidgetKey(it), index.toLong())
|
|
||||||
}
|
|
||||||
registerStudent(selectedStudent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDismissThemeView(){
|
|
||||||
view?.finishView()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
disposable.add(studentRepository.getSavedStudents(false)
|
disposable.add(studentRepository.getSavedStudents(false)
|
||||||
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
|
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
|
||||||
|
@ -64,14 +49,12 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
|
||||||
}, { errorHandler.dispatch(it) }))
|
}, { errorHandler.dispatch(it) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerStudent(student: Student?) {
|
private fun registerStudent(student: Student) {
|
||||||
requireNotNull(student)
|
appWidgetId?.also {
|
||||||
|
sharedPref.putLong(getStudentWidgetKey(it), student.id)
|
||||||
appWidgetId?.let { id ->
|
view?.apply {
|
||||||
sharedPref.putLong(getStudentWidgetKey(id), student.id)
|
updateLuckyNumberWidget(it)
|
||||||
view?.run {
|
setSuccessResult(it)
|
||||||
updateLuckyNumberWidget(id)
|
|
||||||
setSuccessResult(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view?.finishView()
|
view?.finishView()
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package io.github.wulkanowy.ui.modules.luckynumberwidget
|
package io.github.wulkanowy.ui.modules.luckynumberwidget
|
||||||
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureItem
|
||||||
|
|
||||||
interface LuckyNumberWidgetConfigureView : BaseView {
|
interface LuckyNumberWidgetConfigureView : BaseView {
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun showThemeDialog()
|
|
||||||
|
|
||||||
fun updateData(data: List<LuckyNumberWidgetConfigureItem>)
|
fun updateData(data: List<LuckyNumberWidgetConfigureItem>)
|
||||||
|
|
||||||
fun updateLuckyNumberWidget(widgetId: Int)
|
fun updateLuckyNumberWidget(widgetId: Int)
|
||||||
|
|
|
@ -55,10 +55,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
lateinit var sharedPref: SharedPrefProvider
|
lateinit var sharedPref: SharedPrefProvider
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId"
|
fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId"
|
||||||
|
|
||||||
fun getThemeWidgetKey(appWidgetId: Int) = "lucky_number_widget_theme_$appWidgetId"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||||
|
@ -73,26 +70,24 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
|
|
||||||
private fun onUpdate(context: Context, intent: Intent) {
|
private fun onUpdate(context: Context, intent: Intent) {
|
||||||
intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId ->
|
intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId ->
|
||||||
val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
|
RemoteViews(context.packageName, R.layout.widget_luckynumber).apply {
|
||||||
val layoutId = if (savedTheme == 0L) R.layout.widget_luckynumber else R.layout.widget_luckynumber_dark
|
setTextViewText(R.id.luckyNumberWidgetNumber,
|
||||||
|
getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#"
|
||||||
val luckyNumber = getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)
|
)
|
||||||
val appIntent = PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id,
|
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer,
|
||||||
MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT)
|
PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id,
|
||||||
|
MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
|
||||||
val remoteView = RemoteViews(context.packageName, layoutId).apply {
|
}.also {
|
||||||
setTextViewText(R.id.luckyNumberWidgetNumber, luckyNumber?.luckyNumber?.toString() ?: "#")
|
setStyles(it, intent)
|
||||||
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent)
|
appWidgetManager.updateAppWidget(appWidgetId, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
setStyles(remoteView, intent)
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, remoteView)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDelete(intent: Intent) {
|
private fun onDelete(intent: Intent) {
|
||||||
val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0)
|
intent.getIntExtra(EXTRA_APPWIDGET_ID, 0).let {
|
||||||
if (appWidgetId != 0) sharedPref.delete(getStudentWidgetKey(appWidgetId))
|
if (it != 0) sharedPref.delete(getStudentWidgetKey(it))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLuckyNumber(studentId: Long, appWidgetId: Int): LuckyNumber? {
|
private fun getLuckyNumber(studentId: Long, appWidgetId: Int): LuckyNumber? {
|
||||||
|
@ -101,17 +96,19 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
.filter { true }
|
.filter { true }
|
||||||
.flatMap { studentRepository.getSavedStudents().toMaybe() }
|
.flatMap { studentRepository.getSavedStudents().toMaybe() }
|
||||||
.flatMap { students ->
|
.flatMap { students ->
|
||||||
val student = students.singleOrNull { student -> student.id == studentId }
|
students.singleOrNull { student -> student.id == studentId }
|
||||||
when {
|
.let { student ->
|
||||||
student != null -> Maybe.just(student)
|
when {
|
||||||
studentId != 0L -> {
|
student != null -> Maybe.just(student)
|
||||||
studentRepository.isCurrentStudentSet()
|
studentId != 0L -> {
|
||||||
.filter { true }
|
studentRepository.isCurrentStudentSet()
|
||||||
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
|
.filter { true }
|
||||||
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
|
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
|
||||||
|
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
|
||||||
|
}
|
||||||
|
else -> Maybe.empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> Maybe.empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
|
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
|
||||||
.flatMap { luckyNumberRepository.getLuckyNumber(it) }
|
.flatMap { luckyNumberRepository.getLuckyNumber(it) }
|
||||||
|
@ -126,14 +123,11 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onOptionsChange(context: Context, intent: Intent) {
|
private fun onOptionsChange(context: Context, intent: Intent) {
|
||||||
intent.extras?.getInt(EXTRA_APPWIDGET_ID)?.let { appWidgetId ->
|
intent.extras?.let { extras ->
|
||||||
val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
|
RemoteViews(context.packageName, R.layout.widget_luckynumber).apply {
|
||||||
val layoutId = if (savedTheme == 0L) R.layout.widget_luckynumber else R.layout.widget_luckynumber_dark
|
setStyles(this, intent)
|
||||||
|
appWidgetManager.updateAppWidget(extras.getInt(EXTRA_APPWIDGET_ID), this)
|
||||||
val remoteView = RemoteViews(context.packageName, layoutId)
|
}
|
||||||
|
|
||||||
setStyles(remoteView, intent)
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, remoteView)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +144,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
// 1x1
|
// 1x1
|
||||||
maxWidth < 150 && maxHeight < 110 -> {
|
maxWidth < 150 && maxHeight < 110 -> {
|
||||||
Timber.d("Lucky number widget size: 1x1")
|
Timber.d("Lucky number widget size: 1x1")
|
||||||
with(views) {
|
views.run {
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
||||||
|
@ -160,7 +154,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
// 1x2
|
// 1x2
|
||||||
maxWidth < 150 && maxHeight > 110 -> {
|
maxWidth < 150 && maxHeight > 110 -> {
|
||||||
Timber.d("Lucky number widget size: 1x2")
|
Timber.d("Lucky number widget size: 1x2")
|
||||||
with(views) {
|
views.run {
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageTop, VISIBLE)
|
setViewVisibility(R.id.luckyNumberWidgetImageTop, VISIBLE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
||||||
|
@ -170,7 +164,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
// 2x1
|
// 2x1
|
||||||
maxWidth >= 150 && maxHeight <= 110 -> {
|
maxWidth >= 150 && maxHeight <= 110 -> {
|
||||||
Timber.d("Lucky number widget size: 2x1")
|
Timber.d("Lucky number widget size: 2x1")
|
||||||
with(views) {
|
views.run {
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageLeft, VISIBLE)
|
setViewVisibility(R.id.luckyNumberWidgetImageLeft, VISIBLE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
|
||||||
|
@ -180,7 +174,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
|
||||||
// 2x2 and bigger
|
// 2x2 and bigger
|
||||||
else -> {
|
else -> {
|
||||||
Timber.d("Lucky number widget size: 2x2 and bigger")
|
Timber.d("Lucky number widget size: 2x2 and bigger")
|
||||||
with(views) {
|
views.run {
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
|
||||||
setViewVisibility(R.id.luckyNumberWidgetTitle, VISIBLE)
|
setViewVisibility(R.id.luckyNumberWidgetTitle, VISIBLE)
|
||||||
|
|
|
@ -26,25 +26,25 @@ import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceModule
|
||||||
import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog
|
import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog
|
||||||
import io.github.wulkanowy.ui.modules.more.MoreFragment
|
import io.github.wulkanowy.ui.modules.more.MoreFragment
|
||||||
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersModule
|
|
||||||
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
||||||
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
||||||
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
|
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [MainModule.Static::class])
|
@Module
|
||||||
abstract class MainModule {
|
abstract class MainModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object Static {
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
fun provideFragNavController(activity: MainActivity): FragNavController {
|
fun provideFragNavController(activity: MainActivity): FragNavController {
|
||||||
return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer)
|
return FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
//In activities must be injected as Lazy
|
//In activities must be injected as Lazy
|
||||||
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
fun provideElevationOverlayProvider(activity: MainActivity) = ElevationOverlayProvider(activity)
|
fun provideElevationOverlayProvider(activity: MainActivity) = ElevationOverlayProvider(activity)
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,4 @@ abstract class MainModule {
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@ContributesAndroidInjector(modules = [LicenseModule::class])
|
@ContributesAndroidInjector(modules = [LicenseModule::class])
|
||||||
abstract fun bindLicenseFragment(): LicenseFragment
|
abstract fun bindLicenseFragment(): LicenseFragment
|
||||||
|
|
||||||
@PerFragment
|
|
||||||
@ContributesAndroidInjector(modules = [SchoolAndTeachersModule::class])
|
|
||||||
abstract fun bindSchoolAndTeachersFragment(): SchoolAndTeachersFragment
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE
|
import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE
|
import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL
|
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -39,7 +38,7 @@ class MainPresenter @Inject constructor(
|
||||||
|
|
||||||
fun onViewChange(section: MainView.Section?) {
|
fun onViewChange(section: MainView.Section?) {
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL)
|
showActionBarElevation(section != GRADE && section != MESSAGE)
|
||||||
currentViewTitle?.let { setViewTitle(it) }
|
currentViewTitle?.let { setViewTitle(it) }
|
||||||
currentStackSize?.let {
|
currentStackSize?.let {
|
||||||
if (it > 1) showHomeArrow(true)
|
if (it > 1) showHomeArrow(true)
|
||||||
|
|
|
@ -51,7 +51,6 @@ interface MainView : BaseView {
|
||||||
NOTE(7),
|
NOTE(7),
|
||||||
LUCKY_NUMBER(8),
|
LUCKY_NUMBER(8),
|
||||||
SETTINGS(9),
|
SETTINGS(9),
|
||||||
ABOUT(10),
|
ABOUT(10)
|
||||||
SCHOOL(11)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,13 @@ import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
||||||
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
|
import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Module(includes = [MessageModule.Static::class])
|
@Module
|
||||||
abstract class MessageModule {
|
abstract class MessageModule {
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
object Static {
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
@PerFragment
|
@PerFragment
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMessageAdapter(fragment: MessageFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
fun provideMessageAdapter(fragment: MessageFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
||||||
|
|
|
@ -143,7 +143,7 @@ class MessagePreviewFragment : BaseFragment(), MessagePreviewView, MainView.Titl
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun notifyParentMessageDeleted(message: Message) {
|
override fun notifyParentMessageDeleted(message: Message) {
|
||||||
parentFragmentManager.fragments.forEach { if (it is MessageFragment) it.onDeleteMessage(message) }
|
fragmentManager?.fragments?.forEach { if (it is MessageFragment) it.onDeleteMessage(message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package io.github.wulkanowy.ui.modules.mobiledevice.token
|
package io.github.wulkanowy.ui.modules.mobiledevice.token
|
||||||
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
|
@ -11,7 +9,6 @@ import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.getSystemService
|
|
||||||
import dagger.android.support.DaggerDialogFragment
|
import dagger.android.support.DaggerDialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
|
@ -48,18 +45,9 @@ class MobileDeviceTokenDialog : DaggerDialogFragment(), MobileDeviceTokenVIew {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(token: MobileDeviceToken) {
|
override fun updateData(token: MobileDeviceToken) {
|
||||||
with(mobileDeviceDialogToken) {
|
mobileDeviceDialogToken.text = token.token
|
||||||
text = token.token
|
mobileDeviceDialogSymbol.text = token.symbol
|
||||||
setOnClickListener { clickCopy(token.token) }
|
mobileDeviceDialogPin.text = token.pin
|
||||||
}
|
|
||||||
with(mobileDeviceDialogSymbol) {
|
|
||||||
text = token.symbol
|
|
||||||
setOnClickListener { clickCopy(token.symbol) }
|
|
||||||
}
|
|
||||||
with(mobileDeviceDialogPin) {
|
|
||||||
text = token.pin
|
|
||||||
setOnClickListener { clickCopy(token.pin) }
|
|
||||||
}
|
|
||||||
|
|
||||||
mobileDeviceQr.setImageBitmap(Base64.decode(token.qr, Base64.DEFAULT).let {
|
mobileDeviceQr.setImageBitmap(Base64.decode(token.qr, Base64.DEFAULT).let {
|
||||||
BitmapFactory.decodeByteArray(it, 0, it.size)
|
BitmapFactory.decodeByteArray(it, 0, it.size)
|
||||||
|
@ -98,10 +86,4 @@ class MobileDeviceTokenDialog : DaggerDialogFragment(), MobileDeviceTokenVIew {
|
||||||
presenter.onDetachView()
|
presenter.onDetachView()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickCopy(text: String) {
|
|
||||||
val clip = ClipData.newPlainText("wulkanowy", text)
|
|
||||||
activity?.getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
|
||||||
Toast.makeText(context, R.string.all_copied, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,7 @@ import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||||
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
|
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
|
||||||
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment
|
|
||||||
import io.github.wulkanowy.utils.getCompatDrawable
|
import io.github.wulkanowy.utils.getCompatDrawable
|
||||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||||
import kotlinx.android.synthetic.main.fragment_more.*
|
import kotlinx.android.synthetic.main.fragment_more.*
|
||||||
|
@ -56,9 +54,6 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
|
||||||
override val mobileDevicesRes: Pair<String, Drawable?>?
|
override val mobileDevicesRes: Pair<String, Drawable?>?
|
||||||
get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
|
get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
|
||||||
|
|
||||||
override val schoolAndTeachersRes: Pair<String, Drawable?>?
|
|
||||||
get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) }
|
|
||||||
|
|
||||||
override val settingsRes: Pair<String, Drawable?>?
|
override val settingsRes: Pair<String, Drawable?>?
|
||||||
get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) }
|
get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) }
|
||||||
|
|
||||||
|
@ -111,10 +106,6 @@ class MoreFragment : BaseFragment(), MoreView, MainView.TitledView, MainView.Mai
|
||||||
(activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance())
|
(activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openSchoolAndTeachersView() {
|
|
||||||
(activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openSettingsView() {
|
override fun openSettingsView() {
|
||||||
(activity as? MainActivity)?.pushView(SettingsFragment.newInstance())
|
(activity as? MainActivity)?.pushView(SettingsFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ class MorePresenter @Inject constructor(
|
||||||
noteRes?.first -> openNoteView()
|
noteRes?.first -> openNoteView()
|
||||||
luckyNumberRes?.first -> openLuckyNumberView()
|
luckyNumberRes?.first -> openLuckyNumberView()
|
||||||
mobileDevicesRes?.first -> openMobileDevicesView()
|
mobileDevicesRes?.first -> openMobileDevicesView()
|
||||||
schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
|
|
||||||
settingsRes?.first -> openSettingsView()
|
settingsRes?.first -> openSettingsView()
|
||||||
aboutRes?.first -> openAboutView()
|
aboutRes?.first -> openAboutView()
|
||||||
}
|
}
|
||||||
|
@ -52,7 +51,6 @@ class MorePresenter @Inject constructor(
|
||||||
noteRes?.let { MoreItem(it.first, it.second) },
|
noteRes?.let { MoreItem(it.first, it.second) },
|
||||||
luckyNumberRes?.let { MoreItem(it.first, it.second) },
|
luckyNumberRes?.let { MoreItem(it.first, it.second) },
|
||||||
mobileDevicesRes?.let { MoreItem(it.first, it.second) },
|
mobileDevicesRes?.let { MoreItem(it.first, it.second) },
|
||||||
schoolAndTeachersRes?.let { MoreItem(it.first, it.second) },
|
|
||||||
settingsRes?.let { MoreItem(it.first, it.second) },
|
settingsRes?.let { MoreItem(it.first, it.second) },
|
||||||
aboutRes?.let { MoreItem(it.first, it.second) })
|
aboutRes?.let { MoreItem(it.first, it.second) })
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,8 +15,6 @@ interface MoreView : BaseView {
|
||||||
|
|
||||||
val mobileDevicesRes: Pair<String, Drawable?>?
|
val mobileDevicesRes: Pair<String, Drawable?>?
|
||||||
|
|
||||||
val schoolAndTeachersRes: Pair<String, Drawable?>?
|
|
||||||
|
|
||||||
val settingsRes: Pair<String, Drawable?>?
|
val settingsRes: Pair<String, Drawable?>?
|
||||||
|
|
||||||
val aboutRes: Pair<String, Drawable?>?
|
val aboutRes: Pair<String, Drawable?>?
|
||||||
|
@ -40,6 +38,4 @@ interface MoreView : BaseView {
|
||||||
fun openLuckyNumberView()
|
fun openLuckyNumberView()
|
||||||
|
|
||||||
fun openMobileDevicesView()
|
fun openMobileDevicesView()
|
||||||
|
|
||||||
fun openSchoolAndTeachersView()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers
|
|
||||||
|
|
||||||
interface SchoolAndTeachersChildView {
|
|
||||||
|
|
||||||
fun notifyParentDataLoaded()
|
|
||||||
|
|
||||||
fun onParentLoadData(forceRefresh: Boolean)
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.View.INVISIBLE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import io.github.wulkanowy.R
|
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
|
||||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment
|
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
|
||||||
import io.github.wulkanowy.utils.setOnSelectPageListener
|
|
||||||
import kotlinx.android.synthetic.main.fragment_schoolandteachers.*
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SchoolAndTeachersFragment : BaseFragment(), SchoolAndTeachersView, MainView.TitledView {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var presenter: SchoolAndTeachersPresenter
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var pagerAdapter: BaseFragmentPagerAdapter
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance() = SchoolAndTeachersFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val titleStringId: Int get() = R.string.schoolandteachers_title
|
|
||||||
|
|
||||||
override val currentPageIndex get() = schoolandteachersViewPager.currentItem
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_schoolandteachers, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
presenter.onAttachView(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initView() {
|
|
||||||
with(pagerAdapter) {
|
|
||||||
containerId = schoolandteachersViewPager.id
|
|
||||||
addFragmentsWithTitle(mapOf(
|
|
||||||
SchoolFragment.newInstance() to getString(R.string.school_title),
|
|
||||||
TeacherFragment.newInstance() to getString(R.string.teachers_title)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
with(schoolandteachersViewPager) {
|
|
||||||
adapter = pagerAdapter
|
|
||||||
offscreenPageLimit = 2
|
|
||||||
setOnSelectPageListener(presenter::onPageSelected)
|
|
||||||
}
|
|
||||||
|
|
||||||
with(schoolandteachersTabLayout) {
|
|
||||||
setupWithViewPager(schoolandteachersViewPager)
|
|
||||||
setElevationCompat(context.dpToPx(4f))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
|
||||||
schoolandteachersViewPager.visibility = if (show) VISIBLE else INVISIBLE
|
|
||||||
schoolandteachersTabLayout.visibility = if (show) VISIBLE else INVISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
|
||||||
schoolandteachersProgress.visibility = if (show) VISIBLE else INVISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onChildFragmentLoaded() {
|
|
||||||
presenter.onChildViewLoaded()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) {
|
|
||||||
(pagerAdapter.getFragmentInstance(index) as? SchoolAndTeachersChildView)?.onParentLoadData(forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
presenter.onDetachView()
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers
|
|
||||||
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import dagger.android.ContributesAndroidInjector
|
|
||||||
import io.github.wulkanowy.di.scopes.PerChildFragment
|
|
||||||
import io.github.wulkanowy.di.scopes.PerFragment
|
|
||||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
@Module(includes = [SchoolAndTeachersModule.Static::class])
|
|
||||||
abstract class SchoolAndTeachersModule {
|
|
||||||
|
|
||||||
@Module
|
|
||||||
object Static {
|
|
||||||
|
|
||||||
@PerFragment
|
|
||||||
@Provides
|
|
||||||
fun provideSchoolAndTeachersAdapter(fragment: SchoolAndTeachersFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
@PerChildFragment
|
|
||||||
@ContributesAndroidInjector
|
|
||||||
abstract fun provideSchoolFragment(): SchoolFragment
|
|
||||||
|
|
||||||
@PerChildFragment
|
|
||||||
@ContributesAndroidInjector
|
|
||||||
abstract fun provideTeacherFragment(): TeacherFragment
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers
|
|
||||||
|
|
||||||
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.SchedulersProvider
|
|
||||||
import io.reactivex.Completable
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SchoolAndTeachersPresenter @Inject constructor(
|
|
||||||
schedulers: SchedulersProvider,
|
|
||||||
errorHandler: ErrorHandler,
|
|
||||||
studentRepository: StudentRepository
|
|
||||||
) : BasePresenter<SchoolAndTeachersView>(errorHandler, studentRepository, schedulers) {
|
|
||||||
|
|
||||||
override fun onAttachView(view: SchoolAndTeachersView) {
|
|
||||||
super.onAttachView(view)
|
|
||||||
disposable.add(Completable.timer(150, TimeUnit.MILLISECONDS, schedulers.mainThread)
|
|
||||||
.subscribe {
|
|
||||||
view.initView()
|
|
||||||
Timber.i("Message view was initialized")
|
|
||||||
loadData()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onPageSelected(index: Int) {
|
|
||||||
loadChild(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData() {
|
|
||||||
view?.run { loadChild(currentPageIndex) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadChild(index: Int, forceRefresh: Boolean = false) {
|
|
||||||
Timber.i("Load schoolandteachers child view index: $index")
|
|
||||||
view?.notifyChildLoadData(index, forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onChildViewLoaded() {
|
|
||||||
view?.apply {
|
|
||||||
showContent(true)
|
|
||||||
showProgress(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers
|
|
||||||
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
|
||||||
|
|
||||||
interface SchoolAndTeachersView : BaseView {
|
|
||||||
|
|
||||||
val currentPageIndex: Int
|
|
||||||
|
|
||||||
fun initView()
|
|
||||||
|
|
||||||
fun showContent(show: Boolean)
|
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
|
||||||
|
|
||||||
fun notifyChildLoadData(index: Int, forceRefresh: Boolean)
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.school
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import io.github.wulkanowy.R
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
|
|
||||||
import io.github.wulkanowy.utils.dialPhone
|
|
||||||
import io.github.wulkanowy.utils.openMapLocation
|
|
||||||
import kotlinx.android.synthetic.main.fragment_school.*
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SchoolFragment : BaseFragment(), SchoolView, MainView.TitledView, SchoolAndTeachersChildView {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var presenter: SchoolPresenter
|
|
||||||
|
|
||||||
override val titleStringId get() = R.string.school_title
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance() = SchoolFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_school, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
presenter.onAttachView(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initView() {
|
|
||||||
schoolSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
|
||||||
|
|
||||||
schoolAddressButton.setOnClickListener { presenter.onAddressSelected() }
|
|
||||||
schoolTelephoneButton.setOnClickListener { presenter.onTelephoneSelected() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateData(data: School) {
|
|
||||||
schoolName.text = data.name
|
|
||||||
schoolAddress.text = data.address.ifBlank { "-" }
|
|
||||||
schoolAddressButton.visibility = if (data.address.isNotBlank()) View.VISIBLE else View.GONE
|
|
||||||
schoolTelephone.text = data.contact.ifBlank { "-" }
|
|
||||||
schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) View.VISIBLE else View.GONE
|
|
||||||
schoolHeadmaster.text = data.headmaster
|
|
||||||
schoolPedagogue.text = data.pedagogue
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
|
||||||
schoolEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
|
||||||
schoolProgress.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun enableSwipe(enable: Boolean) {
|
|
||||||
schoolSwipe.isEnabled = enable
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
|
||||||
schoolContent.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefresh() {
|
|
||||||
schoolSwipe.isRefreshing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyParentDataLoaded() {
|
|
||||||
(parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onParentLoadData(forceRefresh: Boolean) {
|
|
||||||
presenter.onParentViewLoadData(forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
presenter.onDetachView()
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openMapsLocation(location: String) {
|
|
||||||
context?.openMapLocation(location)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dialPhone(phone: String) {
|
|
||||||
context?.dialPhone(phone)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.school
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.repositories.school.SchoolRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
|
||||||
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 SchoolPresenter @Inject constructor(
|
|
||||||
schedulers: SchedulersProvider,
|
|
||||||
errorHandler: ErrorHandler,
|
|
||||||
studentRepository: StudentRepository,
|
|
||||||
private val semesterRepository: SemesterRepository,
|
|
||||||
private val schoolRepository: SchoolRepository,
|
|
||||||
private val analytics: FirebaseAnalyticsHelper
|
|
||||||
) : BasePresenter<SchoolView>(errorHandler, studentRepository, schedulers) {
|
|
||||||
|
|
||||||
private var address: String? = null
|
|
||||||
|
|
||||||
private var contact: String? = null
|
|
||||||
|
|
||||||
override fun onAttachView(view: SchoolView) {
|
|
||||||
super.onAttachView(view)
|
|
||||||
view.initView()
|
|
||||||
Timber.i("School view was initialized")
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
|
||||||
loadData(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onParentViewLoadData(forceRefresh: Boolean) {
|
|
||||||
loadData(forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onAddressSelected() {
|
|
||||||
address?.let{ view?.openMapsLocation(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onTelephoneSelected() {
|
|
||||||
contact?.let { view?.dialPhone(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(forceRefresh: Boolean = false) {
|
|
||||||
Timber.i("Loading school info started")
|
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
|
||||||
.flatMap { semesterRepository.getCurrentSemester(it) }
|
|
||||||
.flatMapMaybe { schoolRepository.getSchoolInfo(it, forceRefresh) }
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
|
||||||
hideRefresh()
|
|
||||||
showProgress(false)
|
|
||||||
enableSwipe(true)
|
|
||||||
notifyParentDataLoaded()
|
|
||||||
}
|
|
||||||
}.subscribe({
|
|
||||||
Timber.i("Loading teachers result: Success")
|
|
||||||
view?.run {
|
|
||||||
address = it.address.ifBlank { null }
|
|
||||||
contact = it.contact.ifBlank { null }
|
|
||||||
updateData(it)
|
|
||||||
showContent(true)
|
|
||||||
showEmpty(false)
|
|
||||||
}
|
|
||||||
analytics.logEvent("load_school", "force_refresh" to forceRefresh)
|
|
||||||
}, {
|
|
||||||
Timber.i("Loading school result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
}, {
|
|
||||||
Timber.i("Loading school result: No school info found")
|
|
||||||
view?.run {
|
|
||||||
showContent(false)
|
|
||||||
showEmpty(true)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.school
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView
|
|
||||||
|
|
||||||
interface SchoolView : BaseView, SchoolAndTeachersChildView {
|
|
||||||
|
|
||||||
fun initView()
|
|
||||||
|
|
||||||
fun updateData(data: School)
|
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
|
||||||
|
|
||||||
fun showContent(show: Boolean)
|
|
||||||
|
|
||||||
fun hideRefresh()
|
|
||||||
|
|
||||||
fun openMapsLocation(location: String)
|
|
||||||
|
|
||||||
fun dialPhone(phone: String)
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.teacher
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
|
||||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|
||||||
import io.github.wulkanowy.R
|
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
|
|
||||||
import kotlinx.android.synthetic.main.fragment_teacher.*
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class TeacherFragment : BaseFragment(), TeacherView, MainView.TitledView, SchoolAndTeachersChildView {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var presenter: TeacherPresenter
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var teacherAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance() = TeacherFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val titleStringId: Int
|
|
||||||
get() = R.string.teachers_title
|
|
||||||
|
|
||||||
override val noSubjectString get() = getString(R.string.teacher_no_subject)
|
|
||||||
|
|
||||||
override val isViewEmpty: Boolean
|
|
||||||
get() = teacherAdapter.isEmpty
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_teacher, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
presenter.onAttachView(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initView() {
|
|
||||||
teacherRecycler.run {
|
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
|
||||||
adapter = teacherAdapter
|
|
||||||
addItemDecoration(FlexibleItemDecoration(context)
|
|
||||||
.withDefaultDivider()
|
|
||||||
.withDrawDividerOnLastItem(false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
teacherSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateData(data: List<TeacherItem>) {
|
|
||||||
teacherAdapter.updateDataSet(data, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateItem(item: AbstractFlexibleItem<*>) {
|
|
||||||
teacherAdapter.updateItem(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearData() {
|
|
||||||
teacherAdapter.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showEmpty(show: Boolean) {
|
|
||||||
teacherEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
|
||||||
teacherProgress.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun enableSwipe(enable: Boolean) {
|
|
||||||
teacherSwipe.isEnabled = enable
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
|
||||||
teacherRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefresh() {
|
|
||||||
teacherSwipe.isRefreshing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyParentDataLoaded() {
|
|
||||||
(parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onParentLoadData(forceRefresh: Boolean) {
|
|
||||||
presenter.onParentViewLoadData(forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
presenter.onDetachView()
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.teacher
|
|
||||||
|
|
||||||
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.Teacher
|
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
|
||||||
import kotlinx.android.synthetic.main.item_teacher.*
|
|
||||||
|
|
||||||
class TeacherItem(val teacher: Teacher, private val noSubjectText: String) : AbstractFlexibleItem<TeacherItem.ViewHolder>() {
|
|
||||||
|
|
||||||
override fun getLayoutRes() = R.layout.item_teacher
|
|
||||||
|
|
||||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>): TeacherItem.ViewHolder {
|
|
||||||
return TeacherItem.ViewHolder(view, adapter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: TeacherItem.ViewHolder, position: Int, payloads: MutableList<Any>?) {
|
|
||||||
holder.apply {
|
|
||||||
teacherItemName.text = teacher.name
|
|
||||||
teacherItemSubject.text = if (teacher.subject.isNotBlank()) teacher.subject else noSubjectText
|
|
||||||
if (teacher.shortName.isNotBlank()) {
|
|
||||||
teacherItemShortName.visibility = VISIBLE
|
|
||||||
teacherItemShortName.text = "[${teacher.shortName}]"
|
|
||||||
} else {
|
|
||||||
teacherItemShortName.visibility = GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
|
|
||||||
other as TeacherItem
|
|
||||||
|
|
||||||
if (teacher != other.teacher) return false
|
|
||||||
if (teacher.id != other.teacher.id) return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = teacher.hashCode()
|
|
||||||
result = 31 * result + teacher.id.toInt()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer {
|
|
||||||
override val containerView: View
|
|
||||||
get() = contentView
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.teacher
|
|
||||||
|
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.teacher.TeacherRepository
|
|
||||||
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 TeacherPresenter @Inject constructor(
|
|
||||||
schedulers: SchedulersProvider,
|
|
||||||
errorHandler: ErrorHandler,
|
|
||||||
studentRepository: StudentRepository,
|
|
||||||
private val semesterRepository: SemesterRepository,
|
|
||||||
private val teacherRepository: TeacherRepository,
|
|
||||||
private val analytics: FirebaseAnalyticsHelper
|
|
||||||
) : BasePresenter<TeacherView>(errorHandler, studentRepository, schedulers) {
|
|
||||||
|
|
||||||
override fun onAttachView(view: TeacherView) {
|
|
||||||
super.onAttachView(view)
|
|
||||||
view.initView()
|
|
||||||
Timber.i("Teacher view was initialized")
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
|
||||||
loadData(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onParentViewLoadData(forceRefresh: Boolean) {
|
|
||||||
loadData(forceRefresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(forceRefresh: Boolean = false) {
|
|
||||||
Timber.i("Loading teachers data started")
|
|
||||||
disposable.add(studentRepository.getCurrentStudent()
|
|
||||||
.flatMap { semesterRepository.getCurrentSemester(it) }
|
|
||||||
.flatMap { teacherRepository.getTeachers(it, forceRefresh) }
|
|
||||||
.map { it.filter { teacher -> teacher.name.isNotBlank() } }
|
|
||||||
.map { items -> items.map { TeacherItem(it, view?.noSubjectString.orEmpty()) } }
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
|
||||||
hideRefresh()
|
|
||||||
showProgress(false)
|
|
||||||
enableSwipe(true)
|
|
||||||
notifyParentDataLoaded()
|
|
||||||
}
|
|
||||||
}.subscribe({
|
|
||||||
Timber.i("Loading teachers result: Success")
|
|
||||||
view?.run {
|
|
||||||
updateData(it)
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
}
|
|
||||||
analytics.logEvent("load_teachers", "items" to it.size, "force_refresh" to forceRefresh)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading teachers result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package io.github.wulkanowy.ui.modules.schoolandteachers.teacher
|
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
|
||||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView
|
|
||||||
|
|
||||||
interface TeacherView : BaseView, SchoolAndTeachersChildView {
|
|
||||||
|
|
||||||
val isViewEmpty: Boolean
|
|
||||||
|
|
||||||
val noSubjectString: String
|
|
||||||
|
|
||||||
fun initView()
|
|
||||||
|
|
||||||
fun updateData(data: List<TeacherItem>)
|
|
||||||
|
|
||||||
fun updateItem(item: AbstractFlexibleItem<*>)
|
|
||||||
|
|
||||||
fun hideRefresh()
|
|
||||||
|
|
||||||
fun clearData()
|
|
||||||
|
|
||||||
fun showProgress(show: Boolean)
|
|
||||||
|
|
||||||
fun enableSwipe(enable: Boolean)
|
|
||||||
|
|
||||||
fun showContent(show: Boolean)
|
|
||||||
|
|
||||||
fun showEmpty(show: Boolean)
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ import android.view.ViewGroup
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.android.synthetic.main.dialog_timetable.*
|
import kotlinx.android.synthetic.main.dialog_timetable.*
|
||||||
import org.threeten.bp.LocalDateTime
|
import org.threeten.bp.LocalDateTime
|
||||||
|
@ -73,22 +72,13 @@ class TimetableDialog : DialogFragment() {
|
||||||
|
|
||||||
private fun setInfo(info: String, teacher: String, canceled: Boolean, changes: Boolean) {
|
private fun setInfo(info: String, teacher: String, canceled: Boolean, changes: Boolean) {
|
||||||
when {
|
when {
|
||||||
info.isNotBlank() -> {
|
info.isNotBlank() -> timetableDialogChanges.text = when {
|
||||||
if (canceled) {
|
canceled && !changes -> "Lekcja odwołana: $info"
|
||||||
timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
changes && teacher.isNotBlank() -> "Zastępstwo: $teacher"
|
||||||
timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
changes && teacher.isBlank() -> "Zastępstwo, ${info.decapitalize()}"
|
||||||
} else {
|
else -> info.capitalize()
|
||||||
timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange))
|
}
|
||||||
timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange))
|
else -> {
|
||||||
}
|
|
||||||
|
|
||||||
timetableDialogChanges.text = when {
|
|
||||||
canceled && !changes -> "Lekcja odwołana: $info"
|
|
||||||
changes && teacher.isNotBlank() -> "Zastępstwo: $teacher"
|
|
||||||
changes && teacher.isBlank() -> "Zastępstwo, ${info.decapitalize()}"
|
|
||||||
else -> info.capitalize()
|
|
||||||
}
|
|
||||||
} else -> {
|
|
||||||
timetableDialogChangesTitle.visibility = GONE
|
timetableDialogChangesTitle.visibility = GONE
|
||||||
timetableDialogChanges.visibility = GONE
|
timetableDialogChanges.visibility = GONE
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ class TimetableFragment : BaseFragment(), TimetableView, MainView.MainChildView,
|
||||||
|
|
||||||
override val titleStringId get() = R.string.timetable_title
|
override val titleStringId get() = R.string.timetable_title
|
||||||
|
|
||||||
|
override val roomString get() = getString(R.string.timetable_room)
|
||||||
|
|
||||||
override val isViewEmpty get() = timetableAdapter.isEmpty
|
override val isViewEmpty get() = timetableAdapter.isEmpty
|
||||||
|
|
||||||
override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
|
override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
|
||||||
|
|
|
@ -11,12 +11,11 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.item_timetable.*
|
import kotlinx.android.synthetic.main.item_timetable.*
|
||||||
|
|
||||||
class TimetableItem(val lesson: Timetable) :
|
class TimetableItem(val lesson: Timetable, private val roomText: String) :
|
||||||
AbstractFlexibleItem<TimetableItem.ViewHolder>() {
|
AbstractFlexibleItem<TimetableItem.ViewHolder>() {
|
||||||
|
|
||||||
override fun getLayoutRes() = R.layout.item_timetable
|
override fun getLayoutRes() = R.layout.item_timetable
|
||||||
|
@ -27,97 +26,16 @@ class TimetableItem(val lesson: Timetable) :
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>?) {
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder, position: Int, payloads: MutableList<Any>?) {
|
||||||
updateFields(holder)
|
holder.apply {
|
||||||
|
timetableItemNumber.text = lesson.number.toString()
|
||||||
with(holder) {
|
timetableItemSubject.text = lesson.subject
|
||||||
|
timetableItemRoom.text = if (lesson.room.isNotBlank()) "$roomText ${lesson.room}" else ""
|
||||||
|
timetableItemTime.text = "${lesson.start.toFormattedString("HH:mm")} - ${lesson.end.toFormattedString("HH:mm")}"
|
||||||
|
timetableItemAlert.visibility = if (lesson.changes || lesson.canceled) VISIBLE else GONE
|
||||||
timetableItemSubject.paintFlags =
|
timetableItemSubject.paintFlags =
|
||||||
if (lesson.canceled) timetableItemSubject.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
if (lesson.canceled) timetableItemSubject.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
|
||||||
else timetableItemSubject.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
else timetableItemSubject.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDescription(holder)
|
|
||||||
updateColors(holder)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateFields(holder: ViewHolder) {
|
|
||||||
with(holder) {
|
|
||||||
timetableItemNumber.text = lesson.number.toString()
|
|
||||||
timetableItemSubject.text = lesson.subject
|
|
||||||
timetableItemRoom.text = lesson.room
|
|
||||||
timetableItemTeacher.text = lesson.teacher
|
|
||||||
timetableItemTimeStart.text = lesson.start.toFormattedString("HH:mm")
|
|
||||||
timetableItemTimeFinish.text = lesson.end.toFormattedString("HH:mm")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateDescription(holder: ViewHolder) {
|
|
||||||
with(holder) {
|
|
||||||
if (lesson.info.isNotBlank() && !lesson.changes) {
|
|
||||||
updateDescriptionNoChanges(this)
|
|
||||||
} else {
|
|
||||||
timetableItemDescription.visibility = GONE
|
|
||||||
|
|
||||||
timetableItemRoom.visibility = VISIBLE
|
|
||||||
timetableItemTeacher.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateDescriptionNoChanges(holder: ViewHolder) {
|
|
||||||
with(holder) {
|
|
||||||
timetableItemDescription.visibility = VISIBLE
|
|
||||||
timetableItemDescription.text = lesson.info
|
|
||||||
|
|
||||||
timetableItemRoom.visibility = GONE
|
|
||||||
timetableItemTeacher.visibility = GONE
|
|
||||||
|
|
||||||
timetableItemDescription.setTextColor(holder.view.context.getThemeAttrColor(
|
|
||||||
if (lesson.canceled) R.attr.colorPrimary
|
|
||||||
else R.attr.colorTimetableChange
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateColors(holder: ViewHolder) {
|
|
||||||
with(holder) {
|
|
||||||
if (lesson.canceled) {
|
|
||||||
timetableItemNumber.setTextColor(holder.view.context.getThemeAttrColor(R.attr.colorPrimary))
|
|
||||||
timetableItemSubject.setTextColor(holder.view.context.getThemeAttrColor(R.attr.colorPrimary))
|
|
||||||
} else {
|
|
||||||
updateNumberColor(this)
|
|
||||||
updateSubjectColor(this)
|
|
||||||
updateRoomColor(this)
|
|
||||||
updateTeacherColor(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNumberColor(holder: ViewHolder) {
|
|
||||||
holder.timetableItemNumber.setTextColor(holder.view.context.getThemeAttrColor(
|
|
||||||
if (lesson.changes || lesson.info.isNotBlank()) R.attr.colorTimetableChange
|
|
||||||
else android.R.attr.textColorPrimary
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateSubjectColor(holder: ViewHolder) {
|
|
||||||
holder.timetableItemSubject.setTextColor(holder.view.context.getThemeAttrColor(
|
|
||||||
if (lesson.subjectOld.isNotBlank() && lesson.subjectOld != lesson.subject) R.attr.colorTimetableChange
|
|
||||||
else android.R.attr.textColorPrimary
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateRoomColor(holder: ViewHolder) {
|
|
||||||
holder.timetableItemRoom.setTextColor(holder.view.context.getThemeAttrColor(
|
|
||||||
if (lesson.roomOld.isNotBlank() && lesson.roomOld != lesson.room) R.attr.colorTimetableChange
|
|
||||||
else android.R.attr.textColorSecondary
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateTeacherColor(holder: ViewHolder) {
|
|
||||||
holder.timetableItemTeacher.setTextColor(holder.view.context.getThemeAttrColor(
|
|
||||||
if (lesson.teacherOld.isNotBlank() && lesson.teacherOld != lesson.teacher) R.attr.colorTimetableChange
|
|
||||||
else android.R.attr.textColorSecondary
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.github.wulkanowy.ui.modules.timetable
|
package io.github.wulkanowy.ui.modules.timetable
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
|
@ -109,7 +108,7 @@ class TimetablePresenter @Inject constructor(
|
||||||
.flatMap { semesterRepository.getCurrentSemester(it) }
|
.flatMap { semesterRepository.getCurrentSemester(it) }
|
||||||
.delay(200, MILLISECONDS)
|
.delay(200, MILLISECONDS)
|
||||||
.flatMap { timetableRepository.getTimetable(it, currentDate, currentDate, forceRefresh) }
|
.flatMap { timetableRepository.getTimetable(it, currentDate, currentDate, forceRefresh) }
|
||||||
.map { items -> items.map { TimetableItem(it) } }
|
.map { items -> items.map { TimetableItem(it, view?.roomString.orEmpty()) } }
|
||||||
.map { items -> items.sortedBy { it.lesson.number } }
|
.map { items -> items.sortedBy { it.lesson.number } }
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
.observeOn(schedulers.mainThread)
|
.observeOn(schedulers.mainThread)
|
||||||
|
@ -148,12 +147,11 @@ class TimetablePresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
private fun reloadNavigation() {
|
private fun reloadNavigation() {
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalize())
|
updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
interface TimetableView : BaseView {
|
interface TimetableView : BaseView {
|
||||||
|
|
||||||
|
val roomString: String
|
||||||
|
|
||||||
val isViewEmpty: Boolean
|
val isViewEmpty: Boolean
|
||||||
|
|
||||||
val currentStackSize: Int?
|
val currentStackSize: Int?
|
||||||
|
|
|
@ -9,7 +9,6 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.item_completed_lesson.*
|
import kotlinx.android.synthetic.main.item_completed_lesson.*
|
||||||
|
|
||||||
|
@ -24,10 +23,6 @@ class CompletedLessonItem(val completedLesson: CompletedLesson) : AbstractFlexib
|
||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: CompletedLessonItem.ViewHolder?, position: Int, payloads: MutableList<Any>?) {
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: CompletedLessonItem.ViewHolder?, position: Int, payloads: MutableList<Any>?) {
|
||||||
holder?.apply {
|
holder?.apply {
|
||||||
completedLessonItemNumber.text = completedLesson.number.toString()
|
completedLessonItemNumber.text = completedLesson.number.toString()
|
||||||
completedLessonItemNumber.setTextColor(holder.contentView.context.getThemeAttrColor(
|
|
||||||
if (completedLesson.substitution.isNotEmpty()) R.attr.colorTimetableChange
|
|
||||||
else android.R.attr.textColorPrimary
|
|
||||||
))
|
|
||||||
completedLessonItemSubject.text = completedLesson.subject
|
completedLessonItemSubject.text = completedLesson.subject
|
||||||
completedLessonItemTopic.text = completedLesson.topic
|
completedLessonItemTopic.text = completedLesson.topic
|
||||||
completedLessonItemAlert.visibility = if (completedLesson.substitution.isNotEmpty()) VISIBLE else GONE
|
completedLessonItemAlert.visibility = if (completedLesson.substitution.isNotEmpty()) VISIBLE else GONE
|
||||||
|
|
|
@ -135,7 +135,7 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalize())
|
updateNavigationDay(currentDate.toFormattedString("EEEE\ndd.MM.YYYY").capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import android.widget.Toast.LENGTH_LONG
|
import android.widget.Toast.LENGTH_LONG
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
@ -28,8 +27,6 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
|
||||||
@Inject
|
@Inject
|
||||||
override lateinit var presenter: TimetableWidgetConfigurePresenter
|
override lateinit var presenter: TimetableWidgetConfigurePresenter
|
||||||
|
|
||||||
private var dialog: AlertDialog? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
|
@ -41,27 +38,11 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
with(widgetConfigureRecycler) {
|
widgetConfigureRecycler.apply {
|
||||||
adapter = configureAdapter
|
adapter = configureAdapter
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||||
}
|
}
|
||||||
|
configureAdapter.setOnItemClickListener { presenter.onItemSelect(it) }
|
||||||
configureAdapter.setOnItemClickListener(presenter::onItemSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showThemeDialog() {
|
|
||||||
val items = arrayOf(
|
|
||||||
getString(R.string.widget_timetable_theme_light),
|
|
||||||
getString(R.string.widget_timetable_theme_dark)
|
|
||||||
)
|
|
||||||
|
|
||||||
dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher)
|
|
||||||
.setTitle(R.string.widget_timetable_theme_title)
|
|
||||||
.setOnDismissListener { presenter.onDismissThemeView() }
|
|
||||||
.setSingleChoiceItems(items, -1) { _, which ->
|
|
||||||
presenter.onThemeSelect(which)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<TimetableWidgetConfigureItem>) {
|
override fun updateData(data: List<TimetableWidgetConfigureItem>) {
|
||||||
|
@ -91,9 +72,4 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
|
||||||
override fun openLoginView() {
|
override fun openLoginView() {
|
||||||
startActivity(LoginActivity.getStartIntent(this))
|
startActivity(LoginActivity.getStartIntent(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
dialog?.dismiss()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey
|
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -22,8 +21,6 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
|
||||||
|
|
||||||
private var isFromProvider = false
|
private var isFromProvider = false
|
||||||
|
|
||||||
private var selectedStudent: Student? = null
|
|
||||||
|
|
||||||
fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) {
|
fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
this.appWidgetId = appWidgetId
|
this.appWidgetId = appWidgetId
|
||||||
|
@ -34,24 +31,10 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
|
||||||
|
|
||||||
fun onItemSelect(item: AbstractFlexibleItem<*>) {
|
fun onItemSelect(item: AbstractFlexibleItem<*>) {
|
||||||
if (item is TimetableWidgetConfigureItem) {
|
if (item is TimetableWidgetConfigureItem) {
|
||||||
selectedStudent = item.student
|
registerStudent(item.student)
|
||||||
|
|
||||||
if (isFromProvider) registerStudent(selectedStudent)
|
|
||||||
else view?.showThemeDialog()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onThemeSelect(index: Int) {
|
|
||||||
appWidgetId?.let {
|
|
||||||
sharedPref.putLong(getThemeWidgetKey(it), index.toLong())
|
|
||||||
}
|
|
||||||
registerStudent(selectedStudent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDismissThemeView(){
|
|
||||||
view?.finishView()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
disposable.add(studentRepository.getSavedStudents(false)
|
disposable.add(studentRepository.getSavedStudents(false)
|
||||||
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
|
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
|
||||||
|
@ -63,23 +46,18 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
|
||||||
.subscribe({
|
.subscribe({
|
||||||
when {
|
when {
|
||||||
it.isEmpty() -> view?.openLoginView()
|
it.isEmpty() -> view?.openLoginView()
|
||||||
it.size == 1 && !isFromProvider -> {
|
it.size == 1 && !isFromProvider -> registerStudent(it.single().student)
|
||||||
selectedStudent = it.single().student
|
|
||||||
view?.showThemeDialog()
|
|
||||||
}
|
|
||||||
else -> view?.updateData(it)
|
else -> view?.updateData(it)
|
||||||
}
|
}
|
||||||
}, { errorHandler.dispatch(it) }))
|
}, { errorHandler.dispatch(it) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerStudent(student: Student?) {
|
private fun registerStudent(student: Student) {
|
||||||
requireNotNull(student)
|
appWidgetId?.also {
|
||||||
|
sharedPref.putLong(getStudentWidgetKey(it), student.id)
|
||||||
appWidgetId?.let { id ->
|
view?.apply {
|
||||||
sharedPref.putLong(getStudentWidgetKey(id), student.id)
|
updateTimetableWidget(it)
|
||||||
view?.run {
|
setSuccessResult(it)
|
||||||
updateTimetableWidget(id)
|
|
||||||
setSuccessResult(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view?.finishView()
|
view?.finishView()
|
||||||
|
|
|
@ -10,8 +10,6 @@ interface TimetableWidgetConfigureView : BaseView {
|
||||||
|
|
||||||
fun updateTimetableWidget(widgetId: Int)
|
fun updateTimetableWidget(widgetId: Int)
|
||||||
|
|
||||||
fun showThemeDialog()
|
|
||||||
|
|
||||||
fun setSuccessResult(widgetId: Int)
|
fun setSuccessResult(widgetId: Int)
|
||||||
|
|
||||||
fun finishView()
|
fun finishView()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.github.wulkanowy.ui.modules.timetablewidget
|
package io.github.wulkanowy.ui.modules.timetablewidget
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
|
import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -19,9 +18,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
|
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey
|
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
|
@ -39,14 +36,6 @@ class TimetableWidgetFactory(
|
||||||
|
|
||||||
private var lessons = emptyList<Timetable>()
|
private var lessons = emptyList<Timetable>()
|
||||||
|
|
||||||
private var layoutId: Int? = null
|
|
||||||
|
|
||||||
private var primaryColor: Int? = null
|
|
||||||
|
|
||||||
private var textColor: Int? = null
|
|
||||||
|
|
||||||
private var timetableChangeColor: Int? = null
|
|
||||||
|
|
||||||
override fun getLoadingView() = null
|
override fun getLoadingView() = null
|
||||||
|
|
||||||
override fun hasStableIds() = true
|
override fun hasStableIds() = true
|
||||||
|
@ -66,141 +55,63 @@ class TimetableWidgetFactory(
|
||||||
val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0))
|
val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0))
|
||||||
val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0)
|
val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0)
|
||||||
|
|
||||||
updateTheme(appWidgetId)
|
lessons = try {
|
||||||
|
studentRepository.isStudentSaved()
|
||||||
updateLessons(date, studentId)
|
.filter { true }
|
||||||
|
.flatMap { studentRepository.getSavedStudents().toMaybe() }
|
||||||
|
.flatMap {
|
||||||
|
it.singleOrNull { student -> student.id == studentId }
|
||||||
|
.let { student ->
|
||||||
|
if (student != null) Maybe.just(student)
|
||||||
|
else Maybe.empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
|
||||||
|
.flatMap { timetableRepository.getTimetable(it, date, date).toMaybe() }
|
||||||
|
.map { item -> item.sortedBy { it.number } }
|
||||||
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
|
.blockingGet(emptyList())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "An error has occurred in timetable widget factory")
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTheme(appWidgetId: Int) {
|
|
||||||
val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
|
|
||||||
layoutId = if (savedTheme == 0L) R.layout.item_widget_timetable else R.layout.item_widget_timetable_dark
|
|
||||||
|
|
||||||
primaryColor = if (savedTheme == 0L) R.color.colorPrimary else R.color.colorPrimaryLight
|
|
||||||
textColor = if (savedTheme == 0L) android.R.color.black else android.R.color.white
|
|
||||||
timetableChangeColor = if (savedTheme == 0L) R.color.timetable_change_dark else R.color.timetable_change_light
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateLessons(date: LocalDate, studentId: Long) {
|
|
||||||
lessons = try {
|
|
||||||
studentRepository.isStudentSaved()
|
|
||||||
.filter { true }
|
|
||||||
.flatMap { studentRepository.getSavedStudents().toMaybe() }
|
|
||||||
.flatMap {
|
|
||||||
val student = it.singleOrNull { student -> student.id == studentId }
|
|
||||||
|
|
||||||
if (student != null) Maybe.just(student)
|
|
||||||
else Maybe.empty()
|
|
||||||
}
|
|
||||||
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
|
|
||||||
.flatMap { timetableRepository.getTimetable(it, date, date).toMaybe() }
|
|
||||||
.map { item -> item.sortedBy { it.number } }
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.blockingGet(emptyList())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e, "An error has occurred in timetable widget factory")
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
override fun getViewAt(position: Int): RemoteViews? {
|
override fun getViewAt(position: Int): RemoteViews? {
|
||||||
if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null
|
if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null
|
||||||
|
|
||||||
return RemoteViews(context.packageName, layoutId!!).apply {
|
return RemoteViews(context.packageName, R.layout.item_widget_timetable).apply {
|
||||||
val lesson = lessons[position]
|
lessons[position].let {
|
||||||
|
setTextViewText(R.id.timetableWidgetItemSubject, it.subject)
|
||||||
|
setTextViewText(R.id.timetableWidgetItemNumber, it.number.toString())
|
||||||
|
setTextViewText(R.id.timetableWidgetItemTime, it.start.toFormattedString("HH:mm") +
|
||||||
|
" - ${it.end.toFormattedString("HH:mm")}")
|
||||||
|
|
||||||
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
|
if (it.room.isNotBlank()) {
|
||||||
setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString())
|
setTextViewText(R.id.timetableWidgetItemRoom, "${context.getString(R.string.timetable_room)} ${it.room}")
|
||||||
setTextViewText(R.id.timetableWidgetItemTimeStart, lesson.start.toFormattedString("HH:mm"))
|
} else setTextViewText(R.id.timetableWidgetItemRoom, "")
|
||||||
setTextViewText(R.id.timetableWidgetItemTimeFinish, lesson.end.toFormattedString("HH:mm"))
|
|
||||||
|
|
||||||
updateDescription(this, lesson)
|
if (it.info.isNotBlank()) {
|
||||||
|
setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE)
|
||||||
|
setTextViewText(R.id.timetableWidgetItemDescription, it.run {
|
||||||
|
when (true) {
|
||||||
|
canceled && !changes -> "Lekcja odwołana: $info"
|
||||||
|
changes && teacher.isNotBlank() -> "Zastępstwo: $teacher"
|
||||||
|
changes && teacher.isBlank() -> "Zastępstwo, ${info.decapitalize()}"
|
||||||
|
else -> it.info.capitalize()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else setViewVisibility(R.id.timetableWidgetItemDescription, GONE)
|
||||||
|
|
||||||
if (lesson.canceled) {
|
if (it.canceled) {
|
||||||
updateStylesCanceled(this)
|
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags",
|
||||||
} else {
|
STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG)
|
||||||
updateStylesNotCanceled(this, lesson)
|
} else {
|
||||||
|
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
|
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDescription(remoteViews: RemoteViews, lesson: Timetable) {
|
|
||||||
with(remoteViews) {
|
|
||||||
if (lesson.info.isNotBlank() && !lesson.changes) {
|
|
||||||
setTextViewText(R.id.timetableWidgetItemDescription, lesson.info)
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE)
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemRoom, GONE)
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemTeacher, GONE)
|
|
||||||
} else {
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemDescription, GONE)
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemRoom, VISIBLE)
|
|
||||||
setViewVisibility(R.id.timetableWidgetItemTeacher, VISIBLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateStylesCanceled(remoteViews: RemoteViews) {
|
|
||||||
with(remoteViews) {
|
|
||||||
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags",
|
|
||||||
STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG)
|
|
||||||
setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(primaryColor!!))
|
|
||||||
setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(primaryColor!!))
|
|
||||||
setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(primaryColor!!))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateStylesNotCanceled(remoteViews: RemoteViews, lesson: Timetable) {
|
|
||||||
with(remoteViews) {
|
|
||||||
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG)
|
|
||||||
setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(textColor!!))
|
|
||||||
setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(timetableChangeColor!!))
|
|
||||||
|
|
||||||
updateNotCanceledLessonNumberColor(this, lesson)
|
|
||||||
updateNotCanceledSubjectColor(this, lesson)
|
|
||||||
|
|
||||||
val teacherChange = lesson.teacherOld.isNotBlank() && lesson.teacher != lesson.teacherOld
|
|
||||||
updateNotCanceledRoom(this, lesson, teacherChange)
|
|
||||||
updateNotCanceledTeacher(this, lesson, teacherChange)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNotCanceledLessonNumberColor(remoteViews: RemoteViews, lesson: Timetable) {
|
|
||||||
remoteViews.setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(
|
|
||||||
if (lesson.changes || (lesson.info.isNotBlank() && !lesson.canceled)) timetableChangeColor!!
|
|
||||||
else textColor!!
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNotCanceledSubjectColor(remoteViews: RemoteViews, lesson: Timetable) {
|
|
||||||
remoteViews.setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(
|
|
||||||
if (lesson.subjectOld.isNotBlank() && lesson.subject != lesson.subjectOld) timetableChangeColor!!
|
|
||||||
else textColor!!
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNotCanceledRoom(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) {
|
|
||||||
with(remoteViews) {
|
|
||||||
if (lesson.room.isNotBlank()) {
|
|
||||||
setTextViewText(R.id.timetableWidgetItemRoom,
|
|
||||||
if (teacherChange) lesson.room
|
|
||||||
else "${context.getString(R.string.timetable_room)} ${lesson.room}"
|
|
||||||
)
|
|
||||||
|
|
||||||
setTextColor(R.id.timetableWidgetItemRoom, context.getCompatColor(
|
|
||||||
if (lesson.roomOld.isNotBlank() && lesson.room != lesson.roomOld) timetableChangeColor!!
|
|
||||||
else textColor!!
|
|
||||||
))
|
|
||||||
} else setTextViewText(R.id.timetableWidgetItemRoom, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNotCanceledTeacher(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) {
|
|
||||||
remoteViews.setTextViewText(R.id.timetableWidgetItemTeacher,
|
|
||||||
if (teacherChange) lesson.teacher
|
|
||||||
else ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,24 +54,21 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||||
lateinit var analytics: FirebaseAnalyticsHelper
|
lateinit var analytics: FirebaseAnalyticsHelper
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget"
|
|
||||||
|
|
||||||
private const val EXTRA_BUTTON_TYPE = "extraButtonType"
|
|
||||||
|
|
||||||
private const val BUTTON_NEXT = "buttonNext"
|
|
||||||
|
|
||||||
private const val BUTTON_PREV = "buttonPrev"
|
|
||||||
|
|
||||||
private const val BUTTON_RESET = "buttonReset"
|
|
||||||
|
|
||||||
const val EXTRA_FROM_PROVIDER = "extraFromProvider"
|
const val EXTRA_FROM_PROVIDER = "extraFromProvider"
|
||||||
|
|
||||||
|
const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget"
|
||||||
|
|
||||||
|
const val EXTRA_BUTTON_TYPE = "extraButtonType"
|
||||||
|
|
||||||
|
const val BUTTON_NEXT = "buttonNext"
|
||||||
|
|
||||||
|
const val BUTTON_PREV = "buttonPrev"
|
||||||
|
|
||||||
|
const val BUTTON_RESET = "buttonReset"
|
||||||
|
|
||||||
fun getDateWidgetKey(appWidgetId: Int) = "timetable_widget_date_$appWidgetId"
|
fun getDateWidgetKey(appWidgetId: Int) = "timetable_widget_date_$appWidgetId"
|
||||||
|
|
||||||
fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId"
|
fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId"
|
||||||
|
|
||||||
fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
@ -105,56 +102,45 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDelete(intent: Intent) {
|
private fun onDelete(intent: Intent) {
|
||||||
val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0)
|
intent.getIntExtra(EXTRA_APPWIDGET_ID, 0).let {
|
||||||
|
if (it != 0) {
|
||||||
if (appWidgetId != 0) {
|
sharedPref.apply {
|
||||||
with(sharedPref) {
|
delete(getStudentWidgetKey(it))
|
||||||
delete(getStudentWidgetKey(appWidgetId))
|
delete(getDateWidgetKey(it))
|
||||||
delete(getDateWidgetKey(appWidgetId))
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) {
|
private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) {
|
||||||
val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
|
RemoteViews(context.packageName, R.layout.widget_timetable).apply {
|
||||||
val layoutId = if (savedTheme == 0L) R.layout.widget_timetable else R.layout.widget_timetable_dark
|
|
||||||
|
|
||||||
val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)
|
|
||||||
val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)
|
|
||||||
val resetNavIntent = createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET)
|
|
||||||
val adapterIntent = Intent(context, TimetableWidgetService::class.java)
|
|
||||||
.apply {
|
|
||||||
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
|
|
||||||
//make Intent unique
|
|
||||||
action = appWidgetId.toString()
|
|
||||||
}
|
|
||||||
val accountIntent = PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId,
|
|
||||||
Intent(context, TimetableWidgetConfigureActivity::class.java).apply {
|
|
||||||
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
|
|
||||||
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
|
|
||||||
putExtra(EXTRA_FROM_PROVIDER, true)
|
|
||||||
}, FLAG_UPDATE_CURRENT)
|
|
||||||
val appIntent = PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id,
|
|
||||||
MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT)
|
|
||||||
|
|
||||||
val remoteView = RemoteViews(context.packageName, layoutId).apply {
|
|
||||||
setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty)
|
setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty)
|
||||||
setTextViewText(R.id.timetableWidgetDate, date.toFormattedString("EEEE, dd.MM").capitalize())
|
setTextViewText(R.id.timetableWidgetDate, "${date.shortcutWeekDayName.capitalize()} ${date.toFormattedString()}")
|
||||||
setTextViewText(R.id.timetableWidgetName, student?.studentName ?: context.getString(R.string.all_no_data))
|
setTextViewText(R.id.timetableWidgetName, student?.studentName ?: context.getString(R.string.all_no_data))
|
||||||
setRemoteAdapter(R.id.timetableWidgetList, adapterIntent)
|
setRemoteAdapter(R.id.timetableWidgetList, Intent(context, TimetableWidgetService::class.java)
|
||||||
setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent)
|
.apply { putExtra(EXTRA_APPWIDGET_ID, appWidgetId) })
|
||||||
setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent)
|
setOnClickPendingIntent(R.id.timetableWidgetNext, createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT))
|
||||||
setOnClickPendingIntent(R.id.timetableWidgetDate, resetNavIntent)
|
setOnClickPendingIntent(R.id.timetableWidgetPrev, createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV))
|
||||||
setOnClickPendingIntent(R.id.timetableWidgetName, resetNavIntent)
|
createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET).let {
|
||||||
setOnClickPendingIntent(R.id.timetableWidgetAccount, accountIntent)
|
setOnClickPendingIntent(R.id.timetableWidgetDate, it)
|
||||||
setPendingIntentTemplate(R.id.timetableWidgetList, appIntent)
|
setOnClickPendingIntent(R.id.timetableWidgetName, it)
|
||||||
}
|
}
|
||||||
|
setOnClickPendingIntent(R.id.timetableWidgetAccount, PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId,
|
||||||
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
|
Intent(context, TimetableWidgetConfigureActivity::class.java).apply {
|
||||||
with(appWidgetManager) {
|
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList)
|
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
|
||||||
updateAppWidget(appWidgetId, remoteView)
|
putExtra(EXTRA_FROM_PROVIDER, true)
|
||||||
|
}, FLAG_UPDATE_CURRENT))
|
||||||
|
setPendingIntentTemplate(R.id.timetableWidgetList,
|
||||||
|
PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id,
|
||||||
|
MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT))
|
||||||
|
}.also {
|
||||||
|
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
|
||||||
|
appWidgetManager.apply {
|
||||||
|
notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList)
|
||||||
|
updateAppWidget(appWidgetId, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,17 +159,19 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||||
.filter { true }
|
.filter { true }
|
||||||
.flatMap { studentRepository.getSavedStudents(false).toMaybe() }
|
.flatMap { studentRepository.getSavedStudents(false).toMaybe() }
|
||||||
.flatMap { students ->
|
.flatMap { students ->
|
||||||
val student = students.singleOrNull { student -> student.id == studentId }
|
students.singleOrNull { student -> student.id == studentId }
|
||||||
when {
|
.let { student ->
|
||||||
student != null -> Maybe.just(student)
|
when {
|
||||||
studentId != 0L -> {
|
student != null -> Maybe.just(student)
|
||||||
studentRepository.isCurrentStudentSet()
|
studentId != 0L -> {
|
||||||
.filter { true }
|
studentRepository.isCurrentStudentSet()
|
||||||
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
|
.filter { true }
|
||||||
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
|
.flatMap { studentRepository.getCurrentStudent(false).toMaybe() }
|
||||||
|
.doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) }
|
||||||
|
}
|
||||||
|
else -> Maybe.empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> Maybe.empty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
.subscribeOn(schedulers.backgroundThread)
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue