diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..d744bdd14
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,142 @@
+name: Test and deploy
+
+on:
+ push:
+ branches: [ develop ]
+ tags: [ '*' ]
+ pull_request:
+ branches: [ develop ]
+
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Pre-build
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ steps:
+ - uses: fkirc/skip-duplicate-actions@master
+ - uses: actions/checkout@v2
+ - uses: gradle/wrapper-validation-action@v1
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
+ - name: Build
+ run: ./gradlew --build-cache compileFdroidDebugUnitTestKotlin preFdroidDebugAndroidTestBuild dexBuilderFdroidDebugAndroidTest packageFdroidDebug packageFdroidDebugAndroidTest
+ - name: Prepare build cache
+ run: tar -cf prebuild.tar .build-cache .gradle app/build
+ - uses: actions/upload-artifact@v2
+ with:
+ name: prebuild.tar
+ path: prebuild.tar
+
+ unit-tests:
+ name: Unit tests
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ needs: [ build ]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
+ - uses: actions/download-artifact@v2
+ with:
+ name: prebuild.tar
+ - name: Extract build cache
+ run: tar -xf prebuild.tar
+ - name: Unit tests
+ run: |
+ ./gradlew --build-cache -Pcoverage testFdroidDebugUnitTest --stacktrace
+ ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace
+ - uses: codecov/codecov-action@v1
+ with:
+ flags: unit
+
+ instrumentation-tests:
+ name: Instrumentation tests
+ runs-on: macOS-latest
+ timeout-minutes: 15
+ needs: [ build ]
+ strategy:
+ fail-fast: true
+ matrix:
+ api-level: [21, 29]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
+ - uses: actions/download-artifact@v2
+ with:
+ name: prebuild.tar
+ - name: Extract build cache
+ run: tar -xf prebuild.tar
+ - name: Instrumentation tests
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: ${{ matrix.api-level }}
+ arch: x86
+ script: |
+ ./gradlew --build-cache -Pcoverage connectedFdroidDebugAndroidTest --stacktrace
+ ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace
+ - uses: codecov/codecov-action@v1
+ with:
+ flags: instrumented,api-${{ matrix.api-level }}
+
+ deploy-google-play:
+ name: Deploy to google play
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ environment: google-play
+ needs: [ build, unit-tests, instrumentation-tests ]
+ if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
+ - uses: actions/download-artifact@v2
+ with:
+ name: prebuild.tar
+ - name: Extract build cache
+ run: tar -xf prebuild.tar
+ - name: Decrypt keys
+ env:
+ ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
+ SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }}
+ run: |
+ gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg
+ gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg
+ gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg
+ - name: Upload apk to google play
+ env:
+ PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
+ PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
+ PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }}
+ PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
+ run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace;
diff --git a/.gitignore b/.gitignore
index d3fb6e4e9..5d3321e3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@ out/
# Gradle files
.gradle/
build/
+.build-cache
# Local configuration file (sdk path, etc)
local.properties
@@ -113,3 +114,6 @@ Thumbs.db
!/gradle/wrapper/gradle-wrapper.jar
.idea/jarRepositories.xml
+
+
+app/src/release/agconnect-services.json
diff --git a/.travis.yml b/.travis.yml
index 24280c5f8..04db3a616 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,8 @@ jdk: oraclejdk8
env:
global:
- - ANDROID_API_LEVEL=29
- - ANDROID_BUILD_TOOLS_VERSION=29.0.3
+ - ANDROID_API_LEVEL=30
+ - ANDROID_BUILD_TOOLS_VERSION=30.0.2
cache:
directories:
@@ -14,7 +14,7 @@ cache:
branches:
only:
- develop
- - 0.21.2
+ - 0.24.0
android:
licenses:
@@ -28,22 +28,26 @@ android:
- build-tools-$ANDROID_BUILD_TOOLS_VERSION
# The SDK version used to compile your project
- android-$ANDROID_API_LEVEL
- # Additional components
+ # Additional components
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
- addon-google_apis-google-$ANDROID_API_LEVEL
- # Android emulator
+ # Android emulator
- android-22
- sys-img-armeabi-v7a-android-22
+before_install:
+ - yes | sdkmanager "platforms;android-30"
+ - yes | sdkmanager "build-tools;30.0.2"
+
before_script:
- # Launch emulator before the execution
- - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
- - emulator -avd test -no-audio -no-window &
- - android-wait-for-emulator
- - adb shell input keyevent 82 &
- - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
+ # Launch emulator before the execution
+ - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
+ - emulator -avd test -no-audio -no-window &
+ - android-wait-for-emulator
+ - adb shell input keyevent 82 &
+ - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash"
script:
- ./gradlew dependencies --stacktrace --daemon
@@ -54,6 +58,7 @@ script:
- |
if [ $TRAVIS_TAG ]; then
gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg;
+ gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/agconnect-services.json.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg;
gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg;
./gradlew publishPlayRelease -PenableFirebase --stacktrace;
diff --git a/README.en.md b/README.en.md
index 28cce1c34..accc36082 100644
--- a/README.en.md
+++ b/README.en.md
@@ -1,7 +1,8 @@
[Polska wersja README](README.md)
# Wulkanowy
-[](https://travis-ci.com/wulkanowy/wulkanowy)
+
+[](https://github.com/wulkanowy/wulkanowy/actions)
[](https://codecov.io/gh/wulkanowy/wulkanowy)
[](https://discord.gg/vccAQBr)
[](https://f-droid.org/packages/io.github.wulkanowy/)
@@ -32,14 +33,17 @@ Unofficial android VULCAN UONET+ register client for both students and their par
## Download
-You can download the current beta version from the Google Play or the F-Droid store
+You can download the current beta version from the Google Play, F-Droid or Huawei AppGallery store
[
](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
+ alt="Get it on Google Play"
+ height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[
](https://f-droid.org/packages/io.github.wulkanowy/)
+[
](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
You can also download a [development version](https://wulkanowy.github.io/#download) that includes new features being prepared for the next release
@@ -47,7 +51,8 @@ You can also download a [development version](https://wulkanowy.github.io/#downl
* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
-* [Dagger 2](https://github.com/google/dagger)
+* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
+* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
diff --git a/README.md b/README.md
index 02e1900c8..ca3b55904 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
[English version of README](README.en.md)
# Wulkanowy
-[](https://travis-ci.com/wulkanowy/wulkanowy)
+
+[](https://github.com/wulkanowy/wulkanowy/actions)
[](https://codecov.io/gh/wulkanowy/wulkanowy)
[](https://discord.gg/vccAQBr)
[](https://f-droid.org/packages/io.github.wulkanowy/)
@@ -32,14 +33,17 @@ Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica
## Pobierz
-Aktualną wersję beta możesz pobrać ze sklepu Google Play lub F-Droid
+Aktualną wersję beta możesz pobrać ze sklepu Google Play, F-Droid lub Huawei AppGallery
[
](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
+ alt="Pobierz z Google Play"
+ height="80">](https://play.google.com/store/apps/details?id=io.github.wulkanowy)
[
](https://f-droid.org/packages/io.github.wulkanowy/)
+[
](https://appgallery.cloud.huawei.com/ag/n/app/C101440411?channelId=Badge&id=1b3f7fbb700849a9be0dba6b520b2282&s=EB1D3BF9ED9D1564D869B7B94B18016D3CABFCA5AEFB8E29F675FA04E0DC131D&detailType=0&v=)
Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#download), która zawiera nowe funkcje przygotowywane do następnego wydania
@@ -47,8 +51,9 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa
## Zbudowana za pomocą
-* [Wulkanowy SDK](https://github.com/wulkanowy/SDK)
-* [Dagger 2](https://github.com/google/dagger)
+* [Wulkanowy SDK](https://github.com/wulkanowy/sdk)
+* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
+* [Hilt](https://dagger.dev/hilt/)
* [Room](https://developer.android.com/topic/libraries/architecture/room)
* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)
diff --git a/app/build.gradle b/app/build.gradle
index 566094662..efb4fe190 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,16 +10,16 @@ apply from: 'sonarqube.gradle'
apply from: 'hooks.gradle'
android {
- compileSdkVersion 29
- buildToolsVersion '29.0.3'
+ compileSdkVersion 30
+ buildToolsVersion '30.0.2'
defaultConfig {
applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 17
- targetSdkVersion 29
- versionCode 72
- versionName "0.21.2"
+ targetSdkVersion 30
+ versionCode 79
+ versionName "0.24.1"
multiDexEnabled true
resValue "string", "app_name", "Wulkanowy"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -69,12 +69,26 @@ android {
flavorDimensions "platform"
productFlavors {
+ hms {
+ dimension "platform"
+ minSdkVersion 19
+ manifestPlaceholders = [
+ install_channel: "AppGallery"
+ ]
+ }
+
play {
dimension "platform"
+ manifestPlaceholders = [
+ install_channel: "Google Play"
+ ]
}
fdroid {
dimension "platform"
+ manifestPlaceholders = [
+ install_channel: "F-Droid"
+ ]
}
}
@@ -112,29 +126,26 @@ play {
serviceAccountCredentials = file('key.p12')
defaultToAppBundles = false
track = 'alpha'
+ updatePriority = 3
}
ext {
work_manager = "2.4.0"
- room = "2.2.5"
- chucker = "3.2.0"
- mockk = "1.10.0"
- moshi = "1.9.3"
-}
-
-configurations.all {
- resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3"
+ room = "2.2.6"
+ chucker = "3.4.0"
+ mockk = "1.10.5"
+ moshi = "1.11.0"
}
dependencies {
- implementation "io.github.wulkanowy:sdk:0.21.2"
+ implementation "io.github.wulkanowy:sdk:0.24.1"
- coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
- implementation "androidx.core:core-ktx:1.3.1"
+ implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.activity:activity-ktx:1.1.0"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.appcompat:appcompat-resources:1.2.0"
@@ -146,7 +157,7 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
- implementation "androidx.constraintlayout:constraintlayout:2.0.1"
+ implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation "com.google.android.material:material:1.2.1"
implementation "com.github.wulkanowy:material-chips-input:2.1.1"
@@ -154,7 +165,7 @@ dependencies {
implementation "me.zhanghai.android.materialprogressbar:library:1.6.1"
implementation "androidx.work:work-runtime-ktx:$work_manager"
- implementation "androidx.work:work-gcm:$work_manager"
+ playImplementation "androidx.work:work-gcm:$work_manager"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
@@ -179,25 +190,30 @@ dependencies {
implementation "fr.bipi.treessence:treessence:0.3.2"
implementation "com.mikepenz:aboutlibraries-core:$about_libraries"
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
- implementation "io.coil-kt:coil:1.0.0-rc2"
+ implementation "io.coil-kt:coil:1.1.1"
implementation "io.github.wulkanowy:AppKillerManager:3.0.0"
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
- playImplementation 'com.google.firebase:firebase-analytics:17.5.0'
- playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1'
- playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1"
- playImplementation 'com.google.firebase:firebase-messaging:20.2.4'
- playImplementation 'com.google.firebase:firebase-crashlytics:17.2.1'
+ playImplementation platform('com.google.firebase:firebase-bom:26.3.0')
+ playImplementation 'com.google.firebase:firebase-analytics-ktx'
+ playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx'
+ playImplementation "com.google.firebase:firebase-inappmessaging-ktx"
+ playImplementation 'com.google.firebase:firebase-messaging:'
+ playImplementation 'com.google.firebase:firebase-crashlytics:'
+ playImplementation 'com.google.android.play:core-ktx:1.8.1'
playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
+ hmsImplementation 'com.huawei.hms:hianalytics:5.1.0.301'
+ hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.2.301'
+
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker"
debugImplementation "com.amitshekhar.android:debug-db:1.0.6"
- testImplementation "junit:junit:4.13"
+ testImplementation "junit:junit:4.13.1"
testImplementation "io.mockk:mockk:$mockk"
- testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9'
+ testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
androidTestImplementation "androidx.test:core:1.3.0"
androidTestImplementation "androidx.test:runner:1.3.0"
@@ -208,3 +224,4 @@ dependencies {
}
apply plugin: 'com.google.gms.google-services'
+apply plugin: 'com.huawei.agconnect'
diff --git a/app/jacoco.gradle b/app/jacoco.gradle
index a5cf84e63..94469fbc0 100644
--- a/app/jacoco.gradle
+++ b/app/jacoco.gradle
@@ -7,6 +7,7 @@ jacoco {
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
+ jacoco.excludes = ['jdk.internal.*']
}
task jacocoTestReport(type: JacocoReport) {
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json
new file mode 100644
index 000000000..c7c4c0331
--- /dev/null
+++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json
@@ -0,0 +1,1842 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 28,
+ "identityHash": "3a449a55ea73fbfbb7973f1f3f834e10",
+ "entities": [
+ {
+ "tableName": "Students",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "scrapperBaseUrl",
+ "columnName": "scrapper_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mobileBaseUrl",
+ "columnName": "mobile_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginType",
+ "columnName": "login_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginMode",
+ "columnName": "login_mode",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "certificateKey",
+ "columnName": "certificate_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "privateKey",
+ "columnName": "private_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isParent",
+ "columnName": "is_parent",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "symbol",
+ "columnName": "symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "user_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentName",
+ "columnName": "student_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolSymbol",
+ "columnName": "school_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolShortName",
+ "columnName": "school_short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolName",
+ "columnName": "school_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "className",
+ "columnName": "class_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isCurrent",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "registrationDate",
+ "columnName": "registration_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Students_email_symbol_student_id_school_id_class_id",
+ "unique": true,
+ "columnNames": [
+ "email",
+ "symbol",
+ "student_id",
+ "school_id",
+ "class_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Semesters",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "current",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryName",
+ "columnName": "diary_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolYear",
+ "columnName": "school_year",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterName",
+ "columnName": "semester_name",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Semesters_student_id_diary_id_semester_id",
+ "unique": true,
+ "columnNames": [
+ "student_id",
+ "diary_id",
+ "semester_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Exams",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Timetable",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectOld",
+ "columnName": "subjectOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roomOld",
+ "columnName": "roomOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherOld",
+ "columnName": "teacherOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "info",
+ "columnName": "info",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isStudentPlan",
+ "columnName": "student_plan",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "changes",
+ "columnName": "changes",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canceled",
+ "columnName": "canceled",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Attendance",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeId",
+ "columnName": "time_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excused",
+ "columnName": "excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deleted",
+ "columnName": "deleted",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excusable",
+ "columnName": "excusable",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excuseStatus",
+ "columnName": "excuse_status",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "AttendanceSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectId",
+ "columnName": "subject_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "month",
+ "columnName": "month",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceExcused",
+ "columnName": "absence_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceForSchoolReasons",
+ "columnName": "absence_for_school_reasons",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "latenessExcused",
+ "columnName": "lateness_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Grades",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entry",
+ "columnName": "entry",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "modifier",
+ "columnName": "modifier",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "comment",
+ "columnName": "comment",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "color",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gradeSymbol",
+ "columnName": "grade_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weight",
+ "columnName": "weight",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weightValue",
+ "columnName": "weightValue",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPredictedGradeNotified",
+ "columnName": "is_predicted_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isFinalGradeNotified",
+ "columnName": "is_final_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGradeLastChange",
+ "columnName": "predicted_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGradeLastChange",
+ "columnName": "final_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGrade",
+ "columnName": "predicted_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGrade",
+ "columnName": "final_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "proposedPoints",
+ "columnName": "proposed_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalPoints",
+ "columnName": "final_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointsSum",
+ "columnName": "points_sum",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "average",
+ "columnName": "average",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "grade",
+ "columnName": "grade",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "amount",
+ "columnName": "amount",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semester",
+ "columnName": "is_semester",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesPointsStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "others",
+ "columnName": "others",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "student",
+ "columnName": "student",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Messages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unreadBy",
+ "columnName": "unread_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "readBy",
+ "columnName": "read_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sender",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "recipient",
+ "columnName": "recipient_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "folderId",
+ "columnName": "folder_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "removed",
+ "columnName": "removed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasAttachments",
+ "columnName": "has_attachments",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MessageAttachments",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))",
+ "fields": [
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "oneDriveId",
+ "columnName": "one_drive_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filename",
+ "columnName": "filename",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "real_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryType",
+ "columnName": "category_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPointsShow",
+ "columnName": "is_points_show",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "points",
+ "columnName": "points",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Homework",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isDone",
+ "columnName": "is_done",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "attachments",
+ "columnName": "attachments",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Subjects",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "LuckyNumbers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "luckyNumber",
+ "columnName": "lucky_number",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "CompletedLesson",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "substitution",
+ "columnName": "substitution",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "resources",
+ "columnName": "resources",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "ReportingUnits",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderName",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roles",
+ "columnName": "roles",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Recipients",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realName",
+ "columnName": "real_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginId",
+ "columnName": "login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "role",
+ "columnName": "role",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hash",
+ "columnName": "hash",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MobileDevices",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deviceId",
+ "columnName": "device_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Teachers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short_name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "School",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "contact",
+ "columnName": "contact",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "headmaster",
+ "columnName": "headmaster",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pedagogue",
+ "columnName": "pedagogue",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Conferences",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "agenda",
+ "columnName": "agenda",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presentOnConference",
+ "columnName": "present_on_conference",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "conferenceId",
+ "columnName": "conference_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3a449a55ea73fbfbb7973f1f3f834e10')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json
new file mode 100644
index 000000000..3e863c578
--- /dev/null
+++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json
@@ -0,0 +1,1898 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 29,
+ "identityHash": "30e4647c7dd84a6ac9b2f9f3ef7d3264",
+ "entities": [
+ {
+ "tableName": "Students",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "scrapperBaseUrl",
+ "columnName": "scrapper_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mobileBaseUrl",
+ "columnName": "mobile_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginType",
+ "columnName": "login_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginMode",
+ "columnName": "login_mode",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "certificateKey",
+ "columnName": "certificate_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "privateKey",
+ "columnName": "private_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isParent",
+ "columnName": "is_parent",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "symbol",
+ "columnName": "symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "user_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentName",
+ "columnName": "student_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolSymbol",
+ "columnName": "school_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolShortName",
+ "columnName": "school_short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolName",
+ "columnName": "school_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "className",
+ "columnName": "class_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isCurrent",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "registrationDate",
+ "columnName": "registration_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Students_email_symbol_student_id_school_id_class_id",
+ "unique": true,
+ "columnNames": [
+ "email",
+ "symbol",
+ "student_id",
+ "school_id",
+ "class_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Semesters",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "current",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryName",
+ "columnName": "diary_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolYear",
+ "columnName": "school_year",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterName",
+ "columnName": "semester_name",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Semesters_student_id_diary_id_semester_id",
+ "unique": true,
+ "columnNames": [
+ "student_id",
+ "diary_id",
+ "semester_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Exams",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Timetable",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectOld",
+ "columnName": "subjectOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roomOld",
+ "columnName": "roomOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherOld",
+ "columnName": "teacherOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "info",
+ "columnName": "info",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isStudentPlan",
+ "columnName": "student_plan",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "changes",
+ "columnName": "changes",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canceled",
+ "columnName": "canceled",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Attendance",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeId",
+ "columnName": "time_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excused",
+ "columnName": "excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deleted",
+ "columnName": "deleted",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excusable",
+ "columnName": "excusable",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excuseStatus",
+ "columnName": "excuse_status",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "AttendanceSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectId",
+ "columnName": "subject_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "month",
+ "columnName": "month",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceExcused",
+ "columnName": "absence_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceForSchoolReasons",
+ "columnName": "absence_for_school_reasons",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "latenessExcused",
+ "columnName": "lateness_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Grades",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entry",
+ "columnName": "entry",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "modifier",
+ "columnName": "modifier",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "comment",
+ "columnName": "comment",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "color",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gradeSymbol",
+ "columnName": "grade_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weight",
+ "columnName": "weight",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weightValue",
+ "columnName": "weightValue",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPredictedGradeNotified",
+ "columnName": "is_predicted_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isFinalGradeNotified",
+ "columnName": "is_final_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGradeLastChange",
+ "columnName": "predicted_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGradeLastChange",
+ "columnName": "final_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGrade",
+ "columnName": "predicted_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGrade",
+ "columnName": "final_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "proposedPoints",
+ "columnName": "proposed_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalPoints",
+ "columnName": "final_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointsSum",
+ "columnName": "points_sum",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "average",
+ "columnName": "average",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradePartialStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAverage",
+ "columnName": "class_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAverage",
+ "columnName": "student_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAmounts",
+ "columnName": "class_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAmounts",
+ "columnName": "student_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesPointsStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "others",
+ "columnName": "others",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "student",
+ "columnName": "student",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradeSemesterStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "amounts",
+ "columnName": "amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentGrade",
+ "columnName": "student_grade",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Messages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unreadBy",
+ "columnName": "unread_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "readBy",
+ "columnName": "read_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sender",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "recipient",
+ "columnName": "recipient_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "folderId",
+ "columnName": "folder_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "removed",
+ "columnName": "removed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasAttachments",
+ "columnName": "has_attachments",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MessageAttachments",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))",
+ "fields": [
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "oneDriveId",
+ "columnName": "one_drive_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filename",
+ "columnName": "filename",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "real_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryType",
+ "columnName": "category_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPointsShow",
+ "columnName": "is_points_show",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "points",
+ "columnName": "points",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Homework",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isDone",
+ "columnName": "is_done",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "attachments",
+ "columnName": "attachments",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Subjects",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "LuckyNumbers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "luckyNumber",
+ "columnName": "lucky_number",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "CompletedLesson",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "substitution",
+ "columnName": "substitution",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "resources",
+ "columnName": "resources",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "ReportingUnits",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderName",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roles",
+ "columnName": "roles",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Recipients",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realName",
+ "columnName": "real_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginId",
+ "columnName": "login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "role",
+ "columnName": "role",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hash",
+ "columnName": "hash",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MobileDevices",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deviceId",
+ "columnName": "device_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Teachers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short_name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "School",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "contact",
+ "columnName": "contact",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "headmaster",
+ "columnName": "headmaster",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pedagogue",
+ "columnName": "pedagogue",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Conferences",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "agenda",
+ "columnName": "agenda",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presentOnConference",
+ "columnName": "present_on_conference",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "conferenceId",
+ "columnName": "conference_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '30e4647c7dd84a6ac9b2f9f3ef7d3264')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json
new file mode 100644
index 000000000..309f4ac09
--- /dev/null
+++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json
@@ -0,0 +1,1954 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 30,
+ "identityHash": "891980e378373d0a17bd341f9b07cc74",
+ "entities": [
+ {
+ "tableName": "Students",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "scrapperBaseUrl",
+ "columnName": "scrapper_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mobileBaseUrl",
+ "columnName": "mobile_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginType",
+ "columnName": "login_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginMode",
+ "columnName": "login_mode",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "certificateKey",
+ "columnName": "certificate_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "privateKey",
+ "columnName": "private_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isParent",
+ "columnName": "is_parent",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "symbol",
+ "columnName": "symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "user_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentName",
+ "columnName": "student_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolSymbol",
+ "columnName": "school_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolShortName",
+ "columnName": "school_short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolName",
+ "columnName": "school_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "className",
+ "columnName": "class_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isCurrent",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "registrationDate",
+ "columnName": "registration_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Students_email_symbol_student_id_school_id_class_id",
+ "unique": true,
+ "columnNames": [
+ "email",
+ "symbol",
+ "student_id",
+ "school_id",
+ "class_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Semesters",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "current",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryName",
+ "columnName": "diary_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolYear",
+ "columnName": "school_year",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterName",
+ "columnName": "semester_name",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Semesters_student_id_diary_id_semester_id",
+ "unique": true,
+ "columnNames": [
+ "student_id",
+ "diary_id",
+ "semester_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Exams",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Timetable",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectOld",
+ "columnName": "subjectOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roomOld",
+ "columnName": "roomOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherOld",
+ "columnName": "teacherOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "info",
+ "columnName": "info",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isStudentPlan",
+ "columnName": "student_plan",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "changes",
+ "columnName": "changes",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canceled",
+ "columnName": "canceled",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Attendance",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeId",
+ "columnName": "time_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excused",
+ "columnName": "excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deleted",
+ "columnName": "deleted",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excusable",
+ "columnName": "excusable",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excuseStatus",
+ "columnName": "excuse_status",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "AttendanceSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectId",
+ "columnName": "subject_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "month",
+ "columnName": "month",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceExcused",
+ "columnName": "absence_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceForSchoolReasons",
+ "columnName": "absence_for_school_reasons",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "latenessExcused",
+ "columnName": "lateness_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Grades",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entry",
+ "columnName": "entry",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "modifier",
+ "columnName": "modifier",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "comment",
+ "columnName": "comment",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "color",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gradeSymbol",
+ "columnName": "grade_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weight",
+ "columnName": "weight",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weightValue",
+ "columnName": "weightValue",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPredictedGradeNotified",
+ "columnName": "is_predicted_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isFinalGradeNotified",
+ "columnName": "is_final_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGradeLastChange",
+ "columnName": "predicted_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGradeLastChange",
+ "columnName": "final_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGrade",
+ "columnName": "predicted_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGrade",
+ "columnName": "final_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "proposedPoints",
+ "columnName": "proposed_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalPoints",
+ "columnName": "final_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointsSum",
+ "columnName": "points_sum",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "average",
+ "columnName": "average",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradePartialStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAverage",
+ "columnName": "class_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAverage",
+ "columnName": "student_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAmounts",
+ "columnName": "class_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAmounts",
+ "columnName": "student_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesPointsStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "others",
+ "columnName": "others",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "student",
+ "columnName": "student",
+ "affinity": "REAL",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradeSemesterStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "amounts",
+ "columnName": "amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentGrade",
+ "columnName": "student_grade",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Messages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unreadBy",
+ "columnName": "unread_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "readBy",
+ "columnName": "read_by",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sender",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "recipient",
+ "columnName": "recipient_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "folderId",
+ "columnName": "folder_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "removed",
+ "columnName": "removed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasAttachments",
+ "columnName": "has_attachments",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MessageAttachments",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))",
+ "fields": [
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "oneDriveId",
+ "columnName": "one_drive_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filename",
+ "columnName": "filename",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "real_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryType",
+ "columnName": "category_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPointsShow",
+ "columnName": "is_points_show",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "points",
+ "columnName": "points",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Homework",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isDone",
+ "columnName": "is_done",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "attachments",
+ "columnName": "attachments",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Subjects",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "LuckyNumbers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "luckyNumber",
+ "columnName": "lucky_number",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "CompletedLesson",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "substitution",
+ "columnName": "substitution",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "resources",
+ "columnName": "resources",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "ReportingUnits",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderId",
+ "columnName": "sender_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "senderName",
+ "columnName": "sender_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roles",
+ "columnName": "roles",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Recipients",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realName",
+ "columnName": "real_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginId",
+ "columnName": "login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "role",
+ "columnName": "role",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hash",
+ "columnName": "hash",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MobileDevices",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deviceId",
+ "columnName": "device_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Teachers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short_name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "School",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "contact",
+ "columnName": "contact",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "headmaster",
+ "columnName": "headmaster",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pedagogue",
+ "columnName": "pedagogue",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Conferences",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "agenda",
+ "columnName": "agenda",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presentOnConference",
+ "columnName": "present_on_conference",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "conferenceId",
+ "columnName": "conference_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "TimetableAdditional",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '891980e378373d0a17bd341f9b07cc74')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt
index 611161e58..aca287322 100644
--- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt
+++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt
@@ -1,5 +1,6 @@
package io.github.wulkanowy.data.db.migrations
+import android.content.Context
import androidx.preference.PreferenceManager
import androidx.room.Room
import androidx.room.testing.MigrationTestHelper
@@ -22,10 +23,11 @@ abstract class AbstractMigrationTest {
)
fun getMigratedRoomDatabase(): AppDatabase {
+ val context = ApplicationProvider.getApplicationContext()
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
AppDatabase::class.java, dbName)
.addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager
- .getDefaultSharedPreferences(ApplicationProvider.getApplicationContext())))
+ .getDefaultSharedPreferences(context)))
)
.build()
// close the database and release any stream resources when the test finishes
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt
deleted file mode 100644
index 04d13be4b..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.github.wulkanowy.data.repositories
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import java.time.LocalDate.now
-import java.time.LocalDateTime
-
-fun getStudent(): Student {
- return Student(
- email = "test",
- password = "test123",
- schoolSymbol = "23",
- scrapperBaseUrl = "fakelog.cf",
- loginType = "AUTO",
- isCurrent = true,
- userName = "",
- studentName = "",
- schoolShortName = "",
- schoolName = "",
- studentId = 0,
- classId = 1,
- symbol = "",
- registrationDate = LocalDateTime.now(),
- className = "",
- loginMode = "API",
- certificateKey = "",
- privateKey = "",
- mobileBaseUrl = "",
- userLoginId = 0,
- isParent = false
- )
-}
-
-fun getSemester() = Semester(
- semesterId = 1,
- studentId = 1,
- classId = 1,
- diaryId = 2,
- diaryName = "",
- end = now(),
- schoolYear = 2019,
- semesterName = 1,
- start = now(),
- unitId = 1
-)
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt
deleted file mode 100644
index fa1289869..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendance
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Attendance
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDate.now
-import java.time.LocalDate.of
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class AttendanceLocalTest {
-
- private lateinit var attendanceLocal: AttendanceLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build()
- attendanceLocal = AttendanceLocal(testDb.attendanceDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- getAttendanceEntity(
- of(2018, 9, 10),
- SentExcuseStatus.ACCEPTED
- ),
- getAttendanceEntity(
- of(2018, 9, 14),
- SentExcuseStatus.WAITING
- ),
- getAttendanceEntity(
- of(2018, 9, 17),
- SentExcuseStatus.ACCEPTED
- )
- )
- runBlocking { attendanceLocal.saveAttendance(list) }
-
- val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
- val attendance = runBlocking { attendanceLocal.getAttendance(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
- assertEquals(2, attendance.size)
- assertEquals(attendance[0].date, of(2018, 9, 10))
- assertEquals(attendance[1].date, of(2018, 9, 14))
- }
-
- private fun getAttendanceEntity(
- date: LocalDate,
- excuseStatus: SentExcuseStatus
- ) = Attendance(
- studentId = 1,
- diaryId = 2,
- timeId = 3,
- date = date,
- number = 0,
- subject = "",
- name = "",
- presence = false,
- absence = false,
- exemption = false,
- lateness = false,
- excused = false,
- deleted = false,
- excusable = false,
- excuseStatus = excuseStatus.name
- )
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt
deleted file mode 100644
index ca7d0b1be..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.github.wulkanowy.data.repositories.completedlessons
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.CompletedLesson
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDate.now
-import java.time.LocalDate.of
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class CompletedLessonsLocalTest {
-
- private lateinit var completedLessonsLocal: CompletedLessonsLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room
- .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- completedLessonsLocal = CompletedLessonsLocal(testDb.completedLessonsDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- getCompletedLesson(of(2018, 9, 10), 1),
- getCompletedLesson(of(2018, 9, 14), 2),
- getCompletedLesson(of(2018, 9, 17), 3)
- )
- runBlocking { completedLessonsLocal.saveCompletedLessons(list) }
-
- val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
- val completed = runBlocking { completedLessonsLocal.getCompletedLessons(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
- assertEquals(2, completed.size)
- assertEquals(completed[0].date, of(2018, 9, 10))
- assertEquals(completed[1].date, of(2018, 9, 14))
- }
-
- private fun getCompletedLesson(date: LocalDate, number: Int): CompletedLesson {
- return CompletedLesson(1, 2, date, number, "", "", "", "", "", "", "")
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt
deleted file mode 100644
index 14b29c9f6..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package io.github.wulkanowy.data.repositories.exam
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Exam
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate.now
-import java.time.LocalDate.of
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class ExamLocalTest {
-
- private lateinit var examLocal: ExamLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build()
- examLocal = ExamLocal(testDb.examsDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- Exam(1, 2, of(2018, 9, 10), now(), "", "", "", "", "", ""),
- Exam(1, 2, of(2018, 9, 14), now(), "", "", "", "", "", ""),
- Exam(1, 2, of(2018, 9, 17), now(), "", "", "", "", "", "")
- )
- runBlocking { examLocal.saveExams(list) }
-
- val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
- val exams = runBlocking { examLocal.getExams(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
- assertEquals(2, exams.size)
- assertEquals(exams[0].date, of(2018, 9, 10))
- assertEquals(exams[1].date, of(2018, 9, 14))
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt
deleted file mode 100644
index 946ebf8ea..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.github.wulkanowy.data.repositories.grade
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDate.now
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class GradeLocalTest {
-
- private lateinit var gradeLocal: GradeLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room
- .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- createGradeLocal(5, 3.0, LocalDate.of(2018, 9, 10), "", 1),
- createGradeLocal(4, 4.0, LocalDate.of(2019, 2, 27), "", 2),
- createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2)
- )
- runBlocking { gradeLocal.saveGrades(list) }
-
- val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1)
-
- val grades = runBlocking { gradeLocal.getGradesDetails(semester).first() }
-
- assertEquals(2, grades.size)
- assertEquals(grades[0].date, LocalDate.of(2019, 2, 27))
- assertEquals(grades[1].date, LocalDate.of(2019, 2, 28))
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt
deleted file mode 100644
index 5cf9c2196..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt
+++ /dev/null
@@ -1,221 +0,0 @@
-package io.github.wulkanowy.data.repositories.grade
-
-import android.os.Build.VERSION_CODES.P
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Grade
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.mockk.MockKAnnotations
-import io.mockk.coEvery
-import io.mockk.every
-import io.mockk.impl.annotations.MockK
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate.of
-import java.time.LocalDateTime
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-
-@SdkSuppress(minSdkVersion = P)
-@RunWith(AndroidJUnit4::class)
-class GradeRepositoryTest {
-
- @MockK
- private lateinit var semesterMock: Semester
-
- private lateinit var studentMock: Student
-
- @MockK
- private lateinit var gradeRemote: GradeRemote
-
- private lateinit var gradeLocal: GradeLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun initApi() {
- MockKAnnotations.init(this)
- testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
- gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
- studentMock = getStudentMock()
-
- every { semesterMock.studentId } returns 1
- every { semesterMock.diaryId } returns 1
- every { semesterMock.schoolYear } returns 2019
- every { semesterMock.semesterId } returns 1
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun markOlderThanRegisterDateAsRead() {
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
- createGradeLocal(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
- createGradeLocal(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
- createGradeLocal(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
- createGradeLocal(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
- ) to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
- }
-
- assertFalse { grades[0].isRead }
- assertFalse { grades[1].isRead }
- assertTrue { grades[2].isRead }
- assertTrue { grades[3].isRead }
- }
-
- @Test
- fun mitigateOldGradesNotifications() {
- val list = listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Jedna ocena"),
- createGradeLocal(4, 4.0, of(2019, 2, 26), "Druga"),
- createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia")
- )
- runBlocking { gradeLocal.saveGrades(list) }
-
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
- createGradeLocal(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
- createGradeLocal(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
- createGradeLocal(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
- createGradeLocal(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
- ) to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
- }
-
- assertFalse { grades[0].isRead }
- assertFalse { grades[1].isRead }
- assertTrue { grades[2].isRead }
- assertTrue { grades[3].isRead }
- }
-
- @Test
- fun subtractLocaleDuplicateGrades() {
- val list = listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- )
- runBlocking { gradeLocal.saveGrades(list) }
-
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- ) to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!
- }
-
- assertEquals(2, grades.first.size)
- }
-
- @Test
- fun subtractRemoteDuplicateGrades() {
- val list = listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- )
- runBlocking { gradeLocal.saveGrades(list) }
-
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- ) to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!
- }
-
- assertEquals(3, grades.first.size)
- }
-
- @Test
- fun emptyLocal() {
- runBlocking { gradeLocal.saveGrades(listOf()) }
-
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- ) to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!
- }
-
- assertEquals(3, grades.first.size)
- }
-
- @Test
- fun emptyRemote() {
- val list = listOf(
- createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
- createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
- )
- runBlocking { gradeLocal.saveGrades(list) }
-
- coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (emptyList() to emptyList())
-
- val grades = runBlocking {
- GradeRepository(gradeLocal, gradeRemote)
- .getGrades(studentMock, semesterMock, true)
- .filter { it.status == Status.SUCCESS }.first().data!!
- }
-
- assertEquals(0, grades.first.size)
- }
-
- private fun getStudentMock() = Student(
- scrapperBaseUrl = "http://fakelog.cf",
- email = "jan@fakelog.cf",
- certificateKey = "",
- classId = 0,
- className = "",
- isCurrent = false,
- isParent = false,
- loginMode = Sdk.Mode.SCRAPPER.name,
- loginType = "STANDARD",
- mobileBaseUrl = "",
- password = "",
- privateKey = "",
- registrationDate = LocalDateTime.of(2019, 2, 27, 12, 0),
- schoolName = "",
- schoolShortName = "test",
- schoolSymbol = "",
- studentId = 0,
- studentName = "",
- symbol = "",
- userLoginId = 0,
- userName = ""
- )
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt
deleted file mode 100644
index 629c24321..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.github.wulkanowy.data.repositories.grade
-
-import java.time.LocalDate
-import io.github.wulkanowy.sdk.pojo.Grade as GradeRemote
-import io.github.wulkanowy.data.db.entities.Grade as GradeLocal
-
-fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal {
- return GradeLocal(
- semesterId = semesterId,
- studentId = 1,
- modifier = .0,
- teacher = "",
- subject = "",
- date = date,
- color = "",
- comment = "",
- description = desc,
- entry = "",
- gradeSymbol = "",
- value = value.toDouble(),
- weight = "",
- weightValue = weight
- )
-}
-
-fun createGradeApi(value: Int, weight: Double, date: LocalDate, desc: String): GradeRemote {
- return GradeRemote(
- subject = "",
- color = "",
- comment = "",
- date = date,
- description = desc,
- entry = "",
- modifier = .0,
- symbol = "",
- teacher = "",
- value = value.toDouble(),
- weight = weight.toString(),
- weightValue = weight
- )
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt
deleted file mode 100644
index 197d2d0ec..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package io.github.wulkanowy.data.repositories.gradestatistics
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate.now
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class GradeStatisticsLocalTest {
-
- private lateinit var gradeStatisticsLocal: GradeStatisticsLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndRead_subject() {
- val list = listOf(
- getGradeStatistics("Matematyka", 2, 1),
- getGradeStatistics("Fizyka", 1, 2)
- )
- runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
-
- val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
- assertEquals(1, stats.size)
- assertEquals(stats[0].subject, "Matematyka")
- }
-
- @Test
- fun saveAndRead_all() {
- val list = listOf(
- getGradeStatistics("Matematyka", 2, 1),
- getGradeStatistics("Chemia", 2, 1),
- getGradeStatistics("Fizyka", 1, 2)
- )
- runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
-
- val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
- assertEquals(2, stats.size)
-// assertEquals(3, stats.size)
-// assertEquals(stats[0].subject, "Wszystkie") // now in main repo
- assertEquals(stats[0].subject, "Matematyka")
- assertEquals(stats[1].subject, "Chemia")
- }
-
- @Test
- fun saveAndRead_points() {
- val list = listOf(
- getGradePointsStatistics("Matematyka", 2, 1),
- getGradePointsStatistics("Chemia", 2, 1),
- getGradePointsStatistics("Fizyka", 1, 2)
- )
- runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) }
-
- val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
- with(stats[0]) {
- assertEquals(subject, "Matematyka")
- assertEquals(others, 5.0)
- assertEquals(student, 5.0)
- }
- }
-
- @Test
- fun saveAndRead_subjectEmpty() {
- runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
-
- val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
- assertEquals(emptyList(), stats)
- }
-
- @Test
- fun saveAndRead_allEmpty() {
- runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
-
- val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
- assertEquals(emptyList(), stats)
- }
-
- private fun getSemester(): Semester {
- return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1)
- }
-
- private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics {
- return GradeStatistics(studentId, semesterId, subject, 5, 5, false)
- }
-
- private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics {
- return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0)
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt
deleted file mode 100644
index ca38b1fee..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.github.wulkanowy.data.repositories.luckynumber
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.LuckyNumber
-import io.github.wulkanowy.data.db.entities.Student
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDateTime.now
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class LuckyNumberLocalTest {
-
- private lateinit var luckyNumberLocal: LuckyNumberLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room
- .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- luckyNumberLocal = LuckyNumberLocal(testDb.luckyNumberDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val number = LuckyNumber(1, LocalDate.of(2019, 1, 20), 14)
- runBlocking { luckyNumberLocal.saveLuckyNumber(number) }
-
- val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", "", 1, false, now())
- val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() }
-
- assertEquals(1, luckyNumber?.studentId)
- assertEquals(LocalDate.of(2019, 1, 20), luckyNumber?.date)
- assertEquals(14, luckyNumber?.luckyNumber)
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt
deleted file mode 100644
index 6bd1959bd..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package io.github.wulkanowy.data.repositories.recipient
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDateTime
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class RecipientLocalTest {
-
- private lateinit var recipientLocal: RecipientLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- recipientLocal = RecipientLocal(testDb.recipientDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- Recipient(1, "2rPracownik", "Kowalski Jan", "Kowalski Jan [KJ] - Pracownik (Fake123456)", 3, 4, 2, "hash"),
- Recipient(1, "3rPracownik", "Kowalska Karolina", "Kowalska Karolina [KK] - Pracownik (Fake123456)", 4, 4, 2, "hash"),
- Recipient(1, "4rPracownik", "Krupa Stanisław", "Krupa Stanisław [KS] - Uczeń (Fake123456)", 5, 4, 1, "hash")
- )
- runBlocking { recipientLocal.saveRecipients(list) }
-
- val student = Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", "", 1, true, LocalDateTime.now())
- val recipients = runBlocking {
- recipientLocal.getRecipients(
- student = student,
- role = 2,
- unit = ReportingUnit(1, 4, "", 0, "", emptyList())
- )
- }
-
- assertEquals(2, recipients.size)
- assertEquals(1, recipients[0].studentId)
- assertEquals("3rPracownik", recipients[1].realId)
- assertEquals("Kowalski Jan", recipients[0].name)
- assertEquals("Kowalska Karolina [KK] - Pracownik (Fake123456)", recipients[1].realName)
- assertEquals(3, recipients[0].loginId)
- assertEquals(4, recipients[1].unitId)
- assertEquals(2, recipients[0].role)
- assertEquals("hash", recipients[1].hash)
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt
deleted file mode 100644
index d68f15a80..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.github.wulkanowy.data.repositories.student
-
-import android.content.Context
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.TestDispatchersProvider
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.repositories.getStudent
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class StudentLocalTest {
-
- private lateinit var studentLocal: StudentLocal
-
- private lateinit var testDb: AppDatabase
-
- private val student = getStudent()
-
- @Before
- fun createDb() {
- val context = ApplicationProvider.getApplicationContext()
- testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
- .build()
- studentLocal = StudentLocal(testDb.studentDao, TestDispatchersProvider(), context)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- runBlocking { studentLocal.saveStudents(listOf(student)) }
-
- val student = runBlocking { studentLocal.getCurrentStudent(true) }
- assertEquals("23", student?.schoolSymbol)
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt
deleted file mode 100644
index dddf6464c..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-import java.time.LocalDateTime
-import java.time.LocalDateTime.now
-import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal
-import io.github.wulkanowy.sdk.pojo.Timetable as TimetableRemote
-
-fun createTimetableLocal(start: LocalDateTime, number: Int, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableLocal {
- return TimetableLocal(
- studentId = 1,
- diaryId = 2,
- number = number,
- start = start,
- end = now(),
- date = start.toLocalDate(),
- subject = subject,
- subjectOld = "",
- group = "",
- room = room,
- roomOld = "",
- teacher = teacher,
- teacherOld = "",
- info = "",
- isStudentPlan = true,
- changes = changes,
- canceled = false
- )
-}
-
-fun createTimetableRemote(start: LocalDateTime, number: Int = 1, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableRemote {
- return TimetableRemote(
- number = number,
- start = start,
- end = start.plusMinutes(45),
- date = start.toLocalDate(),
- subject = subject,
- group = "",
- room = room,
- teacher = teacher,
- info = "",
- changes = changes,
- canceled = false,
- roomOld = "",
- subjectOld = "",
- teacherOld = "",
- studentPlan = true
- )
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt
deleted file mode 100644
index e793212e6..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDateTime.of
-import kotlin.test.assertEquals
-
-@RunWith(AndroidJUnit4::class)
-class TimetableLocalTest {
-
- private lateinit var timetableDb: TimetableLocal
-
- private lateinit var testDb: AppDatabase
-
- @Before
- fun createDb() {
- testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java)
- .build()
- timetableDb = TimetableLocal(testDb.timetableDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun saveAndReadTest() {
- val list = listOf(
- createTimetableLocal(of(2018, 9, 10, 0, 0, 0), 1),
- createTimetableLocal(of(2018, 9, 14, 0, 0, 0), 1),
- createTimetableLocal(of(2018, 9, 17, 0, 0, 0), 1)
- )
- runBlocking { timetableDb.saveTimetable(list) }
-
- val semester = Semester(1, 2, "", 1, 1, 2019, LocalDate.now(), LocalDate.now(), 1, 1)
- val exams = runBlocking {
- timetableDb.getTimetable(
- semester = semester,
- startDate = LocalDate.of(2018, 9, 10),
- endDate = LocalDate.of(2018, 9, 14)
- ).first()
- }
-
- assertEquals(2, exams.size)
- assertEquals(exams[0].date, LocalDate.of(2018, 9, 10))
- assertEquals(exams[1].date, LocalDate.of(2018, 9, 14))
- }
-}
diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt
deleted file mode 100644
index 1bd3c4679..000000000
--- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt
+++ /dev/null
@@ -1,155 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-import android.os.Build.VERSION_CODES.P
-import androidx.room.Room
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.repositories.getSemester
-import io.github.wulkanowy.data.repositories.getStudent
-import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
-import io.mockk.MockKAnnotations
-import io.mockk.coEvery
-import io.mockk.impl.annotations.MockK
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.LocalDate
-import java.time.LocalDateTime.of
-import kotlin.test.assertEquals
-
-@SdkSuppress(minSdkVersion = P)
-@RunWith(AndroidJUnit4::class)
-class TimetableRepositoryTest {
-
- @MockK(relaxed = true)
- private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper
-
- @MockK
- private lateinit var timetableRemote: TimetableRemote
-
- private lateinit var timetableLocal: TimetableLocal
-
- private lateinit var testDb: AppDatabase
-
- private val student = getStudent()
-
- private val semester = getSemester()
-
- @Before
- fun initApi() {
- MockKAnnotations.init(this)
- testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
- timetableLocal = TimetableLocal(testDb.timetableDao)
- }
-
- @After
- fun closeDb() {
- testDb.close()
- }
-
- @Test
- fun copyRoomToCompletedFromPrevious() {
- runBlocking {
- timetableLocal.saveTimetable(listOf(
- createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "123", "Przyroda"),
- createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "321", "Religia"),
- createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "213", "W-F"),
- createTimetableLocal(of(2019, 3, 5, 10, 30), 3, "213", "W-F", "Jan Kowalski")
- ))
- }
-
- coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
- createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
- createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
- createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
- createTimetableLocal(of(2019, 3, 5, 10, 30), 4, "", "W-F")
- )
-
- val lessons = runBlocking {
- TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
- student = student,
- semester = semester,
- start = LocalDate.of(2019, 3, 5),
- end = LocalDate.of(2019, 3, 5),
- forceRefresh = true
- ).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
- }
-
- assertEquals(4, lessons.size)
- assertEquals("123", lessons[0].room)
- assertEquals("321", lessons[1].room)
- assertEquals("213", lessons[2].room)
- }
-
- @Test
- fun copyTeacherToCompletedFromPrevious() {
- val list = listOf(
- createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
- createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Paweł Poniedziałkowski", false),
- createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Wtorkowska", true),
- createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
-
- createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "Joanna Wtorkowska", false),
- createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "Joanna Wtorkowska", false),
- createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "Joanna Środowska", true),
- createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "Joanna Środowska", true),
-
- createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "", false),
- createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "", false),
- createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "", true),
- createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "", true)
- )
- runBlocking { timetableLocal.saveTimetable(list) }
-
- coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
- createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
- createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
- createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
- createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
-
- createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
- createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
- createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
- createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
-
- createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
- createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
- createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
- createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
- )
-
- val lessons = runBlocking {
- TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
- student = student,
- semester = semester,
- start = LocalDate.of(2019, 12, 23),
- end = LocalDate.of(2019, 12, 25),
- forceRefresh = true
- ).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
- }
-
- assertEquals(12, lessons.size)
-
- assertEquals("Paweł Poniedziałkowski", lessons[0].teacher)
- assertEquals("Jakub Wtorkowski", lessons[1].teacher)
- assertEquals("Joanna Poniedziałkowska", lessons[2].teacher)
- assertEquals("Joanna Wtorkowska", lessons[3].teacher)
-
- assertEquals("Joanna Wtorkowska", lessons[4].teacher)
- assertEquals("", lessons[5].teacher)
- assertEquals("", lessons[6].teacher)
- assertEquals("", lessons[7].teacher)
-
- assertEquals("Paweł Środowski", lessons[8].teacher)
- assertEquals("Paweł Czwartkowski", lessons[9].teacher)
- assertEquals("Paweł Środowski", lessons[10].teacher)
- assertEquals("Paweł Czwartkowski", lessons[11].teacher)
- }
-}
diff --git a/app/src/debug/agconnect-services.json b/app/src/debug/agconnect-services.json
new file mode 100644
index 000000000..48192df01
--- /dev/null
+++ b/app/src/debug/agconnect-services.json
@@ -0,0 +1,33 @@
+{
+ "agcgw":{
+ "backurl":"connect-dre.dbankcloud.cn",
+ "url":"connect-dre.hispace.hicloud.com"
+ },
+ "client":{
+ "cp_id":"890048000024105546",
+ "product_id":"",
+ "client_id":"",
+ "client_secret":"",
+ "app_id":"101440411",
+ "package_name":"io.github.wulkanowy.dev",
+ "api_key":""
+ },
+ "service":{
+ "analytics":{
+ "collector_url":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
+ "resource_id":"p1",
+ "channel_id":""
+ },
+ "search":{
+ "url":"https://search-dre.cloud.huawei.com"
+ },
+ "cloudstorage":{
+ "storage_url":"https://ops-dre.agcstorage.link"
+ },
+ "ml":{
+ "mlservice_url":"ml-api-dre.ai.dbankcloud.com,ml-api-dre.ai.dbankcloud.cn"
+ }
+ },
+ "region":"DE",
+ "configuration_version":"1.0"
+}
diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt
similarity index 75%
rename from app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt
rename to app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt
index f23645bc3..3bf7e1693 100644
--- a/app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt
+++ b/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt
@@ -6,7 +6,7 @@ import javax.inject.Singleton
@Singleton
@Suppress("UNUSED_PARAMETER")
-class FirebaseAnalyticsHelper @Inject constructor() {
+class AnalyticsHelper @Inject constructor() {
fun logEvent(name: String, vararg params: Pair) {
// do nothing
@@ -15,4 +15,8 @@ class FirebaseAnalyticsHelper @Inject constructor() {
fun setCurrentScreen(activity: Activity, name: String?) {
// do nothing
}
+
+ fun popCurrentScreen(name: String?) {
+ // do nothing
+ }
}
diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/CrashLogUtils.kt
similarity index 71%
rename from app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt
rename to app/src/fdroid/java/io/github/wulkanowy/utils/CrashLogUtils.kt
index d03a319a2..5d58270d4 100644
--- a/app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt
+++ b/app/src/fdroid/java/io/github/wulkanowy/utils/CrashLogUtils.kt
@@ -8,6 +8,6 @@ open class TimberTreeNoOp : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {}
}
-class CrashlyticsTree : TimberTreeNoOp()
+class CrashLogTree : TimberTreeNoOp()
-class CrashlyticsExceptionTree : TimberTreeNoOp()
+class CrashLogExceptionTree : TimberTreeNoOp()
diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/UpdateHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/UpdateHelper.kt
new file mode 100644
index 000000000..3abab9629
--- /dev/null
+++ b/app/src/fdroid/java/io/github/wulkanowy/utils/UpdateHelper.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.utils
+
+import android.app.Activity
+import android.view.View
+import javax.inject.Inject
+
+@Suppress("UNUSED_PARAMETER")
+class UpdateHelper @Inject constructor() {
+
+ lateinit var messageContainer: View
+
+ fun checkAndInstallUpdates(activity: Activity) {}
+
+ fun onActivityResult(requestCode: Int, resultCode: Int) {}
+
+ fun onResume(activity: Activity) {}
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt
new file mode 100644
index 000000000..5d33825f1
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt
@@ -0,0 +1,39 @@
+package io.github.wulkanowy.utils
+
+import android.app.Activity
+import android.content.Context
+import android.os.Bundle
+import com.huawei.hms.analytics.HiAnalytics
+import dagger.hilt.android.qualifiers.ApplicationContext
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class AnalyticsHelper @Inject constructor(
+ @ApplicationContext private val context: Context
+) {
+
+ private val analytics by lazy { HiAnalytics.getInstance(context) }
+
+ fun logEvent(name: String, vararg params: Pair) {
+ Bundle().apply {
+ params.forEach {
+ if (it.second == null) return@forEach
+ when (it.second) {
+ is String, is String? -> putString(it.first, it.second as String)
+ is Int, is Int? -> putInt(it.first, it.second as Int)
+ is Boolean, is Boolean? -> putBoolean(it.first, it.second as Boolean)
+ }
+ }
+ analytics.onEvent(name, this)
+ }
+ }
+
+ fun setCurrentScreen(activity: Activity, name: String?) {
+ analytics.pageStart(name, activity::class.simpleName)
+ }
+
+ fun popCurrentScreen(name: String?) {
+ analytics.pageEnd(name)
+ }
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
new file mode 100644
index 000000000..b5fb6ad71
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
@@ -0,0 +1,53 @@
+package io.github.wulkanowy.utils
+
+import android.util.Log
+import com.huawei.agconnect.crash.AGConnectCrash
+import fr.bipi.tressence.base.FormatterPriorityTree
+import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
+import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
+import java.io.InterruptedIOException
+import java.net.SocketTimeoutException
+import java.net.UnknownHostException
+
+class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
+
+ private val connectCrash by lazy { AGConnectCrash.getInstance() }
+
+ override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+ if (skipLog(priority, tag, message, t)) return
+
+ connectCrash.log(format(priority, tag, message))
+ }
+}
+
+class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) {
+
+ private val connectCrash by lazy { AGConnectCrash.getInstance() }
+
+ override fun skipLog(priority: Int, tag: String?, message: String, t: Throwable?): Boolean {
+ return when (t) {
+ is FeatureDisabledException,
+ is FeatureNotAvailableException,
+ is UnknownHostException,
+ is SocketTimeoutException,
+ is InterruptedIOException -> true
+ else -> super.skipLog(priority, tag, message, t)
+ }
+ }
+
+ override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+ if (skipLog(priority, tag, message, t)) return
+
+ // Disabled due to a bug in the Huawei library
+
+ /*connectCrash.setCustomKey("priority", priority)
+ connectCrash.setCustomKey("tag", tag.orEmpty())
+ connectCrash.setCustomKey("message", message)
+
+ if (t != null) {
+ connectCrash.recordException(t)
+ } else {
+ connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
+ }*/
+ }
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
new file mode 100644
index 000000000..3abab9629
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/UpdateHelper.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.utils
+
+import android.app.Activity
+import android.view.View
+import javax.inject.Inject
+
+@Suppress("UNUSED_PARAMETER")
+class UpdateHelper @Inject constructor() {
+
+ lateinit var messageContainer: View
+
+ fun checkAndInstallUpdates(activity: Activity) {}
+
+ fun onActivityResult(requestCode: Int, resultCode: Int) {}
+
+ fun onResume(activity: Activity) {}
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4ec2f7816..eaef43694 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,6 +9,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
{
return arrayOf(
@@ -142,6 +154,9 @@ abstract class AppDatabase : RoomDatabase() {
Migration25(),
Migration26(),
Migration27(),
+ Migration28(),
+ Migration29(),
+ Migration30(),
)
}
@@ -171,9 +186,11 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeSummaryDao: GradeSummaryDao
- abstract val gradeStatistics: GradeStatisticsDao
+ abstract val gradePartialStatisticsDao: GradePartialStatisticsDao
- abstract val gradePointsStatistics: GradePointsStatisticsDao
+ abstract val gradePointsStatisticsDao: GradePointsStatisticsDao
+
+ abstract val gradeSemesterStatisticsDao: GradeSemesterStatisticsDao
abstract val messagesDao: MessagesDao
@@ -198,4 +215,8 @@ abstract class AppDatabase : RoomDatabase() {
abstract val teacherDao: TeacherDao
abstract val schoolDao: SchoolDao
+
+ abstract val conferenceDao: ConferenceDao
+
+ abstract val timetableAdditionalDao: TimetableAdditionalDao
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
index 4a4aaf74f..9301d5fa9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
@@ -6,7 +6,9 @@ import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
+class SharedPrefProvider @Inject constructor(
+ private val sharedPref: SharedPreferences
+) {
companion object {
const val APP_VERSION_CODE_KEY = "app_version_code"
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
index 8c03609d6..097ad7c81 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
@@ -12,5 +12,5 @@ import javax.inject.Singleton
interface CompletedLessonsDao : BaseDao {
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
+ fun loadAll(studentId: Int, diaryId: Int, from: LocalDate, end: LocalDate): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt
new file mode 100644
index 000000000..4ed9aecf5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.Conference
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface ConferenceDao : BaseDao {
+
+ @Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId")
+ fun loadAll(diaryId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt
new file mode 100644
index 000000000..bce6ce572
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface GradePartialStatisticsDao : BaseDao {
+
+ @Query("SELECT * FROM GradePartialStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt
new file mode 100644
index 000000000..09ae81714
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface GradeSemesterStatisticsDao : BaseDao {
+
+ @Query("SELECT * FROM GradeSemesterStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
deleted file mode 100644
index b462ad5db..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.wulkanowy.data.db.dao
-
-import androidx.room.Dao
-import androidx.room.Query
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Singleton
-
-@Singleton
-@Dao
-interface GradeStatisticsDao : BaseDao {
-
- @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
- fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Flow>
-
- @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
- fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Flow>
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
index 8baba2c30..081e859a5 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
@@ -8,6 +8,6 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface MobileDeviceDao : BaseDao {
- @Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
- fun loadAll(studentId: Int): Flow>
+ @Query("SELECT * FROM MobileDevices WHERE student_id = :userLoginId ORDER BY date DESC")
+ fun loadAll(userLoginId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
index 419efde0d..943f3f0cc 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
@@ -9,6 +9,6 @@ import javax.inject.Singleton
@Dao
interface RecipientDao : BaseDao {
- @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
- suspend fun load(studentId: Int, role: Int, unitId: Int): List
+ @Query("SELECT * FROM Recipients WHERE student_id = :userLoginId AND unit_id = :unitId AND role = :role")
+ suspend fun loadAll(userLoginId: Int, unitId: Int, role: Int): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt
new file mode 100644
index 000000000..335e003e1
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt
@@ -0,0 +1,16 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.TimetableAdditional
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface TimetableAdditionalDao : BaseDao {
+
+ @Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
+ fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt
new file mode 100644
index 000000000..8ddcbbb0b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt
@@ -0,0 +1,35 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.LocalDateTime
+
+@Entity(tableName = "Conferences")
+data class Conference(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "diary_id")
+ val diaryId: Int,
+
+ val title: String,
+
+ val subject: String,
+
+ val agenda: String,
+
+ @ColumnInfo(name = "present_on_conference")
+ val presentOnConference: String,
+
+ @ColumnInfo(name = "conference_id")
+ val conferenceId: Int,
+
+ val date: LocalDateTime
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt
new file mode 100644
index 000000000..db164afde
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt
@@ -0,0 +1,33 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "GradePartialStatistics")
+data class GradePartialStatistics(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "semester_id")
+ val semesterId: Int,
+
+ val subject: String,
+
+ @ColumnInfo(name = "class_average")
+ val classAverage: String,
+
+ @ColumnInfo(name = "student_average")
+ val studentAverage: String,
+
+ @ColumnInfo(name = "class_amounts")
+ val classAmounts: List,
+
+ @ColumnInfo(name = "student_amounts")
+ val studentAmounts: List
+
+) {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt
similarity index 61%
rename from app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt
rename to app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt
index 8ad8b8b8d..e747271ce 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt
@@ -4,8 +4,8 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-@Entity(tableName = "GradesStatistics")
-data class GradeStatistics(
+@Entity(tableName = "GradeSemesterStatistics")
+data class GradeSemesterStatistics(
@ColumnInfo(name = "student_id")
val studentId: Int,
@@ -15,13 +15,14 @@ data class GradeStatistics(
val subject: String,
- val grade: Int,
+ val amounts: List,
- val amount: Int,
-
- @ColumnInfo(name = "is_semester")
- val semester: Boolean
+ @ColumnInfo(name = "student_grade")
+ val studentGrade: Int
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @Transient
+ var average: String = ""
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
index 9d8f11625..83d82c0b9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
@@ -10,7 +10,7 @@ import java.time.LocalDateTime
data class MobileDevice(
@ColumnInfo(name = "student_id")
- val studentId: Int,
+ val userLoginId: Int,
@ColumnInfo(name = "device_id")
val deviceId: Int,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
index 3021da72d..b1f1f3530 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
@@ -9,7 +9,7 @@ import java.io.Serializable
data class Recipient(
@ColumnInfo(name = "student_id")
- val studentId: Int,
+ val userLoginId: Int,
@ColumnInfo(name = "real_id")
val realId: String,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
index 601d8aac7..0570a2ffd 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
@@ -12,7 +12,7 @@ data class ReportingUnit(
val studentId: Int,
@ColumnInfo(name = "real_id")
- val realId: Int,
+ val unitId: Int,
@ColumnInfo(name = "short")
val shortName: String,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt
new file mode 100644
index 000000000..c1f1365f9
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt
@@ -0,0 +1,30 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.LocalDate
+import java.time.LocalDateTime
+
+@Entity(tableName = "TimetableAdditional")
+data class TimetableAdditional(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "diary_id")
+ val diaryId: Int,
+
+ val start: LocalDateTime,
+
+ val end: LocalDateTime,
+
+ val date: LocalDate,
+
+ val subject: String,
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt
new file mode 100644
index 000000000..51e7628b5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration28 : Migration(27, 28) {
+
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("""
+ CREATE TABLE IF NOT EXISTS Conferences (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ diary_id INTEGER NOT NULL,
+ title TEXT NOT NULL,
+ subject TEXT NOT NULL,
+ agenda TEXT NOT NULL,
+ present_on_conference TEXT NOT NULL,
+ conference_id INTEGER NOT NULL,
+ date INTEGER NOT NULL
+ )
+ """)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt
new file mode 100644
index 000000000..327552d75
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt
@@ -0,0 +1,33 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration29 : Migration(28, 29) {
+
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS GradesStatistics")
+ database.execSQL("""
+ CREATE TABLE IF NOT EXISTS GradeSemesterStatistics (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ semester_id INTEGER NOT NULL,
+ subject TEXT NOT NULL,
+ amounts TEXT NOT NULL,
+ student_grade INTEGER NOT NULL
+ )
+ """)
+ database.execSQL("""
+ CREATE TABLE IF NOT EXISTS GradePartialStatistics (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ semester_id INTEGER NOT NULL,
+ subject TEXT NOT NULL,
+ class_average TEXT NOT NULL,
+ student_average TEXT NOT NULL,
+ class_amounts TEXT NOT NULL,
+ student_amounts TEXT NOT NULL
+ )
+ """)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt
new file mode 100644
index 000000000..b33914fec
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration30 : Migration(29, 30) {
+
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("""
+ CREATE TABLE TimetableAdditional (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ diary_id INTEGER NOT NULL,
+ start INTEGER NOT NULL,
+ `end` INTEGER NOT NULL,
+ date INTEGER NOT NULL,
+ subject TEXT NOT NULL
+ )
+ """)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt
similarity index 63%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt
rename to app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt
index 06f5a1e05..899ba9085 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.message
+package io.github.wulkanowy.data.enums
enum class MessageFolder(val id: Int = 1) {
RECEIVED(1),
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
similarity index 60%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt
rename to app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
index 50d6b8ed5..99878152f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.attendance
+package io.github.wulkanowy.data.enums
enum class SentExcuseStatus(val id: Int = 0) {
WAITING,
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt
new file mode 100644
index 000000000..46e67fdaa
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt
@@ -0,0 +1,43 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Attendance
+import io.github.wulkanowy.data.db.entities.AttendanceSummary
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance
+import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary
+
+fun List.mapToEntities(semester: Semester) = map {
+ Attendance(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ timeId = it.timeId,
+ number = it.number,
+ subject = it.subject,
+ name = it.name,
+ presence = it.presence,
+ absence = it.absence,
+ exemption = it.exemption,
+ lateness = it.lateness,
+ excused = it.excused,
+ deleted = it.deleted,
+ excusable = it.excusable,
+ excuseStatus = it.excuseStatus?.name
+ )
+}
+
+fun List.mapToEntities(semester: Semester, subjectId: Int) = map {
+ AttendanceSummary(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ subjectId = subjectId,
+ month = it.month,
+ presence = it.presence,
+ absence = it.absence,
+ absenceExcused = it.absenceExcused,
+ absenceForSchoolReasons = it.absenceForSchoolReasons,
+ lateness = it.lateness,
+ latenessExcused = it.latenessExcused,
+ exemption = it.exemption
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt
new file mode 100644
index 000000000..c42126eb7
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.CompletedLesson
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.CompletedLesson as SdkCompletedLesson
+
+fun List.mapToEntities(semester: Semester) = map {
+ CompletedLesson(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ number = it.number,
+ subject = it.subject,
+ topic = it.topic,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol,
+ substitution = it.substitution,
+ absence = it.absence,
+ resources = it.resources
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
new file mode 100644
index 000000000..52dc9b30b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Conference
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Conference as SdkConference
+
+fun List.mapToEntities(semester: Semester) = map {
+ Conference(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ agenda = it.agenda,
+ conferenceId = it.id,
+ date = it.date,
+ presentOnConference = it.presentOnConference,
+ subject = it.subject,
+ title = it.title
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
new file mode 100644
index 000000000..bdb5efbba
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
@@ -0,0 +1,20 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Exam
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Exam as SdkExam
+
+fun List.mapToEntities(semester: Semester) = map {
+ Exam(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ entryDate = it.entryDate,
+ subject = it.subject,
+ group = it.group,
+ type = it.type,
+ description = it.description,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt
new file mode 100644
index 000000000..178de682a
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt
@@ -0,0 +1,42 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Grade
+import io.github.wulkanowy.data.db.entities.GradeSummary
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.GradeSummary as SdkGradeSummary
+import io.github.wulkanowy.sdk.pojo.Grade as SdkGrade
+
+fun List.mapToEntities(semester: Semester) = map {
+ Grade(
+ studentId = semester.studentId,
+ semesterId = semester.semesterId,
+ subject = it.subject,
+ entry = it.entry,
+ value = it.value,
+ modifier = it.modifier,
+ comment = it.comment,
+ color = it.color,
+ gradeSymbol = it.symbol,
+ description = it.description,
+ weight = it.weight,
+ weightValue = it.weightValue,
+ date = it.date,
+ teacher = it.teacher
+ )
+}
+
+@JvmName("mapGradeSummaryToEntities")
+fun List.mapToEntities(semester: Semester) = map {
+ GradeSummary(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ position = 0,
+ subject = it.name,
+ predictedGrade = it.predicted,
+ finalGrade = it.final,
+ pointsSum = it.pointsSum,
+ proposedPoints = it.proposedPoints,
+ finalPoints = it.finalPoints,
+ average = it.average
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt
new file mode 100644
index 000000000..fbd40433c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt
@@ -0,0 +1,80 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
+import io.github.wulkanowy.data.db.entities.GradePointsStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.pojos.GradeStatisticsItem
+import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
+import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject
+import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester
+import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics
+
+@JvmName("mapToEntitiesSubject")
+fun List.mapToEntities(semester: Semester) = map {
+ GradePartialStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ classAverage = it.classAverage,
+ studentAverage = it.studentAverage,
+ classAmounts = it.classItems
+ .sortedBy { item -> item.grade }
+ .map { item -> item.amount },
+ studentAmounts = it.studentItems.map { item -> item.amount }
+ )
+}
+
+@JvmName("mapToEntitiesSemester")
+fun List.mapToEntities(semester: Semester) = map {
+ GradeSemesterStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ amounts = it.items
+ .sortedBy { item -> item.grade }
+ .map { item -> item.amount },
+ studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0
+ )
+}
+
+@JvmName("mapToEntitiesPoints")
+fun List.mapToEntities(semester: Semester) = map {
+ GradePointsStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ others = it.others,
+ student = it.student
+ )
+}
+
+fun List.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map {
+ GradeStatisticsItem(
+ type = ViewType.PARTIAL,
+ average = it.classAverage,
+ partial = it,
+ points = null,
+ semester = null
+ )
+}
+
+fun List.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map {
+ GradeStatisticsItem(
+ type = ViewType.SEMESTER,
+ partial = null,
+ points = null,
+ average = "",
+ semester = it
+ )
+}
+
+fun List.mapPointsToStatisticsItems() = map {
+ GradeStatisticsItem(
+ type = ViewType.POINTS,
+ partial = null,
+ semester = null,
+ average = "",
+ points = it
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt
new file mode 100644
index 000000000..880a26d6d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.sdk.pojo.Homework as SdkHomework
+import io.github.wulkanowy.data.db.entities.Homework
+import io.github.wulkanowy.data.db.entities.Semester
+
+fun List.mapToEntities(semester: Semester) = map {
+ Homework(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ date = it.date,
+ entryDate = it.entryDate,
+ subject = it.subject,
+ content = it.content,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol,
+ attachments = it.attachments.map { attachment ->
+ attachment.url to attachment.name
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt
new file mode 100644
index 000000000..78ebe1d6e
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.LuckyNumber
+import io.github.wulkanowy.data.db.entities.Student
+import java.time.LocalDate
+import io.github.wulkanowy.sdk.pojo.LuckyNumber as SdkLuckyNumber
+
+fun SdkLuckyNumber.mapToEntity(student: Student) = LuckyNumber(
+ studentId = student.studentId,
+ date = LocalDate.now(),
+ luckyNumber = number
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
new file mode 100644
index 000000000..2c815b305
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
@@ -0,0 +1,53 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Message
+import io.github.wulkanowy.data.db.entities.MessageAttachment
+import io.github.wulkanowy.data.db.entities.Recipient
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
+import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
+import java.time.LocalDateTime
+import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
+
+fun List.mapToEntities(student: Student) = map {
+ Message(
+ studentId = student.id.toInt(),
+ realId = it.id ?: 0,
+ messageId = it.messageId ?: 0,
+ sender = it.sender?.name.orEmpty(),
+ senderId = it.sender?.loginId ?: 0,
+ recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
+ subject = it.subject.trim(),
+ date = it.date ?: LocalDateTime.now(),
+ folderId = it.folderId,
+ unread = it.unread ?: false,
+ removed = it.removed,
+ hasAttachments = it.hasAttachments
+ ).apply {
+ content = it.content.orEmpty()
+ unreadBy = it.unreadBy ?: 0
+ readBy = it.readBy ?: 0
+ }
+}
+
+fun List.mapToEntities() = map {
+ MessageAttachment(
+ realId = it.id,
+ messageId = it.messageId,
+ oneDriveId = it.oneDriveId,
+ url = it.url,
+ filename = it.filename
+ )
+}
+
+fun List.mapFromEntities() = map {
+ SdkRecipient(
+ id = it.realId,
+ name = it.realName,
+ loginId = it.loginId,
+ reportingUnitId = it.unitId,
+ role = it.role,
+ hash = it.hash,
+ shortName = it.name
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt
new file mode 100644
index 000000000..f0c375bfa
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.MobileDevice
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.pojos.MobileDeviceToken
+import io.github.wulkanowy.sdk.pojo.Token as SdkToken
+import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
+
+fun List.mapToEntities(semester: Semester) = map {
+ MobileDevice(
+ userLoginId = semester.studentId,
+ date = it.createDate,
+ deviceId = it.id,
+ name = it.name
+ )
+}
+
+fun SdkToken.mapToMobileDeviceToken() = MobileDeviceToken(
+ token = token,
+ symbol = symbol,
+ pin = pin,
+ qr = qrCodeImage
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt
new file mode 100644
index 000000000..70941799b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt
@@ -0,0 +1,19 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Note
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Note as SdkNote
+
+fun List.mapToEntities(semester: Semester) = map {
+ Note(
+ studentId = semester.studentId,
+ date = it.date,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol,
+ category = it.category,
+ categoryType = it.categoryType.id,
+ isPointsShow = it.showPoints,
+ points = it.points,
+ content = it.content
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt
new file mode 100644
index 000000000..9996f6800
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Recipient
+import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
+
+fun List.mapToEntities(userLoginId: Int) = map {
+ Recipient(
+ userLoginId = userLoginId,
+ realId = it.id,
+ realName = it.name,
+ name = it.shortName,
+ hash = it.hash,
+ loginId = it.loginId,
+ role = it.role,
+ unitId = it.reportingUnitId ?: 0
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt
new file mode 100644
index 000000000..71ea7099d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt
@@ -0,0 +1,16 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.ReportingUnit
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit
+
+fun List.mapToEntities(student: Student) = map {
+ ReportingUnit(
+ studentId = student.studentId,
+ unitId = it.id,
+ roles = it.roles,
+ senderId = it.senderId,
+ senderName = it.senderName,
+ shortName = it.short
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt
new file mode 100644
index 000000000..dc3a5a9e9
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.School
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.School as SdkSchool
+
+fun SdkSchool.mapToEntity(semester: Semester) = School(
+ studentId = semester.studentId,
+ classId = semester.classId,
+ name = name,
+ address = address,
+ contact = contact,
+ headmaster = headmaster,
+ pedagogue = pedagogue
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt
new file mode 100644
index 000000000..4dc95aaa7
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt
@@ -0,0 +1,14 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Subject
+import io.github.wulkanowy.sdk.pojo.Subject as SdkSubject
+
+fun List.mapToEntities(semester: Semester) = map {
+ Subject(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ name = it.name,
+ realId = it.id
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt
new file mode 100644
index 000000000..49cb7c294
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Teacher
+import io.github.wulkanowy.sdk.pojo.Teacher as SdkTeacher
+
+fun List.mapToEntities(semester: Semester) = map {
+ Teacher(
+ studentId = semester.studentId,
+ name = it.name,
+ subject = it.subject,
+ shortName = it.short,
+ classId = semester.classId
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt
new file mode 100644
index 000000000..ffd2ae34e
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt
@@ -0,0 +1,41 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Timetable
+import io.github.wulkanowy.data.db.entities.TimetableAdditional
+import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetable
+import io.github.wulkanowy.sdk.pojo.TimetableAdditional as SdkTimetableAdditional
+
+fun List.mapToEntities(semester: Semester) = map {
+ Timetable(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ number = it.number,
+ start = it.start,
+ end = it.end,
+ date = it.date,
+ subject = it.subject,
+ subjectOld = it.subjectOld,
+ group = it.group,
+ room = it.room,
+ roomOld = it.roomOld,
+ teacher = it.teacher,
+ teacherOld = it.teacherOld,
+ info = it.info,
+ isStudentPlan = it.studentPlan,
+ changes = it.changes,
+ canceled = it.canceled
+ )
+}
+
+@JvmName("mapToEntitiesTimetableAdditional")
+fun List.mapToEntities(semester: Semester) = map {
+ TimetableAdditional(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ subject = it.subject,
+ date = it.date,
+ start = it.start,
+ end = it.end
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt
index 34b62abdb..88257470d 100644
--- a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt
@@ -1,14 +1,19 @@
package io.github.wulkanowy.data.pojos
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
data class GradeStatisticsItem(
val type: ViewType,
- val partial: List,
+ val average: String,
+
+ val partial: GradePartialStatistics?,
+
+ val semester: GradeSemesterStatistics?,
val points: GradePointsStatistics?
)
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
similarity index 93%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
index ff538969b..aea8632ac 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.appcreator
+package io.github.wulkanowy.data.repositories
import android.content.res.AssetManager
import com.squareup.moshi.Moshi
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
new file mode 100644
index 000000000..9a6528f39
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt
@@ -0,0 +1,57 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.AttendanceDao
+import io.github.wulkanowy.data.db.entities.Attendance
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.sdk.pojo.Absent
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.monday
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.uniqueSubtract
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.LocalTime
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class AttendanceRepository @Inject constructor(
+ private val attendanceDb: AttendanceDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "attendance"
+
+ fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
+ query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getAttendance(start.monday, end.sunday, semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ attendanceDb.deleteAll(old uniqueSubtract new)
+ attendanceDb.insertAll(new uniqueSubtract old)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
+ },
+ filterResult = { it.filter { item -> item.date in start..end } }
+ )
+
+ suspend fun excuseForAbsence(student: Student, semester: Semester, absenceList: List, reason: String? = null) {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance ->
+ Absent(
+ date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)),
+ timeId = attendance.timeId
+ )
+ }, reason)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt
new file mode 100644
index 000000000..4edb507be
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt
@@ -0,0 +1,39 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class AttendanceSummaryRepository @Inject constructor(
+ private val attendanceDb: AttendanceSummaryDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "attendance_summary"
+
+ fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
+ query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getAttendanceSummary(subjectId)
+ .mapToEntities(semester, subjectId)
+ },
+ saveFetchResult = { old, new ->
+ attendanceDb.deleteAll(old uniqueSubtract new)
+ attendanceDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt
new file mode 100644
index 000000000..59aabdd54
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt
@@ -0,0 +1,43 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.monday
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.uniqueSubtract
+import java.time.LocalDate
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class CompletedLessonsRepository @Inject constructor(
+ private val completedLessonsDb: CompletedLessonsDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "completed"
+
+ fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
+ query = { completedLessonsDb.loadAll(semester.studentId, semester.diaryId, start.monday, end.sunday) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getCompletedLessons(start.monday, end.sunday)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ completedLessonsDb.deleteAll(old uniqueSubtract new)
+ completedLessonsDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
+ },
+ filterResult = { it.filter { item -> item.date in start..end } }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt
new file mode 100644
index 000000000..befcf9e6b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt
@@ -0,0 +1,39 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.ConferenceDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ConferenceRepository @Inject constructor(
+ private val conferenceDb: ConferenceDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "conference"
+
+ fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
+ query = { conferenceDb.loadAll(semester.diaryId, student.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getConferences()
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ conferenceDb.deleteAll(old uniqueSubtract new)
+ conferenceDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
new file mode 100644
index 000000000..bd6e7d2d6
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt
@@ -0,0 +1,43 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.ExamDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.endExamsDay
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.startExamsDay
+import io.github.wulkanowy.utils.uniqueSubtract
+import java.time.LocalDate
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ExamRepository @Inject constructor(
+ private val examDb: ExamDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "exam"
+
+ fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
+ query = { examDb.loadAll(semester.diaryId, semester.studentId, start.startExamsDay, start.endExamsDay) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getExams(start.startExamsDay, start.endExamsDay, semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ examDb.deleteAll(old uniqueSubtract new)
+ examDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
+ },
+ filterResult = { it.filter { item -> item.date in start..end } }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
similarity index 54%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
index 8cbbfdfb0..bab290f32 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt
@@ -1,9 +1,16 @@
-package io.github.wulkanowy.data.repositories.grade
+package io.github.wulkanowy.data.repositories
+import io.github.wulkanowy.data.db.dao.GradeDao
+import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.networkBoundResource
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
@@ -15,24 +22,40 @@ import javax.inject.Singleton
@Singleton
class GradeRepository @Inject constructor(
- private val local: GradeLocal,
- private val remote: GradeRemote
+ private val gradeDb: GradeDao,
+ private val gradeSummaryDb: GradeSummaryDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
) {
+ private val cacheKey = "grade"
+
fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
- shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh },
- query = { local.getGradesDetails(semester).combine(local.getGradesSummary(semester)) { details, summaries -> details to summaries } },
- fetch = { remote.getGrades(student, semester) },
- saveFetchResult = { old, new ->
- refreshGradeDetails(student, old.first, new.first, notify)
- refreshGradeSummaries(old.second, new.second, notify)
+ shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
+ query = {
+ gradeDb.loadAll(semester.semesterId, semester.studentId).combine(gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)) { details, summaries ->
+ details to summaries
+ }
+ },
+ fetch = {
+ val (details, summary) = sdk.init(student)
+ .switchDiary(semester.diaryId, semester.schoolYear)
+ .getGrades(semester.semesterId)
+
+ details.mapToEntities(semester) to summary.mapToEntities(semester)
+ },
+ saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) ->
+ refreshGradeDetails(student, oldDetails, newDetails, notify)
+ refreshGradeSummaries(oldSummary, newSummary, notify)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
}
)
private suspend fun refreshGradeDetails(student: Student, oldGrades: List, newDetails: List, notify: Boolean) {
val notifyBreakDate = oldGrades.maxByOrNull { it.date }?.date ?: student.registrationDate.toLocalDate()
- local.deleteGrades(oldGrades uniqueSubtract newDetails)
- local.saveGrades((newDetails uniqueSubtract oldGrades).onEach {
+ gradeDb.deleteAll(oldGrades uniqueSubtract newDetails)
+ gradeDb.insertAll((newDetails uniqueSubtract oldGrades).onEach {
if (it.date >= notifyBreakDate) it.apply {
isRead = false
if (notify) isNotified = false
@@ -41,8 +64,8 @@ class GradeRepository @Inject constructor(
}
private suspend fun refreshGradeSummaries(oldSummaries: List, newSummary: List, notify: Boolean) {
- local.deleteGradesSummary(oldSummaries uniqueSubtract newSummary)
- local.saveGradesSummary((newSummary uniqueSubtract oldSummaries).onEach { summary ->
+ gradeSummaryDb.deleteAll(oldSummaries uniqueSubtract newSummary)
+ gradeSummaryDb.insertAll((newSummary uniqueSubtract oldSummaries).onEach { summary ->
val oldSummary = oldSummaries.find { oldSummary -> oldSummary.subject == summary.subject }
summary.isPredictedGradeNotified = when {
summary.predictedGrade.isEmpty() -> true
@@ -69,30 +92,30 @@ class GradeRepository @Inject constructor(
}
fun getUnreadGrades(semester: Semester): Flow> {
- return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isRead } }
+ return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isRead } }
}
fun getNotNotifiedGrades(semester: Semester): Flow> {
- return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }
+ return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isNotified } }
}
fun getNotNotifiedPredictedGrades(semester: Semester): Flow> {
- return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }
+ return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }
}
fun getNotNotifiedFinalGrades(semester: Semester): Flow> {
- return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }
+ return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }
}
suspend fun updateGrade(grade: Grade) {
- return local.updateGrades(listOf(grade))
+ return gradeDb.updateAll(listOf(grade))
}
suspend fun updateGrades(grades: List) {
- return local.updateGrades(grades)
+ return gradeDb.updateAll(grades)
}
suspend fun updateGradesSummary(gradesSummary: List) {
- return local.updateGradesSummary(gradesSummary)
+ return gradeSummaryDb.updateAll(gradesSummary)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt
new file mode 100644
index 000000000..ab65fb141
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt
@@ -0,0 +1,144 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
+import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
+import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapPartialToStatisticItems
+import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
+import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import java.util.Locale
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class GradeStatisticsRepository @Inject constructor(
+ private val gradePartialStatisticsDb: GradePartialStatisticsDao,
+ private val gradePointsStatisticsDb: GradePointsStatisticsDao,
+ private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val partialCacheKey = "grade_stats_partial"
+ private val semesterCacheKey = "grade_stats_semester"
+ private val pointsCacheKey = "grade_stats_points"
+
+ fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(partialCacheKey, semester)) },
+ query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getGradesPartialStatistics(semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ gradePartialStatisticsDb.deleteAll(old uniqueSubtract new)
+ gradePartialStatisticsDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(partialCacheKey, semester))
+ },
+ mapResult = { items ->
+ when (subjectName) {
+ "Wszystkie" -> {
+ val numerator = items.map {
+ it.classAverage.replace(",", ".").toDoubleOrNull() ?: .0
+ }.filterNot { it == .0 }
+ (items.reversed() + GradePartialStatistics(
+ studentId = semester.studentId,
+ semesterId = semester.semesterId,
+ subject = subjectName,
+ classAverage = if (numerator.isEmpty()) "" else numerator.average().let {
+ "%.2f".format(Locale.FRANCE, it)
+ },
+ studentAverage = "",
+ classAmounts = items.map { it.classAmounts }.sumGradeAmounts(),
+ studentAmounts = items.map { it.studentAmounts }.sumGradeAmounts()
+ )).reversed()
+ }
+ else -> items.filter { it.subject == subjectName }
+ }.mapPartialToStatisticItems()
+ }
+ )
+
+ fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(semesterCacheKey, semester)) },
+ query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getGradesSemesterStatistics(semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ gradeSemesterStatisticsDb.deleteAll(old uniqueSubtract new)
+ gradeSemesterStatisticsDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(semesterCacheKey, semester))
+ },
+ mapResult = { items ->
+ val itemsWithAverage = items.map { item ->
+ item.copy().apply {
+ val denominator = item.amounts.sum()
+ average = if (denominator == 0) "" else (item.amounts.mapIndexed { gradeValue, amount ->
+ (gradeValue + 1) * amount
+ }.sum().toDouble() / denominator).let {
+ "%.2f".format(Locale.FRANCE, it)
+ }
+ }
+ }
+ when (subjectName) {
+ "Wszystkie" -> (itemsWithAverage.reversed() + GradeSemesterStatistics(
+ studentId = semester.studentId,
+ semesterId = semester.semesterId,
+ subject = subjectName,
+ amounts = itemsWithAverage.map { it.amounts }.sumGradeAmounts(),
+ studentGrade = 0
+ ).apply {
+ average = itemsWithAverage.mapNotNull { it.average.replace(",", ".").toDoubleOrNull() }.average().let {
+ "%.2f".format(Locale.FRANCE, it)
+ }
+ }).reversed()
+ else -> itemsWithAverage.filter { it.subject == subjectName }
+ }.mapSemesterToStatisticItems()
+ }
+ )
+
+ fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(pointsCacheKey, semester)) },
+ query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getGradesPointsStatistics(semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ gradePointsStatisticsDb.deleteAll(old uniqueSubtract new)
+ gradePointsStatisticsDb.insertAll(new uniqueSubtract old)
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(pointsCacheKey, semester))
+ },
+ mapResult = { items ->
+ when (subjectName) {
+ "Wszystkie" -> items
+ else -> items.filter { it.subject == subjectName }
+ }.mapPointsToStatisticsItems()
+ }
+ )
+
+ private fun List>.sumGradeAmounts(): List {
+ val result = mutableListOf(0, 0, 0, 0, 0, 0)
+ forEach {
+ it.forEachIndexed { grade, amount ->
+ result[grade] += amount
+ }
+ }
+ return result
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt
new file mode 100644
index 000000000..7625dbbc8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt
@@ -0,0 +1,50 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.HomeworkDao
+import io.github.wulkanowy.data.db.entities.Homework
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.monday
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.uniqueSubtract
+import java.time.LocalDate
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class HomeworkRepository @Inject constructor(
+ private val homeworkDb: HomeworkDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "homework"
+
+ fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
+ query = { homeworkDb.loadAll(semester.semesterId, semester.studentId, start.monday, end.sunday) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getHomework(start.monday, end.sunday)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ homeworkDb.deleteAll(old uniqueSubtract new)
+ homeworkDb.insertAll(new uniqueSubtract old)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
+ }
+ )
+
+ suspend fun toggleDone(homework: Homework) {
+ homeworkDb.updateAll(listOf(homework.apply {
+ isDone = !isDone
+ }))
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt
similarity index 96%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt
index 85168fee5..6d509b026 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.logger
+package io.github.wulkanowy.data.repositories
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt
new file mode 100644
index 000000000..801292b42
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt
@@ -0,0 +1,41 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.LuckyNumberDao
+import io.github.wulkanowy.data.db.entities.LuckyNumber
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntity
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import java.time.LocalDate.now
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class LuckyNumberRepository @Inject constructor(
+ private val luckyNumberDb: LuckyNumberDao,
+ private val sdk: Sdk
+) {
+
+ fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
+ shouldFetch = { it == null || forceRefresh },
+ query = { luckyNumberDb.load(student.studentId, now()) },
+ 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
+ })))
+ }
+ }
+ )
+
+ suspend fun getNotNotifiedLuckyNumber(student: Student) = luckyNumberDb.load(student.studentId, now()).map {
+ if (it?.isNotified == false) it else null
+ }.first()
+
+ suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) = luckyNumberDb.updateAll(listOfNotNull(luckyNumber))
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
new file mode 100644
index 000000000..ea7b2b0e0
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
@@ -0,0 +1,102 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
+import io.github.wulkanowy.data.db.dao.MessagesDao
+import io.github.wulkanowy.data.db.entities.Message
+import io.github.wulkanowy.data.db.entities.Recipient
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.enums.MessageFolder
+import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
+import io.github.wulkanowy.data.mappers.mapFromEntities
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.sdk.pojo.Folder
+import io.github.wulkanowy.sdk.pojo.SentMessage
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import timber.log.Timber
+import java.time.LocalDateTime.now
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class MessageRepository @Inject constructor(
+ private val messagesDb: MessagesDao,
+ private val messageAttachmentDao: MessageAttachmentDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "message"
+
+ @Suppress("UNUSED_PARAMETER")
+ fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student, folder)) },
+ query = { messagesDb.loadAll(student.id.toInt(), folder.id) },
+ fetch = { sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).mapToEntities(student) },
+ saveFetchResult = { old, new ->
+ messagesDb.deleteAll(old uniqueSubtract new)
+ messagesDb.insertAll((new uniqueSubtract old).onEach {
+ it.isNotified = !notify
+ })
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder))
+ }
+ )
+
+ fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource(
+ shouldFetch = {
+ checkNotNull(it, { "This message no longer exist!" })
+ Timber.d("Message content in db empty: ${it.message.content.isEmpty()}")
+ it.message.unread || it.message.content.isEmpty()
+ },
+ query = { messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) },
+ fetch = {
+ sdk.init(student).getMessageDetails(it!!.message.messageId, message.folderId, markAsRead, message.realId).let { details ->
+ details.content to details.attachments.mapToEntities()
+ }
+ },
+ saveFetchResult = { old, (downloadedMessage, attachments) ->
+ checkNotNull(old, { "Fetched message no longer exist!" })
+ messagesDb.updateAll(listOf(old.message.copy(unread = !markAsRead).apply {
+ id = old.message.id
+ content = content.ifBlank { downloadedMessage }
+ }))
+ messageAttachmentDao.insertAttachments(attachments)
+ Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
+ }
+ )
+
+ fun getNotNotifiedMessages(student: Student): Flow> {
+ return messagesDb.loadAll(student.id.toInt(), RECEIVED.id).map { it.filter { message -> !message.isNotified && message.unread } }
+ }
+
+ suspend fun updateMessages(messages: List) {
+ return messagesDb.updateAll(messages)
+ }
+
+ suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage {
+ return sdk.init(student).sendMessage(
+ subject = subject,
+ content = content,
+ recipients = recipients.mapFromEntities()
+ )
+ }
+
+ suspend fun deleteMessage(student: Student, message: Message) {
+ val isDeleted = sdk.init(student).deleteMessages(listOf(message.messageId), message.folderId)
+
+ if (message.folderId != MessageFolder.TRASHED.id) {
+ if (isDeleted) messagesDb.updateAll(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply {
+ id = message.id
+ content = message.content
+ }))
+ } else messagesDb.deleteAll(listOf(message))
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt
new file mode 100644
index 000000000..7e83ef7d5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt
@@ -0,0 +1,56 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.MobileDeviceDao
+import io.github.wulkanowy.data.db.entities.MobileDevice
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
+import io.github.wulkanowy.data.pojos.MobileDeviceToken
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class MobileDeviceRepository @Inject constructor(
+ private val mobileDb: MobileDeviceDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "devices"
+
+ fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student)) },
+ query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getRegisteredDevices()
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ mobileDb.deleteAll(old uniqueSubtract new)
+ mobileDb.insertAll(new uniqueSubtract old)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
+ }
+ )
+
+ suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .unregisterDevice(device.deviceId)
+
+ mobileDb.deleteAll(listOf(device))
+ }
+
+ suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
+ return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getToken()
+ .mapToMobileDeviceToken()
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
new file mode 100644
index 000000000..85789f098
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt
@@ -0,0 +1,60 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.NoteDao
+import io.github.wulkanowy.data.db.entities.Note
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class NoteRepository @Inject constructor(
+ private val noteDb: NoteDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "note"
+
+ fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
+ query = { noteDb.loadAll(student.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getNotes(semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ noteDb.deleteAll(old uniqueSubtract new)
+ noteDb.insertAll((new uniqueSubtract old).onEach {
+ if (it.date >= student.registrationDate.toLocalDate()) it.apply {
+ isRead = false
+ if (notify) isNotified = false
+ }
+ })
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
+ }
+ )
+
+ fun getNotNotifiedNotes(student: Student): Flow> {
+ return noteDb.loadAll(student.studentId).map { it.filter { note -> !note.isNotified } }
+ }
+
+ suspend fun updateNote(note: Note) {
+ noteDb.updateAll(listOf(note))
+ }
+
+ suspend fun updateNotes(notes: List) {
+ noteDb.updateAll(notes)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
similarity index 98%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
index da31751a1..8cb815cc3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.preferences
+package io.github.wulkanowy.data.repositories
import android.content.Context
import android.content.SharedPreferences
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
new file mode 100644
index 000000000..24ab5f0c9
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
@@ -0,0 +1,40 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.RecipientDao
+import io.github.wulkanowy.data.db.entities.Message
+import io.github.wulkanowy.data.db.entities.Recipient
+import io.github.wulkanowy.data.db.entities.ReportingUnit
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class RecipientRepository @Inject constructor(
+ private val recipientDb: RecipientDao,
+ private val sdk: Sdk
+) {
+
+ suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) {
+ val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.senderId)
+ val old = recipientDb.loadAll(unit.senderId, unit.unitId, role)
+
+ recipientDb.deleteAll(old uniqueSubtract new)
+ recipientDb.insertAll(new uniqueSubtract old)
+ }
+
+ suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List {
+ return recipientDb.loadAll(unit.senderId, unit.unitId, role).ifEmpty {
+ refreshRecipients(student, unit, role)
+
+ recipientDb.loadAll(unit.senderId, unit.unitId, role)
+ }
+ }
+
+ suspend fun getMessageRecipients(student: Student, message: Message): List {
+ return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.userLoginId)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
similarity index 79%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
index 11eac71e0..5e1063558 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt
@@ -1,11 +1,11 @@
-package io.github.wulkanowy.data.repositories.recover
+package io.github.wulkanowy.data.repositories
import io.github.wulkanowy.sdk.Sdk
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class RecoverRemote @Inject constructor(private val sdk: Sdk) {
+class RecoverRepository @Inject constructor(private val sdk: Sdk) {
suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair {
return sdk.getPasswordResetCaptchaCode(host, symbol)
@@ -15,4 +15,3 @@ class RecoverRemote @Inject constructor(private val sdk: Sdk) {
return sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse)
}
}
-
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt
new file mode 100644
index 000000000..792e66b5e
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt
@@ -0,0 +1,42 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.ReportingUnitDao
+import io.github.wulkanowy.data.db.entities.ReportingUnit
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ReportingUnitRepository @Inject constructor(
+ private val reportingUnitDb: ReportingUnitDao,
+ private val sdk: Sdk
+) {
+
+ suspend fun refreshReportingUnits(student: Student) {
+ val new = sdk.init(student).getReportingUnits().mapToEntities(student)
+ val old = reportingUnitDb.load(student.studentId)
+
+ reportingUnitDb.deleteAll(old.uniqueSubtract(new))
+ reportingUnitDb.insertAll(new.uniqueSubtract(old))
+ }
+
+ suspend fun getReportingUnits(student: Student): List {
+ return reportingUnitDb.load(student.studentId).ifEmpty {
+ refreshReportingUnits(student)
+
+ reportingUnitDb.load(student.studentId)
+ }
+ }
+
+ suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
+ return reportingUnitDb.loadOne(student.studentId, unitId) ?: run {
+ refreshReportingUnits(student)
+
+ return reportingUnitDb.loadOne(student.studentId, unitId)
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt
new file mode 100644
index 000000000..36d5c974a
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt
@@ -0,0 +1,31 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.SchoolDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntity
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class SchoolRepository @Inject constructor(
+ private val schoolDb: SchoolDao,
+ private val sdk: Sdk
+) {
+
+ fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it == null || forceRefresh },
+ query = { schoolDb.load(semester.studentId, semester.classId) },
+ fetch = { sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).getSchool().mapToEntity(semester) },
+ saveFetchResult = { old, new ->
+ if (new != old && old != null) {
+ schoolDb.deleteAll(listOf(old))
+ schoolDb.insertAll(listOf(new))
+ }
+ schoolDb.insertAll(listOf(new))
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
similarity index 73%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt
rename to app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
index 2748f1df5..8942391c8 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt
@@ -1,10 +1,13 @@
-package io.github.wulkanowy.data.repositories.semester
+package io.github.wulkanowy.data.repositories
+import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.DispatchersProvider
import io.github.wulkanowy.utils.getCurrentOrLast
+import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.isCurrent
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.withContext
@@ -14,17 +17,17 @@ import javax.inject.Singleton
@Singleton
class SemesterRepository @Inject constructor(
- private val remote: SemesterRemote,
- private val local: SemesterLocal,
+ private val semesterDb: SemesterDao,
+ private val sdk: Sdk,
private val dispatchers: DispatchersProvider
) {
suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false) = withContext(dispatchers.backgroundThread) {
- val semesters = local.getSemesters(student)
+ val semesters = semesterDb.loadAll(student.studentId, student.classId)
if (isShouldFetch(student, semesters, forceRefresh, refreshOnNoCurrent)) {
refreshSemesters(student)
- local.getSemesters(student)
+ semesterDb.loadAll(student.studentId, student.classId)
} else semesters
}
@@ -41,12 +44,12 @@ class SemesterRepository @Inject constructor(
}
private suspend fun refreshSemesters(student: Student) {
- val new = remote.getSemesters(student)
+ val new = sdk.init(student).getSemesters().mapToEntities(student.studentId)
if (new.isEmpty()) return Timber.i("Empty semester list!")
- val old = local.getSemesters(student)
- local.deleteSemesters(old.uniqueSubtract(new))
- local.saveSemesters(new.uniqueSubtract(old))
+ val old = semesterDb.loadAll(student.studentId, student.classId)
+ semesterDb.deleteAll(old.uniqueSubtract(new))
+ semesterDb.insertSemesters(new.uniqueSubtract(old))
}
suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = withContext(dispatchers.backgroundThread) {
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
new file mode 100644
index 000000000..5b80035ba
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt
@@ -0,0 +1,85 @@
+package io.github.wulkanowy.data.repositories
+
+import android.content.Context
+import dagger.hilt.android.qualifiers.ApplicationContext
+import io.github.wulkanowy.data.db.dao.SemesterDao
+import io.github.wulkanowy.data.db.dao.StudentDao
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.db.entities.StudentWithSemesters
+import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.DispatchersProvider
+import io.github.wulkanowy.utils.security.decrypt
+import io.github.wulkanowy.utils.security.encrypt
+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
+) {
+
+ suspend fun isStudentSaved(): Boolean = getSavedStudents(false).isNotEmpty()
+
+ suspend fun isCurrentStudentSet(): Boolean = studentDb.loadCurrent()?.isCurrent ?: false
+
+ suspend fun getStudentsApi(pin: String, symbol: String, token: String): List {
+ return sdk.getStudentsFromMobileApi(token, pin, symbol, "").mapToEntities()
+ }
+
+ suspend fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): List {
+ return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).mapToEntities(password)
+ }
+
+ suspend fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): List {
+ return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).mapToEntities(password)
+ }
+
+ suspend fun getSavedStudents(decryptPass: Boolean = true) = withContext(dispatchers.backgroundThread) {
+ studentDb.loadStudentsWithSemesters().map {
+ it.apply {
+ if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) student.password = decrypt(student.password)
+ }
+ }
+ }
+
+ suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) {
+ studentDb.loadById(id)?.apply {
+ if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
+ }
+ } ?: throw NoCurrentStudentException()
+
+ suspend fun getCurrentStudent(decryptPass: Boolean = true) = withContext(dispatchers.backgroundThread) {
+ studentDb.loadCurrent()?.apply {
+ if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
+ }
+ } ?: throw NoCurrentStudentException()
+
+ suspend fun saveStudents(studentsWithSemesters: List): List {
+ semesterDb.insertSemesters(studentsWithSemesters.flatMap { it.semesters })
+
+ return withContext(dispatchers.backgroundThread) {
+ studentDb.insertAll(studentsWithSemesters.map { it.student }.map {
+ if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
+ else it
+ })
+ }
+ }
+
+ suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) {
+ with(studentDb) {
+ resetCurrent()
+ updateCurrent(studentWithSemesters.student.id)
+ }
+ }
+
+ suspend fun logoutStudent(student: Student) {
+ studentDb.delete(student)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt
new file mode 100644
index 000000000..ef07a1d47
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt
@@ -0,0 +1,32 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.SubjectDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class SubjectRepository @Inject constructor(
+ private val subjectDao: SubjectDao,
+ private val sdk: Sdk
+) {
+
+ fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh },
+ query = { subjectDao.loadAll(semester.diaryId, semester.studentId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getSubjects().mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ subjectDao.deleteAll(old uniqueSubtract new)
+ subjectDao.insertAll(new uniqueSubtract old)
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
new file mode 100644
index 000000000..25da718ca
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt
@@ -0,0 +1,33 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.TeacherDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class TeacherRepository @Inject constructor(
+ private val teacherDb: TeacherDao,
+ private val sdk: Sdk
+) {
+
+ fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
+ shouldFetch = { it.isEmpty() || forceRefresh },
+ query = { teacherDb.loadAll(semester.studentId, semester.classId) },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getTeachers(semester.semesterId)
+ .mapToEntities(semester)
+ },
+ saveFetchResult = { old, new ->
+ teacherDb.deleteAll(old uniqueSubtract new)
+ teacherDb.insertAll(new uniqueSubtract old)
+ }
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
new file mode 100644
index 000000000..fa1898f5b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt
@@ -0,0 +1,84 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
+import io.github.wulkanowy.data.db.dao.TimetableDao
+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.db.entities.TimetableAdditional
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.monday
+import io.github.wulkanowy.utils.networkBoundResource
+import io.github.wulkanowy.utils.sunday
+import io.github.wulkanowy.utils.uniqueSubtract
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import java.time.LocalDate
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class TimetableRepository @Inject constructor(
+ private val timetableDb: TimetableDao,
+ private val timetableAdditionalDb: TimetableAdditionalDao,
+ private val sdk: Sdk,
+ private val schedulerHelper: TimetableNotificationSchedulerHelper,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+
+ private val cacheKey = "timetable"
+
+ fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean, refreshAdditional: Boolean = false) = networkBoundResource(
+ shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
+ query = {
+ timetableDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
+ .map { schedulerHelper.scheduleNotifications(it, student); it }
+ .combine(timetableAdditionalDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)) { timetable, additional ->
+ timetable to additional
+ }
+ },
+ fetch = {
+ sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
+ .getTimetable(start.monday, end.sunday)
+ .let { (normal, additional) -> normal.mapToEntities(semester) to additional.mapToEntities(semester) }
+
+ },
+ saveFetchResult = { (oldTimetable, oldAdditional), (newTimetable, newAdditional) ->
+ refreshTimetable(student, oldTimetable, newTimetable)
+ refreshAdditional(oldAdditional, newAdditional)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
+ },
+ filterResult = { (timetable, additional) ->
+ timetable.filter { item ->
+ item.date in start..end
+ } to additional.filter { item ->
+ item.date in start..end
+ }
+ }
+ )
+
+ private suspend fun refreshTimetable(student: Student, old: List, new: List) {
+ timetableDb.deleteAll(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) })
+ timetableDb.insertAll(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item ->
+ item.also { new ->
+ old.singleOrNull { new.start == it.start }?.let { old ->
+ return@map new.copy(
+ room = if (new.room.isEmpty()) old.room else new.room,
+ teacher = if (new.teacher.isEmpty() && !new.changes && !old.changes) old.teacher else new.teacher
+ )
+ }
+ }
+ })
+ }
+
+ private suspend fun refreshAdditional(old: List, new: List) {
+ timetableAdditionalDb.deleteAll(old.uniqueSubtract(new))
+ timetableAdditionalDb.insertAll(new.uniqueSubtract(old))
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt
deleted file mode 100644
index 9aaa52304..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendance
-
-import io.github.wulkanowy.data.db.dao.AttendanceDao
-import io.github.wulkanowy.data.db.entities.Attendance
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) {
-
- suspend fun saveAttendance(attendance: List) {
- attendanceDb.insertAll(attendance)
- }
-
- suspend fun deleteAttendance(attendance: List) {
- attendanceDb.deleteAll(attendance)
- }
-
- fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> {
- return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt
deleted file mode 100644
index 870690ec0..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendance
-
-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.sdk.Sdk
-import io.github.wulkanowy.sdk.pojo.Absent
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.LocalTime
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getAttendance(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getAttendance(startDate, endDate, semester.semesterId)
- .map {
- Attendance(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- date = it.date,
- timeId = it.timeId,
- number = it.number,
- subject = it.subject,
- name = it.name,
- presence = it.presence,
- absence = it.absence,
- exemption = it.exemption,
- lateness = it.lateness,
- excused = it.excused,
- deleted = it.deleted,
- excusable = it.excusable,
- excuseStatus = it.excuseStatus?.name
- )
- }
- }
-
- suspend fun excuseAbsence(student: Student, semester: Semester, absenceList: List, reason: String?): Boolean {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance ->
- Absent(
- date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)),
- timeId = attendance.timeId
- )
- }, reason)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt
deleted file mode 100644
index 60f864f27..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendance
-
-import io.github.wulkanowy.data.db.entities.Attendance
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.monday
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.sunday
-import io.github.wulkanowy.utils.uniqueSubtract
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceRepository @Inject constructor(
- private val local: AttendanceLocal,
- private val remote: AttendanceRemote
-) {
-
- fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getAttendance(semester, start.monday, end.sunday) },
- fetch = { remote.getAttendance(student, semester, start.monday, end.sunday) },
- saveFetchResult = { old, new ->
- local.deleteAttendance(old uniqueSubtract new)
- local.saveAttendance(new uniqueSubtract old)
- },
- filterResult = { it.filter { item -> item.date in start..end } }
- )
-
- suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List, reason: String? = null) {
- remote.excuseAbsence(student, semester, attendanceList, reason)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt
deleted file mode 100644
index 703bc9474..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendancesummary
-
-import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
-import io.github.wulkanowy.data.db.entities.AttendanceSummary
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: AttendanceSummaryDao) {
-
- suspend fun saveAttendanceSummary(attendance: List) {
- attendanceDb.insertAll(attendance)
- }
-
- suspend fun deleteAttendanceSummary(attendance: List) {
- attendanceDb.deleteAll(attendance)
- }
-
- fun getAttendanceSummary(semester: Semester, subjectId: Int): Flow> {
- return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt
deleted file mode 100644
index 29a0b9a7b..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendancesummary
-
-import io.github.wulkanowy.data.db.entities.AttendanceSummary
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceSummaryRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getAttendanceSummary(subjectId)
- .map {
- AttendanceSummary(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- subjectId = subjectId,
- month = it.month,
- presence = it.presence,
- absence = it.absence,
- absenceExcused = it.absenceExcused,
- absenceForSchoolReasons = it.absenceForSchoolReasons,
- lateness = it.lateness,
- latenessExcused = it.latenessExcused,
- exemption = it.exemption
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt
deleted file mode 100644
index 5dbe1ab05..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.attendancesummary
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AttendanceSummaryRepository @Inject constructor(
- private val local: AttendanceSummaryLocal,
- private val remote: AttendanceSummaryRemote
-) {
-
- fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getAttendanceSummary(semester, subjectId) },
- fetch = { remote.getAttendanceSummary(student, semester, subjectId) },
- saveFetchResult = { old, new ->
- local.deleteAttendanceSummary(old uniqueSubtract new)
- local.saveAttendanceSummary(new uniqueSubtract old)
- }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt
deleted file mode 100644
index 51a1bdbfc..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.completedlessons
-
-import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
-import io.github.wulkanowy.data.db.entities.CompletedLesson
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb: CompletedLessonsDao) {
-
- suspend fun saveCompletedLessons(completedLessons: List) {
- completedLessonsDb.insertAll(completedLessons)
- }
-
- suspend fun deleteCompleteLessons(completedLessons: List) {
- completedLessonsDb.deleteAll(completedLessons)
- }
-
- fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Flow> {
- return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt
deleted file mode 100644
index d15a27623..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.github.wulkanowy.data.repositories.completedlessons
-
-import io.github.wulkanowy.data.db.entities.CompletedLesson
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CompletedLessonsRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getCompletedLessons(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getCompletedLessons(startDate, endDate)
- .map {
- it.absence
- CompletedLesson(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- date = it.date,
- number = it.number,
- subject = it.subject,
- topic = it.topic,
- teacher = it.teacher,
- teacherSymbol = it.teacherSymbol,
- substitution = it.substitution,
- absence = it.absence,
- resources = it.resources
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt
deleted file mode 100644
index 61268a66a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.data.repositories.completedlessons
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.monday
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.sunday
-import io.github.wulkanowy.utils.uniqueSubtract
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CompletedLessonsRepository @Inject constructor(
- private val local: CompletedLessonsLocal,
- private val remote: CompletedLessonsRemote
-) {
-
- fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getCompletedLessons(semester, start.monday, end.sunday) },
- fetch = { remote.getCompletedLessons(student, semester, start.monday, end.sunday) },
- saveFetchResult = { old, new ->
- local.deleteCompleteLessons(old uniqueSubtract new)
- local.saveCompletedLessons(new uniqueSubtract old)
- },
- filterResult = { it.filter { item -> item.date in start..end } }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt
deleted file mode 100644
index acc55b5ec..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.exam
-
-import io.github.wulkanowy.data.db.dao.ExamDao
-import io.github.wulkanowy.data.db.entities.Exam
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ExamLocal @Inject constructor(private val examDb: ExamDao) {
-
- fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> {
- return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
- }
-
- suspend fun saveExams(exams: List) {
- examDb.insertAll(exams)
- }
-
- suspend fun deleteExams(exams: List) {
- examDb.deleteAll(exams)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt
deleted file mode 100644
index ac4aa93d7..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.github.wulkanowy.data.repositories.exam
-
-import io.github.wulkanowy.data.db.entities.Exam
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ExamRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getExams(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getExams(startDate, endDate, semester.semesterId)
- .map {
- Exam(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- date = it.date,
- entryDate = it.entryDate,
- subject = it.subject,
- group = it.group,
- type = it.type,
- description = it.description,
- teacher = it.teacher,
- teacherSymbol = it.teacherSymbol
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt
deleted file mode 100644
index 3f4591a25..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.data.repositories.exam
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.endExamsDay
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.startExamsDay
-import io.github.wulkanowy.utils.uniqueSubtract
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ExamRepository @Inject constructor(
- private val local: ExamLocal,
- private val remote: ExamRemote
-) {
-
- fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getExams(semester, start.startExamsDay, start.endExamsDay) },
- fetch = { remote.getExams(student, semester, start.startExamsDay, start.endExamsDay) },
- saveFetchResult = { old, new ->
- local.deleteExams(old uniqueSubtract new)
- local.saveExams(new uniqueSubtract old)
- },
- filterResult = { it.filter { item -> item.date in start..end } }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt
deleted file mode 100644
index ed3635423..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package io.github.wulkanowy.data.repositories.grade
-
-import io.github.wulkanowy.data.db.dao.GradeDao
-import io.github.wulkanowy.data.db.dao.GradeSummaryDao
-import io.github.wulkanowy.data.db.entities.Grade
-import io.github.wulkanowy.data.db.entities.GradeSummary
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GradeLocal @Inject constructor(
- private val gradeDb: GradeDao,
- private val gradeSummaryDb: GradeSummaryDao
-) {
-
- suspend fun saveGrades(grades: List) {
- gradeDb.insertAll(grades)
- }
-
- suspend fun deleteGrades(grades: List) {
- gradeDb.deleteAll(grades)
- }
-
- suspend fun updateGrades(grades: List) {
- gradeDb.updateAll(grades)
- }
-
- suspend fun updateGradesSummary(gradesSummary: List) {
- gradeSummaryDb.updateAll(gradesSummary)
- }
-
- fun getGradesDetails(semester: Semester): Flow> {
- return gradeDb.loadAll(semester.semesterId, semester.studentId)
- }
-
- suspend fun saveGradesSummary(gradesSummary: List) {
- gradeSummaryDb.insertAll(gradesSummary)
- }
-
- suspend fun deleteGradesSummary(gradesSummary: List) {
- gradeSummaryDb.deleteAll(gradesSummary)
- }
-
- fun getGradesSummary(semester: Semester): Flow> {
- return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt
deleted file mode 100644
index 9534a8910..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.github.wulkanowy.data.repositories.grade
-
-import io.github.wulkanowy.data.db.entities.Grade
-import io.github.wulkanowy.data.db.entities.GradeSummary
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GradeRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getGrades(student: Student, semester: Semester): Pair, List> {
- val (details, summary) = sdk
- .init(student)
- .switchDiary(semester.diaryId, semester.schoolYear)
- .getGrades(semester.semesterId)
-
- return details.map {
- Grade(
- studentId = semester.studentId,
- semesterId = semester.semesterId,
- subject = it.subject,
- entry = it.entry,
- value = it.value,
- modifier = it.modifier,
- comment = it.comment,
- color = it.color,
- gradeSymbol = it.symbol,
- description = it.description,
- weight = it.weight,
- weightValue = it.weightValue,
- date = it.date,
- teacher = it.teacher
- )
- } to summary.map {
- GradeSummary(
- semesterId = semester.semesterId,
- studentId = semester.studentId,
- position = 0,
- subject = it.name,
- predictedGrade = it.predicted,
- finalGrade = it.final,
- pointsSum = it.pointsSum,
- proposedPoints = it.proposedPoints,
- finalPoints = it.finalPoints,
- average = it.average
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt
deleted file mode 100644
index e0e2cd4db..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.github.wulkanowy.data.repositories.gradestatistics
-
-import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
-import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
-import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GradeStatisticsLocal @Inject constructor(
- private val gradeStatisticsDb: GradeStatisticsDao,
- private val gradePointsStatisticsDb: GradePointsStatisticsDao
-) {
-
- fun getGradesStatistics(semester: Semester, isSemester: Boolean): Flow> {
- return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
- }
-
- fun getGradesPointsStatistics(semester: Semester): Flow> {
- return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId)
- }
-
- suspend fun saveGradesStatistics(gradesStatistics: List) {
- gradeStatisticsDb.insertAll(gradesStatistics)
- }
-
- suspend fun saveGradesPointsStatistics(gradePointsStatistics: List) {
- gradePointsStatisticsDb.insertAll(gradePointsStatistics)
- }
-
- suspend fun deleteGradesStatistics(gradesStatistics: List) {
- gradeStatisticsDb.deleteAll(gradesStatistics)
- }
-
- suspend fun deleteGradesPointsStatistics(gradesPointsStatistics: List) {
- gradePointsStatisticsDb.deleteAll(gradesPointsStatistics)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt
deleted file mode 100644
index 1ff8132fc..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package io.github.wulkanowy.data.repositories.gradestatistics
-
-import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getGradeStatistics(student: Student, semester: Semester, isSemester: Boolean): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).let {
- if (isSemester) it.getGradesAnnualStatistics(semester.semesterId)
- else it.getGradesPartialStatistics(semester.semesterId)
- }.map {
- GradeStatistics(
- semesterId = semester.semesterId,
- studentId = semester.studentId,
- subject = it.subject,
- grade = it.gradeValue,
- amount = it.amount,
- semester = isSemester
- )
- }
- }
-
- suspend fun getGradePointsStatistics(student: Student, semester: Semester): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getGradesPointsStatistics(semester.semesterId)
- .map {
- GradePointsStatistics(
- semesterId = semester.semesterId,
- studentId = semester.studentId,
- subject = it.subject,
- others = it.others,
- student = it.student
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt
deleted file mode 100644
index 52ca705f7..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package io.github.wulkanowy.data.repositories.gradestatistics
-
-import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.pojos.GradeStatisticsItem
-import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GradeStatisticsRepository @Inject constructor(
- private val local: GradeStatisticsLocal,
- private val remote: GradeStatisticsRemote
-) {
-
- fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getGradesStatistics(semester, isSemester) },
- fetch = { remote.getGradeStatistics(student, semester, isSemester) },
- saveFetchResult = { old, new ->
- local.deleteGradesStatistics(old uniqueSubtract new)
- local.saveGradesStatistics(new uniqueSubtract old)
- },
- mapResult = { items ->
- when (subjectName) {
- "Wszystkie" -> items.groupBy { it.grade }.map {
- GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
- it.value.fold(0) { acc, e -> acc + e.amount }, false)
- } + items
- else -> items.filter { it.subject == subjectName }
- }.mapToStatisticItems()
- }
- )
-
- fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getGradesPointsStatistics(semester) },
- fetch = { remote.getGradePointsStatistics(student, semester) },
- saveFetchResult = { old, new ->
- local.deleteGradesPointsStatistics(old uniqueSubtract new)
- local.saveGradesPointsStatistics(new uniqueSubtract old)
- },
- mapResult = { items ->
- when (subjectName) {
- "Wszystkie" -> items
- else -> items.filter { it.subject == subjectName }
- }.mapToStatisticsItem()
- }
- )
-
- private fun List.mapToStatisticItems() = groupBy { it.subject }.map {
- GradeStatisticsItem(
- type = ViewType.PARTIAL,
- partial = it.value
- .sortedByDescending { item -> item.grade }
- .filter { item -> item.amount != 0 },
- points = null
- )
- }
-
- private fun List.mapToStatisticsItem() = map {
- GradeStatisticsItem(
- type = ViewType.POINTS,
- partial = emptyList(),
- points = it
- )
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt
deleted file mode 100644
index f2cbb8031..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.data.repositories.homework
-
-import io.github.wulkanowy.data.db.dao.HomeworkDao
-import io.github.wulkanowy.data.db.entities.Homework
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
-
- suspend fun saveHomework(homework: List) {
- homeworkDb.insertAll(homework)
- }
-
- suspend fun deleteHomework(homework: List) {
- homeworkDb.deleteAll(homework)
- }
-
- suspend fun updateHomework(homework: List) {
- homeworkDb.updateAll(homework)
- }
-
- fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> {
- return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt
deleted file mode 100644
index 32109877a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.github.wulkanowy.data.repositories.homework
-
-import io.github.wulkanowy.data.db.entities.Homework
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HomeworkRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getHomework(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getHomework(startDate, endDate)
- .map {
- Homework(
- semesterId = semester.semesterId,
- studentId = semester.studentId,
- date = it.date,
- entryDate = it.entryDate,
- subject = it.subject,
- content = it.content,
- teacher = it.teacher,
- teacherSymbol = it.teacherSymbol,
- attachments = it.attachments.map { attachment -> attachment.url to attachment.name }
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt
deleted file mode 100644
index 54397ea02..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.github.wulkanowy.data.repositories.homework
-
-import io.github.wulkanowy.data.db.entities.Homework
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.monday
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.sunday
-import io.github.wulkanowy.utils.uniqueSubtract
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HomeworkRepository @Inject constructor(
- private val local: HomeworkLocal,
- private val remote: HomeworkRemote
-) {
-
- fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getHomework(semester, start.monday, end.sunday) },
- fetch = { remote.getHomework(student, semester, start.monday, end.sunday) },
- saveFetchResult = { old, new ->
- local.deleteHomework(old uniqueSubtract new)
- local.saveHomework(new uniqueSubtract old)
- }
- )
-
- suspend fun toggleDone(homework: Homework) {
- local.updateHomework(listOf(homework.apply {
- isDone = !isDone
- }))
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt
deleted file mode 100644
index 0c3156d1e..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.data.repositories.luckynumber
-
-import io.github.wulkanowy.data.db.dao.LuckyNumberDao
-import io.github.wulkanowy.data.db.entities.LuckyNumber
-import io.github.wulkanowy.data.db.entities.Student
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) {
-
- suspend fun saveLuckyNumber(luckyNumber: LuckyNumber?) {
- luckyNumberDb.insertAll(listOfNotNull(luckyNumber))
- }
-
- suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) {
- luckyNumberDb.updateAll(listOfNotNull(luckyNumber))
- }
-
- suspend fun deleteLuckyNumber(luckyNumber: LuckyNumber?) {
- luckyNumberDb.deleteAll(listOfNotNull(luckyNumber))
- }
-
- fun getLuckyNumber(student: Student, date: LocalDate): Flow {
- return luckyNumberDb.load(student.studentId, date)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt
deleted file mode 100644
index 2872957d0..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.github.wulkanowy.data.repositories.luckynumber
-
-import io.github.wulkanowy.data.db.entities.LuckyNumber
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LuckyNumberRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getLuckyNumber(student: Student): LuckyNumber? {
- return sdk.init(student).getLuckyNumber(student.schoolShortName)?.let {
- LuckyNumber(
- studentId = student.studentId,
- date = LocalDate.now(),
- luckyNumber = it
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt
deleted file mode 100644
index 173ce7e45..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.github.wulkanowy.data.repositories.luckynumber
-
-import io.github.wulkanowy.data.db.entities.LuckyNumber
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.map
-import java.time.LocalDate.now
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LuckyNumberRepository @Inject constructor(
- private val local: LuckyNumberLocal,
- private val remote: LuckyNumberRemote
-) {
-
- fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
- shouldFetch = { it == null || forceRefresh },
- query = { local.getLuckyNumber(student, now()) },
- fetch = { remote.getLuckyNumber(student) },
- saveFetchResult = { old, new ->
- if (new != old) {
- old?.let { local.deleteLuckyNumber(it) }
- local.saveLuckyNumber(new?.apply {
- if (notify) isNotified = false
- })
- }
- }
- )
-
- suspend fun getNotNotifiedLuckyNumber(student: Student) =
- local.getLuckyNumber(student, now()).map { if (it?.isNotified == false) it else null }.first()
-
- suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) = local.updateLuckyNumber(luckyNumber)
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt
deleted file mode 100644
index f1c8eaf08..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.github.wulkanowy.data.repositories.message
-
-import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
-import io.github.wulkanowy.data.db.dao.MessagesDao
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.MessageAttachment
-import io.github.wulkanowy.data.db.entities.MessageWithAttachment
-import io.github.wulkanowy.data.db.entities.Student
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageLocal @Inject constructor(
- private val messagesDb: MessagesDao,
- private val messageAttachmentDao: MessageAttachmentDao
-) {
-
- suspend fun saveMessages(messages: List) {
- messagesDb.insertAll(messages)
- }
-
- suspend fun updateMessages(messages: List) {
- messagesDb.updateAll(messages)
- }
-
- suspend fun deleteMessages(messages: List) {
- messagesDb.deleteAll(messages)
- }
-
- fun getMessageWithAttachment(student: Student, message: Message): Flow {
- return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId)
- }
-
- suspend fun saveMessageAttachments(attachments: List) {
- messageAttachmentDao.insertAttachments(attachments)
- }
-
- fun getMessages(student: Student, folder: MessageFolder): Flow> {
- return messagesDb.loadAll(student.id.toInt(), folder.id)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt
deleted file mode 100644
index 044a13a28..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package io.github.wulkanowy.data.repositories.message
-
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.MessageAttachment
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.sdk.pojo.Folder
-import io.github.wulkanowy.sdk.pojo.SentMessage
-import io.github.wulkanowy.utils.init
-import java.time.LocalDateTime.now
-import javax.inject.Inject
-import javax.inject.Singleton
-import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
-
-@Singleton
-class MessageRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder): List {
- return sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).map {
- Message(
- studentId = student.id.toInt(),
- realId = it.id ?: 0,
- messageId = it.messageId ?: 0,
- sender = it.sender?.name.orEmpty(),
- senderId = it.sender?.loginId ?: 0,
- recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
- subject = it.subject.trim(),
- date = it.date ?: now(),
- folderId = it.folderId,
- unread = it.unread ?: false,
- removed = it.removed,
- hasAttachments = it.hasAttachments
- ).apply {
- content = it.content.orEmpty()
- unreadBy = it.unreadBy ?: 0
- readBy = it.readBy ?: 0
- }
- }
- }
-
- suspend fun getMessagesContentDetails(student: Student, message: Message, markAsRead: Boolean = false): Pair> {
- return sdk.init(student).getMessageDetails(message.messageId, message.folderId, markAsRead, message.realId).let { details ->
- details.content to details.attachments.map {
- MessageAttachment(
- realId = it.id,
- messageId = it.messageId,
- oneDriveId = it.oneDriveId,
- url = it.url,
- filename = it.filename
- )
- }
- }
- }
-
- suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage {
- return sdk.init(student).sendMessage(
- subject = subject,
- content = content,
- recipients = recipients.map {
- SdkRecipient(
- id = it.realId,
- name = it.realName,
- loginId = it.loginId,
- reportingUnitId = it.unitId,
- role = it.role,
- hash = it.hash,
- shortName = it.name
- )
- }
- )
- }
-
- suspend fun deleteMessage(student: Student, message: Message): Boolean {
- return sdk.init(student).deleteMessages(listOf(message.messageId), message.folderId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt
deleted file mode 100644
index bb9326992..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.github.wulkanowy.data.repositories.message
-
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
-import io.github.wulkanowy.sdk.pojo.SentMessage
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-import timber.log.Timber
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageRepository @Inject constructor(
- private val local: MessageLocal,
- private val remote: MessageRemote
-) {
-
- fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getMessages(student, folder) },
- fetch = { remote.getMessages(student, semester, folder) },
- saveFetchResult = { old, new ->
- local.deleteMessages(old uniqueSubtract new)
- local.saveMessages((new uniqueSubtract old).onEach {
- it.isNotified = !notify
- })
- }
- )
-
- fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource(
- shouldFetch = {
- checkNotNull(it, { "This message no longer exist!" })
- Timber.d("Message content in db empty: ${it.message.content.isEmpty()}")
- it.message.unread || it.message.content.isEmpty()
- },
- query = { local.getMessageWithAttachment(student, message) },
- fetch = { remote.getMessagesContentDetails(student, it!!.message, markAsRead) },
- saveFetchResult = { old, (downloadedMessage, attachments) ->
- checkNotNull(old, { "Fetched message no longer exist!" })
- local.updateMessages(listOf(old.message.copy(unread = !markAsRead).apply {
- id = old.message.id
- content = content.ifBlank { downloadedMessage }
- }))
- local.saveMessageAttachments(attachments)
- Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
- }
- )
-
- fun getNotNotifiedMessages(student: Student): Flow> {
- return local.getMessages(student, RECEIVED).map { it.filter { message -> !message.isNotified && message.unread } }
- }
-
- suspend fun updateMessages(messages: List) {
- return local.updateMessages(messages)
- }
-
- suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage {
- return remote.sendMessage(student, subject, content, recipients)
- }
-
- suspend fun deleteMessage(student: Student, message: Message) {
- val isDeleted = remote.deleteMessage(student, message)
-
- if (message.folderId != MessageFolder.TRASHED.id) {
- if (isDeleted) local.updateMessages(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply {
- id = message.id
- content = message.content
- }))
- } else local.deleteMessages(listOf(message))
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt
deleted file mode 100644
index 0ccb3d7ef..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.wulkanowy.data.repositories.mobiledevice
-
-import io.github.wulkanowy.data.db.dao.MobileDeviceDao
-import io.github.wulkanowy.data.db.entities.MobileDevice
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDao) {
-
- suspend fun saveDevices(devices: List) {
- mobileDb.insertAll(devices)
- }
-
- suspend fun deleteDevices(devices: List) {
- mobileDb.deleteAll(devices)
- }
-
- fun getDevices(semester: Semester): Flow> {
- return mobileDb.loadAll(semester.studentId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt
deleted file mode 100644
index 907e965ce..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.github.wulkanowy.data.repositories.mobiledevice
-
-import io.github.wulkanowy.data.db.entities.MobileDevice
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.pojos.MobileDeviceToken
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MobileDeviceRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getDevices(student: Student, semester: Semester): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getRegisteredDevices()
- .map {
- MobileDevice(
- studentId = semester.studentId,
- date = it.createDate,
- deviceId = it.id,
- name = it.name
- )
- }
- }
-
- suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Boolean {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .unregisterDevice(device.deviceId)
- }
-
- suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getToken()
- .let {
- MobileDeviceToken(
- token = it.token,
- symbol = it.symbol,
- pin = it.pin,
- qr = it.qrCodeImage
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt
deleted file mode 100644
index 65526ef86..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.github.wulkanowy.data.repositories.mobiledevice
-
-import io.github.wulkanowy.data.db.entities.MobileDevice
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.pojos.MobileDeviceToken
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MobileDeviceRepository @Inject constructor(
- private val local: MobileDeviceLocal,
- private val remote: MobileDeviceRemote
-) {
-
- fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getDevices(semester) },
- fetch = { remote.getDevices(student, semester) },
- saveFetchResult = { old, new ->
- local.deleteDevices(old uniqueSubtract new)
- local.saveDevices(new uniqueSubtract old)
- }
- )
-
- suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
- remote.unregisterDevice(student, semester, device)
- local.deleteDevices(listOf(device))
- }
-
- suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
- return remote.getToken(student, semester)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt
deleted file mode 100644
index 85ba5e223..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.github.wulkanowy.data.repositories.note
-
-import io.github.wulkanowy.data.db.dao.NoteDao
-import io.github.wulkanowy.data.db.entities.Note
-import io.github.wulkanowy.data.db.entities.Student
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class NoteLocal @Inject constructor(private val noteDb: NoteDao) {
-
- suspend fun saveNotes(notes: List) {
- noteDb.insertAll(notes)
- }
-
- suspend fun updateNotes(notes: List) {
- noteDb.updateAll(notes)
- }
-
- suspend fun deleteNotes(notes: List) {
- noteDb.deleteAll(notes)
- }
-
- fun getNotes(student: Student): Flow> {
- return noteDb.loadAll(student.studentId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt
deleted file mode 100644
index 0e488b7d9..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.github.wulkanowy.data.repositories.note
-
-import io.github.wulkanowy.data.db.entities.Note
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class NoteRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getNotes(student: Student, semester: Semester): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getNotes(semester.semesterId)
- .map {
- Note(
- studentId = semester.studentId,
- date = it.date,
- teacher = it.teacher,
- teacherSymbol = it.teacherSymbol,
- category = it.category,
- categoryType = it.categoryType.id,
- isPointsShow = it.showPoints,
- points = it.points,
- content = it.content
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt
deleted file mode 100644
index 6cf62ba22..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.github.wulkanowy.data.repositories.note
-
-import io.github.wulkanowy.data.db.entities.Note
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class NoteRepository @Inject constructor(
- private val local: NoteLocal,
- private val remote: NoteRemote
-) {
-
- fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getNotes(student) },
- fetch = { remote.getNotes(student, semester) },
- saveFetchResult = { old, new ->
- local.deleteNotes(old uniqueSubtract new)
- local.saveNotes((new uniqueSubtract old).onEach {
- if (it.date >= student.registrationDate.toLocalDate()) it.apply {
- isRead = false
- if (notify) isNotified = false
- }
- })
- }
- )
-
- fun getNotNotifiedNotes(student: Student): Flow> {
- return local.getNotes(student).map { it.filter { note -> !note.isNotified } }
- }
-
- suspend fun updateNote(note: Note) {
- local.updateNotes(listOf(note))
- }
-
- suspend fun updateNotes(notes: List) {
- return local.updateNotes(notes)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt
deleted file mode 100644
index fac1645e4..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.wulkanowy.data.repositories.recipient
-
-import io.github.wulkanowy.data.db.dao.RecipientDao
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao) {
-
- suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List {
- return recipientDb.load(student.studentId, role, unit.realId)
- }
-
- suspend fun saveRecipients(recipients: List): List {
- return recipientDb.insertAll(recipients)
- }
-
- suspend fun deleteRecipients(recipients: List) {
- recipientDb.deleteAll(recipients)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt
deleted file mode 100644
index a5318e77f..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.github.wulkanowy.data.repositories.recipient
-
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
-
-@Singleton
-class RecipientRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List {
- return sdk.init(student).getRecipients(unit.realId, role)
- .map { it.toRecipient() }
- }
-
- suspend fun getMessageRecipients(student: Student, message: Message): List {
- return sdk.init(student).getMessageRecipients(message.messageId, message.senderId)
- .map { it.toRecipient() }
- }
-
- private fun SdkRecipient.toRecipient(): Recipient {
- return Recipient(
- studentId = sdk.studentId,
- realId = id,
- realName = name,
- name = shortName,
- hash = hash,
- loginId = loginId,
- role = role,
- unitId = reportingUnitId ?: 0
- )
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt
deleted file mode 100644
index f5e876b03..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.github.wulkanowy.data.repositories.recipient
-
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RecipientRepository @Inject constructor(
- private val local: RecipientLocal,
- private val remote: RecipientRemote
-) {
-
- suspend fun refreshRecipients(student: Student, role: Int, unit: ReportingUnit) {
- val new = remote.getRecipients(student, role, unit)
- val old = local.getRecipients(student, role, unit)
-
- local.deleteRecipients(old uniqueSubtract new)
- local.saveRecipients(new uniqueSubtract old)
- }
-
- suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List {
- return local.getRecipients(student, role, unit).ifEmpty {
- refreshRecipients(student, role, unit)
-
- local.getRecipients(student, role, unit)
- }
- }
-
- suspend fun getMessageRecipients(student: Student, message: Message): List {
- return remote.getMessageRecipients(student, message)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt
deleted file mode 100644
index 3117a606a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.github.wulkanowy.data.repositories.recover
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RecoverRepository @Inject constructor(private val remote: RecoverRemote) {
-
- suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair {
- return remote.getReCaptchaSiteKey(host, symbol)
- }
-
- suspend fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): String {
- return remote.sendRecoverRequest(url, symbol, email, reCaptchaResponse)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt
deleted file mode 100644
index 737f1a04f..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.wulkanowy.data.repositories.reportingunit
-
-import io.github.wulkanowy.data.db.dao.ReportingUnitDao
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) {
-
- suspend fun getReportingUnits(student: Student): List {
- return reportingUnitDb.load(student.studentId)
- }
-
- suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
- return reportingUnitDb.loadOne(student.studentId, unitId)
- }
-
- suspend fun saveReportingUnits(reportingUnits: List): List {
- return reportingUnitDb.insertAll(reportingUnits)
- }
-
- suspend fun deleteReportingUnits(reportingUnits: List) {
- reportingUnitDb.deleteAll(reportingUnits)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt
deleted file mode 100644
index 6b11c2cc9..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.reportingunit
-
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReportingUnitRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getReportingUnits(student: Student): List {
- return sdk.init(student).getReportingUnits().map { unit ->
- ReportingUnit(
- studentId = sdk.studentId,
- realId = unit.id,
- roles = unit.roles,
- senderId = unit.senderId,
- senderName = unit.senderName,
- shortName = unit.short
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt
deleted file mode 100644
index ff5839460..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.github.wulkanowy.data.repositories.reportingunit
-
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReportingUnitRepository @Inject constructor(
- private val local: ReportingUnitLocal,
- private val remote: ReportingUnitRemote
-) {
-
- suspend fun refreshReportingUnits(student: Student) {
- val new = remote.getReportingUnits(student)
- val old = local.getReportingUnits(student)
-
- local.deleteReportingUnits(old.uniqueSubtract(new))
- local.saveReportingUnits(new.uniqueSubtract(old))
- }
-
- suspend fun getReportingUnits(student: Student): List {
- return local.getReportingUnits(student).ifEmpty {
- refreshReportingUnits(student)
-
- local.getReportingUnits(student)
- }
- }
-
- suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
- return local.getReportingUnit(student, unitId) ?: run {
- refreshReportingUnits(student)
-
- return local.getReportingUnit(student, unitId)
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt
deleted file mode 100644
index bc1b2f446..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.wulkanowy.data.repositories.school
-
-import io.github.wulkanowy.data.db.dao.SchoolDao
-import io.github.wulkanowy.data.db.entities.School
-import io.github.wulkanowy.data.db.entities.Semester
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-
-class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
-
- suspend fun saveSchool(school: School) {
- schoolDb.insertAll(listOf(school))
- }
-
- suspend fun deleteSchool(school: School) {
- schoolDb.deleteAll(listOf(school))
- }
-
- fun getSchool(semester: Semester): Flow {
- return schoolDb.load(semester.studentId, semester.classId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt
deleted file mode 100644
index 4d2e0cd6c..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.wulkanowy.data.repositories.school
-
-import io.github.wulkanowy.data.db.entities.School
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-
-class SchoolRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getSchoolInfo(student: Student, semester: Semester): School {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getSchool()
- .let {
- School(
- studentId = semester.studentId,
- classId = semester.classId,
- name = it.name,
- address = it.address,
- contact = it.contact,
- headmaster = it.headmaster,
- pedagogue = it.pedagogue
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt
deleted file mode 100644
index 4c84c3194..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.wulkanowy.data.repositories.school
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SchoolRepository @Inject constructor(
- private val local: SchoolLocal,
- private val remote: SchoolRemote
-) {
-
- fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it == null || forceRefresh },
- query = { local.getSchool(semester) },
- fetch = { remote.getSchoolInfo(student, semester) },
- saveFetchResult = { old, new ->
- if (new != old && old != null) {
- local.deleteSchool(old)
- local.saveSchool(new)
- }
- local.saveSchool(new)
- }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt
deleted file mode 100644
index 8ecf1595a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.github.wulkanowy.data.repositories.semester
-
-import io.github.wulkanowy.data.db.dao.SemesterDao
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) {
-
- suspend fun saveSemesters(semesters: List) {
- semesterDb.insertSemesters(semesters)
- }
-
- suspend fun deleteSemesters(semesters: List) {
- semesterDb.deleteAll(semesters)
- }
-
- suspend fun getSemesters(student: Student): List {
- return semesterDb.loadAll(student.studentId, student.classId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt
deleted file mode 100644
index e1a920b6f..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.github.wulkanowy.data.repositories.semester
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SemesterRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getSemesters(student: Student): List {
- return sdk.init(student).getSemesters().map {
- Semester(
- studentId = student.studentId,
- diaryId = it.diaryId,
- diaryName = it.diaryName,
- schoolYear = it.schoolYear,
- semesterId = it.semesterId,
- semesterName = it.semesterNumber,
- start = it.start,
- end = it.end,
- classId = it.classId,
- unitId = it.unitId
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt
deleted file mode 100644
index c01d1d049..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.github.wulkanowy.data.repositories.student
-
-import android.content.Context
-import dagger.hilt.android.qualifiers.ApplicationContext
-import io.github.wulkanowy.data.db.dao.StudentDao
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.DispatchersProvider
-import io.github.wulkanowy.utils.security.decrypt
-import io.github.wulkanowy.utils.security.encrypt
-import kotlinx.coroutines.withContext
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class StudentLocal @Inject constructor(
- private val studentDb: StudentDao,
- private val dispatchers: DispatchersProvider,
- @ApplicationContext private val context: Context
-) {
-
- suspend fun saveStudents(students: List) = withContext(dispatchers.backgroundThread) {
- studentDb.insertAll(students.map {
- if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
- else it
- })
- }
-
- suspend fun getStudents(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
- studentDb.loadStudentsWithSemesters().map {
- it.apply {
- if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) student.password = decrypt(student.password)
- }
- }
- }
-
- suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) {
- studentDb.loadById(id)?.apply {
- if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
- }
- }
-
- suspend fun getCurrentStudent(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
- studentDb.loadCurrent()?.apply {
- if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
- }
- }
-
- suspend fun setCurrentStudent(student: Student) = withContext(dispatchers.backgroundThread) {
- studentDb.run {
- resetCurrent()
- updateCurrent(student.id)
- }
- }
-
- suspend fun logoutStudent(student: Student) = withContext(dispatchers.backgroundThread) {
- studentDb.delete(student)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt
deleted file mode 100644
index dcb126233..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.github.wulkanowy.data.repositories.student
-
-import io.github.wulkanowy.data.mappers.mapToEntities
-import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.sdk.Sdk
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class StudentRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getStudentsMobileApi(token: String, pin: String, symbol: String): List {
- return sdk.getStudentsFromMobileApi(token, pin, symbol, "").mapToEntities()
- }
-
- suspend fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): List {
- return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).mapToEntities(password)
- }
-
- suspend fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): List {
- return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).mapToEntities(password)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt
deleted file mode 100644
index 19e0e2086..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package io.github.wulkanowy.data.repositories.student
-
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
-import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.repositories.semester.SemesterLocal
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class StudentRepository @Inject constructor(
- private val local: StudentLocal,
- private val semestersLocal: SemesterLocal,
- private val remote: StudentRemote
-) {
-
- suspend fun isStudentSaved(): Boolean = local.getStudents(false).isNotEmpty()
-
- suspend fun isCurrentStudentSet(): Boolean = local.getCurrentStudent(false)?.isCurrent ?: false
-
- suspend fun getStudentsApi(pin: String, symbol: String, token: String): List {
- return remote.getStudentsMobileApi(token, pin, symbol)
- }
-
- suspend fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String): List {
- return remote.getStudentsScrapper(email, password, endpoint, symbol)
- }
-
- suspend fun getStudentsHybrid(email: String, password: String, endpoint: String, symbol: String): List {
- return remote.getStudentsHybrid(email, password, endpoint, symbol)
- }
-
- suspend fun getSavedStudents(decryptPass: Boolean = true): List {
- return local.getStudents(decryptPass)
- }
-
- suspend fun getStudentById(id: Int): Student {
- return local.getStudentById(id) ?: throw NoCurrentStudentException()
- }
-
- suspend fun getCurrentStudent(decryptPass: Boolean = true): Student {
- return local.getCurrentStudent(decryptPass) ?: throw NoCurrentStudentException()
- }
-
- suspend fun saveStudents(studentsWithSemesters: List): List {
- semestersLocal.saveSemesters(studentsWithSemesters.flatMap { it.semesters })
- return local.saveStudents(studentsWithSemesters.map { it.student })
- }
-
- suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) {
- return local.setCurrentStudent(studentWithSemesters.student)
- }
-
- suspend fun logoutStudent(student: Student) {
- return local.logoutStudent(student)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt
deleted file mode 100644
index e225a381e..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.github.wulkanowy.data.repositories.subject
-
-import io.github.wulkanowy.data.db.dao.SubjectDao
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Subject
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SubjectLocal @Inject constructor(private val subjectDao: SubjectDao) {
-
- fun getSubjects(semester: Semester): Flow> {
- return subjectDao.loadAll(semester.diaryId, semester.studentId)
- }
-
- suspend fun saveSubjects(subjects: List) {
- subjectDao.insertAll(subjects)
- }
-
- suspend fun deleteSubjects(subjects: List) {
- subjectDao.deleteAll(subjects)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt
deleted file mode 100644
index 624a5a00a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.github.wulkanowy.data.repositories.subject
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.Subject
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SubjectRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getSubjects(student: Student, semester: Semester): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getSubjects()
- .map {
- Subject(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- name = it.name,
- realId = it.id
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt
deleted file mode 100644
index 60a0c3e71..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.subject
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SubjectRepository @Inject constructor(
- private val local: SubjectLocal,
- private val remote: SubjectRemote
-) {
-
- fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getSubjects(semester) },
- fetch = { remote.getSubjects(student, semester) },
- saveFetchResult = { old, new ->
- local.deleteSubjects(old uniqueSubtract new)
- local.saveSubjects(new uniqueSubtract old)
- }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt
deleted file mode 100644
index 908f45a1a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.github.wulkanowy.data.repositories.teacher
-
-import io.github.wulkanowy.data.db.dao.TeacherDao
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Teacher
-import kotlinx.coroutines.flow.Flow
-import javax.inject.Inject
-
-class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
-
- suspend fun saveTeachers(teachers: List) {
- teacherDb.insertAll(teachers)
- }
-
- suspend fun deleteTeachers(teachers: List) {
- teacherDb.deleteAll(teachers)
- }
-
- fun getTeachers(semester: Semester): Flow> {
- return teacherDb.loadAll(semester.studentId, semester.classId)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt
deleted file mode 100644
index 1d1caa686..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.github.wulkanowy.data.repositories.teacher
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.db.entities.Teacher
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TeacherRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getTeachers(student: Student, semester: Semester): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getTeachers(semester.semesterId)
- .map {
- Teacher(
- studentId = semester.studentId,
- name = it.name,
- subject = it.subject,
- shortName = it.short,
- classId = semester.classId
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt
deleted file mode 100644
index df25a53ec..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.teacher
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TeacherRepository @Inject constructor(
- private val local: TeacherLocal,
- private val remote: TeacherRemote
-) {
-
- fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getTeachers(semester) },
- fetch = { remote.getTeachers(student, semester) },
- saveFetchResult = { old, new ->
- local.deleteTeachers(old uniqueSubtract new)
- local.saveTeachers(new uniqueSubtract old)
- }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt
deleted file mode 100644
index df4bfb20a..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-import io.github.wulkanowy.data.db.dao.TimetableDao
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Timetable
-import kotlinx.coroutines.flow.Flow
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao) {
-
- suspend fun saveTimetable(timetables: List) {
- timetableDb.insertAll(timetables)
- }
-
- suspend fun deleteTimetable(timetables: List) {
- timetableDb.deleteAll(timetables)
- }
-
- fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> {
- return timetableDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt
deleted file mode 100644
index eef8729e8..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-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.sdk.Sdk
-import io.github.wulkanowy.utils.init
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimetableRemote @Inject constructor(private val sdk: Sdk) {
-
- suspend fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List {
- return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
- .getTimetable(startDate, endDate)
- .map {
- Timetable(
- studentId = semester.studentId,
- diaryId = semester.diaryId,
- number = it.number,
- start = it.start,
- end = it.end,
- date = it.date,
- subject = it.subject,
- subjectOld = it.subjectOld,
- group = it.group,
- room = it.room,
- roomOld = it.roomOld,
- teacher = it.teacher,
- teacherOld = it.teacherOld,
- info = it.info,
- isStudentPlan = it.studentPlan,
- changes = it.changes,
- canceled = it.canceled
- )
- }
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt
deleted file mode 100644
index ee2734aaf..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.github.wulkanowy.data.repositories.timetable
-
-import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
-import io.github.wulkanowy.utils.monday
-import io.github.wulkanowy.utils.networkBoundResource
-import io.github.wulkanowy.utils.sunday
-import io.github.wulkanowy.utils.uniqueSubtract
-import kotlinx.coroutines.flow.map
-import java.time.LocalDate
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimetableRepository @Inject constructor(
- private val local: TimetableLocal,
- private val remote: TimetableRemote,
- private val schedulerHelper: TimetableNotificationSchedulerHelper
-) {
-
- fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
- shouldFetch = { it.isEmpty() || forceRefresh },
- query = { local.getTimetable(semester, start.monday, end.sunday).map { schedulerHelper.scheduleNotifications(it, student); it } },
- fetch = { remote.getTimetable(student, semester, start.monday, end.sunday) },
- saveFetchResult = { old, new ->
- local.deleteTimetable(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) })
- local.saveTimetable(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item ->
- item.also { new ->
- old.singleOrNull { new.start == it.start }?.let { old ->
- return@map new.copy(
- room = if (new.room.isEmpty()) old.room else new.room,
- teacher = if (new.teacher.isEmpty() && !new.changes && !old.changes) old.teacher else new.teacher
- )
- }
- }
- })
- },
- filterResult = { it.filter { item -> item.date in start..end } }
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
index 9133c34ed..4efb4d84a 100644
--- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt
@@ -6,13 +6,13 @@ import com.yariksoffice.lingver.Lingver
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
import io.github.wulkanowy.utils.DispatchersProvider
import javax.inject.Singleton
@Module
-@InstallIn(ApplicationComponent::class)
+@InstallIn(SingletonComponent::class)
internal class AppModule {
@Singleton
diff --git a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt
index ac5a84e8f..891f07da0 100644
--- a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt
@@ -9,8 +9,8 @@ import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
-import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet
import io.github.wulkanowy.services.sync.channels.Channel
import io.github.wulkanowy.services.sync.channels.DebugChannel
@@ -38,7 +38,7 @@ import javax.inject.Singleton
@Suppress("unused")
@Module
-@InstallIn(ApplicationComponent::class)
+@InstallIn(SingletonComponent::class)
abstract class ServicesModule {
companion object {
diff --git a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt
index 592d0919e..8eefc032f 100644
--- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt
@@ -12,7 +12,7 @@ import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.HiltBroadcastReceiver
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
import io.github.wulkanowy.ui.modules.main.MainActivity
diff --git a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt
index 5c4b916bc..c0eba2f92 100644
--- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt
@@ -11,7 +11,7 @@ import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.Timetable
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_END
import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_NEXT_ROOM
import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_NEXT_TITLE
@@ -72,18 +72,22 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
withContext(dispatchersProvider.backgroundThread) {
lessons.groupBy { it.date }
.map { it.value.sortedBy { lesson -> lesson.start } }
- .map { it.filter { lesson -> !lesson.canceled && lesson.isStudentPlan } }
+ .map { it.filter { lesson -> lesson.isStudentPlan } }
.map { day ->
- day.forEachIndexed { index, lesson ->
- val intent = createIntent(student, lesson, day.getOrNull(index + 1))
+ val canceled = day.filter { it.canceled }
+ val active = day.filter { !it.canceled }
+
+ cancelScheduled(canceled)
+ active.forEachIndexed { index, lesson ->
+ val intent = createIntent(student, lesson, active.getOrNull(index + 1))
if (lesson.start > now()) {
- scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_UPCOMING, getUpcomingLessonTime(index, day, lesson))
+ scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_UPCOMING, getUpcomingLessonTime(index, active, lesson))
}
if (lesson.end > now()) {
scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_CURRENT, lesson.start)
- if (day.lastIndex == index) {
+ if (active.lastIndex == index) {
scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION, lesson.end)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
index 47a949273..b94d97e33 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
@@ -18,7 +18,7 @@ import androidx.work.WorkInfo
import androidx.work.WorkManager
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.Channel
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.isHolidays
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt
index 13326ca06..a428b702b 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt
@@ -11,9 +11,9 @@ import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
import io.github.wulkanowy.services.sync.channels.DebugChannel
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt
index 9e4ab9025..cbe1fe6bd 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository
+import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
import io.github.wulkanowy.utils.waitForResult
import javax.inject.Inject
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt
index ecf0be018..788e4ea2c 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
+import io.github.wulkanowy.data.repositories.AttendanceRepository
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
import io.github.wulkanowy.utils.waitForResult
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt
index 212ea6327..17bd61292 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository
+import io.github.wulkanowy.data.repositories.CompletedLessonsRepository
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
import io.github.wulkanowy.utils.waitForResult
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt
index 899d45cba..b75499301 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.exam.ExamRepository
+import io.github.wulkanowy.data.repositories.ExamRepository
import io.github.wulkanowy.utils.waitForResult
import java.time.LocalDate.now
import javax.inject.Inject
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt
index 3d61a423b..4575b419b 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository
+import io.github.wulkanowy.data.repositories.GradeStatisticsRepository
import io.github.wulkanowy.utils.waitForResult
import javax.inject.Inject
@@ -12,8 +12,8 @@ class GradeStatisticsWork @Inject constructor(
override suspend fun doWork(student: Student, semester: Semester) {
with(gradeStatisticsRepository) {
- getGradesStatistics(student, semester, "Wszystkie", isSemester = true, forceRefresh = true).waitForResult()
- getGradesStatistics(student, semester, "Wszystkie", isSemester = false, forceRefresh = true).waitForResult()
+ getGradesPartialStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
+ getGradesSemesterStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
getGradesPointsStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt
index 00bce109e..19c26edd0 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt
@@ -13,8 +13,8 @@ import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.grade.GradeRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.GradeRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewGradesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt
index a07f11073..a16841e9a 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
+import io.github.wulkanowy.data.repositories.HomeworkRepository
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
import io.github.wulkanowy.utils.waitForResult
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
index 7b9f5ab30..9f5365535 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt
@@ -12,8 +12,8 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.LuckyNumberRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.LuckyNumberChannel
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
index 7b32f13bb..93c30b57c 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
@@ -12,9 +12,9 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
-import io.github.wulkanowy.data.repositories.message.MessageRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
+import io.github.wulkanowy.data.repositories.MessageRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.services.sync.channels.NewMessagesChannel
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
index b08896966..50f418ed3 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt
@@ -12,8 +12,8 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.note.NoteRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.NoteRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.NEUTRAL
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.POSITIVE
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
index c433c0ac8..34ab3db04 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
@@ -2,8 +2,8 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.recipient.RecipientRepository
-import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository
+import io.github.wulkanowy.data.repositories.RecipientRepository
+import io.github.wulkanowy.data.repositories.ReportingUnitRepository
import javax.inject.Inject
class RecipientWork @Inject constructor(
@@ -16,7 +16,7 @@ class RecipientWork @Inject constructor(
reportingUnitRepository.getReportingUnits(student).let { units ->
units.map {
- recipientRepository.refreshRecipients(student, 2, it)
+ recipientRepository.refreshRecipients(student, it, 2)
}
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt
index a9abdaa72..7c614c6c5 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.teacher.TeacherRepository
+import io.github.wulkanowy.data.repositories.TeacherRepository
import io.github.wulkanowy.utils.waitForResult
import javax.inject.Inject
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt
index 3b8c6f5dc..2df2c9dcb 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
+import io.github.wulkanowy.data.repositories.TimetableRepository
import io.github.wulkanowy.utils.monday
import io.github.wulkanowy.utils.sunday
import io.github.wulkanowy.utils.waitForResult
diff --git a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
index 42c6d3bfd..45cd2b04e 100644
--- a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt
@@ -4,10 +4,10 @@ import android.content.Intent
import android.widget.RemoteViewsService
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.data.db.SharedPrefProvider
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
-import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
+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.modules.timetablewidget.TimetableWidgetFactory
import timber.log.Timber
import javax.inject.Inject
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
index 18cd58b41..1c31976ee 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt
@@ -3,10 +3,15 @@ package io.github.wulkanowy.ui.base
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.lifecycleAwareVariable
+import javax.inject.Inject
abstract class BaseDialogFragment : DialogFragment(), BaseView {
+ @Inject
+ lateinit var analyticsHelper: AnalyticsHelper
+
protected var binding: VB by lifecycleAwareVariable()
override fun showError(text: String, error: Throwable) {
@@ -28,4 +33,14 @@ abstract class BaseDialogFragment : DialogFragment(), BaseView
override fun showErrorDetailsDialog(error: Throwable) {
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
}
+
+ override fun onResume() {
+ super.onResume()
+ analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ analyticsHelper.popCurrentScreen(this::class.simpleName)
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
index ba8bfd85f..b222b0abb 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt
@@ -1,7 +1,7 @@
package io.github.wulkanowy.ui.base
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.utils.flowWithResource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
index 8d6739a15..341ae4590 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt
@@ -22,9 +22,11 @@ import io.github.wulkanowy.utils.getString
import io.github.wulkanowy.utils.openAppInMarket
import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
+import okhttp3.internal.http2.StreamResetException
import java.io.InterruptedIOException
import java.io.PrintWriter
import java.io.StringWriter
+import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import javax.inject.Inject
@@ -85,6 +87,8 @@ class ErrorDialog : BaseDialogFragment() {
errorDialogReport.isEnabled = when (error) {
is UnknownHostException,
is InterruptedIOException,
+ is ConnectException,
+ is StreamResetException,
is SocketTimeoutException,
is ServiceUnavailableException,
is FeatureDisabledException,
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
index 946e661b1..34dd3ec16 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt
@@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.base
import android.content.res.Resources
-import com.chuckerteam.chucker.api.ChuckerCollector
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
import io.github.wulkanowy.utils.getString
@@ -9,7 +8,7 @@ import io.github.wulkanowy.utils.security.ScramblerException
import timber.log.Timber
import javax.inject.Inject
-open class ErrorHandler @Inject constructor(protected val resources: Resources, private val chuckerCollector: ChuckerCollector) {
+open class ErrorHandler @Inject constructor(protected val resources: Resources) {
var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> }
@@ -18,7 +17,6 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources,
var onNoCurrentStudent: () -> Unit = {}
fun dispatch(error: Throwable) {
- chuckerCollector.onError(error.javaClass.simpleName, error)
Timber.e(error, "An exception occurred while the Wulkanowy was running")
proceed(error)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
index 501348612..a2379c3e7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt
@@ -7,7 +7,7 @@ import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import javax.inject.Inject
import javax.inject.Singleton
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
index 5ec1a66e3..0730033f1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt
@@ -58,6 +58,11 @@ class AboutFragment : BaseFragment(R.layout.fragment_about
Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord))
}
+ override val facebookRes: Triple?
+ get() = context?.run {
+ Triple(getString(R.string.about_facebook), getString(R.string.about_facebook_summary), getCompatDrawable(R.drawable.ic_about_facebook))
+ }
+
override val homepageRes: Triple?
get() = context?.run {
Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage))
@@ -113,6 +118,10 @@ class AboutFragment : BaseFragment(R.layout.fragment_about
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
}
+ override fun openFacebookPage() {
+ context?.openInternetBrowser("https://www.facebook.com/wulkanowy", ::showMessage)
+ }
+
override fun openHomepage() {
context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
index 24e59d36b..fde20267d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt
@@ -1,10 +1,10 @@
package io.github.wulkanowy.ui.modules.about
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import timber.log.Timber
import javax.inject.Inject
@@ -12,7 +12,7 @@ class AboutPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val appInfo: AppInfo,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
override fun onAttachView(view: AboutView) {
@@ -46,6 +46,11 @@ class AboutPresenter @Inject constructor(
openDiscordInvite()
analytics.logEvent("about_open", "name" to "discord")
}
+ facebookRes?.first -> {
+ Timber.i("Opening facebook")
+ openFacebookPage()
+ analytics.logEvent("about_open", "name" to "facebook")
+ }
homepageRes?.first -> {
Timber.i("Opening homepage")
openHomepage()
@@ -78,6 +83,7 @@ class AboutPresenter @Inject constructor(
feedbackRes,
faqRes,
discordRes,
+ facebookRes,
homepageRes,
licensesRes,
privacyRes
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
index 4c4b002f9..54882b302 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt
@@ -15,6 +15,8 @@ interface AboutView : BaseView {
val discordRes: Triple?
+ val facebookRes: Triple?
+
val homepageRes: Triple?
val licensesRes: Triple?
@@ -31,6 +33,8 @@ interface AboutView : BaseView {
fun openDiscordInvite()
+ fun openFacebookPage()
+
fun openEmailClient()
fun openFaqPage()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt
index 78fdb43a1..ef4b540e6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt
@@ -2,8 +2,8 @@ package io.github.wulkanowy.ui.modules.about.contributor
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.pojos.Contributor
-import io.github.wulkanowy.data.repositories.appcreator.AppCreatorRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.AppCreatorRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.flowWithResource
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt
index 18d257eed..cc430fc2c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.about.license
import com.mikepenz.aboutlibraries.entity.Library
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.DispatchersProvider
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt
index 85eae8e6e..80020c81d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt
@@ -1,8 +1,8 @@
package io.github.wulkanowy.ui.modules.about.logviewer
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.logger.LoggerRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.LoggerRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.utils.flowWithResource
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt
index 4eaee4291..be01f7c54 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt
@@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.account
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
index 8e8a6149d..03ec1c842 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt
@@ -7,7 +7,7 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Attendance
-import io.github.wulkanowy.data.repositories.attendance.SentExcuseStatus
+import io.github.wulkanowy.data.enums.SentExcuseStatus
import io.github.wulkanowy.databinding.ItemAttendanceBinding
import io.github.wulkanowy.utils.description
import javax.inject.Inject
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
index c7caef069..a106bc501 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt
@@ -191,8 +191,8 @@ class AttendanceFragment : BaseFragment(R.layout.frag
binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE
}
- override fun hideRefresh() {
- binding.attendanceSwipe.isRefreshing = false
+ override fun showRefresh(show: Boolean) {
+ binding.attendanceSwipe.isRefreshing = show
}
override fun showPreButton(show: Boolean) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
index 158f08ba3..68802c0c7 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt
@@ -3,13 +3,13 @@ package io.github.wulkanowy.ui.modules.attendance
import android.annotation.SuppressLint
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Attendance
-import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.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.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn
@@ -34,7 +34,7 @@ class AttendancePresenter @Inject constructor(
private val attendanceRepository: AttendanceRepository,
private val semesterRepository: SemesterRepository,
private val prefRepository: PreferencesRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var baseDate: LocalDate = now().previousOrSameSchoolDay
@@ -51,23 +51,23 @@ class AttendancePresenter @Inject constructor(
view.initView()
Timber.i("Attendance view was initialized")
errorHandler.showErrorMessage = ::showErrorViewOnError
- loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
+ reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
+ loadData()
if (currentDate.isHolidays) setBaseDateOnHolidays()
- reloadView()
}
fun onPreviousDay() {
view?.finishActionMode()
attendanceToExcuseList.clear()
- loadData(currentDate.previousSchoolDay)
- reloadView()
+ reloadView(currentDate.previousSchoolDay)
+ loadData()
}
fun onNextDay() {
view?.finishActionMode()
attendanceToExcuseList.clear()
- loadData(currentDate.nextSchoolDay)
- reloadView()
+ reloadView(currentDate.nextSchoolDay)
+ loadData()
}
fun onPickDate() {
@@ -75,13 +75,13 @@ class AttendancePresenter @Inject constructor(
}
fun onDateSet(year: Int, month: Int, day: Int) {
- loadData(LocalDate.of(year, month, day))
- reloadView()
+ reloadView(LocalDate.of(year, month, day))
+ loadData()
}
fun onSwipeRefresh() {
Timber.i("Force refreshing the attendance")
- loadData(currentDate, true)
+ loadData(true)
}
fun onRetry() {
@@ -89,7 +89,7 @@ class AttendancePresenter @Inject constructor(
showErrorView(false)
showProgress(true)
}
- loadData(currentDate, true)
+ loadData(true)
}
fun onDetailsClick() {
@@ -102,8 +102,8 @@ class AttendancePresenter @Inject constructor(
if (view.currentStackSize == 1) {
baseDate.also {
if (currentDate != it) {
- loadData(it)
- reloadView()
+ reloadView(it)
+ loadData()
} else if (!view.isViewEmpty) view.resetView()
}
} else view.popView()
@@ -184,17 +184,30 @@ class AttendancePresenter @Inject constructor(
}.launch("holidays")
}
- private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
+ private fun loadData(forceRefresh: Boolean = false) {
Timber.i("Loading attendance data started")
- currentDate = date
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
val semester = semesterRepository.getCurrentSemester(student)
- attendanceRepository.getAttendance(student, semester, date, date, forceRefresh)
+ attendanceRepository.getAttendance(student, semester, currentDate, currentDate, forceRefresh)
}.onEach {
when (it.status) {
- Status.LOADING -> view?.showExcuseButton(false)
+ Status.LOADING -> {
+ view?.showExcuseButton(false)
+ if (!it.data.isNullOrEmpty()) {
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showContent(true)
+ updateData(it.data.let { items ->
+ if (prefRepository.isShowPresent) items
+ else items.filter { item -> !item.presence }
+ }.sortedBy { item -> item.number })
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading attendance result: Success")
view?.apply {
@@ -220,7 +233,7 @@ class AttendancePresenter @Inject constructor(
}
}.afterLoading {
view?.run {
- hideRefresh()
+ showRefresh(false)
showProgress(false)
enableSwipe(true)
}
@@ -250,12 +263,12 @@ class AttendancePresenter @Inject constructor(
showContent(true)
showProgress(false)
}
- loadData(currentDate, forceRefresh = true)
+ loadData(forceRefresh = true)
}
Status.ERROR -> {
Timber.i("Excusing for absence result: An exception occurred")
errorHandler.dispatch(it.error!!)
- loadData(currentDate)
+ loadData()
}
}
}.launch("excuse")
@@ -272,11 +285,14 @@ class AttendancePresenter @Inject constructor(
}
}
- private fun reloadView() {
+ private fun reloadView(date: LocalDate) {
+ currentDate = date
+
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
view?.apply {
showProgress(true)
enableSwipe(false)
+ showRefresh(false)
showContent(false)
showEmpty(false)
showErrorView(false)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
index d54fb8bf1..0459dfcf6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt
@@ -24,7 +24,7 @@ interface AttendanceView : BaseView {
fun clearData()
- fun hideRefresh()
+ fun showRefresh(show: Boolean)
fun resetView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
index 2f8622374..6b971f26a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt
@@ -121,8 +121,8 @@ class AttendanceSummaryFragment :
binding.attendanceSummarySubjectsContainer.visibility = if (show) VISIBLE else INVISIBLE
}
- override fun hideRefresh() {
- binding.attendanceSummarySwipe.isRefreshing = false
+ override fun showRefresh(show: Boolean) {
+ binding.attendanceSummarySwipe.isRefreshing = show
}
override fun onSaveInstanceState(outState: Bundle) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
index e5dce9ac8..e53cda749 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt
@@ -1,14 +1,15 @@
package io.github.wulkanowy.ui.modules.attendance.summary
import io.github.wulkanowy.data.Status
+import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.Subject
-import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
-import io.github.wulkanowy.data.repositories.subject.SubjectRepository
+import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
+import io.github.wulkanowy.data.repositories.SubjectRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach
@@ -22,7 +23,7 @@ class AttendanceSummaryPresenter @Inject constructor(
private val attendanceSummaryRepository: AttendanceSummaryRepository,
private val subjectRepository: SubjectRepository,
private val semesterRepository: SemesterRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var subjects = emptyList()
@@ -74,6 +75,8 @@ class AttendanceSummaryPresenter @Inject constructor(
}
private fun loadData(subjectId: Int, forceRefresh: Boolean = false) {
+ Timber.i("Loading attendance summary data started")
+
currentSubjectId = subjectId
flowWithResourceIn {
@@ -82,15 +85,23 @@ class AttendanceSummaryPresenter @Inject constructor(
attendanceSummaryRepository.getAttendanceSummary(student, semester, subjectId, forceRefresh)
}.onEach {
when (it.status) {
- Status.LOADING -> Timber.i("Loading attendance summary data started")
+ Status.LOADING -> {
+ if (!it.data.isNullOrEmpty()) {
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showContent(true)
+ updateDataSet(sortItems(it.data))
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading attendance summary result: Success")
view?.apply {
showEmpty(it.data!!.isEmpty())
showContent(it.data.isNotEmpty())
- updateDataSet(it.data.sortedByDescending { item ->
- if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value
- })
+ updateDataSet(sortItems(it.data))
}
analytics.logEvent(
"load_data",
@@ -106,13 +117,17 @@ class AttendanceSummaryPresenter @Inject constructor(
}
}.afterLoading {
view?.run {
- hideRefresh()
+ showRefresh(false)
showProgress(false)
enableSwipe(true)
}
}.launch()
}
+ private fun sortItems(items: List) = items.sortedByDescending { item ->
+ if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value
+ }
+
private fun showErrorViewOnError(message: String, error: Throwable) {
view?.run {
if (isViewEmpty) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
index dd4053c72..66f370c5c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt
@@ -9,7 +9,7 @@ interface AttendanceSummaryView : BaseView {
fun initView()
- fun hideRefresh()
+ fun showRefresh(show: Boolean)
fun showContent(show: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt
new file mode 100644
index 000000000..c87286149
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt
@@ -0,0 +1,36 @@
+package io.github.wulkanowy.ui.modules.conference
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import io.github.wulkanowy.data.db.entities.Conference
+import io.github.wulkanowy.databinding.ItemConferenceBinding
+import io.github.wulkanowy.utils.toFormattedString
+import javax.inject.Inject
+
+class ConferenceAdapter @Inject constructor() :
+ RecyclerView.Adapter() {
+
+ var items = emptyList()
+
+ override fun getItemCount() = items.size
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
+ ItemConferenceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ )
+
+ override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
+ val item = items[position]
+ with(holder.binding) {
+ conferenceItemDate.text = item.date.toFormattedString("dd.MM.yyyy HH:mm")
+ conferenceItemName.text = item.presentOnConference
+ conferenceItemTitle.text = item.title
+ conferenceItemSubject.text = item.subject
+ conferenceItemContent.text = item.agenda
+ conferenceItemContent.visibility = if (item.agenda.isBlank()) View.GONE else View.VISIBLE
+ }
+ }
+
+ class ItemViewHolder(val binding: ItemConferenceBinding) : RecyclerView.ViewHolder(binding.root)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt
new file mode 100644
index 000000000..6173c15be
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt
@@ -0,0 +1,102 @@
+package io.github.wulkanowy.ui.modules.conference
+
+import android.os.Bundle
+import android.view.View
+import androidx.recyclerview.widget.LinearLayoutManager
+import dagger.hilt.android.AndroidEntryPoint
+import io.github.wulkanowy.R
+import io.github.wulkanowy.data.db.entities.Conference
+import io.github.wulkanowy.databinding.FragmentConferenceBinding
+import io.github.wulkanowy.ui.base.BaseFragment
+import io.github.wulkanowy.ui.modules.main.MainView
+import io.github.wulkanowy.ui.widgets.DividerItemDecoration
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class ConferenceFragment : BaseFragment(R.layout.fragment_conference),
+ ConferenceView, MainView.TitledView {
+
+ @Inject
+ lateinit var presenter: ConferencePresenter
+
+ @Inject
+ lateinit var conferencesAdapter: ConferenceAdapter
+
+ companion object {
+ fun newInstance() = ConferenceFragment()
+ }
+
+ override val isViewEmpty: Boolean
+ get() = conferencesAdapter.items.isEmpty()
+
+ override val titleStringId: Int
+ get() = R.string.conferences_title
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding = FragmentConferenceBinding.bind(view)
+ messageContainer = binding.conferenceRecycler
+ presenter.onAttachView(this)
+ }
+
+ override fun initView() {
+ with(binding.conferenceRecycler) {
+ layoutManager = LinearLayoutManager(context)
+ adapter = conferencesAdapter
+ addItemDecoration(DividerItemDecoration(context))
+ }
+
+ with(binding) {
+ conferenceSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
+ conferenceErrorRetry.setOnClickListener { presenter.onRetry() }
+ conferenceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
+ }
+ }
+
+ override fun updateData(data: List) {
+ with(conferencesAdapter) {
+ items = data
+ notifyDataSetChanged()
+ }
+ }
+
+ override fun clearData() {
+ with(conferencesAdapter) {
+ items = emptyList()
+ notifyDataSetChanged()
+ }
+ }
+
+ override fun showRefresh(show: Boolean) {
+ binding.conferenceSwipe.isRefreshing = show
+ }
+
+ override fun showProgress(show: Boolean) {
+ binding.conferenceProgress.visibility = if (show) View.VISIBLE else View.GONE
+ }
+
+ override fun showEmpty(show: Boolean) {
+ binding.conferenceEmpty.visibility = if (show) View.VISIBLE else View.GONE
+ }
+
+ override fun showErrorView(show: Boolean) {
+ binding.conferenceError.visibility = if (show) View.VISIBLE else View.GONE
+ }
+
+ override fun setErrorDetails(message: String) {
+ binding.conferenceErrorMessage.text = message
+ }
+
+ override fun enableSwipe(enable: Boolean) {
+ binding.conferenceSwipe.isEnabled = enable
+ }
+
+ override fun showContent(show: Boolean) {
+ binding.conferenceRecycler.visibility = if (show) View.VISIBLE else View.GONE
+ }
+
+ override fun onDestroyView() {
+ presenter.onDetachView()
+ super.onDestroyView()
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt
new file mode 100644
index 000000000..cc7e50db5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt
@@ -0,0 +1,108 @@
+package io.github.wulkanowy.ui.modules.conference
+
+import io.github.wulkanowy.data.Status
+import io.github.wulkanowy.data.repositories.ConferenceRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
+import io.github.wulkanowy.ui.base.BasePresenter
+import io.github.wulkanowy.ui.base.ErrorHandler
+import io.github.wulkanowy.utils.AnalyticsHelper
+import io.github.wulkanowy.utils.afterLoading
+import io.github.wulkanowy.utils.flowWithResourceIn
+import kotlinx.coroutines.flow.onEach
+import timber.log.Timber
+import javax.inject.Inject
+
+class ConferencePresenter @Inject constructor(
+ errorHandler: ErrorHandler,
+ studentRepository: StudentRepository,
+ private val semesterRepository: SemesterRepository,
+ private val conferenceRepository: ConferenceRepository,
+ private val analytics: AnalyticsHelper
+) : BasePresenter(errorHandler, studentRepository) {
+
+ private lateinit var lastError: Throwable
+
+ override fun onAttachView(view: ConferenceView) {
+ super.onAttachView(view)
+ view.initView()
+ Timber.i("Conferences view was initialized")
+ errorHandler.showErrorMessage = ::showErrorViewOnError
+ loadData()
+ }
+
+ fun onSwipeRefresh() {
+ loadData(true)
+ }
+
+ fun onRetry() {
+ view?.run {
+ showErrorView(false)
+ showProgress(true)
+ }
+ loadData(true)
+ }
+
+ fun onDetailsClick() {
+ view?.showErrorDetailsDialog(lastError)
+ }
+
+ private fun showErrorViewOnError(message: String, error: Throwable) {
+ view?.run {
+ if (isViewEmpty) {
+ lastError = error
+ setErrorDetails(message)
+ showErrorView(true)
+ showEmpty(false)
+ } else showError(message, error)
+ }
+ }
+
+ private fun loadData(forceRefresh: Boolean = false) {
+ Timber.i("Loading conference data started")
+
+ flowWithResourceIn {
+ val student = studentRepository.getCurrentStudent()
+ val semester = semesterRepository.getCurrentSemester(student)
+ conferenceRepository.getConferences(student, semester, forceRefresh)
+ }.onEach {
+ when (it.status) {
+ Status.LOADING -> {
+ if (!it.data.isNullOrEmpty()) {
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showContent(true)
+ updateData(it.data.sortedByDescending { conference -> conference.date })
+ }
+ }
+ }
+ Status.SUCCESS -> {
+ Timber.i("Loading conference result: Success")
+ view?.run {
+ updateData(it.data!!.sortedByDescending { conference -> conference.date })
+ showContent(it.data.isNotEmpty())
+ showEmpty(it.data.isEmpty())
+ showErrorView(false)
+ }
+ analytics.logEvent(
+ "load_data",
+ "type" to "conferences",
+ "items" to it.data!!.size
+ )
+ }
+ Status.ERROR -> {
+ Timber.i("Loading conference result: An exception occurred")
+ errorHandler.dispatch(it.error!!)
+ }
+ }
+ }.afterLoading {
+ view?.run {
+ showRefresh(false)
+ showProgress(false)
+ enableSwipe(true)
+ }
+ }.launch()
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt
new file mode 100644
index 000000000..f3d1b3b3f
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt
@@ -0,0 +1,29 @@
+package io.github.wulkanowy.ui.modules.conference
+
+import io.github.wulkanowy.data.db.entities.Conference
+import io.github.wulkanowy.ui.base.BaseView
+
+interface ConferenceView : BaseView {
+
+ val isViewEmpty: Boolean
+
+ fun initView()
+
+ fun updateData(data: List)
+
+ fun clearData()
+
+ fun showRefresh(show: Boolean)
+
+ fun showEmpty(show: Boolean)
+
+ fun showErrorView(show: Boolean)
+
+ fun setErrorDetails(message: String)
+
+ fun showProgress(show: Boolean)
+
+ fun enableSwipe(enable: Boolean)
+
+ fun showContent(show: Boolean)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
index 000da00f8..9cc1aeda3 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt
@@ -65,8 +65,8 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam),
}
}
- override fun hideRefresh() {
- binding.examSwipe.isRefreshing = false
+ override fun showRefresh(show: Boolean) {
+ binding.examSwipe.isRefreshing = show
}
override fun updateData(data: List>) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
index f63316a8d..b70a648f4 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt
@@ -2,12 +2,12 @@ package io.github.wulkanowy.ui.modules.exam
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Exam
-import io.github.wulkanowy.data.repositories.exam.ExamRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.ExamRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@@ -30,7 +30,7 @@ class ExamPresenter @Inject constructor(
studentRepository: StudentRepository,
private val examRepository: ExamRepository,
private val semesterRepository: SemesterRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var baseDate: LocalDate = now().nextOrSameSchoolDay
@@ -45,24 +45,24 @@ class ExamPresenter @Inject constructor(
view.initView()
Timber.i("Exam view was initialized")
errorHandler.showErrorMessage = ::showErrorViewOnError
- loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
+ reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
+ loadData()
if (currentDate.isHolidays) setBaseDateOnHolidays()
- reloadView()
}
fun onPreviousWeek() {
- loadData(currentDate.minusDays(7))
- reloadView()
+ reloadView(currentDate.minusDays(7))
+ loadData()
}
fun onNextWeek() {
- loadData(currentDate.plusDays(7))
- reloadView()
+ reloadView(currentDate.plusDays(7))
+ loadData()
}
fun onSwipeRefresh() {
Timber.i("Force refreshing the exam")
- loadData(currentDate, true)
+ loadData(true)
}
fun onRetry() {
@@ -70,7 +70,7 @@ class ExamPresenter @Inject constructor(
showErrorView(false)
showProgress(true)
}
- loadData(currentDate, true)
+ loadData(true)
}
fun onDetailsClick() {
@@ -86,8 +86,8 @@ class ExamPresenter @Inject constructor(
Timber.i("Exam view is reselected")
baseDate.also {
if (currentDate != it) {
- loadData(it)
- reloadView()
+ reloadView(it)
+ loadData()
} else if (view?.isViewEmpty == false) view?.resetView()
}
}
@@ -105,8 +105,8 @@ class ExamPresenter @Inject constructor(
}.launch("holidays")
}
- private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
- currentDate = date
+ private fun loadData(forceRefresh: Boolean = false) {
+ Timber.i("Loading exam data started")
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
@@ -114,7 +114,17 @@ class ExamPresenter @Inject constructor(
examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh)
}.onEach {
when (it.status) {
- Status.LOADING -> Timber.i("Loading exam data started")
+ Status.LOADING -> {
+ if (!it.data.isNullOrEmpty()) {
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showContent(true)
+ updateData(createExamItems(it.data))
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading exam result: Success")
view?.apply {
@@ -136,7 +146,7 @@ class ExamPresenter @Inject constructor(
}
}.afterLoading {
view?.run {
- hideRefresh()
+ showRefresh(false)
showProgress(false)
enableSwipe(true)
}
@@ -162,7 +172,9 @@ class ExamPresenter @Inject constructor(
}.flatten()
}
- private fun reloadView() {
+ private fun reloadView(date: LocalDate) {
+ currentDate = date
+
Timber.i("Reload exam view with the date ${currentDate.toFormattedString()}")
view?.apply {
showProgress(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
index 00429bae6..ac1a87fe9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt
@@ -15,7 +15,7 @@ interface ExamView : BaseView {
fun clearData()
- fun hideRefresh()
+ fun showRefresh(show: Boolean)
fun resetView()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
index 5d0a310f2..0bd971ecc 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt
@@ -1,14 +1,13 @@
package io.github.wulkanowy.ui.modules.grade
import io.github.wulkanowy.data.Resource
-import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.grade.GradeRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
+import io.github.wulkanowy.data.repositories.GradeRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ALL_YEAR
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.BOTH_SEMESTERS
@@ -18,10 +17,8 @@ import io.github.wulkanowy.utils.changeModifier
import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.flatMapConcat
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import javax.inject.Inject
@@ -50,20 +47,20 @@ class GradeAverageProvider @Inject constructor(
val selectedSemester = semesters.single { it.semesterId == semesterId }
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
- return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
- val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
+ val selectedSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh)
- if (selectedSemester != firstSemester) {
- getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
- secondDetails.copy(data = selectedDetails.data?.map { selected ->
- val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
- selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
- val selectedGrades = selected.grades.updateModifiers(student).calcAverage()
- (selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2
- } else (selected.average + (second?.average ?: selected.average)) / 2)
- })
- }.filter { it.status != Status.LOADING }.filter { it.data != null }
- } else flowOf(selectedDetails)
+ return if (selectedSemester == firstSemester) selectedSemesterDetailsWithAverage else {
+ val firstSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, firstSemester, forceRefresh)
+ selectedSemesterDetailsWithAverage.combine(firstSemesterDetailsWithAverage) { selectedDetails, secondDetails ->
+ val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
+ secondDetails.copy(data = selectedDetails.data?.map { selected ->
+ val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
+ selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
+ val selectedGrades = selected.grades.updateModifiers(student).calcAverage()
+ (selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2
+ } else (selected.average + (second?.average ?: selected.average)) / 2)
+ })
+ }
}
}
@@ -71,19 +68,19 @@ class GradeAverageProvider @Inject constructor(
val selectedSemester = semesters.single { it.semesterId == semesterId }
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
- return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
- val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
+ val selectedSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh)
- if (selectedSemester != firstSemester) {
- getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
- secondDetails.copy(data = selectedDetails.data?.map { selected ->
- val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
- selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
- (selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage()
- } else selected.average)
- })
- }.filter { it.status != Status.LOADING }.filter { it.data != null }
- } else flowOf(selectedDetails)
+ return if (selectedSemester == firstSemester) selectedSemesterDetailsWithAverage else {
+ val firstSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, firstSemester, forceRefresh)
+ selectedSemesterDetailsWithAverage.combine(firstSemesterDetailsWithAverage) { selectedDetails, secondDetails ->
+ val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
+ secondDetails.copy(data = selectedDetails.data?.map { selected ->
+ val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
+ selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
+ (selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage()
+ } else selected.average)
+ })
+ }
}
}
@@ -93,7 +90,7 @@ class GradeAverageProvider @Inject constructor(
val isAnyAverage = summaries.orEmpty().any { it.average != .0 }
val allGrades = details.orEmpty().groupBy { it.subject }
- Resource(res.status, summaries?.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage)?.map { summary ->
+ val items = summaries?.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage)?.map { summary ->
val grades = allGrades[summary.subject].orEmpty()
GradeDetailsWithAverage(
subject = summary.subject,
@@ -104,7 +101,9 @@ class GradeAverageProvider @Inject constructor(
summary = summary,
grades = grades
)
- }, res.error)
+ }
+
+ Resource(res.status, items, res.error)
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
index d4c9f210a..d64613c01 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt
@@ -2,11 +2,11 @@ package io.github.wulkanowy.ui.modules.grade
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Semester
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.getCurrentOrLast
import kotlinx.coroutines.delay
@@ -18,7 +18,7 @@ class GradePresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
var selectedIndex = 0
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
index c129d9485..6f9321692 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt
@@ -40,10 +40,6 @@ class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter
-)
+) {
+ var newGrades = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
index 97b7b71c6..afec6b5ee 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt
@@ -3,17 +3,17 @@ package io.github.wulkanowy.ui.modules.grade.details
import android.annotation.SuppressLint
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Grade
-import io.github.wulkanowy.data.repositories.grade.GradeRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.GradeRepository
+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.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.ALPHABETIC
import io.github.wulkanowy.ui.modules.grade.GradeSortingMode.DATE
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn
@@ -29,7 +29,7 @@ class GradeDetailsPresenter @Inject constructor(
private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository,
private val averageProvider: GradeAverageProvider,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var newGradesAmount: Int = 0
@@ -81,7 +81,10 @@ class GradeDetailsPresenter @Inject constructor(
}.onEach {
when (it.status) {
Status.LOADING -> Timber.i("Select mark grades as read")
- Status.SUCCESS -> Timber.i("Mark as read result: Success")
+ Status.SUCCESS -> {
+ Timber.i("Mark as read result: Success")
+ loadData(currentSemesterId, false)
+ }
Status.ERROR -> {
Timber.i("Mark as read result: An exception occurred")
errorHandler.dispatch(it.error!!)
@@ -134,15 +137,37 @@ class GradeDetailsPresenter @Inject constructor(
}
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
+ Timber.i("Loading grade details data started")
+
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
}.onEach {
+ Timber.d("Loading grade details status: ${it.status}, data: ${it.data != null}")
when (it.status) {
- Status.LOADING -> Timber.i("Loading grade details data started")
+ Status.LOADING -> {
+ val items = createGradeItems(it.data.orEmpty())
+ if (items.isNotEmpty()) {
+ Timber.i("Loading grade details result: load cached data")
+ view?.run {
+ updateNewGradesAmount(it.data.orEmpty())
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showEmpty(false)
+ showContent(true)
+ updateData(
+ data = items,
+ isGradeExpandable = preferencesRepository.isGradeExpandable,
+ gradeColorTheme = preferencesRepository.gradeColorTheme
+ )
+ notifyParentDataLoaded(semesterId)
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading grade details result: Success")
- newGradesAmount = it.data!!.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
+ updateNewGradesAmount(it.data!!)
updateMarkAsDoneButton()
val items = createGradeItems(it.data)
view?.run {
@@ -176,6 +201,10 @@ class GradeDetailsPresenter @Inject constructor(
}.launch()
}
+ private fun updateNewGradesAmount(grades: List) {
+ newGradesAmount = grades.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
+ }
+
private fun showErrorViewOnError(message: String, error: Throwable) {
view?.run {
if (isViewEmpty) {
@@ -210,9 +239,10 @@ class GradeDetailsPresenter @Inject constructor(
subject = subject,
average = average,
pointsSum = points,
- newGrades = grades.filter { grade -> !grade.isRead }.size,
grades = subItems
- ), ViewType.HEADER)) + if (preferencesRepository.isGradeExpandable) emptyList() else subItems
+ ).apply {
+ newGrades = grades.filter { grade -> !grade.isRead }.size
+ }, ViewType.HEADER)) + if (preferencesRepository.isGradeExpandable) emptyList() else subItems
}.flatten()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
index dbb60910a..cbcb444a1 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt
@@ -17,8 +17,9 @@ import com.github.mikephil.charting.data.PieDataSet
import com.github.mikephil.charting.data.PieEntry
import com.github.mikephil.charting.formatter.ValueFormatter
import io.github.wulkanowy.R
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.pojos.GradeStatisticsItem
import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
@@ -68,22 +69,32 @@ class GradeStatisticsAdapter @Inject constructor() :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
- ViewType.PARTIAL.id, ViewType.SEMESTER.id -> PieViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
- ViewType.POINTS.id -> BarViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false))
+ ViewType.PARTIAL.id -> PartialViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
+ ViewType.SEMESTER.id -> SemesterViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
+ ViewType.POINTS.id -> PointsViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false))
else -> throw IllegalStateException()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
- is PieViewHolder -> bindPieChart(holder, items[position].partial)
- is BarViewHolder -> bindBarChart(holder, items[position].points!!)
+ is PartialViewHolder -> bindPartialChart(holder, items[position].partial!!)
+ is SemesterViewHolder -> bindSemesterChart(holder, items[position].semester!!)
+ is PointsViewHolder -> bindBarChart(holder, items[position].points!!)
}
}
- private fun bindPieChart(holder: PieViewHolder, partials: List) {
- with(holder.binding.gradeStatisticsPieTitle) {
- text = partials.firstOrNull()?.subject
+ private fun bindPartialChart(holder: PartialViewHolder, partials: GradePartialStatistics) {
+ bindPieChart(holder.binding, partials.subject, partials.classAverage, partials.classAmounts)
+ }
+
+ private fun bindSemesterChart(holder: SemesterViewHolder, semester: GradeSemesterStatistics) {
+ bindPieChart(holder.binding, semester.subject, semester.average, semester.amounts)
+ }
+
+ private fun bindPieChart(binding: ItemGradeStatisticsPieBinding, subject: String, average: String, amounts: List) {
+ with(binding.gradeStatisticsPieTitle) {
+ text = subject
visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE
}
@@ -92,22 +103,23 @@ class GradeStatisticsAdapter @Inject constructor() :
else -> materialGradeColors
}
- val dataset = PieDataSet(partials.map {
- PieEntry(it.amount.toFloat(), it.grade.toString())
- }, "Legenda")
+ val dataset = PieDataSet(amounts.mapIndexed { grade, amount ->
+ PieEntry(amount.toFloat(), (grade + 1).toString())
+ }.reversed().filterNot { it.value == 0f }, "Legenda")
with(dataset) {
valueTextSize = 12f
sliceSpace = 1f
valueTextColor = Color.WHITE
- setColors(partials.map {
- gradeColors.single { color -> color.first == it.grade }.second
- }.toIntArray(), holder.binding.root.context)
+ val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }.filterNot { it.second == 0 }
+ setColors(grades.reversed().map { (grade, _) ->
+ gradeColors.single { color -> color.first == grade }.second
+ }.toIntArray(), binding.root.context)
}
- with(holder.binding.gradeStatisticsPie) {
+ with(binding.gradeStatisticsPie) {
setTouchEnabled(false)
- if (partials.size == 1) animateXY(1000, 1000)
+ if (amounts.size == 1) animateXY(1000, 1000)
data = PieData(dataset).apply {
setValueFormatter(object : ValueFormatter() {
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
@@ -128,8 +140,9 @@ class GradeStatisticsAdapter @Inject constructor() :
minAngleForSlices = 25f
description.isEnabled = false
- centerText = partials.fold(0) { acc, it -> acc + it.amount }
- .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) }
+ centerText = amounts.fold(0) { acc, it -> acc + it }
+ .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } +
+ ("\n\nŚrednia: $average").takeIf { average.isNotBlank() }.orEmpty()
setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground))
setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary))
@@ -137,7 +150,7 @@ class GradeStatisticsAdapter @Inject constructor() :
}
}
- private fun bindBarChart(holder: BarViewHolder, points: GradePointsStatistics) {
+ private fun bindBarChart(holder: PointsViewHolder, points: GradePointsStatistics) {
with(holder.binding.gradeStatisticsBarTitle) {
text = points.subject
visibility = if (items.size == 1) GONE else VISIBLE
@@ -200,9 +213,12 @@ class GradeStatisticsAdapter @Inject constructor() :
}
}
- private class PieViewHolder(val binding: ItemGradeStatisticsPieBinding) :
+ private class PartialViewHolder(val binding: ItemGradeStatisticsPieBinding) :
RecyclerView.ViewHolder(binding.root)
- private class BarViewHolder(val binding: ItemGradeStatisticsBarBinding) :
+ private class SemesterViewHolder(val binding: ItemGradeStatisticsPieBinding) :
+ RecyclerView.ViewHolder(binding.root)
+
+ private class PointsViewHolder(val binding: ItemGradeStatisticsBarBinding) :
RecyclerView.ViewHolder(binding.root)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
index 73cee9e96..37f478693 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt
@@ -2,14 +2,15 @@ package io.github.wulkanowy.ui.modules.grade.statistics
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Subject
-import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
-import io.github.wulkanowy.data.repositories.subject.SubjectRepository
+import io.github.wulkanowy.data.pojos.GradeStatisticsItem
+import io.github.wulkanowy.data.repositories.GradeStatisticsRepository
+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.SubjectRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach
@@ -23,7 +24,7 @@ class GradeStatisticsPresenter @Inject constructor(
private val subjectRepository: SubjectRepository,
private val semesterRepository: SemesterRepository,
private val preferencesRepository: PreferencesRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var subjects = emptyList()
@@ -143,6 +144,8 @@ class GradeStatisticsPresenter @Inject constructor(
}
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
+ Timber.i("Loading grade stats data started")
+
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
currentType = type
@@ -153,19 +156,33 @@ class GradeStatisticsPresenter @Inject constructor(
with(gradeStatisticsRepository) {
when (type) {
- ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh)
- ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, forceRefresh)
+ ViewType.PARTIAL -> getGradesPartialStatistics(student, semester, currentSubjectName, forceRefresh)
+ ViewType.SEMESTER -> getGradesSemesterStatistics(student, semester, currentSubjectName, forceRefresh)
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
}
}
}.onEach {
when (it.status) {
- Status.LOADING -> Timber.i("Loading grade stats data started")
+ Status.LOADING -> {
+ val isNoContent = it.data == null || checkIsNoContent(it.data, type)
+ if (!isNoContent) {
+ view?.run {
+ showEmpty(isNoContent)
+ showContent(!isNoContent)
+ showErrorView(false)
+ enableSwipe(true)
+ showRefresh(true)
+ updateData(it.data!!, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
+ showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading grade stats result: Success")
view?.run {
- showEmpty(it.data!!.isEmpty() || it.data.first().partial.isEmpty())
- showContent(it.data.isNotEmpty() && it.data.first().partial.isNotEmpty())
+ val isNoContent = checkIsNoContent(it.data!!, type)
+ showEmpty(isNoContent)
+ showContent(!isNoContent)
showErrorView(false)
updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
@@ -191,6 +208,16 @@ class GradeStatisticsPresenter @Inject constructor(
}.launch("load")
}
+ private fun checkIsNoContent(items: List, type: ViewType): Boolean {
+ return items.isEmpty() || when (type) {
+ ViewType.SEMESTER -> items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
+ ViewType.PARTIAL -> items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
+ ViewType.POINTS -> items.firstOrNull()?.points?.let { points ->
+ points.student == .0 && points.others == .0
+ } ?: false
+ }
+ }
+
private fun showErrorViewOnError(message: String, error: Throwable) {
view?.run {
if (isViewEmpty) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
index caa3cb84d..17c14b85c 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt
@@ -2,12 +2,12 @@ package io.github.wulkanowy.ui.modules.grade.summary
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.GradeSummary
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach
@@ -18,7 +18,7 @@ class GradeSummaryPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val averageProvider: GradeAverageProvider,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private lateinit var lastError: Throwable
@@ -37,12 +37,28 @@ class GradeSummaryPresenter @Inject constructor(
}
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
+ Timber.i("Loading grade summary started")
+
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
}.onEach {
+ Timber.d("Loading grade summary status: ${it.status}, data: ${it.data != null}")
when (it.status) {
- Status.LOADING -> Timber.i("Loading grade summary started")
+ Status.LOADING -> {
+ val items = createGradeSummaryItems(it.data.orEmpty())
+ if (items.isNotEmpty()) {
+ Timber.i("Loading grade summary result: load cached data")
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showEmpty(false)
+ showContent(true)
+ updateData(items)
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading grade summary result: Success")
val items = createGradeSummaryItems(it.data!!)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
index e1d7ac52f..85173e91d 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt
@@ -83,8 +83,8 @@ class HomeworkFragment : BaseFragment(R.layout.fragment
binding.homeworkNavDate.text = date
}
- override fun hideRefresh() {
- binding.homeworkSwipe.isRefreshing = false
+ override fun showRefresh(show: Boolean) {
+ binding.homeworkSwipe.isRefreshing = show
}
override fun showEmpty(show: Boolean) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
index 8af0d83f6..11c54dc24 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt
@@ -2,12 +2,12 @@ package io.github.wulkanowy.ui.modules.homework
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Homework
-import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
-import io.github.wulkanowy.data.repositories.semester.SemesterRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.HomeworkRepository
+import io.github.wulkanowy.data.repositories.SemesterRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
@@ -29,7 +29,7 @@ class HomeworkPresenter @Inject constructor(
studentRepository: StudentRepository,
private val homeworkRepository: HomeworkRepository,
private val semesterRepository: SemesterRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay
@@ -44,24 +44,24 @@ class HomeworkPresenter @Inject constructor(
view.initView()
Timber.i("Homework view was initialized")
errorHandler.showErrorMessage = ::showErrorViewOnError
- loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
+ reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
+ loadData()
if (currentDate.isHolidays) setBaseDateOnHolidays()
- reloadView()
}
fun onPreviousDay() {
- loadData(currentDate.minusDays(7))
- reloadView()
+ reloadView(currentDate.minusDays(7))
+ loadData()
}
fun onNextDay() {
- loadData(currentDate.plusDays(7))
- reloadView()
+ reloadView(currentDate.plusDays(7))
+ loadData()
}
fun onSwipeRefresh() {
Timber.i("Force refreshing the homework")
- loadData(currentDate, true)
+ loadData(true)
}
fun onRetry() {
@@ -69,7 +69,7 @@ class HomeworkPresenter @Inject constructor(
showErrorView(false)
showProgress(true)
}
- loadData(currentDate, true)
+ loadData(true)
}
fun onDetailsClick() {
@@ -94,16 +94,26 @@ class HomeworkPresenter @Inject constructor(
}.launch("holidays")
}
- private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
- currentDate = date
+ private fun loadData(forceRefresh: Boolean = false) {
+ Timber.i("Loading homework data started")
flowWithResourceIn {
val student = studentRepository.getCurrentStudent()
val semester = semesterRepository.getCurrentSemester(student)
- homeworkRepository.getHomework(student, semester, date, date, forceRefresh)
+ homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh)
}.onEach {
when (it.status) {
- Status.LOADING -> Timber.i("Loading homework data started")
+ Status.LOADING -> {
+ if (!it.data.isNullOrEmpty()) {
+ view?.run {
+ enableSwipe(true)
+ showRefresh(true)
+ showProgress(false)
+ showContent(true)
+ updateData(createHomeworkItem(it.data))
+ }
+ }
+ }
Status.SUCCESS -> {
Timber.i("Loading homework result: Success")
view?.apply {
@@ -125,7 +135,7 @@ class HomeworkPresenter @Inject constructor(
}
}.afterLoading {
view?.run {
- hideRefresh()
+ showRefresh(false)
showProgress(false)
enableSwipe(true)
}
@@ -151,7 +161,9 @@ class HomeworkPresenter @Inject constructor(
}.flatten()
}
- private fun reloadView() {
+ private fun reloadView(date: LocalDate) {
+ currentDate = date
+
Timber.i("Reload homework view with the date ${currentDate.toFormattedString()}")
view?.apply {
showProgress(true)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
index 2a678cd4c..a1d6a04a9 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt
@@ -15,7 +15,7 @@ interface HomeworkView : BaseView {
fun updateNavigationWeek(date: String)
- fun hideRefresh()
+ fun showRefresh(show: Boolean)
fun showEmpty(show: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
index e485dd748..ca6fc71ee 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt
@@ -2,12 +2,12 @@ package io.github.wulkanowy.ui.modules.homework.details
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Homework
-import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.HomeworkRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
@@ -17,7 +17,7 @@ class HomeworkDetailsPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val homeworkRepository: HomeworkRepository,
- private val analytics: FirebaseAnalyticsHelper,
+ private val analytics: AnalyticsHelper,
private val preferencesRepository: PreferencesRepository
) : BasePresenter(errorHandler, studentRepository) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
index 749989e3a..aff1c84ca 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt
@@ -14,6 +14,7 @@ import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
+import io.github.wulkanowy.utils.UpdateHelper
import io.github.wulkanowy.utils.setOnSelectPageListener
import javax.inject.Inject
@@ -25,6 +26,9 @@ class LoginActivity : BaseActivity(), Logi
private val loginAdapter = BaseFragmentPagerAdapter(supportFragmentManager)
+ @Inject
+ lateinit var updateHelper: UpdateHelper
+
companion object {
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
@@ -37,8 +41,20 @@ class LoginActivity : BaseActivity(), Logi
setContentView(ActivityLoginBinding.inflate(layoutInflater).apply { binding = this }.root)
setSupportActionBar(binding.loginToolbar)
messageContainer = binding.loginContainer
+ updateHelper.messageContainer = binding.loginContainer
presenter.onAttachView(this)
+ updateHelper.checkAndInstallUpdates(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ updateHelper.onResume(this)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ updateHelper.onActivityResult(requestCode, resultCode)
}
override fun initView() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
index f30825cff..ed4563246 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt
@@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.modules.login
import android.content.res.Resources
import android.database.sqlite.SQLiteConstraintException
-import com.chuckerteam.chucker.api.ChuckerCollector
import io.github.wulkanowy.R
import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException
import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
@@ -12,10 +11,7 @@ import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
import io.github.wulkanowy.ui.base.ErrorHandler
import javax.inject.Inject
-class LoginErrorHandler @Inject constructor(
- resources: Resources,
- chuckerCollector: ChuckerCollector
-) : ErrorHandler(resources, chuckerCollector) {
+class LoginErrorHandler @Inject constructor(resources: Resources) : ErrorHandler(resources) {
var onBadCredentials: () -> Unit = {}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt
index 7e731772f..aa1e7eced 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt
@@ -1,7 +1,7 @@
package io.github.wulkanowy.ui.modules.login
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import timber.log.Timber
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
index dfe82ad8b..891a6b0bb 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt
@@ -2,11 +2,11 @@ package io.github.wulkanowy.ui.modules.login.advanced
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
@@ -17,7 +17,7 @@ import javax.inject.Inject
class LoginAdvancedPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
override fun onAttachView(view: LoginAdvancedView) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
index 41345686a..c6d0209da 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt
@@ -89,6 +89,8 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
}
}
+ override fun getHostsValues(): List = hostValues.toList()
+
override fun setCredentials(username: String, pass: String) {
with(binding) {
loginFormUsername.setText(username)
@@ -96,6 +98,12 @@ class LoginFormFragment : BaseFragment(R.layout.fragme
}
}
+ override fun setHost(host: String) {
+ binding.loginFormHost.setText(
+ hostKeys.getOrNull(hostValues.indexOf(host)).orEmpty()
+ )
+ }
+
override fun setUsernameLabel(label: String) {
binding.loginFormUsernameLayout.hint = label
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
index b921140c7..f6a528ae3 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt
@@ -1,10 +1,11 @@
package io.github.wulkanowy.ui.modules.login.form
+import androidx.core.net.toUri
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
@@ -15,7 +16,7 @@ import javax.inject.Inject
class LoginFormPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null
@@ -56,7 +57,7 @@ class LoginFormPresenter @Inject constructor(
fun updateUsernameLabel() {
view?.run {
- setUsernameLabel(if ("standard" in formHostValue) emailLabel else nicknameLabel)
+ setUsernameLabel(if ("email" !in formHostValue) nicknameLabel else emailLabel)
}
}
@@ -66,6 +67,16 @@ class LoginFormPresenter @Inject constructor(
fun onUsernameTextChanged() {
view?.clearUsernameError()
+
+ val username = view?.formUsernameValue.orEmpty().trim()
+ if ("@" in username && "@vulcan" !in username) {
+ val hosts = view?.getHostsValues().orEmpty().map { it.toUri().host to it }.toMap()
+ val usernameHost = username.substringAfter("@")
+
+ hosts[usernameHost]?.let {
+ view?.setHost(it)
+ }
+ }
}
fun onSignInClick() {
@@ -135,12 +146,12 @@ class LoginFormPresenter @Inject constructor(
view?.setErrorUsernameRequired()
isCorrect = false
} else {
- if ("@" in login && "standard" !in host) {
+ if ("@" in login && "login" in host) {
view?.setErrorLoginRequired()
isCorrect = false
}
- if ("@" !in login && "standard" in host) {
+ if ("@" !in login && "email" in host) {
view?.setErrorEmailRequired()
isCorrect = false
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
index 77e665389..31f8a6217 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt
@@ -19,8 +19,12 @@ interface LoginFormView : BaseView {
val emailLabel: String
+ fun getHostsValues(): List
+
fun setCredentials(username: String, pass: String)
+ fun setHost(host: String)
+
fun setUsernameLabel(label: String)
fun setErrorUsernameRequired()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt
index e58377058..271e8a8a0 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt
@@ -1,10 +1,10 @@
package io.github.wulkanowy.ui.modules.login.recover
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.recover.RecoverRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.RecoverRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
@@ -15,7 +15,7 @@ import javax.inject.Inject
class LoginRecoverPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: RecoverErrorHandler,
- private val analytics: FirebaseAnalyticsHelper,
+ private val analytics: AnalyticsHelper,
private val recoverRepository: RecoverRepository
) : BasePresenter(loginErrorHandler, studentRepository) {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt
index 110dd82e5..8619369dd 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt
@@ -1,17 +1,13 @@
package io.github.wulkanowy.ui.modules.login.recover
import android.content.res.Resources
-import com.chuckerteam.chucker.api.ChuckerCollector
import io.github.wulkanowy.sdk.scrapper.exception.InvalidCaptchaException
import io.github.wulkanowy.sdk.scrapper.exception.InvalidEmailException
import io.github.wulkanowy.sdk.scrapper.exception.NoAccountFoundException
import io.github.wulkanowy.ui.base.ErrorHandler
import javax.inject.Inject
-class RecoverErrorHandler @Inject constructor(
- resources: Resources,
- chuckerCollector: ChuckerCollector
-) : ErrorHandler(resources, chuckerCollector) {
+class RecoverErrorHandler @Inject constructor(resources: Resources) : ErrorHandler(resources) {
var onInvalidUsername: (String) -> Unit = {}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
index 1384f25a0..c344bf441 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt
@@ -3,10 +3,10 @@ package io.github.wulkanowy.ui.modules.login.studentselect
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
import kotlinx.coroutines.flow.onEach
@@ -17,7 +17,7 @@ import javax.inject.Inject
class LoginStudentSelectPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
index a2cda4fc1..4593d880a 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt
@@ -1,10 +1,10 @@
package io.github.wulkanowy.ui.modules.login.symbol
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
@@ -16,7 +16,7 @@ import javax.inject.Inject
class LoginSymbolPresenter @Inject constructor(
studentRepository: StudentRepository,
private val loginErrorHandler: LoginErrorHandler,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(loginErrorHandler, studentRepository) {
private var lastError: Throwable? = null
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
index 90aea441e..fd0598d8f 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt
@@ -1,11 +1,11 @@
package io.github.wulkanowy.ui.modules.luckynumber
import io.github.wulkanowy.data.Status
-import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.LuckyNumberRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResourceIn
import kotlinx.coroutines.flow.onEach
@@ -16,7 +16,7 @@ class LuckyNumberPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val luckyNumberRepository: LuckyNumberRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
private lateinit var lastError: Throwable
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
index 574120b36..f4041e9e4 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
index b7f4b740e..49a199431 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt
@@ -16,8 +16,8 @@ import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
-import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.LuckyNumberRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.toFirstResult
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
index 95b4aa77a..25b41aab5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt
@@ -38,8 +38,9 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.more.MoreFragment
import io.github.wulkanowy.ui.modules.note.NoteFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.UpdateHelper
import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.safelyPopFragments
@@ -54,7 +55,10 @@ class MainActivity : BaseActivity(), MainVie
override lateinit var presenter: MainPresenter
@Inject
- lateinit var analytics: FirebaseAnalyticsHelper
+ lateinit var analytics: AnalyticsHelper
+
+ @Inject
+ lateinit var updateHelper: UpdateHelper
@Inject
lateinit var appInfo: AppInfo
@@ -100,6 +104,7 @@ class MainActivity : BaseActivity(), MainVie
setContentView(ActivityMainBinding.inflate(layoutInflater).apply { binding = this }.root)
setSupportActionBar(binding.mainToolbar)
messageContainer = binding.mainFragmentContainer
+ updateHelper.messageContainer = binding.mainFragmentContainer
presenter.onAttachView(this, MainView.Section.values().singleOrNull { it.id == intent.getIntExtra(EXTRA_START_MENU, -1) })
@@ -107,6 +112,18 @@ class MainActivity : BaseActivity(), MainVie
initialize(startMenuIndex, savedInstanceState)
pushFragment(moreMenuFragments[startMenuMoreIndex])
}
+ updateHelper.checkAndInstallUpdates(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ updateHelper.onResume(this)
+ }
+
+ @SuppressLint("NewApi")
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ updateHelper.onActivityResult(requestCode, resultCode)
if (appInfo.systemVersion >= Build.VERSION_CODES.N_MR1) initShortcuts()
}
@@ -165,7 +182,10 @@ class MainActivity : BaseActivity(), MainVie
}
with(navController) {
- setOnViewChangeListener(presenter::onViewChange)
+ setOnViewChangeListener { section, name ->
+ analytics.setCurrentScreen(this@MainActivity, name)
+ presenter.onViewChange(section)
+ }
fragmentHideStrategy = HIDE
rootFragments = listOf(
GradeFragment.newInstance(),
@@ -177,12 +197,8 @@ class MainActivity : BaseActivity(), MainVie
}
}
- override fun setCurrentScreen(name: String?) {
- analytics.setCurrentScreen(this, name)
- }
-
- override fun onOptionsItemSelected(item: MenuItem?): Boolean {
- return if (item?.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected()
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected()
else false
}
@@ -191,6 +207,7 @@ class MainActivity : BaseActivity(), MainVie
}
override fun switchMenuView(position: Int) {
+ analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.switchTab(position)
}
@@ -228,10 +245,12 @@ class MainActivity : BaseActivity(), MainVie
}
fun pushView(fragment: Fragment) {
+ analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.pushFragment(fragment)
}
override fun popView(depth: Int) {
+ analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName)
navController.safelyPopFragments(depth)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
index 8d5c9d67f..59937b332 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt
@@ -1,14 +1,14 @@
package io.github.wulkanowy.ui.modules.main
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.services.sync.SyncManager
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE
import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE
import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
+import io.github.wulkanowy.utils.AnalyticsHelper
import timber.log.Timber
import javax.inject.Inject
@@ -17,7 +17,7 @@ class MainPresenter @Inject constructor(
studentRepository: StudentRepository,
private val prefRepository: PreferencesRepository,
private val syncManager: SyncManager,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
fun onAttachView(view: MainView, initMenu: MainView.Section?) {
@@ -35,9 +35,8 @@ class MainPresenter @Inject constructor(
analytics.logEvent("app_open", "destination" to initMenu?.name)
}
- fun onViewChange(section: MainView.Section?, name: String?) {
+ fun onViewChange(section: MainView.Section?) {
view?.apply {
- setCurrentScreen(name)
showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL)
currentViewTitle?.let { setViewTitle(it) }
currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) }
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
index 7e5831471..97b556e3e 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt
@@ -24,8 +24,6 @@ interface MainView : BaseView {
fun showAccountPicker()
- fun setCurrentScreen(name: String?)
-
fun showActionBarElevation(show: Boolean)
fun notifyMenuViewReselected()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
index 16e0184a0..72fc627f8 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt
@@ -6,9 +6,9 @@ import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
-import io.github.wulkanowy.data.repositories.message.MessageFolder.SENT
-import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
+import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
+import io.github.wulkanowy.data.enums.MessageFolder.SENT
+import io.github.wulkanowy.data.enums.MessageFolder.TRASHED
import io.github.wulkanowy.databinding.FragmentMessageBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
index 0fb454b31..7b8c3d0f5 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt
@@ -1,6 +1,6 @@
package io.github.wulkanowy.ui.modules.message
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import kotlinx.coroutines.delay
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 740f4927c..74f8f57ec 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -65,6 +65,9 @@ class MessagePreviewFragment :
override val printHTML: String
get() = requireContext().assets.open("message-print-page.html").bufferedReader().use { it.readText() }
+ override val messageNotExists: String
+ get() = getString(R.string.message_not_exists)
+
companion object {
const val MESSAGE_ID_KEY = "message_id"
@@ -174,7 +177,7 @@ class MessagePreviewFragment :
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun printDocument(html: String, jobName: String) {
- val webView = WebView(activity)
+ val webView = WebView(requireContext())
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
index 7a633a2df..55b9631af 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
@@ -5,13 +5,13 @@ import android.os.Build
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment
-import io.github.wulkanowy.data.repositories.message.MessageFolder
-import io.github.wulkanowy.data.repositories.message.MessageRepository
-import io.github.wulkanowy.data.repositories.student.StudentRepository
+import io.github.wulkanowy.data.enums.MessageFolder
+import io.github.wulkanowy.data.repositories.MessageRepository
+import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.flowWithResourceIn
@@ -24,7 +24,7 @@ class MessagePreviewPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val messageRepository: MessageRepository,
- private val analytics: FirebaseAnalyticsHelper,
+ private val analytics: AnalyticsHelper,
private var appInfo: AppInfo
) : BasePresenter