Compare commits
122 Commits
Author | SHA1 | Date | |
---|---|---|---|
f893170dec | |||
cff08d6322 | |||
9dee7f01f6 | |||
8324a9cac3 | |||
5316e3e1bf | |||
81e80181f2 | |||
6ee38e9259 | |||
40df80371c | |||
a3596c35b8 | |||
66b7ea4cb4 | |||
770749e158 | |||
0aa83b020e | |||
4d1218d1d3 | |||
0ea6cbc8ed | |||
eb31f9578f | |||
f69d50d2c1 | |||
8a424ee6a4 | |||
7dfa48bbe3 | |||
d811cdb919 | |||
e2f2e21081 | |||
c812310497 | |||
7f6475cf35 | |||
a2a7d2ebb2 | |||
a5bc45c5da | |||
5646befbd7 | |||
75f496b5d2 | |||
23d989d22a | |||
9e013f7cd9 | |||
c63a7c03f1 | |||
5ceee84f0e | |||
7f4539fd27 | |||
71ebf1260b | |||
784ee58384 | |||
eceef3f582 | |||
0d950fbd86 | |||
003d63b516 | |||
b4c0440a8e | |||
137c305295 | |||
2c40c221c3 | |||
e82ac78d4a | |||
59d46ce956 | |||
17caa8ecbd | |||
e9540b4012 | |||
643ad60455 | |||
01f892ce5c | |||
f61b6a5e78 | |||
650cf7484e | |||
037cbb0b19 | |||
e49835e89e | |||
c64be2fab0 | |||
ce9cb35172 | |||
7fa9219c7b | |||
1fe1618220 | |||
d9bab2af78 | |||
06b6d88dd1 | |||
3bf27baed5 | |||
6802d74002 | |||
3fd2683df7 | |||
b708c70ea2 | |||
aba08e6aa9 | |||
124b6dfd79 | |||
1dbaa8bfdc | |||
25ac171298 | |||
387ff1cba7 | |||
eef3464d0b | |||
61297a01c7 | |||
762d4b1393 | |||
2e86b67eec | |||
6071b7571b | |||
fcea2218b5 | |||
a4a191700e | |||
3d76d41b55 | |||
0e1c20a952 | |||
5d14ee7f4e | |||
83527d91f3 | |||
9d62410530 | |||
5dffbdadfa | |||
516922d5aa | |||
9098e74065 | |||
2f5577cc54 | |||
3272c38356 | |||
bcd305bef3 | |||
fc5ad16cb7 | |||
c8332a0642 | |||
3212efe21e | |||
693ce8217d | |||
2cdd322ed4 | |||
c04b3e40d2 | |||
d1d665bbdf | |||
d70568c446 | |||
1d8378e136 | |||
4a2bf539f0 | |||
4d085f8266 | |||
fca69e7234 | |||
711de0f77f | |||
58d5196ac9 | |||
26a95ecb99 | |||
1835446468 | |||
4d3b16ec80 | |||
95b4d53fac | |||
0fa197d520 | |||
646b4a149d | |||
afd0c8513a | |||
c4a3da93ca | |||
ff2aa6f195 | |||
1d8d71709f | |||
aabd7345c1 | |||
09d16cf6d8 | |||
81d8f7ea48 | |||
05a804832b | |||
db02f0c1e1 | |||
0a40237809 | |||
017d46e5db | |||
8478b8b7ed | |||
8cc69728aa | |||
c82e6ae95b | |||
50a177d18c | |||
a77b3d4cd7 | |||
aff56a8311 | |||
5238e4d187 | |||
10f9812495 | |||
ab1de323d4 |
4
.github/workflows/deploy-store.yml
vendored
4
.github/workflows/deploy-store.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
environment: google-play
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
@ -49,7 +49,7 @@ jobs:
|
||||
environment: app-gallery
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
|
4
.github/workflows/deploy-test.yml
vendored
4
.github/workflows/deploy-test.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
environment: app-center
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
@ -89,7 +89,7 @@ jobs:
|
||||
if: github.event_name != 'pull_request_target'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
|
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
- uses: fkirc/skip-duplicate-actions@master
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
@ -45,7 +45,7 @@ jobs:
|
||||
- uses: fkirc/skip-duplicate-actions@master
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
@ -71,7 +71,7 @@ jobs:
|
||||
- uses: fkirc/skip-duplicate-actions@master
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
|
10
.idea/migrations.xml
generated
Normal file
10
.idea/migrations.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -20,19 +20,18 @@ apply from: 'hooks.gradle'
|
||||
|
||||
android {
|
||||
namespace 'io.github.wulkanowy'
|
||||
compileSdk 33
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 33
|
||||
versionCode 131
|
||||
versionName "2.1.0"
|
||||
targetSdkVersion 34
|
||||
versionCode 142
|
||||
versionName "2.3.2"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
|
||||
manifestPlaceholders = [
|
||||
firebase_enabled: project.hasProperty("enableFirebase"),
|
||||
admob_project_id: ""
|
||||
@ -69,6 +68,7 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
@ -78,6 +78,7 @@ android {
|
||||
versionNameSuffix "-dev"
|
||||
ext.enableCrashlytics = project.hasProperty("enableFirebase")
|
||||
buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\""
|
||||
buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"'
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +113,7 @@ android {
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
buildConfig true
|
||||
}
|
||||
|
||||
bundle {
|
||||
@ -160,7 +162,7 @@ play {
|
||||
defaultToAppBundles = false
|
||||
track = 'production'
|
||||
releaseStatus = ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.25d
|
||||
userFraction = 0.99d
|
||||
updatePriority = 3
|
||||
enabled.set(false)
|
||||
}
|
||||
@ -182,44 +184,44 @@ huaweiPublish {
|
||||
}
|
||||
|
||||
ext {
|
||||
work_manager = "2.8.1"
|
||||
android_hilt = "1.0.0"
|
||||
room = "2.5.2"
|
||||
chucker = "3.5.2"
|
||||
mockk = "1.13.7"
|
||||
work_manager = "2.9.0"
|
||||
android_hilt = "1.1.0"
|
||||
room = "2.6.1"
|
||||
chucker = "4.0.0"
|
||||
mockk = "1.13.9"
|
||||
coroutines = "1.7.3"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'io.github.wulkanowy:sdk:2.1.0'
|
||||
implementation 'io.github.wulkanowy:sdk:2.3.4'
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||
|
||||
implementation "androidx.core:core-ktx:1.10.1"
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
implementation "androidx.activity:activity-ktx:1.7.2"
|
||||
implementation "androidx.activity:activity-ktx:1.8.2"
|
||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||
implementation "androidx.fragment:fragment-ktx:1.6.1"
|
||||
implementation "androidx.annotation:annotation:1.6.0"
|
||||
implementation "androidx.fragment:fragment-ktx:1.6.2"
|
||||
implementation "androidx.annotation:annotation:1.7.1"
|
||||
|
||||
implementation "androidx.preference:preference-ktx:1.2.1"
|
||||
implementation "androidx.recyclerview:recyclerview:1.3.1"
|
||||
implementation "androidx.recyclerview:recyclerview:1.3.2"
|
||||
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||
implementation "com.google.android.material:material:1.9.0"
|
||||
implementation "com.google.android.material:material:1.10.0"
|
||||
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||
implementation 'com.github.lopspower:CircularImageView:4.3.0'
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:$work_manager"
|
||||
implementation "androidx.work:work-runtime:$work_manager"
|
||||
playImplementation "androidx.work:work-gcm:$work_manager"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
|
||||
|
||||
implementation "androidx.room:room-runtime:$room"
|
||||
implementation "androidx.room:room-ktx:$room"
|
||||
@ -235,33 +237,36 @@ dependencies {
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
|
||||
|
||||
implementation "com.jakewharton.timber:timber:5.0.1"
|
||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||
implementation 'com.github.bastienpaulfr:Treessence:1.0.5'
|
||||
implementation 'com.github.Faierbel:slf4j-timber:2.0'
|
||||
implementation 'com.github.bastienpaulfr:Treessence:1.1.2'
|
||||
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
|
||||
implementation "io.coil-kt:coil:2.4.0"
|
||||
implementation 'io.coil-kt:coil:2.5.0'
|
||||
implementation "io.github.wulkanowy:AppKillerManager:3.0.1"
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
|
||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||
implementation 'org.apache.commons:commons-text:1.11.0'
|
||||
|
||||
playImplementation platform('com.google.firebase:firebase-bom:32.2.2')
|
||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||
playImplementation platform('com.google.firebase:firebase-bom:32.7.0')
|
||||
playImplementation 'com.google.firebase:firebase-analytics'
|
||||
playImplementation 'com.google.firebase:firebase-messaging'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||
playImplementation 'com.google.firebase:firebase-config-ktx'
|
||||
playImplementation 'com.google.android.play:core:1.10.3'
|
||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:22.2.0'
|
||||
playImplementation 'com.google.firebase:firebase-config'
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.10.0.303'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.300'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:22.6.0'
|
||||
playImplementation "com.google.android.play:integrity:1.3.0"
|
||||
playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
|
||||
playImplementation 'com.google.android.play:review-ktx:2.0.1'
|
||||
playImplementation "com.google.android.ump:user-messaging-platform:2.1.0"
|
||||
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.303'
|
||||
|
||||
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
|
||||
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:$chucker"
|
||||
|
||||
debugImplementation "com.github.chuckerteam.chucker:library:$chucker"
|
||||
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6'
|
||||
debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04'
|
||||
|
||||
@ -270,7 +275,7 @@ dependencies {
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
testImplementation 'org.robolectric:robolectric:4.10.3'
|
||||
testImplementation 'org.robolectric:robolectric:4.11.1'
|
||||
testImplementation "androidx.test:runner:1.5.2"
|
||||
testImplementation "androidx.test.ext:junit:1.1.5"
|
||||
testImplementation "androidx.test:core:1.5.0"
|
||||
|
@ -1,16 +1,16 @@
|
||||
apply plugin: "jacoco"
|
||||
|
||||
jacoco {
|
||||
toolVersion "0.8.7"
|
||||
toolVersion "0.8.11"
|
||||
reportsDirectory.set(file("$buildDir/reports"))
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
tasks.withType(Test).configureEach {
|
||||
jacoco.includeNoLocationClasses = true
|
||||
jacoco.excludes = ['jdk.internal.*']
|
||||
}
|
||||
|
||||
task jacocoTestReport(type: JacocoReport) {
|
||||
tasks.register('jacocoTestReport', JacocoReport) {
|
||||
|
||||
group = "Reporting"
|
||||
description = "Generate Jacoco coverage reports"
|
||||
@ -33,19 +33,19 @@ task jacocoTestReport(type: JacocoReport) {
|
||||
'**/*_Factory.*']
|
||||
|
||||
classDirectories.setFrom(fileTree(
|
||||
dir: "$buildDir/intermediates/classes/debug",
|
||||
excludes: excludes
|
||||
dir: "$buildDir/intermediates/classes/debug",
|
||||
excludes: excludes
|
||||
) + fileTree(
|
||||
dir: "$buildDir/tmp/kotlin-classes/fdroidDebug",
|
||||
excludes: excludes
|
||||
dir: "$buildDir/tmp/kotlin-classes/fdroidDebug",
|
||||
excludes: excludes
|
||||
))
|
||||
|
||||
sourceDirectories.setFrom(files([
|
||||
"src/main/java",
|
||||
"src/fdroid/java"
|
||||
"src/main/java",
|
||||
"src/fdroid/java"
|
||||
]))
|
||||
executionData.setFrom(fileTree(
|
||||
dir: project.projectDir,
|
||||
includes: ["**/*.exec", "**/*.ec"]
|
||||
dir: project.projectDir,
|
||||
includes: ["**/*.exec", "**/*.ec"]
|
||||
))
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.view.View
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("unused")
|
||||
@ -13,9 +14,11 @@ class AdsHelper @Inject constructor(
|
||||
private val preferencesRepository: PreferencesRepository
|
||||
) {
|
||||
|
||||
val isMobileAdsSdkInitialized = MutableStateFlow(false)
|
||||
val canShowAd = false
|
||||
|
||||
fun initialize() {
|
||||
preferencesRepository.isAdsEnabled = false
|
||||
preferencesRepository.isAgreeToProcessData = false
|
||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
class InAppUpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates() {}
|
||||
|
||||
fun onResume() {}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class IntegrityHelper @Inject constructor() {
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun getIntegrityToken(requestId: String): String? = null
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class UpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates(activity: Activity) {}
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||
|
||||
fun onResume(activity: Activity) {}
|
||||
}
|
@ -5,6 +5,7 @@ import android.view.View
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("unused")
|
||||
@ -12,10 +13,11 @@ class AdsHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val preferencesRepository: PreferencesRepository
|
||||
) {
|
||||
val isMobileAdsSdkInitialized = MutableStateFlow(false)
|
||||
val canShowAd = false
|
||||
|
||||
fun initialize() {
|
||||
preferencesRepository.isAdsEnabled = false
|
||||
preferencesRepository.isAgreeToProcessData = false
|
||||
preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ package io.github.wulkanowy.utils
|
||||
|
||||
import android.util.Log
|
||||
import com.huawei.agconnect.crash.AGConnectCrash
|
||||
import fr.bipi.tressence.base.FormatterPriorityTree
|
||||
import fr.bipi.tressence.common.StackTraceRecorder
|
||||
import fr.bipi.treessence.base.FormatterPriorityTree
|
||||
import fr.bipi.treessence.common.StackTraceRecorder
|
||||
|
||||
class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
class InAppUpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates() {}
|
||||
|
||||
fun onResume() {}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class IntegrityHelper @Inject constructor() {
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun getIntegrityToken(requestId: String): String? = null
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class UpdateHelper @Inject constructor() {
|
||||
|
||||
lateinit var messageContainer: View
|
||||
|
||||
fun checkAndInstallUpdates(activity: Activity) {}
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int) {}
|
||||
|
||||
fun onResume(activity: Activity) {}
|
||||
}
|
@ -1,24 +1,29 @@
|
||||
package io.github.wulkanowy
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log.*
|
||||
import android.util.Log.DEBUG
|
||||
import android.util.Log.INFO
|
||||
import android.util.Log.VERBOSE
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.work.Configuration
|
||||
import com.yariksoffice.lingver.Lingver
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import fr.bipi.tressence.file.FileLoggerTree
|
||||
import fr.bipi.treessence.file.FileLoggerTree
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.ui.base.ThemeManager
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.CrashLogExceptionTree
|
||||
import io.github.wulkanowy.utils.CrashLogTree
|
||||
import io.github.wulkanowy.utils.DebugLogTree
|
||||
import io.github.wulkanowy.utils.RemoteConfigHelper
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidApp
|
||||
class WulkanowyApp : Application(), Configuration.Provider {
|
||||
|
||||
@Inject
|
||||
lateinit var workerFactory: HiltWorkerFactory
|
||||
|
||||
@Inject
|
||||
lateinit var themeManager: ThemeManager
|
||||
|
||||
@ -32,16 +37,21 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||
lateinit var analyticsHelper: AnalyticsHelper
|
||||
|
||||
@Inject
|
||||
lateinit var adsHelper: AdsHelper
|
||||
lateinit var remoteConfigHelper: RemoteConfigHelper
|
||||
|
||||
@Inject
|
||||
lateinit var remoteConfigHelper: RemoteConfigHelper
|
||||
lateinit var workerFactory: HiltWorkerFactory
|
||||
|
||||
override val workManagerConfiguration: Configuration
|
||||
get() = Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
.build()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
initializeAppLanguage()
|
||||
themeManager.applyDefaultTheme()
|
||||
adsHelper.initialize()
|
||||
remoteConfigHelper.initialize()
|
||||
initLogging()
|
||||
}
|
||||
@ -74,9 +84,4 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
||||
analyticsHelper.logEvent("language", "startup" to preferencesRepository.appLanguage)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||
.setWorkerFactory(workerFactory)
|
||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||
.build()
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import io.github.wulkanowy.data.api.AdminMessageService
|
||||
import io.github.wulkanowy.data.api.SchoolsService
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
@ -82,19 +83,29 @@ internal class DataModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideRetrofit(
|
||||
fun provideAdminMessageService(
|
||||
okHttpClient: OkHttpClient,
|
||||
json: Json,
|
||||
appInfo: AppInfo
|
||||
): Retrofit = Retrofit.Builder()
|
||||
): AdminMessageService = Retrofit.Builder()
|
||||
.baseUrl(appInfo.messagesBaseUrl)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideAdminMessageService(retrofit: Retrofit): AdminMessageService = retrofit.create()
|
||||
fun provideSchoolsService(
|
||||
okHttpClient: OkHttpClient,
|
||||
json: Json,
|
||||
appInfo: AppInfo,
|
||||
): SchoolsService = Retrofit.Builder()
|
||||
.baseUrl(appInfo.schoolsBaseUrl)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
|
@ -0,0 +1,14 @@
|
||||
package io.github.wulkanowy.data.api
|
||||
|
||||
import io.github.wulkanowy.data.pojos.IntegrityRequest
|
||||
import io.github.wulkanowy.data.pojos.LoginEvent
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.POST
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
interface SchoolsService {
|
||||
|
||||
@POST("/log/loginEvent")
|
||||
suspend fun logLoginEvent(@Body request: IntegrityRequest<LoginEvent>)
|
||||
}
|
@ -1,10 +1,16 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.StudentName
|
||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -33,12 +39,12 @@ abstract class StudentDao {
|
||||
abstract suspend fun loadAll(): List<Student>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Students")
|
||||
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
|
||||
@Query("SELECT * FROM Students JOIN Semesters ON Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id")
|
||||
abstract suspend fun loadStudentsWithSemesters(): Map<Student, List<Semester>>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM Students WHERE id = :id")
|
||||
abstract suspend fun loadStudentWithSemestersById(id: Long): StudentWithSemesters?
|
||||
@Query("SELECT * FROM Students JOIN Semesters ON Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id WHERE Students.id = :id")
|
||||
abstract suspend fun loadStudentWithSemestersById(id: Long): Map<Student, List<Semester>>
|
||||
|
||||
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
|
||||
abstract suspend fun updateCurrent(id: Long)
|
||||
@ -46,6 +52,9 @@ abstract class StudentDao {
|
||||
@Query("UPDATE Students SET is_current = 0")
|
||||
abstract suspend fun resetCurrent()
|
||||
|
||||
@Query("DELETE FROM Students WHERE email = :email AND user_name = :userName")
|
||||
abstract suspend fun deleteByEmailAndUserName(email: String, userName: String)
|
||||
|
||||
@Transaction
|
||||
open suspend fun switchCurrent(id: Long) {
|
||||
resetCurrent()
|
||||
|
@ -1,13 +1,8 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Relation
|
||||
import java.io.Serializable
|
||||
|
||||
data class StudentWithSemesters(
|
||||
@Embedded
|
||||
val student: Student,
|
||||
|
||||
@Relation(parentColumn = "student_id", entityColumn = "student_id")
|
||||
val semesters: List<Semester>
|
||||
) : Serializable
|
||||
|
@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration10 : Migration(9, 10) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration11 : Migration(10, 11) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Grades_temp (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_read INTEGER NOT NULL,
|
||||
@ -26,9 +27,10 @@ class Migration11 : Migration(10, 11) {
|
||||
date INTEGER NOT NULL,
|
||||
teacher TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades")
|
||||
database.execSQL("DROP TABLE Grades")
|
||||
database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades")
|
||||
"""
|
||||
)
|
||||
db.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades")
|
||||
db.execSQL("DROP TABLE Grades")
|
||||
db.execSQL("ALTER TABLE Grades_temp RENAME TO Grades")
|
||||
}
|
||||
}
|
||||
|
@ -5,16 +5,17 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration12 : Migration(11, 12) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
createTempStudentsTable(database)
|
||||
replaceStudentTable(database)
|
||||
updateStudentsWithClassId(database, getStudentsIds(database))
|
||||
removeStudentsWithNoClassId(database)
|
||||
ensureThereIsOnlyOneCurrentStudent(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
createTempStudentsTable(db)
|
||||
replaceStudentTable(db)
|
||||
updateStudentsWithClassId(db, getStudentsIds(db))
|
||||
removeStudentsWithNoClassId(db)
|
||||
ensureThereIsOnlyOneCurrentStudent(db)
|
||||
}
|
||||
|
||||
private fun createTempStudentsTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
private fun createTempStudentsTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Students_tmp (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
endpoint TEXT NOT NULL,
|
||||
@ -30,15 +31,16 @@ class Migration12 : Migration(11, 12) {
|
||||
registration_date INTEGER NOT NULL,
|
||||
class_id INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)")
|
||||
"""
|
||||
)
|
||||
db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)")
|
||||
}
|
||||
|
||||
private fun replaceStudentTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||
database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students")
|
||||
database.execSQL("DROP TABLE Students")
|
||||
database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
|
||||
private fun replaceStudentTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||
db.execSQL("INSERT INTO Students_tmp SELECT * FROM Students")
|
||||
db.execSQL("DROP TABLE Students")
|
||||
db.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
|
||||
}
|
||||
|
||||
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
||||
@ -54,18 +56,18 @@ class Migration12 : Migration(11, 12) {
|
||||
return students
|
||||
}
|
||||
|
||||
private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List<Int>) {
|
||||
private fun updateStudentsWithClassId(db: SupportSQLiteDatabase, students: List<Int>) {
|
||||
students.forEach {
|
||||
database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it")
|
||||
db.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it")
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Students WHERE class_id = 0")
|
||||
private fun removeStudentsWithNoClassId(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM Students WHERE class_id = 0")
|
||||
}
|
||||
|
||||
private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("UPDATE Students SET is_current = 0")
|
||||
database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)")
|
||||
private fun ensureThereIsOnlyOneCurrentStudent(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("UPDATE Students SET is_current = 0")
|
||||
db.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)")
|
||||
}
|
||||
}
|
||||
|
@ -5,27 +5,30 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration13 : Migration(12, 13) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
addClassNameToStudents(database, getStudentsIds(database))
|
||||
updateSemestersTable(database)
|
||||
markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database))
|
||||
clearMessagesTable(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
addClassNameToStudents(db, getStudentsIds(db))
|
||||
updateSemestersTable(db)
|
||||
markAtLeastAndOnlyOneSemesterAtCurrent(db, getStudentsAndClassIds(db))
|
||||
clearMessagesTable(db)
|
||||
}
|
||||
|
||||
private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List<Pair<Int, String>>) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL")
|
||||
private fun addClassNameToStudents(
|
||||
db: SupportSQLiteDatabase,
|
||||
students: List<Pair<Int, String>>
|
||||
) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL")
|
||||
|
||||
students.forEach { (id, name) ->
|
||||
val schoolName = name.substringAfter(" - ")
|
||||
val className = name.substringBefore(" - ", "").replace("Klasa ", "")
|
||||
database.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'")
|
||||
database.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'")
|
||||
db.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'")
|
||||
db.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
private fun getStudentsIds(db: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val students = mutableListOf<Pair<Int, String>>()
|
||||
database.query("SELECT id, school_name FROM Students").use {
|
||||
db.query("SELECT id, school_name FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(it.getInt(0) to it.getString(1))
|
||||
@ -36,15 +39,15 @@ class Migration13 : Migration(12, 13) {
|
||||
return students
|
||||
}
|
||||
|
||||
private fun updateSemestersTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL")
|
||||
database.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL")
|
||||
database.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL")
|
||||
private fun updateSemestersTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL")
|
||||
db.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL")
|
||||
db.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL")
|
||||
}
|
||||
|
||||
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
||||
private fun getStudentsAndClassIds(db: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
||||
val students = mutableListOf<Pair<Int, Int>>()
|
||||
database.query("SELECT student_id, class_id FROM Students").use {
|
||||
db.query("SELECT student_id, class_id FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(it.getInt(0) to it.getInt(1))
|
||||
@ -55,14 +58,17 @@ class Migration13 : Migration(12, 13) {
|
||||
return students
|
||||
}
|
||||
|
||||
private fun markAtLeastAndOnlyOneSemesterAtCurrent(database: SupportSQLiteDatabase, students: List<Pair<Int, Int>>) {
|
||||
private fun markAtLeastAndOnlyOneSemesterAtCurrent(
|
||||
db: SupportSQLiteDatabase,
|
||||
students: List<Pair<Int, Int>>
|
||||
) {
|
||||
students.forEach { (studentId, classId) ->
|
||||
database.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'")
|
||||
database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)")
|
||||
db.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'")
|
||||
db.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)")
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearMessagesTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Messages")
|
||||
private fun clearMessagesTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM Messages")
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration14 : Migration(13, 14) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS GradesSummary")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS GradesSummary")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS GradesSummary (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
semester_id INTEGER NOT NULL,
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration15 : Migration(14, 15) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS MobileDevices (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -14,6 +15,7 @@ class Migration15 : Migration(14, 15) {
|
||||
name TEXT NOT NULL,
|
||||
date INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration16 : Migration(15, 16) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Teachers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -15,6 +16,7 @@ class Migration16 : Migration(15, 16) {
|
||||
name TEXT NOT NULL,
|
||||
short_name TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration17 : Migration(16, 17) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
createGradesPointsStatisticsTable(database)
|
||||
truncateSemestersTable(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
createGradesPointsStatisticsTable(db)
|
||||
truncateSemestersTable(db)
|
||||
}
|
||||
|
||||
private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
private fun createGradesPointsStatisticsTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS GradesPointsStatistics(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -20,10 +21,11 @@ class Migration17 : Migration(16, 17) {
|
||||
others REAL NOT NULL,
|
||||
student REAL NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun truncateSemestersTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Semesters")
|
||||
private fun truncateSemestersTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM Semesters")
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration18 : Migration(17, 18) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS School (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -6,16 +6,17 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
|
||||
class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migration(18, 19) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
migrateMessages(database)
|
||||
migrateGrades(database)
|
||||
migrateStudents(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
migrateMessages(db)
|
||||
migrateGrades(db)
|
||||
migrateStudents(db)
|
||||
migrateSharedPreferences()
|
||||
}
|
||||
|
||||
private fun migrateMessages(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE Messages")
|
||||
database.execSQL("""
|
||||
private fun migrateMessages(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE Messages")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
@ -34,12 +35,14 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
|
||||
read_by INTEGER NOT NULL,
|
||||
removed INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun migrateGrades(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE Grades")
|
||||
database.execSQL("""
|
||||
private fun migrateGrades(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE Grades")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Grades (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
is_read INTEGER NOT NULL,
|
||||
@ -59,11 +62,13 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
|
||||
date INTEGER NOT NULL,
|
||||
teacher TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun migrateStudents(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
private fun migrateStudents(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Students_tmp (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
scrapper_base_url TEXT NOT NULL,
|
||||
@ -86,26 +91,29 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
|
||||
is_current INTEGER NOT NULL,
|
||||
registration_date INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";")
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";")
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;")
|
||||
|
||||
database.execSQL("""
|
||||
db.execSQL(
|
||||
"""
|
||||
INSERT INTO Students_tmp(
|
||||
id, scrapper_base_url, mobile_base_url, is_parent, login_type, login_mode, certificate_key, private_key, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date)
|
||||
SELECT
|
||||
id, endpoint, apiBaseUrl, is_parent, loginType, "SCRAPPER", certificateKey, privateKey, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date
|
||||
FROM Students
|
||||
""")
|
||||
database.execSQL("DROP TABLE Students")
|
||||
database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
|
||||
database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)")
|
||||
"""
|
||||
)
|
||||
db.execSQL("DROP TABLE Students")
|
||||
db.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
|
||||
db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)")
|
||||
}
|
||||
|
||||
private fun migrateSharedPreferences() {
|
||||
|
@ -5,14 +5,16 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration2 : Migration(1, 2) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS LuckyNumbers (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
date INTEGER NOT NULL,
|
||||
lucky_number INTEGER NOT NULL)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,15 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration20 : Migration(19, 20) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
migrateTimetable(database)
|
||||
truncateSubjects(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
migrateTimetable(db)
|
||||
truncateSubjects(db)
|
||||
}
|
||||
|
||||
private fun migrateTimetable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE Timetable")
|
||||
database.execSQL("""
|
||||
private fun migrateTimetable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE Timetable")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Timetable` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`student_id` INTEGER NOT NULL,
|
||||
@ -33,10 +34,11 @@ class Migration20 : Migration(19, 20) {
|
||||
`changes` INTEGER NOT NULL,
|
||||
`canceled` INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
private fun truncateSubjects(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Subjects")
|
||||
private fun truncateSubjects(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM Subjects")
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration21 : Migration(20, 21) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL")
|
||||
|
||||
database.execSQL("DELETE FROM Semesters")
|
||||
db.execSQL("DELETE FROM Semesters")
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration22 : Migration(21, 22) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration23 : Migration(22, 23) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''")
|
||||
database.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''")
|
||||
db.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration24 : Migration(23, 24) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS MessageAttachments (
|
||||
real_id INTEGER NOT NULL,
|
||||
message_id INTEGER NOT NULL,
|
||||
@ -16,6 +17,7 @@ class Migration24 : Migration(23, 24) {
|
||||
filename TEXT NOT NULL,
|
||||
PRIMARY KEY(real_id)
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration25 : Migration(24, 25) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"")
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration26 : Migration(25, 26) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
db.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
@ -5,24 +5,25 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration27 : Migration(26, 27) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"")
|
||||
|
||||
val students = getStudentsIdsAndNames(database)
|
||||
val units = getReportingUnits(database)
|
||||
val students = getStudentsIdsAndNames(db)
|
||||
val units = getReportingUnits(db)
|
||||
|
||||
students.forEach { (id, userLoginId, studentName) ->
|
||||
val userNameFromUnits = units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second
|
||||
val userNameFromUnits =
|
||||
units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second
|
||||
val normalizedStudentName = studentName.split(" ").asReversed().joinToString(" ")
|
||||
|
||||
val userName = userNameFromUnits ?: normalizedStudentName
|
||||
database.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'")
|
||||
db.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||
private fun getStudentsIdsAndNames(db: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||
database.query("SELECT id, user_login_id, student_name FROM Students").use {
|
||||
db.query("SELECT id, user_login_id, student_name FROM Students").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2)))
|
||||
@ -33,9 +34,9 @@ class Migration27 : Migration(26, 27) {
|
||||
return students
|
||||
}
|
||||
|
||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
private fun getReportingUnits(db: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||
val units = mutableListOf<Pair<Int, String>>()
|
||||
database.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
|
||||
db.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
|
||||
if (it.moveToFirst()) {
|
||||
do {
|
||||
units.add(it.getInt(0) to it.getString(1))
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration28 : Migration(27, 28) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Conferences (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration29 : Migration(28, 29) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS GradesStatistics")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS GradesStatistics")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS GradeSemesterStatistics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -16,8 +17,10 @@ class Migration29 : Migration(28, 29) {
|
||||
amounts TEXT NOT NULL,
|
||||
student_grade INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
database.execSQL("""
|
||||
"""
|
||||
)
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS GradePartialStatistics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration3 : Migration(2, 3) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS CompletedLesson (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration30 : Migration(29, 30) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE TimetableAdditional (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -16,6 +17,7 @@ class Migration30 : Migration(29, 30) {
|
||||
date INTEGER NOT NULL,
|
||||
subject TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration31 : Migration(30, 31) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""CREATE TABLE IF NOT EXISTS StudentInfo (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration32 : Migration(31, 32) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN nick TEXT NOT NULL DEFAULT \"\"")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN nick TEXT NOT NULL DEFAULT \"\"")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration33 : Migration(32, 33) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS StudentInfo")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS StudentInfo")
|
||||
|
||||
database.execSQL(
|
||||
db.execSQL(
|
||||
"""CREATE TABLE IF NOT EXISTS StudentInfo (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration34 : Migration(33, 34) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM ReportingUnits")
|
||||
database.execSQL("DELETE FROM Recipients")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM ReportingUnits")
|
||||
db.execSQL("DELETE FROM Recipients")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,13 @@ import io.github.wulkanowy.utils.AppInfo
|
||||
|
||||
class Migration35(private val appInfo: AppInfo) : Migration(34, 35) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
||||
|
||||
database.query("SELECT * FROM Students").use {
|
||||
db.query("SELECT * FROM Students").use {
|
||||
while (it.moveToNext()) {
|
||||
val studentId = it.getLongOrNull(0)
|
||||
database.execSQL(
|
||||
db.execSQL(
|
||||
"""
|
||||
UPDATE Students
|
||||
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration36 : Migration(35, 36) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Exams ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE Homework ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Exams ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
db.execSQL("ALTER TABLE Homework ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration37 : Migration(36, 37) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS TimetableHeaders (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration38 : Migration(37, 38) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`student_id` INTEGER NOT NULL,
|
||||
@ -14,6 +15,7 @@ class Migration38 : Migration(37, 38) {
|
||||
`subject` TEXT NOT NULL,
|
||||
`content` TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration39 : Migration(38, 39) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Conferences ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE SchoolAnnouncements ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Conferences ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
db.execSQL("ALTER TABLE SchoolAnnouncements ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration4 : Migration(3, 4) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_notified INTEGER NOT NULL,
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration40 : Migration(39, 40) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Notifications` (
|
||||
`student_id` INTEGER NOT NULL,
|
||||
@ -20,4 +20,4 @@ class Migration40 : Migration(39, 40) {
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ import io.github.wulkanowy.data.enums.GradeExpandMode
|
||||
|
||||
class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migration(40, 41) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
migrateSharedPreferences()
|
||||
database.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0")
|
||||
db.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
|
||||
private fun migrateSharedPreferences() {
|
||||
@ -18,4 +18,4 @@ class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migratio
|
||||
}
|
||||
sharedPrefProvider.delete("pref_key_expand_grade")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration42 : Migration(41, 42) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""CREATE TABLE IF NOT EXISTS `AdminMessages` (
|
||||
`id` INTEGER NOT NULL,
|
||||
`title` TEXT NOT NULL,
|
||||
@ -21,4 +21,4 @@ class Migration42 : Migration(41, 42) {
|
||||
PRIMARY KEY(`id`))"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration43 : Migration(42, 43) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
db.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration44 : Migration(43, 44) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
@ -8,65 +8,65 @@ import java.time.ZoneOffset
|
||||
|
||||
class Migration46 : Migration(45, 46) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
migrateConferences(database)
|
||||
migrateMessages(database)
|
||||
migrateMobileDevices(database)
|
||||
migrateNotifications(database)
|
||||
migrateTimetable(database)
|
||||
migrateTimetableAdditional(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
migrateConferences(db)
|
||||
migrateMessages(db)
|
||||
migrateMobileDevices(db)
|
||||
migrateNotifications(db)
|
||||
migrateTimetable(db)
|
||||
migrateTimetableAdditional(db)
|
||||
}
|
||||
|
||||
private fun migrateConferences(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM Conferences").use {
|
||||
private fun migrateConferences(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM Conferences").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id")
|
||||
db.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateMessages(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM Messages").use {
|
||||
private fun migrateMessages(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM Messages").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id")
|
||||
db.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateMobileDevices(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM MobileDevices").use {
|
||||
private fun migrateMobileDevices(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM MobileDevices").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id")
|
||||
db.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateNotifications(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM Notifications").use {
|
||||
private fun migrateNotifications(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM Notifications").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
|
||||
val timestampUtc = timestampLocal.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id")
|
||||
db.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTimetable(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM Timetable").use {
|
||||
private fun migrateTimetable(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM Timetable").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
|
||||
@ -74,13 +74,13 @@ class Migration46 : Migration(45, 46) {
|
||||
val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
|
||||
val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
||||
db.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTimetableAdditional(database: SupportSQLiteDatabase) {
|
||||
database.query("SELECT * FROM TimetableAdditional").use {
|
||||
private fun migrateTimetableAdditional(db: SupportSQLiteDatabase) {
|
||||
db.query("SELECT * FROM TimetableAdditional").use {
|
||||
while (it.moveToNext()) {
|
||||
val id = it.getLong(it.getColumnIndexOrThrow("id"))
|
||||
val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
|
||||
@ -88,7 +88,7 @@ class Migration46 : Migration(45, 46) {
|
||||
val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
|
||||
val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
|
||||
|
||||
database.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
||||
db.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration49 : Migration(48, 49) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements")
|
||||
|
||||
database.execSQL(
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` (
|
||||
`user_login_id` INTEGER NOT NULL,
|
||||
|
@ -7,11 +7,16 @@ import java.time.ZoneOffset
|
||||
|
||||
class Migration5 : Migration(4, 5) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
|
||||
database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'")
|
||||
database.execSQL("DROP TABLE IF EXISTS Notes")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
|
||||
db.execSQL(
|
||||
"UPDATE Students SET registration_date = '${
|
||||
now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()
|
||||
}'"
|
||||
)
|
||||
db.execSQL("DROP TABLE IF EXISTS Notes")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Notes (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
is_read INTEGER NOT NULL,
|
||||
@ -21,6 +26,7 @@ class Migration5 : Migration(4, 5) {
|
||||
teacher TEXT NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
content TEXT NOT NULL)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration50 : Migration(49, 50) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS MobileDevices")
|
||||
database.execSQL(
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS MobileDevices")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `MobileDevices` (
|
||||
`user_login_id` INTEGER NOT NULL,
|
||||
|
@ -5,17 +5,17 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration51 : Migration(50, 51) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
createMailboxTable(database)
|
||||
recreateMessagesTable(database)
|
||||
recreateMessageAttachmentsTable(database)
|
||||
recreateRecipientsTable(database)
|
||||
deleteReportingUnitTable(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
createMailboxTable(db)
|
||||
recreateMessagesTable(db)
|
||||
recreateMessageAttachmentsTable(db)
|
||||
recreateRecipientsTable(db)
|
||||
deleteReportingUnitTable(db)
|
||||
}
|
||||
|
||||
private fun createMailboxTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
||||
database.execSQL(
|
||||
private fun createMailboxTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Mailboxes` (
|
||||
`globalKey` TEXT NOT NULL,
|
||||
@ -30,9 +30,9 @@ class Migration51 : Migration(50, 51) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun recreateMessagesTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL(
|
||||
private fun recreateMessagesTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Messages` (
|
||||
`message_global_key` TEXT NOT NULL,
|
||||
@ -52,9 +52,9 @@ class Migration51 : Migration(50, 51) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun recreateMessageAttachmentsTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS MessageAttachments")
|
||||
database.execSQL(
|
||||
private fun recreateMessageAttachmentsTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS MessageAttachments")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `MessageAttachments` (
|
||||
`real_id` INTEGER NOT NULL,
|
||||
@ -66,9 +66,9 @@ class Migration51 : Migration(50, 51) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun recreateRecipientsTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Recipients")
|
||||
database.execSQL(
|
||||
private fun recreateRecipientsTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Recipients")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Recipients` (
|
||||
`mailboxGlobalKey` TEXT NOT NULL,
|
||||
@ -82,7 +82,7 @@ class Migration51 : Migration(50, 51) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun deleteReportingUnitTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS ReportingUnits")
|
||||
private fun deleteReportingUnitTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS ReportingUnits")
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration53 : Migration(52, 53) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
createMailboxTable(database)
|
||||
recreateMessagesTable(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
createMailboxTable(db)
|
||||
recreateMessagesTable(db)
|
||||
}
|
||||
|
||||
private fun createMailboxTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
||||
database.execSQL(
|
||||
private fun createMailboxTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Mailboxes")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Mailboxes` (
|
||||
`globalKey` TEXT NOT NULL,
|
||||
@ -29,9 +29,9 @@ class Migration53 : Migration(52, 53) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun recreateMessagesTable(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL(
|
||||
private fun recreateMessagesTable(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `Messages` (
|
||||
`email` TEXT NOT NULL,
|
||||
|
@ -5,22 +5,24 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration54 : Migration(53, 54) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
migrateResman(database)
|
||||
removeTomaszowMazowieckiStudents(database)
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
migrateResman(db)
|
||||
removeTomaszowMazowieckiStudents(db)
|
||||
}
|
||||
|
||||
private fun migrateResman(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
private fun migrateResman(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
UPDATE Students SET
|
||||
scrapper_base_url = 'https://vulcan.net.pl',
|
||||
login_type = 'ADFSLightScoped',
|
||||
symbol = 'rzeszowprojekt'
|
||||
WHERE scrapper_base_url = 'https://resman.pl'
|
||||
""".trimIndent())
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private fun removeTomaszowMazowieckiStudents(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'")
|
||||
private fun removeTomaszowMazowieckiStudents(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'")
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration6 : Migration(5, 6) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS ReportingUnits (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -15,9 +16,11 @@ class Migration6 : Migration(5, 6) {
|
||||
sender_id INTEGER NOT NULL,
|
||||
sender_name TEXT NOT NULL,
|
||||
roles TEXT NOT NULL)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
database.execSQL("""
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Recipients (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -28,10 +31,11 @@ class Migration6 : Migration(5, 6) {
|
||||
unit_id INTEGER NOT NULL,
|
||||
role INTEGER NOT NULL,
|
||||
hash TEXT NOT NULL)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
database.execSQL("DELETE FROM Semesters WHERE 1")
|
||||
database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||
database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
|
||||
db.execSQL("DELETE FROM Semesters WHERE 1")
|
||||
db.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
|
||||
db.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration7 : Migration(6, 7) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS GradesStatistics (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
@ -15,6 +16,7 @@ class Migration7 : Migration(6, 7) {
|
||||
grade INTEGER NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
is_semester INTEGER NOT NULL)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration8 : Migration(7, 8) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
|
||||
database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
|
||||
db.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
|
||||
db.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration9 : Migration(8, 9) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
database.execSQL("""
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL("DROP TABLE IF EXISTS Messages")
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
|
@ -0,0 +1,21 @@
|
||||
package io.github.wulkanowy.data.pojos
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class LoginEvent(
|
||||
val uuid: String,
|
||||
val schoolName: String,
|
||||
val schoolShort: String,
|
||||
val schoolAddress: String,
|
||||
val scraperBaseUrl: String,
|
||||
val symbol: String,
|
||||
val schoolId: String,
|
||||
val loginType: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class IntegrityRequest<T>(
|
||||
val tokenString: String,
|
||||
val data: T,
|
||||
)
|
@ -35,12 +35,15 @@ class LuckyNumberRepository @Inject constructor(
|
||||
fetch = {
|
||||
sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student)
|
||||
},
|
||||
saveFetchResult = { old, new ->
|
||||
if (new != old) {
|
||||
old?.let { luckyNumberDb.deleteAll(listOfNotNull(it)) }
|
||||
luckyNumberDb.insertAll(listOfNotNull((new?.apply {
|
||||
if (notify) isNotified = false
|
||||
})))
|
||||
saveFetchResult = { oldLuckyNumber, newLuckyNumber ->
|
||||
newLuckyNumber ?: return@networkBoundResource
|
||||
|
||||
if (newLuckyNumber != oldLuckyNumber) {
|
||||
val updatedLuckNumberList =
|
||||
listOf(newLuckyNumber.apply { if (notify) isNotified = false })
|
||||
|
||||
oldLuckyNumber?.let { luckyNumberDb.deleteAll(listOfNotNull(it)) }
|
||||
luckyNumberDb.insertAll(updatedLuckNumberList)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -9,7 +9,12 @@ import com.fredporciuncula.flow.preferences.Preference
|
||||
import com.fredporciuncula.flow.preferences.Serializer
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.enums.*
|
||||
import io.github.wulkanowy.data.enums.AppTheme
|
||||
import io.github.wulkanowy.data.enums.GradeColorTheme
|
||||
import io.github.wulkanowy.data.enums.GradeExpandMode
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode
|
||||
import io.github.wulkanowy.data.enums.TimetableGapsMode
|
||||
import io.github.wulkanowy.data.enums.TimetableMode
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
||||
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
|
||||
@ -18,7 +23,7 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -194,12 +199,6 @@ class PreferencesRepository @Inject constructor(
|
||||
)
|
||||
)
|
||||
|
||||
val showTimetableTimers: Boolean
|
||||
get() = getBoolean(
|
||||
R.string.pref_key_timetable_show_timers,
|
||||
R.bool.pref_default_timetable_show_timers
|
||||
)
|
||||
|
||||
val showTimetableGaps: TimetableGapsMode
|
||||
get() = TimetableGapsMode.getByValue(
|
||||
getString(
|
||||
@ -309,19 +308,6 @@ class PreferencesRepository @Inject constructor(
|
||||
get() = sharedPref.getBoolean(PREF_KEY_APP_SUPPORT_SHOWN, false)
|
||||
set(value) = sharedPref.edit { putBoolean(PREF_KEY_APP_SUPPORT_SHOWN, value) }
|
||||
|
||||
var isAgreeToProcessData: Boolean
|
||||
get() = getBoolean(
|
||||
R.string.pref_key_ads_consent_data_processing,
|
||||
R.bool.pref_default_ads_consent_data_processing
|
||||
)
|
||||
set(value) = sharedPref.edit {
|
||||
putBoolean(context.getString(R.string.pref_key_ads_consent_data_processing), value)
|
||||
}
|
||||
|
||||
var isPersonalizedAdsEnabled: Boolean
|
||||
get() = sharedPref.getBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, false)
|
||||
set(value) = sharedPref.edit { putBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, value) }
|
||||
|
||||
val isAdsEnabledFlow = flowSharedPref.getBoolean(
|
||||
context.getString(R.string.pref_key_ads_enabled),
|
||||
context.resources.getBoolean(R.bool.pref_default_ads_enabled)
|
||||
@ -404,7 +390,6 @@ class PreferencesRepository @Inject constructor(
|
||||
private const val PREF_KEY_IN_APP_REVIEW_DATE = "in_app_review_date"
|
||||
private const val PREF_KEY_IN_APP_REVIEW_DONE = "in_app_review_done"
|
||||
private const val PREF_KEY_APP_SUPPORT_SHOWN = "app_support_shown"
|
||||
private const val PREF_KEY_PERSONALIZED_ADS_ENABLED = "personalized_ads_enabled"
|
||||
private const val PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS = "admin_message_dismissed_ids"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import io.github.wulkanowy.data.api.SchoolsService
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||
import io.github.wulkanowy.data.pojos.IntegrityRequest
|
||||
import io.github.wulkanowy.data.pojos.LoginEvent
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.utils.IntegrityHelper
|
||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
||||
import io.github.wulkanowy.utils.init
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Singleton
|
||||
class SchoolsRepository @Inject constructor(
|
||||
private val integrityHelper: IntegrityHelper,
|
||||
private val schoolsService: SchoolsService,
|
||||
private val sdk: Sdk,
|
||||
) {
|
||||
|
||||
suspend fun logSchoolLogin(loginData: LoginData, students: List<StudentWithSemesters>) {
|
||||
students.forEach {
|
||||
runCatching {
|
||||
withTimeout(10.seconds) {
|
||||
logLogin(loginData, it.student, it.semesters.getCurrentOrLast())
|
||||
}
|
||||
}
|
||||
.onFailure { Timber.e(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun logLogin(loginData: LoginData, student: Student, semester: Semester) {
|
||||
val requestId = UUID.randomUUID().toString()
|
||||
val token = integrityHelper.getIntegrityToken(requestId) ?: return
|
||||
|
||||
val schoolInfo = sdk
|
||||
.init(student.copy(password = loginData.password))
|
||||
.switchDiary(
|
||||
diaryId = semester.diaryId,
|
||||
kindergartenDiaryId = semester.kindergartenDiaryId,
|
||||
schoolYear = semester.schoolYear
|
||||
)
|
||||
.getSchool()
|
||||
|
||||
schoolsService.logLoginEvent(
|
||||
IntegrityRequest(
|
||||
tokenString = token,
|
||||
data = LoginEvent(
|
||||
uuid = requestId,
|
||||
schoolAddress = schoolInfo.address,
|
||||
schoolName = schoolInfo.name,
|
||||
schoolShort = student.schoolShortName,
|
||||
scraperBaseUrl = student.scrapperBaseUrl,
|
||||
loginType = student.loginType,
|
||||
symbol = student.symbol,
|
||||
schoolId = student.schoolSymbol,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package io.github.wulkanowy.data.repositories
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.withTransaction
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.data.db.AppDatabase
|
||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||
@ -17,20 +15,19 @@ import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.security.decrypt
|
||||
import io.github.wulkanowy.utils.security.encrypt
|
||||
import io.github.wulkanowy.utils.security.Scrambler
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class StudentRepository @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val dispatchers: DispatchersProvider,
|
||||
private val studentDb: StudentDao,
|
||||
private val semesterDb: SemesterDao,
|
||||
private val sdk: Sdk,
|
||||
private val appDatabase: AppDatabase
|
||||
private val appDatabase: AppDatabase,
|
||||
private val scrambler: Scrambler,
|
||||
) {
|
||||
|
||||
suspend fun isCurrentStudentSet() = studentDb.loadCurrent()?.isCurrent ?: false
|
||||
@ -62,23 +59,31 @@ class StudentRepository @Inject constructor(
|
||||
.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol)
|
||||
.mapToPojo(password)
|
||||
|
||||
suspend fun getSavedStudents(decryptPass: Boolean = true) =
|
||||
studentDb.loadStudentsWithSemesters()
|
||||
.map {
|
||||
it.apply {
|
||||
suspend fun getSavedStudents(decryptPass: Boolean = true): List<StudentWithSemesters> {
|
||||
return studentDb.loadStudentsWithSemesters().map { (student, semesters) ->
|
||||
StudentWithSemesters(
|
||||
student = student.apply {
|
||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
||||
student.password = withContext(dispatchers.io) {
|
||||
decrypt(student.password)
|
||||
scrambler.decrypt(student.password)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
semesters = semesters,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true) =
|
||||
studentDb.loadStudentWithSemestersById(id)?.apply {
|
||||
suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true): StudentWithSemesters? =
|
||||
studentDb.loadStudentWithSemestersById(id).let { res ->
|
||||
StudentWithSemesters(
|
||||
student = res.keys.firstOrNull() ?: return null,
|
||||
semesters = res.values.first(),
|
||||
)
|
||||
}.apply {
|
||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
||||
student.password = withContext(dispatchers.io) {
|
||||
decrypt(student.password)
|
||||
scrambler.decrypt(student.password)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +93,7 @@ class StudentRepository @Inject constructor(
|
||||
|
||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
||||
student.password = withContext(dispatchers.io) {
|
||||
decrypt(student.password)
|
||||
scrambler.decrypt(student.password)
|
||||
}
|
||||
}
|
||||
return student
|
||||
@ -99,7 +104,7 @@ class StudentRepository @Inject constructor(
|
||||
|
||||
if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) {
|
||||
student.password = withContext(dispatchers.io) {
|
||||
decrypt(student.password)
|
||||
scrambler.decrypt(student.password)
|
||||
}
|
||||
}
|
||||
return student
|
||||
@ -112,7 +117,7 @@ class StudentRepository @Inject constructor(
|
||||
it.apply {
|
||||
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.HEBE) {
|
||||
password = withContext(dispatchers.io) {
|
||||
encrypt(password, context)
|
||||
scrambler.encrypt(password)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,4 +163,15 @@ class StudentRepository @Inject constructor(
|
||||
|
||||
studentDb.update(studentName)
|
||||
}
|
||||
|
||||
suspend fun deleteStudentsAssociatedWithAccount(student: Student) {
|
||||
studentDb.deleteByEmailAndUserName(student.email, student.userName)
|
||||
}
|
||||
|
||||
suspend fun clearAll() {
|
||||
withContext(dispatchers.io) {
|
||||
scrambler.clearKeyPair()
|
||||
appDatabase.clearAllTables()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,11 +68,20 @@ abstract class BaseActivity<T : BasePresenter<out BaseView>, VB : ViewBinding> :
|
||||
} else Toast.makeText(this, text, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
override fun showExpiredCredentialsDialog() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.main_expired_credentials_title)
|
||||
.setMessage(R.string.main_expired_credentials_description)
|
||||
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onConfirmExpiredCredentialsSelected() }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.main_session_expired)
|
||||
.setMessage(R.string.main_session_relogin)
|
||||
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() }
|
||||
.setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onConfirmDecryptionFailedSelected() }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
@ -28,8 +28,12 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView
|
||||
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredDialog()
|
||||
override fun showExpiredCredentialsDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
|
||||
override fun openClearLoginView() {
|
||||
|
@ -39,8 +39,12 @@ abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragme
|
||||
}
|
||||
}
|
||||
|
||||
override fun showExpiredDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredDialog()
|
||||
override fun showExpiredCredentialsDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog()
|
||||
}
|
||||
|
||||
override fun showDecryptionFailedDialog() {
|
||||
(activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog()
|
||||
}
|
||||
|
||||
override fun showAuthDialog() {
|
||||
|
@ -28,20 +28,37 @@ open class BasePresenter<T : BaseView>(
|
||||
this.view = view
|
||||
errorHandler.apply {
|
||||
showErrorMessage = view::showError
|
||||
onSessionExpired = view::showExpiredDialog
|
||||
onExpiredCredentials = view::showExpiredCredentialsDialog
|
||||
onDecryptionFailed = view::showDecryptionFailedDialog
|
||||
onNoCurrentStudent = view::openClearLoginView
|
||||
onPasswordChangeRequired = view::showChangePasswordSnackbar
|
||||
onAuthorizationRequired = view::showAuthDialog
|
||||
}
|
||||
}
|
||||
|
||||
fun onExpiredLoginSelected() {
|
||||
Timber.i("Attempt to switch the student after the session expires")
|
||||
fun onConfirmDecryptionFailedSelected() {
|
||||
Timber.i("Attempt to clear all data")
|
||||
|
||||
presenterScope.launch {
|
||||
runCatching { studentRepository.clearAll() }
|
||||
.onFailure {
|
||||
Timber.i("Clear data result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
.onSuccess {
|
||||
Timber.i("Clear data result: Open login view")
|
||||
view?.openClearLoginView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onConfirmExpiredCredentialsSelected() {
|
||||
Timber.i("Attempt to delete students associated with the account and switch to new student")
|
||||
|
||||
presenterScope.launch {
|
||||
runCatching {
|
||||
val student = studentRepository.getCurrentStudent(false)
|
||||
studentRepository.logoutStudent(student)
|
||||
studentRepository.deleteStudentsAssociatedWithAccount(student)
|
||||
|
||||
val students = studentRepository.getSavedStudents(false)
|
||||
if (students.isNotEmpty()) {
|
||||
@ -50,11 +67,11 @@ open class BasePresenter<T : BaseView>(
|
||||
}
|
||||
}
|
||||
.onFailure {
|
||||
Timber.i("Switch student result: An exception occurred")
|
||||
Timber.i("Delete students result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
.onSuccess {
|
||||
Timber.i("Switch student result: Open login view")
|
||||
Timber.i("Delete students result: Open login view")
|
||||
view?.openClearLoginView()
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ interface BaseView {
|
||||
|
||||
fun showMessage(text: String)
|
||||
|
||||
fun showExpiredDialog()
|
||||
fun showExpiredCredentialsDialog()
|
||||
|
||||
fun showDecryptionFailedDialog()
|
||||
|
||||
fun showAuthDialog()
|
||||
|
||||
|
@ -15,7 +15,9 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
||||
|
||||
var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> }
|
||||
|
||||
var onSessionExpired: () -> Unit = {}
|
||||
var onExpiredCredentials: () -> Unit = {}
|
||||
|
||||
var onDecryptionFailed: () -> Unit = {}
|
||||
|
||||
var onNoCurrentStudent: () -> Unit = {}
|
||||
|
||||
@ -32,7 +34,8 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
||||
showErrorMessage(context.resources.getErrorString(error), error)
|
||||
when (error) {
|
||||
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
|
||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||
is ScramblerException -> onDecryptionFailed()
|
||||
is BadCredentialsException -> onExpiredCredentials()
|
||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||
is AuthorizationRequiredException -> onAuthorizationRequired()
|
||||
}
|
||||
@ -40,7 +43,8 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
||||
|
||||
open fun clear() {
|
||||
showErrorMessage = { _, _ -> }
|
||||
onSessionExpired = {}
|
||||
onExpiredCredentials = {}
|
||||
onDecryptionFailed = {}
|
||||
onNoCurrentStudent = {}
|
||||
onPasswordChangeRequired = {}
|
||||
onAuthorizationRequired = {}
|
||||
|
@ -148,6 +148,10 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
||||
binding.attendanceNavDate.text = date
|
||||
}
|
||||
|
||||
override fun showNavigation(show: Boolean) {
|
||||
binding.attendanceNavContainer.isVisible = show
|
||||
}
|
||||
|
||||
override fun clearData() {
|
||||
with(attendanceAdapter) {
|
||||
items = emptyList()
|
||||
@ -281,7 +285,9 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
presenter.currentDate?.let {
|
||||
outState.putLong(SAVED_DATE_KEY, it.toEpochDay())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -3,10 +3,14 @@ package io.github.wulkanowy.ui.modules.attendance
|
||||
import android.annotation.SuppressLint
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.*
|
||||
@ -14,6 +18,7 @@ import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDate.now
|
||||
import java.time.LocalDate.ofEpochDay
|
||||
@ -28,9 +33,10 @@ class AttendancePresenter @Inject constructor(
|
||||
private val analytics: AnalyticsHelper
|
||||
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
|
||||
|
||||
private var baseDate: LocalDate = now().previousOrSameSchoolDay
|
||||
private var initialDate: LocalDate? = null
|
||||
private var isWeekendHasLessons: Boolean = false
|
||||
|
||||
lateinit var currentDate: LocalDate
|
||||
var currentDate: LocalDate? = null
|
||||
private set
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
@ -44,27 +50,34 @@ class AttendancePresenter @Inject constructor(
|
||||
view.initView()
|
||||
Timber.i("Attendance view was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
currentDate = date?.let(::ofEpochDay)
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
val date = if (isWeekendHasLessons) {
|
||||
currentDate?.minusDays(1)
|
||||
} else currentDate?.previousSchoolDay
|
||||
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
reloadView(currentDate.previousSchoolDay)
|
||||
reloadView(date ?: return)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
val date = if (isWeekendHasLessons) {
|
||||
currentDate?.plusDays(1)
|
||||
} else currentDate?.nextSchoolDay
|
||||
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
reloadView(currentDate.nextSchoolDay)
|
||||
reloadView(date ?: return)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
view?.showDatePickerDialog(currentDate)
|
||||
view?.showDatePickerDialog(currentDate ?: return)
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
@ -93,10 +106,8 @@ class AttendancePresenter @Inject constructor(
|
||||
Timber.i("Attendance view is reselected")
|
||||
view?.let { view ->
|
||||
if (view.currentStackSize == 1) {
|
||||
baseDate = now().previousOrSameSchoolDay
|
||||
|
||||
if (currentDate != baseDate) {
|
||||
reloadView(baseDate)
|
||||
if (currentDate != initialDate) {
|
||||
reloadView(initialDate ?: return)
|
||||
loadData()
|
||||
} else if (!view.isViewEmpty) {
|
||||
view.resetView()
|
||||
@ -188,19 +199,6 @@ class AttendancePresenter @Inject constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun setBaseDateOnHolidays() {
|
||||
flow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
emit(semesterRepository.getCurrentSemester(student))
|
||||
}.catch {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
}.onEach {
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading attendance data started")
|
||||
|
||||
@ -211,11 +209,13 @@ class AttendancePresenter @Inject constructor(
|
||||
isParent = student.isParent
|
||||
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
checkInitialAndCurrentDate(student, semester)
|
||||
attendanceRepository.getAttendance(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = currentDate,
|
||||
end = currentDate,
|
||||
start = currentDate ?: now(),
|
||||
end = currentDate ?: now(),
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
@ -231,6 +231,8 @@ class AttendancePresenter @Inject constructor(
|
||||
}.sortedBy { item -> item.number }
|
||||
}
|
||||
.onResourceData {
|
||||
isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessons(it)
|
||||
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showProgress(false)
|
||||
@ -238,6 +240,7 @@ class AttendancePresenter @Inject constructor(
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
updateData(it)
|
||||
reloadNavigation()
|
||||
}
|
||||
}
|
||||
.onResourceIntermediate { view?.showRefresh(true) }
|
||||
@ -263,6 +266,43 @@ class AttendancePresenter @Inject constructor(
|
||||
.launch()
|
||||
}
|
||||
|
||||
private suspend fun checkInitialAndCurrentDate(student: Student, semester: Semester) {
|
||||
if (initialDate == null) {
|
||||
val lessons = attendanceRepository.getAttendance(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = now().monday,
|
||||
end = now().sunday,
|
||||
forceRefresh = false,
|
||||
).toFirstResult().dataOrNull.orEmpty()
|
||||
isWeekendHasLessons = isWeekendHasLessons(lessons)
|
||||
initialDate = getInitialDate(semester)
|
||||
}
|
||||
|
||||
if (currentDate == null) {
|
||||
currentDate = initialDate
|
||||
}
|
||||
}
|
||||
|
||||
private fun isWeekendHasLessons(
|
||||
lessons: List<Attendance>,
|
||||
): Boolean = lessons.any {
|
||||
it.date.dayOfWeek in listOf(
|
||||
DayOfWeek.SATURDAY,
|
||||
DayOfWeek.SUNDAY,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getInitialDate(semester: Semester): LocalDate {
|
||||
val now = now()
|
||||
|
||||
return when {
|
||||
now.isHolidays -> now.getLastSchoolDayIfHoliday(semester.schoolYear)
|
||||
isWeekendHasLessons -> now
|
||||
else -> now.previousOrSameSchoolDay
|
||||
}
|
||||
}
|
||||
|
||||
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
||||
resourceFlow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
@ -311,7 +351,7 @@ class AttendancePresenter @Inject constructor(
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
|
||||
Timber.i("Reload attendance view with the date ${currentDate?.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
enableSwipe(false)
|
||||
@ -326,10 +366,13 @@ class AttendancePresenter @Inject constructor(
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private fun reloadNavigation() {
|
||||
val currentDate = currentDate ?: return
|
||||
|
||||
view?.apply {
|
||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
|
||||
showNavigation(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ interface AttendanceView : BaseView {
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showNavigation(show: Boolean)
|
||||
|
||||
fun showPreButton(show: Boolean)
|
||||
|
||||
fun showNextButton(show: Boolean)
|
||||
|
@ -30,7 +30,12 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
|
||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.capitalise
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.getErrorString
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -1,19 +1,46 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.dataOrNull
|
||||
import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.enums.MessageFolder
|
||||
import io.github.wulkanowy.data.enums.MessageType
|
||||
import io.github.wulkanowy.data.repositories.*
|
||||
import io.github.wulkanowy.data.errorOrNull
|
||||
import io.github.wulkanowy.data.flatResourceFlow
|
||||
import io.github.wulkanowy.data.mapResourceData
|
||||
import io.github.wulkanowy.data.onResourceError
|
||||
import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
|
||||
import io.github.wulkanowy.data.repositories.ConferenceRepository
|
||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
||||
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
|
||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AdsHelper
|
||||
import io.github.wulkanowy.utils.calculatePercentage
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNot
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.time.Instant
|
||||
@ -48,6 +75,11 @@ class DashboardPresenter @Inject constructor(
|
||||
|
||||
private val firstLoadedItemList = mutableListOf<DashboardItem.Type>()
|
||||
|
||||
private val selectedDashboardTiles
|
||||
get() = preferencesRepository.selectedDashboardTiles
|
||||
.filterNot { it == DashboardItem.Tile.ADS && !adsHelper.canShowAd }
|
||||
.toSet()
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
override fun onAttachView(view: DashboardView) {
|
||||
@ -59,10 +91,19 @@ class DashboardPresenter @Inject constructor(
|
||||
showContent(false)
|
||||
}
|
||||
|
||||
val selectedDashboardTilesFlow = preferencesRepository.selectedDashboardTilesFlow
|
||||
.map { selectedDashboardTiles }
|
||||
val isAdsEnabledFlow = preferencesRepository.isAdsEnabledFlow
|
||||
.filter { (adsHelper.canShowAd && it) || !it }
|
||||
.map { selectedDashboardTiles }
|
||||
val isMobileAdsSdkInitializedFlow = adsHelper.isMobileAdsSdkInitialized
|
||||
.filter { it }
|
||||
.map { selectedDashboardTiles }
|
||||
|
||||
merge(
|
||||
preferencesRepository.selectedDashboardTilesFlow,
|
||||
preferencesRepository.isAdsEnabledFlow
|
||||
.map { preferencesRepository.selectedDashboardTiles }
|
||||
selectedDashboardTilesFlow,
|
||||
isAdsEnabledFlow,
|
||||
isMobileAdsSdkInitializedFlow
|
||||
)
|
||||
.onEach { loadData(tilesToLoad = it) }
|
||||
.launch("dashboard_pref")
|
||||
@ -71,7 +112,7 @@ class DashboardPresenter @Inject constructor(
|
||||
fun onAdminMessageDismissed(adminMessage: AdminMessage) {
|
||||
preferencesRepository.dismissedAdminMessageIds += adminMessage.id
|
||||
|
||||
loadData(preferencesRepository.selectedDashboardTiles)
|
||||
loadData(selectedDashboardTiles)
|
||||
}
|
||||
|
||||
fun onDragAndDropEnd(list: List<DashboardItem>) {
|
||||
@ -187,7 +228,7 @@ class DashboardPresenter @Inject constructor(
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the dashboard")
|
||||
loadData(preferencesRepository.selectedDashboardTiles, forceRefresh = true)
|
||||
loadData(selectedDashboardTiles, forceRefresh = true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -195,7 +236,7 @@ class DashboardPresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(preferencesRepository.selectedDashboardTiles, forceRefresh = true)
|
||||
loadData(selectedDashboardTiles, forceRefresh = true)
|
||||
}
|
||||
|
||||
fun onViewReselected() {
|
||||
@ -216,7 +257,7 @@ class DashboardPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onDashboardTileSettingsSelected(): Boolean {
|
||||
view?.showDashboardTileSettings(preferencesRepository.selectedDashboardTiles.toList())
|
||||
view?.showDashboardTileSettings(selectedDashboardTiles.toList())
|
||||
return true
|
||||
}
|
||||
|
||||
@ -232,7 +273,7 @@ class DashboardPresenter @Inject constructor(
|
||||
|
||||
private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) {
|
||||
flow {
|
||||
val selectedTiles = preferencesRepository.selectedDashboardTiles
|
||||
val selectedTiles = selectedDashboardTiles
|
||||
val flowSuccess = flowOf(Resource.Success(null))
|
||||
|
||||
val luckyNumberFlow = luckyNumberRepository.getLuckyNumber(student, forceRefresh)
|
||||
@ -386,7 +427,7 @@ class DashboardPresenter @Inject constructor(
|
||||
private fun loadLessons(student: Student, forceRefresh: Boolean) {
|
||||
flatResourceFlow {
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val date = LocalDate.now().nextOrSameSchoolDay
|
||||
val date = LocalDate.now()
|
||||
|
||||
timetableRepository.getTimetable(
|
||||
student = student,
|
||||
|
@ -58,7 +58,7 @@ class GradeAverageProvider @Inject constructor(
|
||||
when (params.gradeAverageMode) {
|
||||
ONE_SEMESTER -> getGradeSubjects(
|
||||
student = student,
|
||||
semester = semesters.single { it.semesterId == semesterId },
|
||||
semester = semesters.first { it.semesterId == semesterId },
|
||||
forceRefresh = forceRefresh,
|
||||
params = params,
|
||||
)
|
||||
|
@ -22,6 +22,8 @@ import io.github.wulkanowy.databinding.ItemGradeStatisticsHeaderBinding
|
||||
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class GradeStatisticsAdapter @Inject constructor() :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
@ -269,7 +271,7 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
valueTextSize = 12f
|
||||
valueTextColor = binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||
valueFormatter = object : ValueFormatter() {
|
||||
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%"
|
||||
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}"
|
||||
}
|
||||
colors = gradePointsColors
|
||||
}
|
||||
@ -304,15 +306,20 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
}
|
||||
xAxis.setDrawLabels(false)
|
||||
xAxis.setDrawGridLines(false)
|
||||
|
||||
val yMaxFromValues = (max(points.others, points.student)).roundToInt() + 30f
|
||||
val yMaxFromValuesWithMargin = ((yMaxFromValues / 10.0).roundToInt() * 10).toFloat()
|
||||
val yMax = yMaxFromValuesWithMargin.coerceAtLeast(100f)
|
||||
val yLabelCount = (yMax / 10).toInt() + 1
|
||||
with(axisLeft) {
|
||||
axisMinimum = 0f
|
||||
axisMaximum = 100f
|
||||
labelCount = 11
|
||||
axisMaximum = yMax
|
||||
labelCount = yLabelCount
|
||||
}
|
||||
with(axisRight) {
|
||||
axisMinimum = 0f
|
||||
axisMaximum = 100f
|
||||
labelCount = 11
|
||||
axisMaximum = yMax
|
||||
labelCount = yLabelCount
|
||||
}
|
||||
invalidate()
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||
}
|
||||
.logResourceStatus("load grade summary", showData = true)
|
||||
.logResourceStatus("load grade summary")
|
||||
.mapResourceData { createGradeSummaryItems(it) }
|
||||
.onResourceData {
|
||||
view?.run {
|
||||
|
@ -23,7 +23,7 @@ import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.notifications.NotificationsFragment
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.UpdateHelper
|
||||
import io.github.wulkanowy.utils.InAppUpdateHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -33,7 +33,7 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
override lateinit var presenter: LoginPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var updateHelper: UpdateHelper
|
||||
lateinit var inAppUpdateHelper: InAppUpdateHelper
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
@ -47,10 +47,10 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
setContentView(ActivityLoginBinding.inflate(layoutInflater).apply { binding = this }.root)
|
||||
setSupportActionBar(binding.loginToolbar)
|
||||
messageContainer = binding.loginContainer
|
||||
updateHelper.messageContainer = binding.loginContainer
|
||||
inAppUpdateHelper.messageContainer = binding.loginContainer
|
||||
|
||||
presenter.onAttachView(this)
|
||||
updateHelper.checkAndInstallUpdates(this)
|
||||
inAppUpdateHelper.checkAndInstallUpdates()
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
openFragment(LoginFormFragment.newInstance(), clearBackStack = true)
|
||||
@ -117,14 +117,6 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateHelper.onResume(this)
|
||||
}
|
||||
|
||||
//https://developer.android.com/guide/playcore/in-app-updates#status_callback
|
||||
@Deprecated("Deprecated in Java")
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
updateHelper.onActivityResult(requestCode, resultCode)
|
||||
inAppUpdateHelper.onResume()
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -184,7 +186,9 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
|
||||
override fun clearPassError() {
|
||||
binding.loginFormPassLayout.error = null
|
||||
binding.loginFormPassLayout.setEndIconTintList(null)
|
||||
binding.loginFormPassLayout.setEndIconTintList(
|
||||
requireContext().getAttrColorStateList(R.attr.colorOnSurface)
|
||||
)
|
||||
binding.loginFormErrorBox.isVisible = false
|
||||
}
|
||||
|
||||
@ -236,8 +240,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
}
|
||||
|
||||
override fun showContact(show: Boolean) {
|
||||
binding.loginFormContact.visibility = if (show) VISIBLE else GONE
|
||||
binding.loginFormRecoverLink.visibility = if (show) GONE else VISIBLE
|
||||
binding.loginFormContact.isVisible = show
|
||||
}
|
||||
|
||||
override fun openPrivacyPolicyPage() {
|
||||
@ -281,20 +284,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
presenter.updateCustomDomainSuffixVisibility()
|
||||
}
|
||||
|
||||
override fun openEmail(lastError: String) {
|
||||
context?.openEmailClient(
|
||||
chooserTitle = requireContext().getString(R.string.login_email_intent_title),
|
||||
email = "wulkanowyinc@gmail.com",
|
||||
subject = requireContext().getString(R.string.login_email_subject),
|
||||
body = requireContext().getString(
|
||||
R.string.login_email_text,
|
||||
"${appInfo.systemManufacturer} ${appInfo.systemModel}",
|
||||
appInfo.systemVersion.toString(),
|
||||
"${appInfo.versionName}-${appInfo.buildFlavor}",
|
||||
"$formHostValue/$formHostSymbol",
|
||||
preferencesRepository.installationId,
|
||||
lastError
|
||||
)
|
||||
)
|
||||
override fun openEmail(supportInfo: LoginSupportInfo) {
|
||||
LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog")
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
@ -133,7 +134,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onSignInClick() {
|
||||
private fun getLoginData(): LoginData {
|
||||
val email = view?.formUsernameValue.orEmpty().trim()
|
||||
val password = view?.formPassValue.orEmpty().trim()
|
||||
val host = view?.formHostValue.orEmpty().trim()
|
||||
@ -142,15 +143,27 @@ class LoginFormPresenter @Inject constructor(
|
||||
}.orEmpty()
|
||||
val symbol = view?.formHostSymbol.orEmpty().trim()
|
||||
|
||||
if (!validateCredentials(email, password, host)) return
|
||||
return LoginData(
|
||||
login = email,
|
||||
password = password,
|
||||
baseUrl = host,
|
||||
domainSuffix = domainSuffix,
|
||||
symbol = symbol
|
||||
)
|
||||
}
|
||||
|
||||
fun onSignInClick() {
|
||||
val loginData = getLoginData()
|
||||
|
||||
if (!validateCredentials(loginData.login, loginData.password, loginData.baseUrl)) return
|
||||
|
||||
resourceFlow {
|
||||
studentRepository.getUserSubjectsFromScrapper(
|
||||
email = email,
|
||||
password = password,
|
||||
scrapperBaseUrl = host,
|
||||
domainSuffix = domainSuffix,
|
||||
symbol = symbol
|
||||
email = loginData.login,
|
||||
password = loginData.password,
|
||||
scrapperBaseUrl = loginData.baseUrl,
|
||||
domainSuffix = loginData.domainSuffix,
|
||||
symbol = loginData.symbol.orEmpty(),
|
||||
)
|
||||
}
|
||||
.logResourceStatus("login")
|
||||
@ -162,7 +175,6 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
.onResourceSuccess {
|
||||
val loginData = LoginData(email, password, host, domainSuffix, symbol)
|
||||
when (it.symbols.size) {
|
||||
0 -> view?.navigateToSymbol(loginData)
|
||||
else -> view?.navigateToStudentSelect(loginData, it)
|
||||
@ -170,7 +182,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to true,
|
||||
"scrapperBaseUrl" to host,
|
||||
"scrapperBaseUrl" to loginData.baseUrl,
|
||||
"error" to "No error"
|
||||
)
|
||||
}
|
||||
@ -187,7 +199,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to false,
|
||||
"scrapperBaseUrl" to host,
|
||||
"scrapperBaseUrl" to loginData.baseUrl,
|
||||
"error" to it.message.ifNullOrBlank { "No message" }
|
||||
)
|
||||
}
|
||||
@ -199,7 +211,14 @@ class LoginFormPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onEmailClick() {
|
||||
view?.openEmail(lastError?.message.ifNullOrBlank { "none" })
|
||||
view?.openEmail(
|
||||
LoginSupportInfo(
|
||||
loginData = getLoginData(),
|
||||
lastErrorMessage = lastError?.message,
|
||||
registerUser = null,
|
||||
enteredSymbol = null,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun onRecoverClick() {
|
||||
|
@ -4,6 +4,7 @@ import io.github.wulkanowy.data.db.entities.AdminMessage
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
|
||||
interface LoginFormView : BaseView {
|
||||
|
||||
@ -79,7 +80,7 @@ interface LoginFormView : BaseView {
|
||||
|
||||
fun openFaqPage()
|
||||
|
||||
fun openEmail(lastError: String)
|
||||
fun openEmail(supportInfo: LoginSupportInfo)
|
||||
|
||||
fun openAdvancedLogin()
|
||||
|
||||
|
@ -46,7 +46,7 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
|
||||
fun updateFields() {
|
||||
view?.run {
|
||||
setUsernameHint(if ("standard" in recoverHostValue) emailHintString else loginPeselEmailHintString)
|
||||
setUsernameHint(if ("email" in recoverHostValue) emailHintString else loginPeselEmailHintString)
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
isCorrect = false
|
||||
}
|
||||
|
||||
if ("standard" in host && "@" !in username) {
|
||||
if ("email" in host && "@" !in username) {
|
||||
view?.setUsernameError(view?.invalidEmailString.orEmpty())
|
||||
isCorrect = false
|
||||
}
|
||||
|
@ -10,8 +10,11 @@ import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.auth.AuthDialog
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openEmailClient
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
@ -106,21 +109,8 @@ class LoginStudentSelectFragment :
|
||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
||||
}
|
||||
|
||||
override fun openEmail(lastError: String) {
|
||||
context?.openEmailClient(
|
||||
chooserTitle = requireContext().getString(R.string.login_email_intent_title),
|
||||
email = "wulkanowyinc@gmail.com",
|
||||
subject = requireContext().getString(R.string.login_email_subject),
|
||||
body = requireContext().getString(
|
||||
R.string.login_email_text,
|
||||
"${appInfo.systemManufacturer} ${appInfo.systemModel}",
|
||||
appInfo.systemVersion.toString(),
|
||||
"${appInfo.versionName}-${appInfo.buildFlavor}",
|
||||
"Select users to log in",
|
||||
preferencesRepository.installationId,
|
||||
lastError
|
||||
)
|
||||
)
|
||||
override fun openEmail(supportInfo: LoginSupportInfo) {
|
||||
LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog")
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -9,23 +9,25 @@ import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.data.repositories.SchoolsRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.resourceFlow
|
||||
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
|
||||
import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException
|
||||
import io.github.wulkanowy.services.sync.SyncManager
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import io.github.wulkanowy.utils.isCurrent
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoginStudentSelectPresenter @Inject constructor(
|
||||
studentRepository: StudentRepository,
|
||||
private val schoolsRepository: SchoolsRepository,
|
||||
private val loginErrorHandler: LoginErrorHandler,
|
||||
private val syncManager: SyncManager,
|
||||
private val analytics: AnalyticsHelper,
|
||||
@ -71,7 +73,14 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
students = it.dataOrNull.orEmpty()
|
||||
when (it) {
|
||||
is Resource.Loading -> Timber.d("Login student select students load started")
|
||||
is Resource.Success -> refreshItems()
|
||||
is Resource.Success -> {
|
||||
getStudentsWithCurrentlyActiveSemesters()
|
||||
selectedStudents.clear()
|
||||
selectedStudents.addAll(getStudentsWithCurrentlyActiveSemesters())
|
||||
view?.enableSignIn(selectedStudents.isNotEmpty())
|
||||
refreshItems()
|
||||
}
|
||||
|
||||
is Resource.Error -> {
|
||||
errorHandler.dispatch(it.error)
|
||||
lastError = it.error
|
||||
@ -81,6 +90,23 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun getStudentsWithCurrentlyActiveSemesters(): List<LoginStudentSelectItem.Student> {
|
||||
val students = registerUser.symbols.flatMap { symbol ->
|
||||
symbol.schools.flatMap { unit ->
|
||||
unit.students.map {
|
||||
createStudentItem(it, symbol, unit, students)
|
||||
}
|
||||
}
|
||||
}
|
||||
return students
|
||||
.filter { it.isEnabled }
|
||||
.filter { student ->
|
||||
student.student.semesters.any { semester ->
|
||||
semester.isCurrent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createItems(): List<LoginStudentSelectItem> = buildList {
|
||||
val notEmptySymbols = registerUser.symbols.filter { it.schools.isNotEmpty() }
|
||||
val emptySymbols = registerUser.symbols.filter { it.schools.isEmpty() }
|
||||
@ -236,17 +262,20 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun registerStudents(students: List<LoginStudentSelectItem>) {
|
||||
val studentsWithSemesters = students
|
||||
.filterIsInstance<LoginStudentSelectItem.Student>().map { item ->
|
||||
item.student.mapToStudentWithSemesters(
|
||||
user = registerUser,
|
||||
symbol = item.symbol,
|
||||
scrapperDomainSuffix = loginData.domainSuffix,
|
||||
unit = item.unit,
|
||||
colors = appInfo.defaultColorsForAvatar,
|
||||
)
|
||||
}
|
||||
resourceFlow { studentRepository.saveStudents(studentsWithSemesters) }
|
||||
val filteredStudents = students.filterIsInstance<LoginStudentSelectItem.Student>()
|
||||
val studentsWithSemesters = filteredStudents.map { item ->
|
||||
item.student.mapToStudentWithSemesters(
|
||||
user = registerUser,
|
||||
symbol = item.symbol,
|
||||
scrapperDomainSuffix = loginData.domainSuffix,
|
||||
unit = item.unit,
|
||||
colors = appInfo.defaultColorsForAvatar,
|
||||
)
|
||||
}
|
||||
resourceFlow {
|
||||
studentRepository.saveStudents(studentsWithSemesters)
|
||||
schoolsRepository.logSchoolLogin(loginData, studentsWithSemesters)
|
||||
}
|
||||
.logResourceStatus("registration")
|
||||
.onEach {
|
||||
when (it) {
|
||||
@ -254,11 +283,13 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
|
||||
is Resource.Success -> {
|
||||
syncManager.startOneTimeSyncWorker(quiet = true)
|
||||
view?.navigateToNext()
|
||||
logRegisterEvent(studentsWithSemesters)
|
||||
}
|
||||
|
||||
is Resource.Error -> {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
@ -281,28 +312,14 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun onEmailClick() {
|
||||
view?.openEmail(lastError?.message.ifNullOrBlank {
|
||||
loginData.baseUrl + "/" + loginData.symbol + "\n" + registerUser.symbols.filterNot {
|
||||
(it.error is AccountPermissionException || it.error is InvalidSymbolException) && it.symbol != loginData.symbol
|
||||
}.joinToString(";\n") { symbol ->
|
||||
buildString {
|
||||
append(" -")
|
||||
append(symbol.symbol)
|
||||
append("(${symbol.error?.message?.let { it.take(46) + "..." } ?: symbol.schools.size})")
|
||||
if (symbol.schools.isNotEmpty()) {
|
||||
append(": ")
|
||||
}
|
||||
append(symbol.schools.joinToString(", ") { unit ->
|
||||
buildString {
|
||||
append(unit.schoolShortName)
|
||||
append("(${unit.error?.message?.let { it.take(46) + "..." } ?: unit.students.size})")
|
||||
}
|
||||
})
|
||||
}
|
||||
} + "\nPozostałe: " + registerUser.symbols.filter {
|
||||
it.error is AccountPermissionException || it.error is InvalidSymbolException
|
||||
}.joinToString(", ") { it.symbol }
|
||||
})
|
||||
view?.openEmail(
|
||||
LoginSupportInfo(
|
||||
loginData = loginData,
|
||||
registerUser = registerUser,
|
||||
lastErrorMessage = lastError?.message,
|
||||
enteredSymbol = loginData.symbol,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun logRegisterEvent(
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
|
||||
interface LoginStudentSelectView : BaseView {
|
||||
|
||||
@ -23,5 +24,5 @@ interface LoginStudentSelectView : BaseView {
|
||||
|
||||
fun openDiscordInvite()
|
||||
|
||||
fun openEmail(lastError: String)
|
||||
fun openEmail(supportInfo: LoginSupportInfo)
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
package io.github.wulkanowy.ui.modules.login.support
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Patterns
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.databinding.DialogLoginSupportBinding
|
||||
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
|
||||
import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.openEmailClient
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class LoginSupportDialog : BaseDialogFragment<DialogLoginSupportBinding>() {
|
||||
|
||||
@Inject
|
||||
lateinit var appInfo: AppInfo
|
||||
|
||||
@Inject
|
||||
lateinit var preferencesRepository: PreferencesRepository
|
||||
|
||||
private lateinit var supportInfo: LoginSupportInfo
|
||||
|
||||
companion object {
|
||||
private const val ARGUMENT_KEY = "info"
|
||||
|
||||
fun newInstance(info: LoginSupportInfo) = LoginSupportDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to info)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_FRAME, R.style.WulkanowyTheme_NoActionBar)
|
||||
supportInfo = requireArguments().serializable(ARGUMENT_KEY)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val binding = DialogLoginSupportBinding.inflate(inflater)
|
||||
.apply { binding = this }
|
||||
binding.dialogLoginSupportToolbar.setNavigationOnClickListener { dismiss() }
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
with(binding) {
|
||||
dialogLoginSupportSchoolInput.doOnTextChanged { _, _, _, _ ->
|
||||
with(dialogLoginSupportSchoolLayout) {
|
||||
isErrorEnabled = false
|
||||
error = null
|
||||
}
|
||||
}
|
||||
dialogLoginSupportSubmit.setOnClickListener { onSubmitClick() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSubmitClick() {
|
||||
when {
|
||||
binding.dialogLoginSupportSchoolInput.text.isNullOrBlank() -> {
|
||||
with(binding.dialogLoginSupportSchoolLayout) {
|
||||
isErrorEnabled = true
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
Patterns.EMAIL_ADDRESS.matcher(
|
||||
binding.dialogLoginSupportSchoolInput.text.toString()
|
||||
).matches() -> {
|
||||
with(binding.dialogLoginSupportSchoolLayout) {
|
||||
isErrorEnabled = true
|
||||
error = getString(R.string.login_support_school_invalid)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
openEmailClientWithFilledTemplate()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openEmailClientWithFilledTemplate() {
|
||||
with(binding) {
|
||||
context?.openEmailClient(
|
||||
chooserTitle = requireContext().getString(R.string.login_email_intent_title),
|
||||
email = "wulkanowyinc@gmail.com",
|
||||
subject = requireContext().getString(R.string.login_email_subject),
|
||||
body = requireContext().getString(
|
||||
R.string.login_email_text,
|
||||
"${appInfo.systemManufacturer} ${appInfo.systemModel}",
|
||||
appInfo.systemVersion.toString(),
|
||||
"${appInfo.versionName}-${appInfo.buildFlavor}",
|
||||
supportInfo.loginData.baseUrl + "/" + supportInfo.loginData.symbol,
|
||||
preferencesRepository.installationId,
|
||||
getLastErrorFromStudentSelectScreen(),
|
||||
dialogLoginSupportSchoolInput.text.takeIf { !it.isNullOrBlank() }
|
||||
?: return@with,
|
||||
dialogLoginSupportAdditionalInput.text,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLastErrorFromStudentSelectScreen(): String {
|
||||
if (!supportInfo.lastErrorMessage.isNullOrBlank()) {
|
||||
return supportInfo.lastErrorMessage!!
|
||||
}
|
||||
if (supportInfo.registerUser?.symbols.isNullOrEmpty()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "\n" + supportInfo.registerUser?.symbols?.filterNot {
|
||||
(it.error is AccountPermissionException || it.error is InvalidSymbolException) &&
|
||||
it.symbol != supportInfo.enteredSymbol
|
||||
}?.joinToString(";\n") { symbol ->
|
||||
buildString {
|
||||
append(" -")
|
||||
append(symbol.symbol)
|
||||
append("(${symbol.error?.message?.let { it.take(46) + "..." } ?: symbol.schools.size})")
|
||||
if (symbol.schools.isNotEmpty()) {
|
||||
append(": ")
|
||||
}
|
||||
append(symbol.schools.joinToString(", ") { unit ->
|
||||
buildString {
|
||||
append(unit.schoolShortName)
|
||||
append("(${unit.error?.message?.let { it.take(46) + "..." } ?: unit.students.size})")
|
||||
}
|
||||
})
|
||||
}
|
||||
} + "\nPozostałe: " + supportInfo.registerUser?.symbols?.filter {
|
||||
it.error is AccountPermissionException || it.error is InvalidSymbolException
|
||||
}?.joinToString(", ") { it.symbol }
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.login.support
|
||||
|
||||
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import java.io.Serializable
|
||||
|
||||
data class LoginSupportInfo(
|
||||
val loginData: LoginData,
|
||||
val registerUser: RegisterUser?,
|
||||
val lastErrorMessage: String?,
|
||||
val enteredSymbol: String?,
|
||||
) : Serializable
|
@ -18,7 +18,13 @@ import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.hideSoftInput
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import io.github.wulkanowy.utils.serializable
|
||||
import io.github.wulkanowy.utils.showSoftInput
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -100,6 +106,13 @@ class LoginSymbolFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override fun setErrorSymbolDefinitelyInvalid() {
|
||||
with(binding.loginSymbolNameLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_invalid_symbol_definitely)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setErrorSymbolRequire() {
|
||||
setErrorSymbol(getString(R.string.error_field_required))
|
||||
}
|
||||
@ -163,20 +176,7 @@ class LoginSymbolFragment :
|
||||
)
|
||||
}
|
||||
|
||||
override fun openEmail(host: String, lastError: String) {
|
||||
context?.openEmailClient(
|
||||
chooserTitle = requireContext().getString(R.string.login_email_intent_title),
|
||||
email = "wulkanowyinc@gmail.com",
|
||||
subject = requireContext().getString(R.string.login_email_subject),
|
||||
body = requireContext().getString(
|
||||
R.string.login_email_text,
|
||||
"${appInfo.systemManufacturer} ${appInfo.systemModel}",
|
||||
appInfo.systemVersion.toString(),
|
||||
"${appInfo.versionName}-${appInfo.buildFlavor}",
|
||||
"$host/${binding.loginSymbolName.text}",
|
||||
preferencesRepository.installationId,
|
||||
lastError
|
||||
)
|
||||
)
|
||||
override fun openSupportDialog(supportInfo: LoginSupportInfo) {
|
||||
LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog")
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -53,6 +54,10 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
view?.setErrorSymbolRequire()
|
||||
return
|
||||
}
|
||||
if (isFormDefinitelyInvalid()) {
|
||||
view?.setErrorSymbolDefinitelyInvalid()
|
||||
return
|
||||
}
|
||||
|
||||
loginData = loginData.copy(
|
||||
symbol = view?.symbolValue?.getNormalizedSymbol(),
|
||||
@ -74,6 +79,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
|
||||
is Resource.Success -> {
|
||||
when (user.data.symbols.size) {
|
||||
0 -> {
|
||||
@ -83,6 +89,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
showContact(true)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
val enteredSymbolDetails = user.data.symbols
|
||||
.firstOrNull()
|
||||
@ -107,6 +114,7 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
"error" to "No error"
|
||||
)
|
||||
}
|
||||
|
||||
is Resource.Error -> {
|
||||
Timber.i("Login with symbol result: An exception occurred")
|
||||
analytics.logEvent(
|
||||
@ -130,17 +138,25 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
}.launch("login")
|
||||
}
|
||||
|
||||
private fun isFormDefinitelyInvalid(): Boolean {
|
||||
val definitelyInvalidSymbols = listOf("vulcan", "uonet", "wulkanowy", "standardowa")
|
||||
val normalizedSymbol = view?.symbolValue.orEmpty().getNormalizedSymbol()
|
||||
|
||||
return normalizedSymbol in definitelyInvalidSymbols
|
||||
}
|
||||
|
||||
fun onFaqClick() {
|
||||
view?.openFaqPage()
|
||||
}
|
||||
|
||||
fun onEmailClick() {
|
||||
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank {
|
||||
registerUser?.symbols?.flatMap { symbol ->
|
||||
symbol.schools.map { it.error?.message } + symbol.error?.message
|
||||
}?.filterNotNull()?.distinct()?.joinToString(";") {
|
||||
it.take(46) + "..."
|
||||
} ?: "blank"
|
||||
})
|
||||
view?.openSupportDialog(
|
||||
LoginSupportInfo(
|
||||
loginData = loginData,
|
||||
registerUser = registerUser,
|
||||
lastErrorMessage = lastError?.message,
|
||||
enteredSymbol = view?.symbolValue,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user