diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index cdce0759b..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,4 +0,0 @@ -# These are supported funding model platforms - -github: wulkanowy -custom: https://www.paypal.com/paypalme/wulkanowy diff --git a/.github/workflows/deploy-store.yml b/.github/workflows/deploy-store.yml index e8237a381..3ce618ca7 100644 --- a/.github/workflows/deploy-store.yml +++ b/.github/workflows/deploy-store.yml @@ -13,10 +13,10 @@ jobs: environment: google-play steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | @@ -49,10 +49,10 @@ jobs: environment: app-gallery steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | diff --git a/.github/workflows/deploy-test.yml b/.github/workflows/deploy-test.yml index c4f55e6af..20082590d 100644 --- a/.github/workflows/deploy-test.yml +++ b/.github/workflows/deploy-test.yml @@ -19,10 +19,10 @@ jobs: environment: app-center steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | @@ -89,10 +89,10 @@ jobs: if: github.event_name != 'pull_request_target' steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d50c45d5..3def08953 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,12 +2,10 @@ name: Tests on: push: - branches: - - master - - develop - - 'hotfix/**' + branches: [ master, develop ] tags: [ '*' ] pull_request: + branches: [ master, develop ] jobs: @@ -19,10 +17,10 @@ jobs: - uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | @@ -45,10 +43,10 @@ jobs: - uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | @@ -71,10 +69,10 @@ jobs: - uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: 17 + java-version: 11 - uses: actions/cache@v3 with: path: | diff --git a/.gitignore b/.gitignore index 69d3ad5d2..cd5ff7146 100644 --- a/.gitignore +++ b/.gitignore @@ -65,12 +65,6 @@ captures/ .idea/uiDesigner.xml .idea/runConfigurations.xml .idea/discord.xml -.idea/migrations.xml -.idea/androidTestResultsUserPreferences.xml -.idea/copilot -.idea/deploymentTargetDropDown.xml -.idea/deploymentTargetSelector.xml -.idea/kotlinc.xml # Keystore files *.jks @@ -125,4 +119,3 @@ Thumbs.db app/src/release/agconnect-services.json app/src/release/agconnect-credentials.json .idea/deploymentTargetDropDown.xml -.idea/kotlinc.xml diff --git a/LICENSE b/LICENSE index a1fc37058..c97032f74 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2023 Wulkanowy + Copyright 2022 Wulkanowy Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.cs.md b/README.cs.md index 8171b27d6..d3d4e2557 100644 --- a/README.cs.md +++ b/README.cs.md @@ -2,7 +2,7 @@ # Wulkanowy -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Tests/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) diff --git a/README.de.md b/README.de.md index 972f66ba9..853abd13e 100644 --- a/README.de.md +++ b/README.de.md @@ -2,7 +2,7 @@ # Wulkanowy -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Tests/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) diff --git a/README.en.md b/README.en.md index 6e4da4637..7877bf377 100644 --- a/README.en.md +++ b/README.en.md @@ -2,7 +2,7 @@ # Wulkanowy -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Tests/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) diff --git a/README.md b/README.md index f3d2e29a2..09480e7d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Wulkanowy -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Tests/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) diff --git a/README.sk.md b/README.sk.md index ff0c6e3c9..64786556e 100644 --- a/README.sk.md +++ b/README.sk.md @@ -2,7 +2,7 @@ # Wulkanowy -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wulkanowy/wulkanowy/test.yml?branch=develop&style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Tests/develop?style=flat-square)](https://github.com/wulkanowy/wulkanowy/actions) [![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) [![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr) [![F-Droid](https://img.shields.io/f-droid/v/io.github.wulkanowy.svg?style=flat-square)](https://f-droid.org/packages/io.github.wulkanowy/) diff --git a/app/build.gradle b/app/build.gradle index e3e8a7e00..f6a82ad20 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,8 @@ -import com.github.triplet.gradle.androidpublisher.ReleaseStatus -import ru.cian.huawei.publish.ReleaseNote - apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlinx-serialization' apply plugin: 'kotlin-parcelize' -apply plugin: 'com.google.devtools.ksp' +apply plugin: 'kotlin-kapt' apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' @@ -13,29 +10,37 @@ apply plugin: 'com.github.triplet.play' apply plugin: 'ru.cian.huawei-publish' apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'com.huawei.agconnect' -apply plugin: 'kotlin-kapt' apply from: 'jacoco.gradle' apply from: 'sonarqube.gradle' apply from: 'hooks.gradle' android { namespace 'io.github.wulkanowy' - compileSdk 34 + compileSdkVersion 32 defaultConfig { applicationId "io.github.wulkanowy" testApplicationId "io.github.tests.wulkanowy" minSdkVersion 21 - targetSdkVersion 34 - versionCode 155 - versionName "2.5.6" + targetSdkVersion 32 + versionCode 116 + versionName "1.8.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" resValue "string", "app_name", "Wulkanowy" + manifestPlaceholders = [ firebase_enabled: project.hasProperty("enableFirebase"), admob_project_id: "" ] + javaCompileOptions { + annotationProcessorOptions { + arguments += [ + "room.schemaLocation": "$projectDir/schemas".toString(), + "room.incremental" : "true" + ] + } + } buildConfigField "String", "SINGLE_SUPPORT_AD_ID", "null" buildConfigField "String", "DASHBOARD_TILE_AD_ID", "null" @@ -68,7 +73,6 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\"" - buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"' } debug { minifyEnabled false @@ -78,11 +82,10 @@ android { versionNameSuffix "-dev" ext.enableCrashlytics = project.hasProperty("enableFirebase") buildConfigField "String", "MESSAGES_BASE_URL", "\"https://messages.wulkanowy.net.pl\"" - buildConfigField "String", "SCHOOLS_BASE_URL", '"https://schools.wulkanowy.net.pl"' } } - flavorDimensions += "platform" + flavorDimensions "platform" productFlavors { hms { @@ -113,7 +116,6 @@ android { buildFeatures { viewBinding true - buildConfig true } bundle { @@ -122,29 +124,27 @@ android { } } - testOptions { - unitTests.includeAndroidResources = true + testOptions.unitTests { + includeAndroidResources = true // workaround HMS test errors https://github.com/robolectric/robolectric/issues/2750 - unitTests.all { jvmArgs '-noverify' } + all { jvmArgs '-noverify' } } compileOptions { coreLibraryDesugaringEnabled true - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = "17" + jvmTarget = "11" freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all"] } packagingOptions { resources { excludes += ['META-INF/library_release.kotlin_module', - 'META-INF/library-core_release.kotlin_module', - 'META-INF/LICENSE.md', - 'META-INF/LICENSE-notice.md'] + 'META-INF/library-core_release.kotlin_module'] } } @@ -156,16 +156,13 @@ android { kapt { correctErrorTypes true } -ksp { - arg("room.schemaLocation", "$projectDir/schemas".toString()) -} play { defaultToAppBundles = false track = 'production' - releaseStatus = ReleaseStatus.IN_PROGRESS - userFraction = 0.99d - updatePriority = 3 + releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS + userFraction = 0.10d + updatePriority = 4 enabled.set(false) } @@ -174,60 +171,54 @@ huaweiPublish { hmsRelease { credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json" buildFormat = "aab" - deployType = "publish" - releaseNotes = [ - new ReleaseNote( - "pl-PL", - "$projectDir/src/main/play/release-notes/pl-PL/default.txt" - ) - ] + deployType = "draft" } } } ext { - work_manager = "2.9.0" - android_hilt = "1.2.0" - room = "2.6.1" - chucker = "4.0.0" - mockk = "1.13.10" - coroutines = "1.8.0" + work_manager = "2.7.1" + android_hilt = "1.0.0" + room = "2.4.3" + chucker = "3.5.2" + mockk = "1.13.2" + coroutines = "1.6.4" } dependencies { - implementation 'io.github.wulkanowy:sdk:2.5.6' + implementation "io.github.wulkanowy:sdk:1.8.1" - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8' - implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines" - implementation 'androidx.core:core-ktx:1.12.0' - implementation 'androidx.core:core-splashscreen:1.0.1' - implementation "androidx.activity:activity-ktx:1.8.2" - implementation "androidx.appcompat:appcompat:1.6.1" - implementation "androidx.fragment:fragment-ktx:1.6.2" - implementation "androidx.annotation:annotation:1.7.1" + implementation "androidx.core:core-ktx:1.8.0" + implementation 'androidx.core:core-splashscreen:1.0.0' + implementation "androidx.activity:activity-ktx:1.5.1" + implementation "androidx.appcompat:appcompat:1.5.1" + implementation "androidx.fragment:fragment-ktx:1.5.4" + implementation "androidx.annotation:annotation:1.5.0" - implementation "androidx.preference:preference-ktx:1.2.1" - implementation "androidx.recyclerview:recyclerview:1.3.2" - implementation "androidx.viewpager2:viewpager2:1.1.0-beta02" + implementation "androidx.preference:preference-ktx:1.2.0" + implementation "androidx.recyclerview:recyclerview:1.2.1" + implementation "androidx.viewpager2:viewpager2:1.1.0-beta01" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0" - implementation "com.google.android.material:material:1.10.0" + implementation "com.google.android.material:material:1.7.0" implementation "com.github.wulkanowy:material-chips-input:2.3.1" implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" implementation 'com.github.lopspower:CircularImageView:4.3.0' - implementation "androidx.work:work-runtime:$work_manager" + implementation "androidx.work:work-runtime-ktx:$work_manager" playImplementation "androidx.work:work-gcm:$work_manager" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.7.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-ktx:$room" - ksp "androidx.room:room-compiler:$room" + kapt "androidx.room:room-compiler:$room" implementation "com.google.dagger:hilt-android:$hilt_version" kapt "com.google.dagger:hilt-android-compiler:$hilt_version" @@ -238,38 +229,32 @@ dependencies { implementation "com.github.YarikSOffice:lingver:1.3.0" implementation 'com.squareup.retrofit2:retrofit:2.9.0' - implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0" - implementation "com.squareup.okhttp3:logging-interceptor:4.12.0" - implementation "com.squareup.okhttp3:okhttp-urlconnection:4.12.0" + implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0" + implementation "com.squareup.okhttp3:logging-interceptor:4.10.0" implementation "com.jakewharton.timber:timber:5.0.1" - implementation 'com.github.Faierbel:slf4j-timber:2.0' - implementation 'com.github.bastienpaulfr:Treessence:1.1.2' + implementation "at.favre.lib:slf4j-timber:1.0.1" + implementation 'com.github.bastienpaulfr:Treessence:1.0.5' implementation "com.mikepenz:aboutlibraries-core:$about_libraries" - implementation 'io.coil-kt:coil:2.6.0' - implementation "io.github.wulkanowy:AppKillerManager:3.0.1" + implementation "io.coil-kt:coil:2.2.2" + implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.4.0' - implementation 'com.fredporciuncula:flow-preferences:1.9.1' - implementation 'org.apache.commons:commons-text:1.11.0' + implementation 'com.fredporciuncula:flow-preferences:1.8.0' - playImplementation platform('com.google.firebase:firebase-bom:32.7.3') - playImplementation 'com.google.firebase:firebase-analytics' - playImplementation 'com.google.firebase:firebase-messaging' + playImplementation platform('com.google.firebase:firebase-bom:31.0.3') + playImplementation 'com.google.firebase:firebase-analytics-ktx' + playImplementation 'com.google.firebase:firebase-messaging:' playImplementation 'com.google.firebase:firebase-crashlytics:' - playImplementation 'com.google.firebase:firebase-config' + playImplementation 'com.google.android.play:core:1.10.3' + playImplementation 'com.google.android.play:core-ktx:1.8.1' + playImplementation 'com.google.android.gms:play-services-ads:21.3.0' - playImplementation 'com.google.android.gms:play-services-ads:22.6.0' - playImplementation "com.google.android.play:integrity:1.3.0" - playImplementation 'com.google.android.play:app-update-ktx:2.1.0' - playImplementation 'com.google.android.play:review-ktx:2.0.1' - playImplementation "com.google.android.ump:user-messaging-platform:2.1.0" + hmsImplementation 'com.huawei.hms:hianalytics:6.8.0.300' + hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.7.3.300' - hmsImplementation 'com.huawei.hms:hianalytics:6.12.0.301' - hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.9.1.303' + releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" - releaseImplementation "com.github.chuckerteam.chucker:library-no-op:$chucker" - - debugImplementation "com.github.chuckerteam.chucker:library:$chucker" + debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker" debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:1.0.6' debugImplementation 'com.github.haroldadmin:WhatTheStack:1.0.0-alpha04' @@ -278,17 +263,17 @@ dependencies { testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines" testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" - testImplementation 'org.robolectric:robolectric:4.11.1' - testImplementation "androidx.test:runner:1.5.2" - testImplementation "androidx.test.ext:junit:1.1.5" + testImplementation 'org.robolectric:robolectric:4.9' + testImplementation "androidx.test:runner:1.5.1" + testImplementation "androidx.test.ext:junit:1.1.4" testImplementation "androidx.test:core:1.5.0" testImplementation "androidx.room:room-testing:$room" testImplementation "com.google.dagger:hilt-android-testing:$hilt_version" kaptTest "com.google.dagger:hilt-android-compiler:$hilt_version" - androidTestImplementation "androidx.test:core:1.5.0" - androidTestImplementation "androidx.test:runner:1.5.2" - androidTestImplementation "androidx.test.ext:junit:1.1.5" + androidTestImplementation "androidx.test:core:1.4.0" + androidTestImplementation "androidx.test:runner:1.4.0" + androidTestImplementation "androidx.test.ext:junit:1.1.3" androidTestImplementation "io.mockk:mockk-android:$mockk" androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" } diff --git a/app/jacoco.gradle b/app/jacoco.gradle index 67ffdb13b..f253673e6 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -1,16 +1,16 @@ apply plugin: "jacoco" jacoco { - toolVersion "0.8.11" + toolVersion "0.8.7" reportsDirectory.set(file("$buildDir/reports")) } -tasks.withType(Test).configureEach { +tasks.withType(Test) { jacoco.includeNoLocationClasses = true jacoco.excludes = ['jdk.internal.*'] } -tasks.register('jacocoTestReport', JacocoReport) { +task jacocoTestReport(type: JacocoReport) { group = "Reporting" description = "Generate Jacoco coverage reports" @@ -33,19 +33,19 @@ tasks.register('jacocoTestReport', JacocoReport) { '**/*_Factory.*'] classDirectories.setFrom(fileTree( - dir: "$buildDir/intermediates/classes/debug", - excludes: excludes + dir: "$buildDir/intermediates/classes/debug", + excludes: excludes ) + fileTree( - dir: "$buildDir/tmp/kotlin-classes/fdroidDebug", - excludes: excludes + dir: "$buildDir/tmp/kotlin-classes/fdroidDebug", + excludes: excludes )) sourceDirectories.setFrom(files([ - "src/main/java", - "src/fdroid/java" + "src/main/java", + "src/fdroid/java" ])) executionData.setFrom(fileTree( - dir: project.projectDir, - includes: ["**/*.exec", "**/*.ec"] + dir: project.projectDir, + includes: ["**/*.exec", "**/*.ec"] )) } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 0fd49f6ac..fd9482613 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,5 @@ # General -dontobfuscate --ignorewarnings #Config for wulkanowy @@ -25,18 +24,3 @@ #Config for Material Components -keep class com.google.android.material.tabs.** { *; } - - -#Config for HMS SDK --keepattributes *Annotation* --keepattributes Exceptions --keepattributes InnerClasses --keepattributes Signature --keep class com.huawei.agconnect.**{*;} --keep class com.huawei.hianalytics.**{*;} --keep class com.huawei.updatesdk.**{*;} --keep class com.huawei.hms.**{*;} - - -#Config for Wulkanowy SDK --keep,allowobfuscation,allowshrinking class retrofit2.Response diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/54.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/54.json deleted file mode 100644 index 7b41672b9..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/54.json +++ /dev/null @@ -1,2439 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 54, - "identityHash": "1dc96a366125ec9f8567da87cdc9c863", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "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" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_global_key` 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": "messageGlobalKey", - "columnName": "message_global_key", - "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}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "globalKey" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `type` TEXT NOT NULL, `is_dismissible` INTEGER NOT NULL, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isDismissible", - "columnName": "is_dismissible", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": false - }, - "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, '1dc96a366125ec9f8567da87cdc9c863')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json deleted file mode 100644 index 60c2efbe0..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/55.json +++ /dev/null @@ -1,2435 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 55, - "identityHash": "cba22eea6d26cf4d6b9a388ba3329a12", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "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" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "message_global_key", - "url", - "filename" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "globalKey" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `type` TEXT NOT NULL, `is_dismissible` INTEGER NOT NULL, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isDismissible", - "columnName": "is_dismissible", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": false - }, - "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, 'cba22eea6d26cf4d6b9a388ba3329a12')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/56.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/56.json deleted file mode 100644 index 1a26e717b..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/56.json +++ /dev/null @@ -1,2442 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 56, - "identityHash": "48f0538bd21601eb5322a7d850e04134", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `type` TEXT NOT NULL, `is_dismissible` INTEGER NOT NULL, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isDismissible", - "columnName": "is_dismissible", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "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, '48f0538bd21601eb5322a7d850e04134')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/57.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/57.json deleted file mode 100644 index 2eff12231..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/57.json +++ /dev/null @@ -1,2443 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 57, - "identityHash": "d15dbe7d7e4d7df98ec98d9a3a4b5fcd", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_dismissible` INTEGER NOT NULL, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isDismissible", - "columnName": "is_dismissible", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "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, 'd15dbe7d7e4d7df98ec98d9a3a4b5fcd')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/58.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/58.json deleted file mode 100644 index e6e71229c..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/58.json +++ /dev/null @@ -1,2451 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 58, - "identityHash": "cd1d4f8f2b6e3860fbc1de93d4f5ca42", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "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, 'cd1d4f8f2b6e3860fbc1de93d4f5ca42')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/59.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/59.json deleted file mode 100644 index a3f2e0dc6..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/59.json +++ /dev/null @@ -1,2501 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 59, - "identityHash": "3bd95e40b587e8131a2a2c23aee538c1", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesDescriptive", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "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, '3bd95e40b587e8131a2a2c23aee538c1')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json deleted file mode 100644 index 20eacad1c..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json +++ /dev/null @@ -1,2527 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 60, - "identityHash": "3672d3f4d5e6b874e5a22d2bb458dc65", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MutedMessageSenders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`author` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesDescriptive", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "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, '3672d3f4d5e6b874e5a22d2bb458dc65')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/61.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/61.json deleted file mode 100644 index e36dcc8a6..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/61.json +++ /dev/null @@ -1,2533 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 61, - "identityHash": "41fbd2ff00aba10b2ef0a079e6037c87", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `author` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MutedMessageSenders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`author` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesDescriptive", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "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, '41fbd2ff00aba10b2ef0a079e6037c87')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/62.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/62.json deleted file mode 100644 index ab63c679f..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/62.json +++ /dev/null @@ -1,2547 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 62, - "identityHash": "ee2464d218b254ca868667c0fc756c0b", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `is_authorized` INTEGER NOT NULL DEFAULT 0, `is_edu_one` INTEGER NOT NULL DEFAULT 0, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "isAuthorized", - "columnName": "is_authorized", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isEduOne", - "columnName": "is_edu_one", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `author` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MutedMessageSenders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`author` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesDescriptive", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "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, 'ee2464d218b254ca868667c0fc756c0b')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/63.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/63.json deleted file mode 100644 index 9c774bb4d..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/63.json +++ /dev/null @@ -1,2547 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 63, - "identityHash": "8c04a56e74b1c4f55302f28ede94cac0", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `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, `is_authorized` INTEGER NOT NULL DEFAULT 0, `is_edu_one` INTEGER DEFAULT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperDomainSuffix", - "columnName": "scrapper_domain_suffix", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "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 - }, - { - "fieldPath": "isAuthorized", - "columnName": "is_authorized", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isEduOne", - "columnName": "is_edu_one", - "affinity": "INTEGER", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "orders": [], - "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}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "kindergartenDiaryId", - "columnName": "kindergarten_diary_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "kindergarten_diary_id", - "semester_id" - ], - "orders": [], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)", - "fields": [ - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mailboxKey", - "columnName": "mailbox_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "correspondents", - "columnName": "correspondents", - "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": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "recipients", - "columnName": "recipients", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))", - "fields": [ - { - "fieldPath": "messageGlobalKey", - "columnName": "message_global_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "message_global_key", - "url", - "filename" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "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 - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Mailboxes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))", - "fields": [ - { - "fieldPath": "globalKey", - "columnName": "globalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolId", - "columnName": "schoolId", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "studentName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolNameShort", - "columnName": "schoolNameShort", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "globalKey" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Recipients", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "mailboxGlobalKey", - "columnName": "mailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentMailboxGlobalKey", - "columnName": "studentMailboxGlobalKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "fullName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "userName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "schoolShortName", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MobileDevices", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)", - "fields": [ - { - "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 - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "repeatId", - "columnName": "repeat_id", - "affinity": "BLOB", - "notNull": false, - "defaultValue": "NULL" - }, - { - "fieldPath": "isAddedByUser", - "columnName": "is_added_by_user", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableHeaders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "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": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "SchoolAnnouncements", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `author` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notifications", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "destination", - "columnName": "destination", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'" - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "data", - "columnName": "data", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AdminMessages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "versionMin", - "columnName": "version_name", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMax", - "columnName": "version_max", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "targetRegisterHost", - "columnName": "target_register_host", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "targetFlavor", - "columnName": "target_flavor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "destinationUrl", - "columnName": "destination_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "priority", - "columnName": "priority", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "types", - "columnName": "types", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'[]'" - }, - { - "fieldPath": "isOkVisible", - "columnName": "is_ok_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "isXVisible", - "columnName": "is_x_visible", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - } - ], - "primaryKey": { - "autoGenerate": false, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MutedMessageSenders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`author` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", - "fields": [ - { - "fieldPath": "author", - "columnName": "author", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesDescriptive", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)", - "fields": [ - { - "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": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "id" - ] - }, - "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, '8c04a56e74b1c4f55302f28ede94cac0')" - ] - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt b/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt index 1b0319f69..0c47e6bb6 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt @@ -14,37 +14,34 @@ import kotlin.test.assertFailsWith @RunWith(AndroidJUnit4::class) class ScramblerTest { - private val scrambler = Scrambler(ApplicationProvider.getApplicationContext()) - @Test fun encryptDecryptTest() { - assertEquals( - "TEST", scrambler.decrypt(scrambler.encrypt("TEST")) - ) + assertEquals("TEST", decrypt(encrypt("TEST", + ApplicationProvider.getApplicationContext()))) } @Test fun emptyTextEncryptTest() { assertFailsWith { - scrambler.decrypt("") + decrypt("") } assertFailsWith { - scrambler.encrypt("") + encrypt("", ApplicationProvider.getApplicationContext()) } } @Test @SdkSuppress(minSdkVersion = 18) fun emptyKeyStoreTest() { - val text = scrambler.encrypt("test") + val text = encrypt("test", ApplicationProvider.getApplicationContext()) val keyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) keyStore.deleteEntry("wulkanowy_password") assertFailsWith { - scrambler.decrypt(text) + decrypt(text) } } } diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml index 9c21d49d9..7dbec2cb9 100644 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,5 @@ - + - - + \ No newline at end of file diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..7dbec2cb9 --- /dev/null +++ b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..81e723ecc Binary files /dev/null and b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..394b57076 Binary files /dev/null and b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..365b4d663 Binary files /dev/null and b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..463c089b3 Binary files /dev/null and b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..53d6f5bbd Binary files /dev/null and b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt index 3a3b5948f..461d29951 100644 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt +++ b/app/src/fdroid/java/io/github/wulkanowy/utils/AdsHelper.kt @@ -5,7 +5,6 @@ import android.view.View import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.ui.modules.dashboard.DashboardItem -import kotlinx.coroutines.flow.MutableStateFlow import javax.inject.Inject @Suppress("unused") @@ -14,11 +13,9 @@ class AdsHelper @Inject constructor( private val preferencesRepository: PreferencesRepository ) { - val isMobileAdsSdkInitialized = MutableStateFlow(false) - val canShowAd = false - fun initialize() { preferencesRepository.isAdsEnabled = false + preferencesRepository.isAgreeToProcessData = false preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS } diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt deleted file mode 100644 index 51b22ec74..000000000 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.utils - -import android.view.View -import javax.inject.Inject - -class InAppUpdateHelper @Inject constructor() { - - lateinit var messageContainer: View - - fun checkAndInstallUpdates() {} - - fun onResume() {} -} diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/IntegrityHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/IntegrityHelper.kt deleted file mode 100644 index 7af68058c..000000000 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/IntegrityHelper.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.utils - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class IntegrityHelper @Inject constructor() { - - @Suppress("UNUSED_PARAMETER") - fun getIntegrityToken(requestId: String): String? = null -} diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt deleted file mode 100644 index 88f2598f8..000000000 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.utils - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper() 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/AdsHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/AdsHelper.kt index 165a6204f..0e9227022 100644 --- a/app/src/hms/java/io/github/wulkanowy/utils/AdsHelper.kt +++ b/app/src/hms/java/io/github/wulkanowy/utils/AdsHelper.kt @@ -5,7 +5,6 @@ import android.view.View import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.ui.modules.dashboard.DashboardItem -import kotlinx.coroutines.flow.MutableStateFlow import javax.inject.Inject @Suppress("unused") @@ -13,11 +12,10 @@ class AdsHelper @Inject constructor( @ApplicationContext private val context: Context, private val preferencesRepository: PreferencesRepository ) { - val isMobileAdsSdkInitialized = MutableStateFlow(false) - val canShowAd = false fun initialize() { preferencesRepository.isAdsEnabled = false + preferencesRepository.isAgreeToProcessData = false preferencesRepository.selectedDashboardTiles -= DashboardItem.Tile.ADS } diff --git a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt index 2b1f1d30e..377e83666 100644 --- a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt +++ b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt @@ -2,8 +2,8 @@ package io.github.wulkanowy.utils import android.util.Log import com.huawei.agconnect.crash.AGConnectCrash -import fr.bipi.treessence.base.FormatterPriorityTree -import fr.bipi.treessence.common.StackTraceRecorder +import fr.bipi.tressence.base.FormatterPriorityTree +import fr.bipi.tressence.common.StackTraceRecorder class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) { diff --git a/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt deleted file mode 100644 index 51b22ec74..000000000 --- a/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.utils - -import android.view.View -import javax.inject.Inject - -class InAppUpdateHelper @Inject constructor() { - - lateinit var messageContainer: View - - fun checkAndInstallUpdates() {} - - fun onResume() {} -} diff --git a/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt deleted file mode 100644 index 7af68058c..000000000 --- a/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.utils - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class IntegrityHelper @Inject constructor() { - - @Suppress("UNUSED_PARAMETER") - fun getIntegrityToken(requestId: String): String? = null -} diff --git a/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt deleted file mode 100644 index 88f2598f8..000000000 --- a/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.utils - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper() 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 f43dfdd2c..7835db902 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,8 +8,7 @@ - - + @@ -37,15 +36,13 @@ + tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"> Resource.dataOrNull: T? get() = when (this) { is Resource.Success -> this.data is Resource.Intermediate -> this.data - else -> null - } - -val Resource.dataOrThrow: T - get() = when (this) { - is Resource.Success -> this.data - is Resource.Intermediate -> this.data - is Resource.Loading -> throw IllegalStateException("Resource is in loading state") - is Resource.Error -> throw this.error + is Resource.Loading -> null + is Resource.Error -> null } val Resource.errorOrNull: Throwable? @@ -148,7 +131,7 @@ inline fun networkBoundResource( query().map { Resource.Success(filterResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) - flowOf(Resource.Error(throwable)) + query().map { Resource.Error(throwable) } } } else { query().map { Resource.Success(filterResult(it)) } @@ -165,7 +148,7 @@ inline fun networkBoundResource( crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, crossinline onFetchFailed: (Throwable) -> Unit = { }, crossinline shouldFetch: (ResultType) -> Boolean = { true }, - crossinline mapResult: (ResultType) -> T, + crossinline mapResult: (ResultType) -> T ) = flow { emit(Resource.Loading()) @@ -182,7 +165,7 @@ inline fun networkBoundResource( query().map { Resource.Success(mapResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) - flowOf(Resource.Error(throwable)) + query().map { Resource.Error(throwable) } } } else { query().map { Resource.Success(mapResult(it)) } diff --git a/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt b/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt deleted file mode 100644 index 83268a0e5..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt +++ /dev/null @@ -1,125 +0,0 @@ -package io.github.wulkanowy.data - -import com.chuckerteam.chucker.api.ChuckerInterceptor -import io.github.wulkanowy.data.db.dao.StudentDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentIsEduOne -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.RemoteConfigHelper -import io.github.wulkanowy.utils.WebkitCookieManagerProxy -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import timber.log.Timber -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class WulkanowySdkFactory @Inject constructor( - private val chuckerInterceptor: ChuckerInterceptor, - private val remoteConfig: RemoteConfigHelper, - private val webkitCookieManagerProxy: WebkitCookieManagerProxy, - private val studentDb: StudentDao, -) { - - private val eduOneMutex = Mutex() - private val migrationFailedStudentIds = mutableSetOf() - - private val sdk = Sdk().apply { - androidVersion = android.os.Build.VERSION.RELEASE - buildTag = android.os.Build.MODEL - userAgentTemplate = remoteConfig.userAgentTemplate - setSimpleHttpLogger { Timber.d(it) } - setAdditionalCookieManager(webkitCookieManagerProxy) - - // for debug only - addInterceptor(chuckerInterceptor, network = true) - } - - fun create() = sdk - - suspend fun create(student: Student, semester: Semester? = null): Sdk { - val overrideIsEduOne = checkEduOneAndMigrateIfNecessary(student) - return buildSdk(student, semester, overrideIsEduOne) - } - - private fun buildSdk(student: Student, semester: Semester?, isStudentEduOne: Boolean): Sdk { - return create().apply { - email = student.email - password = student.password - symbol = student.symbol - schoolSymbol = student.schoolSymbol - studentId = student.studentId - classId = student.classId - emptyCookieJarInterceptor = true - isEduOne = isStudentEduOne - - if (Sdk.Mode.valueOf(student.loginMode) == Sdk.Mode.HEBE) { - mobileBaseUrl = student.mobileBaseUrl - } else { - scrapperBaseUrl = student.scrapperBaseUrl - domainSuffix = student.scrapperDomainSuffix - loginType = Sdk.ScrapperLoginType.valueOf(student.loginType) - } - - mode = Sdk.Mode.valueOf(student.loginMode) - mobileBaseUrl = student.mobileBaseUrl - keyId = student.certificateKey - privatePem = student.privateKey - - if (semester != null) { - diaryId = semester.diaryId - kindergartenDiaryId = semester.kindergartenDiaryId - schoolYear = semester.schoolYear - unitId = semester.unitId - } - } - } - - private suspend fun checkEduOneAndMigrateIfNecessary(student: Student): Boolean { - if (student.isEduOne != null) return student.isEduOne - - if (student.id in migrationFailedStudentIds) { - Timber.i("Migration eduOne: skipping because of previous failure") - return false - } - - eduOneMutex.withLock { - if (student.id in migrationFailedStudentIds) { - Timber.i("Migration eduOne: skipping because of previous failure") - return false - } - - val studentFromDatabase = studentDb.loadById(student.id) - if (studentFromDatabase?.isEduOne != null) { - Timber.i("Migration eduOne: already done") - return studentFromDatabase.isEduOne - } - - Timber.i("Migration eduOne: flag missing. Running migration...") - val initializedSdk = buildSdk( - student = student, - semester = null, - isStudentEduOne = false, // doesn't matter - ) - val newCurrentStudent = runCatching { initializedSdk.getCurrentStudent() } - .onFailure { Timber.e(it, "Migration eduOne: can't get current student") } - .getOrNull() - - if (newCurrentStudent == null) { - Timber.i("Migration eduOne: failed, so skipping") - migrationFailedStudentIds.add(student.id) - return false - } - - Timber.i("Migration eduOne: success. New isEduOne flag: ${newCurrentStudent.isEduOne}") - - val studentIsEduOne = StudentIsEduOne( - id = student.id, - isEduOne = newCurrentStudent.isEduOne - ) - studentDb.update(studentIsEduOne) - return newCurrentStudent.isEduOne - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/api/SchoolsService.kt b/app/src/main/java/io/github/wulkanowy/data/api/SchoolsService.kt deleted file mode 100644 index a7da9b63c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/api/SchoolsService.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.data.api - -import io.github.wulkanowy.data.pojos.IntegrityRequest -import io.github.wulkanowy.data.pojos.LoginEvent -import retrofit2.http.Body -import retrofit2.http.POST -import javax.inject.Singleton - -@Singleton -interface SchoolsService { - - @POST("/log/loginEvent") - suspend fun logLoginEvent(@Body request: IntegrityRequest) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index ec22c5a3d..792611a81 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -1,129 +1,11 @@ package io.github.wulkanowy.data.db import android.content.Context -import androidx.room.AutoMigration -import androidx.room.Database -import androidx.room.Room -import androidx.room.RoomDatabase +import androidx.room.* import androidx.room.RoomDatabase.JournalMode.TRUNCATE -import androidx.room.TypeConverters -import io.github.wulkanowy.data.db.dao.AdminMessageDao -import io.github.wulkanowy.data.db.dao.AttendanceDao -import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao -import io.github.wulkanowy.data.db.dao.CompletedLessonsDao -import io.github.wulkanowy.data.db.dao.ConferenceDao -import io.github.wulkanowy.data.db.dao.ExamDao -import io.github.wulkanowy.data.db.dao.GradeDao -import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao -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.dao.GradeSummaryDao -import io.github.wulkanowy.data.db.dao.HomeworkDao -import io.github.wulkanowy.data.db.dao.LuckyNumberDao -import io.github.wulkanowy.data.db.dao.MailboxDao -import io.github.wulkanowy.data.db.dao.MessageAttachmentDao -import io.github.wulkanowy.data.db.dao.MessagesDao -import io.github.wulkanowy.data.db.dao.MobileDeviceDao -import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao -import io.github.wulkanowy.data.db.dao.NoteDao -import io.github.wulkanowy.data.db.dao.NotificationDao -import io.github.wulkanowy.data.db.dao.RecipientDao -import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao -import io.github.wulkanowy.data.db.dao.SchoolDao -import io.github.wulkanowy.data.db.dao.SemesterDao -import io.github.wulkanowy.data.db.dao.StudentDao -import io.github.wulkanowy.data.db.dao.StudentInfoDao -import io.github.wulkanowy.data.db.dao.SubjectDao -import io.github.wulkanowy.data.db.dao.TeacherDao -import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao -import io.github.wulkanowy.data.db.dao.TimetableDao -import io.github.wulkanowy.data.db.dao.TimetableHeaderDao -import io.github.wulkanowy.data.db.entities.AdminMessage -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Conference -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive -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.GradeSummary -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Mailbox -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.MutedMessageSender -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Notification -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.SchoolAnnouncement -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentInfo -import io.github.wulkanowy.data.db.entities.Subject -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.db.entities.TimetableAdditional -import io.github.wulkanowy.data.db.entities.TimetableHeader -import io.github.wulkanowy.data.db.migrations.Migration10 -import io.github.wulkanowy.data.db.migrations.Migration11 -import io.github.wulkanowy.data.db.migrations.Migration12 -import io.github.wulkanowy.data.db.migrations.Migration13 -import io.github.wulkanowy.data.db.migrations.Migration14 -import io.github.wulkanowy.data.db.migrations.Migration15 -import io.github.wulkanowy.data.db.migrations.Migration16 -import io.github.wulkanowy.data.db.migrations.Migration17 -import io.github.wulkanowy.data.db.migrations.Migration18 -import io.github.wulkanowy.data.db.migrations.Migration19 -import io.github.wulkanowy.data.db.migrations.Migration2 -import io.github.wulkanowy.data.db.migrations.Migration20 -import io.github.wulkanowy.data.db.migrations.Migration21 -import io.github.wulkanowy.data.db.migrations.Migration22 -import io.github.wulkanowy.data.db.migrations.Migration23 -import io.github.wulkanowy.data.db.migrations.Migration24 -import io.github.wulkanowy.data.db.migrations.Migration25 -import io.github.wulkanowy.data.db.migrations.Migration26 -import io.github.wulkanowy.data.db.migrations.Migration27 -import io.github.wulkanowy.data.db.migrations.Migration28 -import io.github.wulkanowy.data.db.migrations.Migration29 -import io.github.wulkanowy.data.db.migrations.Migration3 -import io.github.wulkanowy.data.db.migrations.Migration30 -import io.github.wulkanowy.data.db.migrations.Migration31 -import io.github.wulkanowy.data.db.migrations.Migration32 -import io.github.wulkanowy.data.db.migrations.Migration33 -import io.github.wulkanowy.data.db.migrations.Migration34 -import io.github.wulkanowy.data.db.migrations.Migration35 -import io.github.wulkanowy.data.db.migrations.Migration36 -import io.github.wulkanowy.data.db.migrations.Migration37 -import io.github.wulkanowy.data.db.migrations.Migration38 -import io.github.wulkanowy.data.db.migrations.Migration39 -import io.github.wulkanowy.data.db.migrations.Migration4 -import io.github.wulkanowy.data.db.migrations.Migration40 -import io.github.wulkanowy.data.db.migrations.Migration41 -import io.github.wulkanowy.data.db.migrations.Migration42 -import io.github.wulkanowy.data.db.migrations.Migration43 -import io.github.wulkanowy.data.db.migrations.Migration44 -import io.github.wulkanowy.data.db.migrations.Migration46 -import io.github.wulkanowy.data.db.migrations.Migration49 -import io.github.wulkanowy.data.db.migrations.Migration5 -import io.github.wulkanowy.data.db.migrations.Migration50 -import io.github.wulkanowy.data.db.migrations.Migration51 -import io.github.wulkanowy.data.db.migrations.Migration53 -import io.github.wulkanowy.data.db.migrations.Migration54 -import io.github.wulkanowy.data.db.migrations.Migration55 -import io.github.wulkanowy.data.db.migrations.Migration57 -import io.github.wulkanowy.data.db.migrations.Migration58 -import io.github.wulkanowy.data.db.migrations.Migration6 -import io.github.wulkanowy.data.db.migrations.Migration63 -import io.github.wulkanowy.data.db.migrations.Migration7 -import io.github.wulkanowy.data.db.migrations.Migration8 -import io.github.wulkanowy.data.db.migrations.Migration9 +import io.github.wulkanowy.data.db.dao.* +import io.github.wulkanowy.data.db.entities.* +import io.github.wulkanowy.data.db.migrations.* import io.github.wulkanowy.utils.AppInfo import javax.inject.Singleton @@ -159,24 +41,13 @@ import javax.inject.Singleton TimetableHeader::class, SchoolAnnouncement::class, Notification::class, - AdminMessage::class, - MutedMessageSender::class, - GradeDescriptive::class, + AdminMessage::class ], autoMigrations = [ AutoMigration(from = 44, to = 45), AutoMigration(from = 46, to = 47), AutoMigration(from = 47, to = 48), AutoMigration(from = 51, to = 52), - AutoMigration(from = 54, to = 55, spec = Migration55::class), - AutoMigration(from = 55, to = 56), - AutoMigration(from = 56, to = 57, spec = Migration57::class), - AutoMigration(from = 57, to = 58, spec = Migration58::class), - AutoMigration(from = 58, to = 59), - AutoMigration(from = 59, to = 60), - AutoMigration(from = 60, to = 61), - AutoMigration(from = 61, to = 62), - AutoMigration(from = 62, to = 63, spec = Migration63::class), ], version = AppDatabase.VERSION_SCHEMA, exportSchema = true @@ -185,7 +56,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 63 + const val VERSION_SCHEMA = 53 fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf( Migration2(), @@ -236,7 +107,6 @@ abstract class AppDatabase : RoomDatabase() { Migration50(), Migration51(), Migration53(), - Migration54(), ) fun newInstance( @@ -310,8 +180,4 @@ abstract class AppDatabase : RoomDatabase() { abstract val notificationDao: NotificationDao abstract val adminMessagesDao: AdminMessageDao - - abstract val mutedMessageSendersDao: MutedMessageSendersDao - - abstract val gradeDescriptiveDao: GradeDescriptiveDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt index 7bc8d12a2..9d3beae1f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt @@ -1,7 +1,6 @@ package io.github.wulkanowy.data.db import androidx.room.TypeConverter -import io.github.wulkanowy.data.enums.MessageType import io.github.wulkanowy.ui.modules.Destination import io.github.wulkanowy.utils.toTimestamp import kotlinx.serialization.SerializationException @@ -69,9 +68,4 @@ class Converters { @TypeConverter fun stringToDestination(destination: String): Destination = json.decodeFromString(destination) - @TypeConverter - fun messageTypesToString(types: List): String = json.encodeToString(types) - - @TypeConverter - fun stringToMessageTypes(text: String): List = json.decodeFromString(text) } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt index 6c8d7e471..87f4812da 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt @@ -2,14 +2,24 @@ package io.github.wulkanowy.data.db.dao import androidx.room.Dao import androidx.room.Query +import androidx.room.Transaction import io.github.wulkanowy.data.db.entities.AdminMessage import kotlinx.coroutines.flow.Flow import javax.inject.Singleton @Singleton @Dao -interface AdminMessageDao : BaseDao { +abstract class AdminMessageDao : BaseDao { @Query("SELECT * FROM AdminMessages") - fun loadAll(): Flow> -} + abstract fun loadAll(): Flow> + + @Transaction + open suspend fun removeOldAndSaveNew( + oldMessages: List, + newMessages: List + ) { + deleteAll(oldMessages) + insertAll(newMessages) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt index 937e98248..056a5cbd1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt @@ -3,7 +3,6 @@ package io.github.wulkanowy.data.db.dao import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy -import androidx.room.Transaction import androidx.room.Update interface BaseDao { @@ -16,10 +15,4 @@ interface BaseDao { @Delete suspend fun deleteAll(items: List) - - @Transaction - suspend fun removeOldAndSaveNew(oldItems: List, newItems: List) { - deleteAll(oldItems) - insertAll(newItems) - } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt deleted file mode 100644 index 6282c0804..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.GradeDescriptive -import kotlinx.coroutines.flow.Flow -import javax.inject.Singleton - -@Singleton -@Dao -interface GradeDescriptiveDao : BaseDao { - - @Query("SELECT * FROM GradesDescriptive WHERE semester_id = :semesterId AND student_id = :studentId") - fun loadAll(semesterId: Int, studentId: Int): Flow> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt index 11e6da1e7..1709f7636 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt @@ -5,23 +5,15 @@ import androidx.room.Query import androidx.room.Transaction import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor import kotlinx.coroutines.flow.Flow @Dao interface MessagesDao : BaseDao { + @Transaction @Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey") fun loadMessageWithAttachment(messageGlobalKey: String): Flow - @Transaction - @Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC") - fun loadMessagesWithMutedAuthor(mailboxKey: String, folder: Int): Flow> - - @Transaction - @Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC") - fun loadMessagesWithMutedAuthor(folder: Int, email: String): Flow> - @Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC") fun loadAll(mailboxKey: String, folder: Int): 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 5ddb4dd08..96382cc10 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 user_login_id = :studentId ORDER BY date DESC") - fun loadAll(studentId: Int): Flow> + @Query("SELECT * FROM MobileDevices WHERE user_login_id = :userLoginId ORDER BY date DESC") + fun loadAll(userLoginId: Int): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt deleted file mode 100644 index 0a8664010..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.MutedMessageSender - -@Dao -interface MutedMessageSendersDao : BaseDao { - - @Query("SELECT COUNT(*) FROM MutedMessageSenders WHERE author = :author") - suspend fun checkMute(author: String): Boolean - - @Insert(onConflict = OnConflictStrategy.IGNORE) - suspend fun insertMute(mute: MutedMessageSender): Long - - @Query("DELETE FROM MutedMessageSenders WHERE author = :author") - suspend fun deleteMute(author: String) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt index 64d49bce7..c32e4aba3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt @@ -10,6 +10,6 @@ import javax.inject.Singleton @Singleton interface SchoolAnnouncementDao : BaseDao { - @Query("SELECT * FROM SchoolAnnouncements WHERE user_login_id = :studentId ORDER BY date DESC") - fun loadAll(studentId: Int): Flow> + @Query("SELECT * FROM SchoolAnnouncements WHERE user_login_id = :userLoginId ORDER BY date DESC") + fun loadAll(userLoginId: Int): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt index bf9a34d05..4d171907c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt @@ -14,6 +14,6 @@ interface SemesterDao : BaseDao { @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insertSemesters(items: List): List - @Query("SELECT * FROM Semesters WHERE (student_id = :studentId AND class_id = :classId) OR (student_id = :studentId AND class_id = 0)") + @Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId") suspend fun loadAll(studentId: Int, classId: Int): List } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt index 5302b320c..87b3e0b32 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt @@ -1,42 +1,25 @@ package io.github.wulkanowy.data.db.dao -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import androidx.room.Transaction -import androidx.room.Update -import io.github.wulkanowy.data.db.entities.Semester +import androidx.room.* +import androidx.room.OnConflictStrategy.ABORT import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentIsAuthorized -import io.github.wulkanowy.data.db.entities.StudentIsEduOne -import io.github.wulkanowy.data.db.entities.StudentName import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import javax.inject.Singleton @Singleton @Dao abstract class StudentDao { - @Insert(onConflict = OnConflictStrategy.ABORT) + @Insert(onConflict = ABORT) abstract suspend fun insertAll(student: List): List @Delete abstract suspend fun delete(student: Student) - @Update(entity = Student::class) - abstract suspend fun update(studentIsAuthorized: StudentIsAuthorized) - - @Update(entity = Student::class) - abstract suspend fun update(studentIsEduOne: StudentIsEduOne) - @Update(entity = Student::class) abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar) - @Update(entity = Student::class) - abstract suspend fun update(studentName: StudentName) - @Query("SELECT * FROM Students WHERE is_current = 1") abstract suspend fun loadCurrent(): Student? @@ -47,12 +30,12 @@ abstract class StudentDao { abstract suspend fun loadAll(): List @Transaction - @Query("SELECT * FROM Students JOIN Semesters ON (Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id) OR (Students.student_id = Semesters.student_id AND Semesters.class_id = 0)") - abstract suspend fun loadStudentsWithSemesters(): Map> + @Query("SELECT * FROM Students") + abstract suspend fun loadStudentsWithSemesters(): List @Transaction - @Query("SELECT * FROM Students JOIN Semesters ON (Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id) OR (Students.student_id = Semesters.student_id AND Semesters.class_id = 0) WHERE Students.id = :id") - abstract suspend fun loadStudentWithSemestersById(id: Long): Map> + @Query("SELECT * FROM Students WHERE id = :id") + abstract suspend fun loadStudentWithSemestersById(id: Long): StudentWithSemesters? @Query("UPDATE Students SET is_current = 1 WHERE id = :id") abstract suspend fun updateCurrent(id: Long) @@ -60,9 +43,6 @@ abstract class StudentDao { @Query("UPDATE Students SET is_current = 0") abstract suspend fun resetCurrent() - @Query("DELETE FROM Students WHERE email = :email AND user_name = :userName") - abstract suspend fun deleteByEmailAndUserName(email: String, userName: String) - @Transaction open suspend fun switchCurrent(id: Long) { resetCurrent() diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt index 40d97ea96..b4b7379f2 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt @@ -15,5 +15,5 @@ interface TimetableDao : BaseDao { fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow> @Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") - suspend fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List + fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt index 0c8f1a5d1..97fec69b7 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt @@ -3,7 +3,6 @@ package io.github.wulkanowy.data.db.entities import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -import io.github.wulkanowy.data.enums.MessageType import kotlinx.serialization.Serializable @Serializable @@ -34,12 +33,8 @@ data class AdminMessage( val priority: String, - @ColumnInfo(name = "types", defaultValue = "[]") - val types: List = emptyList(), + val type: String, - @ColumnInfo(name = "is_ok_visible", defaultValue = "0") - val isOkVisible: Boolean = false, - - @ColumnInfo(name = "is_x_visible", defaultValue = "0") - val isXVisible: Boolean = false + @ColumnInfo(name = "is_dismissible") + val isDismissible: Boolean = false ) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt index 2292c3e62..50299e607 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt @@ -22,7 +22,6 @@ data class Exam( val subject: String, - @Deprecated("not available anymore") val group: String, val type: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt deleted file mode 100644 index 9aec9599a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "GradesDescriptive") -data class GradeDescriptive( - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val subject: String, - - val description: String, -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_notified") - var isNotified: Boolean = true -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt index 6f0c84ad7..93f042999 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt @@ -2,14 +2,16 @@ package io.github.wulkanowy.data.db.entities import androidx.room.ColumnInfo import androidx.room.Entity +import androidx.room.PrimaryKey import java.io.Serializable -@Entity( - tableName = "MessageAttachments", - primaryKeys = ["message_global_key", "url", "filename"], -) +@Entity(tableName = "MessageAttachments") data class MessageAttachment( + @PrimaryKey + @ColumnInfo(name = "real_id") + val realId: Int, + @ColumnInfo(name = "message_global_key") val messageGlobalKey: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt index fc890e760..cd468215d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt @@ -2,15 +2,11 @@ package io.github.wulkanowy.data.db.entities import androidx.room.Embedded import androidx.room.Relation -import java.io.Serializable data class MessageWithAttachment( @Embedded val message: Message, @Relation(parentColumn = "message_global_key", entityColumn = "message_global_key") - val attachments: List, - - @Relation(parentColumn = "correspondents", entityColumn = "author") - val mutedMessageSender: MutedMessageSender?, -) : Serializable + val attachments: List +) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt deleted file mode 100644 index e3cd1ca7d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.Embedded -import androidx.room.Relation - -data class MessageWithMutedAuthor( - @Embedded - val message: Message, - - @Relation(parentColumn = "correspondents", entityColumn = "author") - val mutedMessageSender: MutedMessageSender?, -) 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 44e900647..89b04ccc8 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 @@ -9,8 +9,8 @@ import java.time.Instant @Entity(tableName = "MobileDevices") data class MobileDevice( - @ColumnInfo(name = "user_login_id") // todo: change column name - val studentId: Int, + @ColumnInfo(name = "user_login_id") + val userLoginId: Int, @ColumnInfo(name = "device_id") val deviceId: Int, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt deleted file mode 100644 index f1770e64c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "MutedMessageSenders") -data class MutedMessageSender( - @ColumnInfo(name = "author") - val author: String, -) : Serializable { - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt index 814a3c8dd..25e27ef18 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt @@ -9,16 +9,14 @@ import java.time.LocalDate @Entity(tableName = "SchoolAnnouncements") data class SchoolAnnouncement( - @ColumnInfo(name = "user_login_id") // todo: change column name - val studentId: Int, + @ColumnInfo(name = "user_login_id") + val userLoginId: Int, val date: LocalDate, val subject: String, - val content: String, - - val author: String? = null, + val content: String ) : Serializable { @PrimaryKey(autoGenerate = true) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt index 0300506ac..76da9643d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt @@ -19,9 +19,6 @@ data class Student( @ColumnInfo(name = "scrapper_base_url") val scrapperBaseUrl: String, - @ColumnInfo(name = "scrapper_domain_suffix", defaultValue = "") - val scrapperDomainSuffix: String, - @ColumnInfo(name = "mobile_base_url") val mobileBaseUrl: String, @@ -49,7 +46,6 @@ data class Student( @ColumnInfo(name = "student_id") val studentId: Int, - @Deprecated("not available in VULCAN anymore") @ColumnInfo(name = "user_login_id") val userLoginId: Int, @@ -79,13 +75,6 @@ data class Student( @ColumnInfo(name = "registration_date") val registrationDate: Instant, - - @ColumnInfo(name = "is_authorized", defaultValue = "0") - val isAuthorized: Boolean, - - @ColumnInfo(name = "is_edu_one", defaultValue = "NULL") - val isEduOne: Boolean?, - ) : Serializable { @PrimaryKey(autoGenerate = true) @@ -96,22 +85,3 @@ data class Student( @ColumnInfo(name = "avatar_color") var avatarColor = 0L } - -@Entity -data class StudentIsAuthorized( - - @PrimaryKey - var id: Long, - - @ColumnInfo(name = "is_authorized", defaultValue = "NULL") - val isAuthorized: Boolean?, -) : Serializable - -@Entity -data class StudentIsEduOne( - @PrimaryKey - var id: Long, - - @ColumnInfo(name = "is_edu_one", defaultValue = "NULL") - val isEduOne: Boolean?, -) : Serializable diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt deleted file mode 100644 index 46f754b5e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity -data class StudentName( - - @ColumnInfo(name = "student_name") - val studentName: String - -) : Serializable { - - @PrimaryKey - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt index f9869d4e2..9362a954e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt @@ -1,8 +1,13 @@ package io.github.wulkanowy.data.db.entities +import androidx.room.Embedded +import androidx.room.Relation import java.io.Serializable data class StudentWithSemesters( + @Embedded val student: Student, + + @Relation(parentColumn = "student_id", entityColumn = "student_id") val semesters: List ) : Serializable diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt index 0e7e14097..c26a02d1f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt @@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration10 : Migration(9, 10) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt index 342e2e2e3..6d129bca0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration11 : Migration(10, 11) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS Grades_temp ( id INTEGER PRIMARY KEY NOT NULL, is_read INTEGER NOT NULL, @@ -27,10 +26,9 @@ class Migration11 : Migration(10, 11) { date INTEGER NOT NULL, teacher TEXT NOT NULL ) - """ - ) - db.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades") - db.execSQL("DROP TABLE Grades") - db.execSQL("ALTER TABLE Grades_temp RENAME TO Grades") + """) + database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades") + database.execSQL("DROP TABLE Grades") + database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt index 6cc726953..c827b82ba 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt @@ -5,17 +5,16 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration12 : Migration(11, 12) { - override fun migrate(db: SupportSQLiteDatabase) { - createTempStudentsTable(db) - replaceStudentTable(db) - updateStudentsWithClassId(db, getStudentsIds(db)) - removeStudentsWithNoClassId(db) - ensureThereIsOnlyOneCurrentStudent(db) + override fun migrate(database: SupportSQLiteDatabase) { + createTempStudentsTable(database) + replaceStudentTable(database) + updateStudentsWithClassId(database, getStudentsIds(database)) + removeStudentsWithNoClassId(database) + ensureThereIsOnlyOneCurrentStudent(database) } - private fun createTempStudentsTable(db: SupportSQLiteDatabase) { - db.execSQL( - """ + private fun createTempStudentsTable(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS Students_tmp ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, endpoint TEXT NOT NULL, @@ -31,16 +30,15 @@ class Migration12 : Migration(11, 12) { registration_date INTEGER NOT NULL, class_id INTEGER NOT NULL ) - """ - ) - db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)") + """) + database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)") } - private fun replaceStudentTable(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") - db.execSQL("INSERT INTO Students_tmp SELECT * FROM Students") - db.execSQL("DROP TABLE Students") - db.execSQL("ALTER TABLE Students_tmp RENAME TO Students") + private fun replaceStudentTable(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") + database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students") + database.execSQL("DROP TABLE Students") + database.execSQL("ALTER TABLE Students_tmp RENAME TO Students") } private fun getStudentsIds(database: SupportSQLiteDatabase): List { @@ -56,18 +54,18 @@ class Migration12 : Migration(11, 12) { return students } - private fun updateStudentsWithClassId(db: SupportSQLiteDatabase, students: List) { + private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List) { students.forEach { - db.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it") + database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it") } } - private fun removeStudentsWithNoClassId(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Students WHERE class_id = 0") + private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Students WHERE class_id = 0") } - private fun ensureThereIsOnlyOneCurrentStudent(db: SupportSQLiteDatabase) { - db.execSQL("UPDATE Students SET is_current = 0") - db.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)") + private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) { + database.execSQL("UPDATE Students SET is_current = 0") + database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt index c5030232b..36de1e837 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt @@ -5,30 +5,27 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration13 : Migration(12, 13) { - override fun migrate(db: SupportSQLiteDatabase) { - addClassNameToStudents(db, getStudentsIds(db)) - updateSemestersTable(db) - markAtLeastAndOnlyOneSemesterAtCurrent(db, getStudentsAndClassIds(db)) - clearMessagesTable(db) + override fun migrate(database: SupportSQLiteDatabase) { + addClassNameToStudents(database, getStudentsIds(database)) + updateSemestersTable(database) + markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database)) + clearMessagesTable(database) } - private fun addClassNameToStudents( - db: SupportSQLiteDatabase, - students: List> - ) { - db.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL") + private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List>) { + database.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL") students.forEach { (id, name) -> val schoolName = name.substringAfter(" - ") val className = name.substringBefore(" - ", "").replace("Klasa ", "") - db.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'") - db.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'") + database.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'") + database.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'") } } - private fun getStudentsIds(db: SupportSQLiteDatabase): MutableList> { + private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList> { val students = mutableListOf>() - db.query("SELECT id, school_name FROM Students").use { + database.query("SELECT id, school_name FROM Students").use { if (it.moveToFirst()) { do { students.add(it.getInt(0) to it.getString(1)) @@ -39,15 +36,15 @@ class Migration13 : Migration(12, 13) { return students } - private fun updateSemestersTable(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL") - db.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL") - db.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL") + private fun updateSemestersTable(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL") + database.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL") + database.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL") } - private fun getStudentsAndClassIds(db: SupportSQLiteDatabase): List> { + private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List> { val students = mutableListOf>() - db.query("SELECT student_id, class_id FROM Students").use { + database.query("SELECT student_id, class_id FROM Students").use { if (it.moveToFirst()) { do { students.add(it.getInt(0) to it.getInt(1)) @@ -58,17 +55,14 @@ class Migration13 : Migration(12, 13) { return students } - private fun markAtLeastAndOnlyOneSemesterAtCurrent( - db: SupportSQLiteDatabase, - students: List> - ) { + private fun markAtLeastAndOnlyOneSemesterAtCurrent(database: SupportSQLiteDatabase, students: List>) { students.forEach { (studentId, classId) -> - db.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'") - db.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)") + database.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'") + database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)") } } - private fun clearMessagesTable(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Messages") + private fun clearMessagesTable(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Messages") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt index 793b4a9d2..4dac0d306 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt @@ -5,10 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration14 : Migration(13, 14) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS GradesSummary") - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS GradesSummary") + database.execSQL(""" CREATE TABLE IF NOT EXISTS GradesSummary ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, semester_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt index 5ff44e9ca..5be49a95b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration15 : Migration(14, 15) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS MobileDevices ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, @@ -15,7 +14,6 @@ class Migration15 : Migration(14, 15) { name TEXT NOT NULL, date INTEGER NOT NULL ) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt index 8a8f5b8f2..7f40c0f8d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration16 : Migration(15, 16) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS Teachers ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, @@ -16,7 +15,6 @@ class Migration16 : Migration(15, 16) { name TEXT NOT NULL, short_name TEXT NOT NULL ) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt index cf3318ad4..e2a2574db 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt @@ -5,14 +5,13 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration17 : Migration(16, 17) { - override fun migrate(db: SupportSQLiteDatabase) { - createGradesPointsStatisticsTable(db) - truncateSemestersTable(db) + override fun migrate(database: SupportSQLiteDatabase) { + createGradesPointsStatisticsTable(database) + truncateSemestersTable(database) } - private fun createGradesPointsStatisticsTable(db: SupportSQLiteDatabase) { - db.execSQL( - """ + private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS GradesPointsStatistics( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, @@ -21,11 +20,10 @@ class Migration17 : Migration(16, 17) { others REAL NOT NULL, student REAL NOT NULL ) - """ - ) + """) } - private fun truncateSemestersTable(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Semesters") + private fun truncateSemestersTable(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Semesters") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt index 713f8e724..6c5e56c6a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration18 : Migration(17, 18) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS School ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt index 021cdbb37..d38f1245a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt @@ -6,17 +6,16 @@ import io.github.wulkanowy.data.db.SharedPrefProvider class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migration(18, 19) { - override fun migrate(db: SupportSQLiteDatabase) { - migrateMessages(db) - migrateGrades(db) - migrateStudents(db) + override fun migrate(database: SupportSQLiteDatabase) { + migrateMessages(database) + migrateGrades(database) + migrateStudents(database) migrateSharedPreferences() } - private fun migrateMessages(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE Messages") - db.execSQL( - """ + private fun migrateMessages(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE Messages") + database.execSQL(""" CREATE TABLE IF NOT EXISTS Messages ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, is_notified INTEGER NOT NULL, @@ -35,14 +34,12 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio read_by INTEGER NOT NULL, removed INTEGER NOT NULL ) - """ - ) + """) } - private fun migrateGrades(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE Grades") - db.execSQL( - """ + private fun migrateGrades(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE Grades") + database.execSQL(""" CREATE TABLE IF NOT EXISTS Grades ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, is_read INTEGER NOT NULL, @@ -62,13 +59,11 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio date INTEGER NOT NULL, teacher TEXT NOT NULL ) - """ - ) + """) } - private fun migrateStudents(db: SupportSQLiteDatabase) { - db.execSQL( - """ + private fun migrateStudents(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS Students_tmp ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, scrapper_base_url TEXT NOT NULL, @@ -91,29 +86,26 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio is_current INTEGER NOT NULL, registration_date INTEGER NOT NULL ) - """ - ) + """) - db.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";") - db.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";") - db.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;") - db.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";") - db.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";") - db.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";") - db.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;") + database.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";") + database.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";") + database.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;") + database.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";") + database.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";") + database.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";") + database.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;") - db.execSQL( - """ + database.execSQL(""" INSERT INTO Students_tmp( id, scrapper_base_url, mobile_base_url, is_parent, login_type, login_mode, certificate_key, private_key, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date) SELECT id, endpoint, apiBaseUrl, is_parent, loginType, "SCRAPPER", certificateKey, privateKey, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date FROM Students - """ - ) - db.execSQL("DROP TABLE Students") - db.execSQL("ALTER TABLE Students_tmp RENAME TO Students") - db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)") + """) + database.execSQL("DROP TABLE Students") + database.execSQL("ALTER TABLE Students_tmp RENAME TO Students") + database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)") } private fun migrateSharedPreferences() { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt index be8675092..c5a30991a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt @@ -5,16 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration2 : Migration(1, 2) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS LuckyNumbers ( id INTEGER PRIMARY KEY NOT NULL, is_notified INTEGER NOT NULL, student_id INTEGER NOT NULL, date INTEGER NOT NULL, lucky_number INTEGER NOT NULL) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt index 7ad43230b..2fcfc183d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt @@ -5,15 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration20 : Migration(19, 20) { - override fun migrate(db: SupportSQLiteDatabase) { - migrateTimetable(db) - truncateSubjects(db) + override fun migrate(database: SupportSQLiteDatabase) { + migrateTimetable(database) + truncateSubjects(database) } - private fun migrateTimetable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE Timetable") - db.execSQL( - """ + private fun migrateTimetable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE Timetable") + database.execSQL(""" CREATE TABLE IF NOT EXISTS `Timetable` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, @@ -34,11 +33,10 @@ class Migration20 : Migration(19, 20) { `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL ) - """ - ) + """) } - private fun truncateSubjects(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Subjects") + private fun truncateSubjects(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM Subjects") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt index 60e044cdc..bc0ff900c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt @@ -5,11 +5,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration21 : Migration(20, 21) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL") - db.execSQL("DELETE FROM Semesters") + database.execSQL("DELETE FROM Semesters") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt index ef525a49d..cf50a6c3e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt @@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration22 : Migration(21, 22) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt index 3650307a6..22de94c3f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt @@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration23 : Migration(22, 23) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''") - db.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''") + database.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt index a3cd98197..604ed4875 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt @@ -5,10 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration24 : Migration(23, 24) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0") - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0") + database.execSQL(""" CREATE TABLE IF NOT EXISTS MessageAttachments ( real_id INTEGER NOT NULL, message_id INTEGER NOT NULL, @@ -17,7 +16,6 @@ class Migration24 : Migration(23, 24) { filename TEXT NOT NULL, PRIMARY KEY(real_id) ) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt index cb395d7e0..4749bac73 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration25 : Migration(24, 25) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt index 94746b456..7130d86d8 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt @@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration26 : Migration(25, 26) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1") - db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1") - db.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0") - db.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1") + database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1") + database.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt index a7ba763df..5c60beead 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt @@ -5,25 +5,24 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration27 : Migration(26, 27) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"") - val students = getStudentsIdsAndNames(db) - val units = getReportingUnits(db) + val students = getStudentsIdsAndNames(database) + val units = getReportingUnits(database) students.forEach { (id, userLoginId, studentName) -> - val userNameFromUnits = - units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second + val userNameFromUnits = units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second val normalizedStudentName = studentName.split(" ").asReversed().joinToString(" ") val userName = userNameFromUnits ?: normalizedStudentName - db.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'") + database.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'") } } - private fun getStudentsIdsAndNames(db: SupportSQLiteDatabase): MutableList> { + private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList> { val students = mutableListOf>() - db.query("SELECT id, user_login_id, student_name FROM Students").use { + database.query("SELECT id, user_login_id, student_name FROM Students").use { if (it.moveToFirst()) { do { students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2))) @@ -34,9 +33,9 @@ class Migration27 : Migration(26, 27) { return students } - private fun getReportingUnits(db: SupportSQLiteDatabase): MutableList> { + private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList> { val units = mutableListOf>() - db.query("SELECT sender_id, sender_name FROM ReportingUnits").use { + database.query("SELECT sender_id, sender_name FROM ReportingUnits").use { if (it.moveToFirst()) { do { units.add(it.getInt(0) to it.getString(1)) 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 index e8a5a4a86..51e7628b5 100644 --- 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 @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration28 : Migration(27, 28) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + 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, 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 index dac303d27..327552d75 100644 --- 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 @@ -5,10 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration29 : Migration(28, 29) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS GradesStatistics") - db.execSQL( - """ + 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, @@ -17,10 +16,8 @@ class Migration29 : Migration(28, 29) { amounts TEXT NOT NULL, student_grade INTEGER NOT NULL ) - """ - ) - db.execSQL( - """ + """) + database.execSQL(""" CREATE TABLE IF NOT EXISTS GradePartialStatistics ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt index 44d421648..d9699c0f4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration3 : Migration(2, 3) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS CompletedLesson ( id INTEGER PRIMARY KEY NOT NULL, student_id INTEGER 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 index 3fea8ec0e..b33914fec 100644 --- 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 @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration30 : Migration(29, 30) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE TimetableAdditional ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, @@ -17,7 +16,6 @@ class Migration30 : Migration(29, 30) { date INTEGER NOT NULL, subject TEXT NOT NULL ) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt index 28fb10562..064a3e5bc 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration31 : Migration(30, 31) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( """CREATE TABLE IF NOT EXISTS StudentInfo ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt index 347873936..508485e08 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration32 : Migration(31, 32) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN nick TEXT NOT NULL DEFAULT \"\"") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN nick TEXT NOT NULL DEFAULT \"\"") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt index 9778d2790..4a57880d4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt @@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration33 : Migration(32, 33) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS StudentInfo") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS StudentInfo") - db.execSQL( + database.execSQL( """CREATE TABLE IF NOT EXISTS StudentInfo ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, student_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt index e9eec58cd..2c57eb00a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt @@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration34 : Migration(33, 34) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM ReportingUnits") - db.execSQL("DELETE FROM Recipients") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DELETE FROM ReportingUnits") + database.execSQL("DELETE FROM Recipients") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt index b238ce8b4..f63431d00 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt @@ -7,13 +7,13 @@ import io.github.wulkanowy.utils.AppInfo class Migration35(private val appInfo: AppInfo) : Migration(34, 35) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0") - db.query("SELECT * FROM Students").use { + database.query("SELECT * FROM Students").use { while (it.moveToNext()) { val studentId = it.getLongOrNull(0) - db.execSQL( + database.execSQL( """ UPDATE Students SET avatar_color = ${appInfo.defaultColorsForAvatar.random()} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt index 62ce346cd..7ea106585 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration36 : Migration(35, 36) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Exams ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") - db.execSQL("ALTER TABLE Homework ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Exams ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + database.execSQL("ALTER TABLE Homework ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt index 9ab35514f..a3fcd51a6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration37 : Migration(36, 37) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( """ CREATE TABLE IF NOT EXISTS TimetableHeaders ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt index bb9b32bfa..1f90f5a44 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration38 : Migration(37, 38) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, @@ -15,7 +14,6 @@ class Migration38 : Migration(37, 38) { `subject` TEXT NOT NULL, `content` TEXT NOT NULL ) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt index 2e5315bf4..6c0d36dd2 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration39 : Migration(38, 39) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Conferences ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") - db.execSQL("ALTER TABLE SchoolAnnouncements ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Conferences ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + database.execSQL("ALTER TABLE SchoolAnnouncements ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt index b6089aa62..0ae89bdd6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt @@ -5,10 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration4 : Migration(3, 4) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Messages") - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Messages") + database.execSQL(""" CREATE TABLE IF NOT EXISTS Messages ( id INTEGER PRIMARY KEY NOT NULL, is_notified INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt index 8e38b0c84..6d2795c7c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration40 : Migration(39, 40) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Notifications` ( `student_id` INTEGER NOT NULL, @@ -20,4 +20,4 @@ class Migration40 : Migration(39, 40) { """ ) } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt index bfc28334b..ccaf85755 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt @@ -7,9 +7,9 @@ import io.github.wulkanowy.data.enums.GradeExpandMode class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migration(40, 41) { - override fun migrate(db: SupportSQLiteDatabase) { + override fun migrate(database: SupportSQLiteDatabase) { migrateSharedPreferences() - db.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0") + database.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0") } private fun migrateSharedPreferences() { @@ -18,4 +18,4 @@ class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migratio } sharedPrefProvider.delete("pref_key_expand_grade") } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt index 14356e279..3d66f301b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration42 : Migration(41, 42) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( """CREATE TABLE IF NOT EXISTS `AdminMessages` ( `id` INTEGER NOT NULL, `title` TEXT NOT NULL, @@ -21,4 +21,4 @@ class Migration42 : Migration(41, 42) { PRIMARY KEY(`id`))""" ) } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt index ef8108166..68c2834d6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt @@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration43 : Migration(42, 43) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") - db.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") + database.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt index 0a4e5f962..7bdcab5f4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt @@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration44 : Migration(43, 44) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt index 0bacbaa0e..d3fa5cf93 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt @@ -8,65 +8,65 @@ import java.time.ZoneOffset class Migration46 : Migration(45, 46) { - override fun migrate(db: SupportSQLiteDatabase) { - migrateConferences(db) - migrateMessages(db) - migrateMobileDevices(db) - migrateNotifications(db) - migrateTimetable(db) - migrateTimetableAdditional(db) + override fun migrate(database: SupportSQLiteDatabase) { + migrateConferences(database) + migrateMessages(database) + migrateMobileDevices(database) + migrateNotifications(database) + migrateTimetable(database) + migrateTimetableAdditional(database) } - private fun migrateConferences(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM Conferences").use { + private fun migrateConferences(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM Conferences").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date")) val timestampUtc = timestampLocal.timestampLocalToUTC() - db.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id") + database.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id") } } } - private fun migrateMessages(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM Messages").use { + private fun migrateMessages(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM Messages").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date")) val timestampUtc = timestampLocal.timestampLocalToUTC() - db.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id") + database.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id") } } } - private fun migrateMobileDevices(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM MobileDevices").use { + private fun migrateMobileDevices(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM MobileDevices").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date")) val timestampUtc = timestampLocal.timestampLocalToUTC() - db.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id") + database.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id") } } } - private fun migrateNotifications(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM Notifications").use { + private fun migrateNotifications(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM Notifications").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date")) val timestampUtc = timestampLocal.timestampLocalToUTC() - db.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id") + database.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id") } } } - private fun migrateTimetable(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM Timetable").use { + private fun migrateTimetable(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM Timetable").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start")) @@ -74,13 +74,13 @@ class Migration46 : Migration(45, 46) { val timestampUtcStart = timestampLocalStart.timestampLocalToUTC() val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC() - db.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id") + database.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id") } } } - private fun migrateTimetableAdditional(db: SupportSQLiteDatabase) { - db.query("SELECT * FROM TimetableAdditional").use { + private fun migrateTimetableAdditional(database: SupportSQLiteDatabase) { + database.query("SELECT * FROM TimetableAdditional").use { while (it.moveToNext()) { val id = it.getLong(it.getColumnIndexOrThrow("id")) val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start")) @@ -88,7 +88,7 @@ class Migration46 : Migration(45, 46) { val timestampUtcStart = timestampLocalStart.timestampLocalToUTC() val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC() - db.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id") + database.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id") } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt index 97766c01e..6e1de19d4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt @@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration49 : Migration(48, 49) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements") - db.execSQL( + database.execSQL( """ CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` ( `user_login_id` INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt index a5b4e8e1a..dbcd916ba 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt @@ -7,16 +7,11 @@ import java.time.ZoneOffset class Migration5 : Migration(4, 5) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL") - db.execSQL( - "UPDATE Students SET registration_date = '${ - now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli() - }'" - ) - db.execSQL("DROP TABLE IF EXISTS Notes") - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL") + database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'") + database.execSQL("DROP TABLE IF EXISTS Notes") + database.execSQL(""" CREATE TABLE IF NOT EXISTS Notes ( id INTEGER PRIMARY KEY NOT NULL, is_read INTEGER NOT NULL, @@ -26,7 +21,6 @@ class Migration5 : Migration(4, 5) { teacher TEXT NOT NULL, category TEXT NOT NULL, content TEXT NOT NULL) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt index 577998ca0..d45a81570 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt @@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration50 : Migration(49, 50) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS MobileDevices") - db.execSQL( + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS MobileDevices") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `MobileDevices` ( `user_login_id` INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt index 7023049f9..e78e2e3a7 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt @@ -5,17 +5,17 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration51 : Migration(50, 51) { - override fun migrate(db: SupportSQLiteDatabase) { - createMailboxTable(db) - recreateMessagesTable(db) - recreateMessageAttachmentsTable(db) - recreateRecipientsTable(db) - deleteReportingUnitTable(db) + override fun migrate(database: SupportSQLiteDatabase) { + createMailboxTable(database) + recreateMessagesTable(database) + recreateMessageAttachmentsTable(database) + recreateRecipientsTable(database) + deleteReportingUnitTable(database) } - private fun createMailboxTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Mailboxes") - db.execSQL( + private fun createMailboxTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Mailboxes") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Mailboxes` ( `globalKey` TEXT NOT NULL, @@ -30,9 +30,9 @@ class Migration51 : Migration(50, 51) { ) } - private fun recreateMessagesTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Messages") - db.execSQL( + private fun recreateMessagesTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Messages") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Messages` ( `message_global_key` TEXT NOT NULL, @@ -52,9 +52,9 @@ class Migration51 : Migration(50, 51) { ) } - private fun recreateMessageAttachmentsTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS MessageAttachments") - db.execSQL( + private fun recreateMessageAttachmentsTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS MessageAttachments") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `MessageAttachments` ( `real_id` INTEGER NOT NULL, @@ -66,9 +66,9 @@ class Migration51 : Migration(50, 51) { ) } - private fun recreateRecipientsTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Recipients") - db.execSQL( + private fun recreateRecipientsTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Recipients") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Recipients` ( `mailboxGlobalKey` TEXT NOT NULL, @@ -82,7 +82,7 @@ class Migration51 : Migration(50, 51) { ) } - private fun deleteReportingUnitTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS ReportingUnits") + private fun deleteReportingUnitTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS ReportingUnits") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt index dd9e68c97..12624a51a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt @@ -5,14 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration53 : Migration(52, 53) { - override fun migrate(db: SupportSQLiteDatabase) { - createMailboxTable(db) - recreateMessagesTable(db) + override fun migrate(database: SupportSQLiteDatabase) { + createMailboxTable(database) + recreateMessagesTable(database) } - private fun createMailboxTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Mailboxes") - db.execSQL( + private fun createMailboxTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Mailboxes") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Mailboxes` ( `globalKey` TEXT NOT NULL, @@ -29,9 +29,9 @@ class Migration53 : Migration(52, 53) { ) } - private fun recreateMessagesTable(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Messages") - db.execSQL( + private fun recreateMessagesTable(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Messages") + database.execSQL( """ CREATE TABLE IF NOT EXISTS `Messages` ( `email` TEXT NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt deleted file mode 100644 index 60bd21f0a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration54 : Migration(53, 54) { - - override fun migrate(db: SupportSQLiteDatabase) { - migrateResman(db) - removeTomaszowMazowieckiStudents(db) - } - - private fun migrateResman(db: SupportSQLiteDatabase) { - db.execSQL( - """ - UPDATE Students SET - scrapper_base_url = 'https://vulcan.net.pl', - login_type = 'ADFSLightScoped', - symbol = 'rzeszowprojekt' - WHERE scrapper_base_url = 'https://resman.pl' - """.trimIndent() - ) - } - - private fun removeTomaszowMazowieckiStudents(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt deleted file mode 100644 index 424be171b..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.DeleteColumn -import androidx.room.migration.AutoMigrationSpec -import androidx.sqlite.db.SupportSQLiteDatabase - -@DeleteColumn( - tableName = "MessageAttachments", - columnName = "real_id", -) -class Migration55 : AutoMigrationSpec { - - override fun onPostMigrate(db: SupportSQLiteDatabase) { - db.execSQL("DELETE FROM Messages") - db.execSQL("DELETE FROM MessageAttachments") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt deleted file mode 100644 index 2fc8718f9..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.DeleteColumn -import androidx.room.migration.AutoMigrationSpec - -@DeleteColumn( - tableName = "AdminMessages", - columnName = "type", -) -class Migration57 : AutoMigrationSpec diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt deleted file mode 100644 index c440d58d6..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.DeleteColumn -import androidx.room.migration.AutoMigrationSpec - -@DeleteColumn( - tableName = "AdminMessages", - columnName = "is_dismissible", -) -class Migration58 : AutoMigrationSpec diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt index 06cd5f0fd..fa9436187 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration6 : Migration(5, 6) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS ReportingUnits ( id INTEGER PRIMARY KEY NOT NULL, student_id INTEGER NOT NULL, @@ -16,11 +15,9 @@ class Migration6 : Migration(5, 6) { sender_id INTEGER NOT NULL, sender_name TEXT NOT NULL, roles TEXT NOT NULL) - """ - ) + """) - db.execSQL( - """ + database.execSQL(""" CREATE TABLE IF NOT EXISTS Recipients ( id INTEGER PRIMARY KEY NOT NULL, student_id INTEGER NOT NULL, @@ -31,11 +28,10 @@ class Migration6 : Migration(5, 6) { unit_id INTEGER NOT NULL, role INTEGER NOT NULL, hash TEXT NOT NULL) - """ - ) + """) - db.execSQL("DELETE FROM Semesters WHERE 1") - db.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") - db.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL") + database.execSQL("DELETE FROM Semesters WHERE 1") + database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") + database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt deleted file mode 100644 index f88d31fcc..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.AutoMigrationSpec -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration63 : AutoMigrationSpec { - - override fun onPostMigrate(db: SupportSQLiteDatabase) { - db.execSQL("UPDATE Students SET is_edu_one = NULL WHERE is_edu_one = 0") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt index 83a822f22..120716c81 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt @@ -5,9 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration7 : Migration(6, 7) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" CREATE TABLE IF NOT EXISTS GradesStatistics ( id INTEGER PRIMARY KEY NOT NULL, student_id INTEGER NOT NULL, @@ -16,7 +15,6 @@ class Migration7 : Migration(6, 7) { grade INTEGER NOT NULL, amount INTEGER NOT NULL, is_semester INTEGER NOT NULL) - """ - ) + """) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt index 992e8c68d..7009ee129 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt @@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration8 : Migration(7, 8) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL") - db.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL") - db.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL") + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL") + database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL") + database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL") } } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt index b83c34c41..d79a57062 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt @@ -5,10 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase class Migration9 : Migration(8, 9) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("DROP TABLE IF EXISTS Messages") - db.execSQL( - """ + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS Messages") + database.execSQL(""" CREATE TABLE IF NOT EXISTS Messages ( id INTEGER PRIMARY KEY NOT NULL, student_id INTEGER NOT NULL, diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt index 7cb4202a1..899ba9085 100644 --- a/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt +++ b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt @@ -3,10 +3,5 @@ package io.github.wulkanowy.data.enums enum class MessageFolder(val id: Int = 1) { RECEIVED(1), SENT(2), - TRASHED(3), - ; - - companion object { - fun byId(id: Int) = entries.first { it.id == id } - } + TRASHED(3) } diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt deleted file mode 100644 index 531684e4e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.data.enums - -enum class MessageType { - GENERAL_MESSAGE, - DASHBOARD_MESSAGE, - LOGIN_MESSAGE, - PASS_RESET_MESSAGE, - ERROR_OVERRIDE, -} diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt deleted file mode 100644 index c8310c02d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.data.enums - -enum class TimetableGapsMode(val value: String) { - NO_GAPS("no_gaps"), - BETWEEN_LESSONS("between"), - BETWEEN_AND_BEFORE_LESSONS("before_and_between"); - - companion object { - fun getByValue(value: String) = entries.find { it.value == value } ?: BETWEEN_LESSONS - } -} 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 index add6439d4..17a9e5cdb 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt @@ -10,9 +10,9 @@ fun List.mapToEntities(semester: Semester) = map { diaryId = semester.diaryId, agenda = it.agenda, conferenceId = it.id, - date = it.date.toInstant(), + date = it.dateZoned.toInstant(), presentOnConference = it.presentOnConference, - subject = it.topic, - title = it.place, + subject = it.subject, + title = it.title ) } diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt index 1a84a6a5e..16f1bbac0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt @@ -3,26 +3,12 @@ package io.github.wulkanowy.data.mappers import io.github.wulkanowy.data.db.entities.SchoolAnnouncement import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.sdk.pojo.DirectorInformation as SdkDirectorInformation -import io.github.wulkanowy.sdk.pojo.LastAnnouncement as SdkLastAnnouncement -@JvmName("mapDirectorInformationToEntities") fun List.mapToEntities(student: Student) = map { SchoolAnnouncement( - studentId = student.studentId, + userLoginId = student.userLoginId, date = it.date, subject = it.subject, content = it.content, - author = null, - ) -} - -@JvmName("mapLastAnnouncementsToEntities") -fun List.mapToEntities(student: Student) = map { - SchoolAnnouncement( - studentId = student.studentId, - date = it.date, - subject = it.subject, - content = it.content, - author = it.author, ) } 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 index 173dfebf9..bdb5efbba 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt @@ -11,7 +11,7 @@ fun List.mapToEntities(semester: Semester) = map { date = it.date, entryDate = it.entryDate, subject = it.subject, - group = "", + group = it.group, type = it.type, description = it.description, teacher = it.teacher, 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 index 66e922171..178de682a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt @@ -1,12 +1,10 @@ package io.github.wulkanowy.data.mappers import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.sdk.pojo.Grade as SdkGrade -import io.github.wulkanowy.sdk.pojo.GradeDescriptive as SdkGradeDescriptive 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( @@ -42,15 +40,3 @@ fun List.mapToEntities(semester: Semester) = map { average = it.average ) } - -@JvmName("mapGradeDescriptiveToEntities") -fun List.mapToEntities(semester: Semester) = map { - GradeDescriptive( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - description = it.description - ) -} - - 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 index a26d76651..120eb183a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt @@ -2,7 +2,6 @@ package io.github.wulkanowy.data.mappers import io.github.wulkanowy.data.db.entities.* import io.github.wulkanowy.sdk.pojo.MailboxType -import timber.log.Timber import io.github.wulkanowy.sdk.pojo.Message as SdkMessage import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient @@ -17,16 +16,13 @@ fun List.mapToEntities( mailboxKey = mailbox?.globalKey ?: allMailboxes.find { box -> box.fullName == it.mailbox }?.globalKey.let { mailboxKey -> - if (mailboxKey == null) { - Timber.e("Can't find ${it.mailbox} in $allMailboxes") - "unknown" - } else mailboxKey + requireNotNull(mailboxKey) { "Can't find ${it.mailbox} in $allMailboxes" } }, email = student.email, messageId = it.id, correspondents = it.correspondents, subject = it.subject.trim(), - date = it.date.toInstant(), + date = it.dateZoned.toInstant(), folderId = it.folderId, unread = it.unread, unreadBy = it.unreadBy, @@ -40,6 +36,7 @@ fun List.mapToEntities( fun List.mapToEntities(messageGlobalKey: String) = map { MessageAttachment( messageGlobalKey = messageGlobalKey, + realId = it.url.hashCode(), url = it.url, filename = it.filename ) 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 index 3818f01aa..1a1c501f6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt @@ -8,8 +8,8 @@ import io.github.wulkanowy.sdk.pojo.Token as SdkToken fun List.mapToEntities(student: Student) = map { MobileDevice( - studentId = student.studentId, - date = it.createDate.toInstant(), + userLoginId = student.userLoginId, + date = it.createDateZoned.toInstant(), deviceId = it.id, name = it.name ) diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt deleted file mode 100644 index 7e6a8166d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/RegisterUserMapper.kt +++ /dev/null @@ -1,94 +0,0 @@ -package io.github.wulkanowy.data.mappers - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.pojos.* -import java.time.Instant -import io.github.wulkanowy.sdk.pojo.RegisterStudent as SdkRegisterStudent -import io.github.wulkanowy.sdk.pojo.RegisterUser as SdkRegisterUser - -fun SdkRegisterUser.mapToPojo(password: String?) = RegisterUser( - email = email, - login = login, - password = password, - scrapperBaseUrl = scrapperBaseUrl, - loginMode = loginMode, - loginType = loginType, - symbols = symbols.map { registerSymbol -> - RegisterSymbol( - symbol = registerSymbol.symbol, - error = registerSymbol.error, - hebeBaseUrl = registerSymbol.hebeBaseUrl, - keyId = registerSymbol.keyId, - privatePem = registerSymbol.privatePem, - userName = registerSymbol.userName, - schools = registerSymbol.schools.map { - RegisterUnit( - userLoginId = it.userLoginId, - schoolId = it.schoolId, - schoolName = it.schoolName, - schoolShortName = it.schoolShortName, - parentIds = it.parentIds, - studentIds = it.studentIds, - employeeIds = it.employeeIds, - error = it.error, - students = it.subjects - .filterIsInstance() - .map { registerStudent -> - RegisterStudent( - studentId = registerStudent.studentId, - studentName = registerStudent.studentName, - studentSecondName = registerStudent.studentSecondName, - studentSurname = registerStudent.studentSurname, - className = registerStudent.className, - classId = registerStudent.classId, - isParent = registerStudent.isParent, - isAuthorized = registerStudent.isAuthorized, - isEduOne = registerStudent.isEduOne, - semesters = registerStudent.semesters - .mapToEntities(registerStudent.studentId), - ) - }, - ) - } - ) - }, -) - -fun RegisterStudent.mapToStudentWithSemesters( - user: RegisterUser, - scrapperDomainSuffix: String, - symbol: RegisterSymbol, - unit: RegisterUnit, - colors: List, -): StudentWithSemesters = StudentWithSemesters( - semesters = semesters, - student = Student( - email = user.login, // for compatibility - userName = symbol.userName, - userLoginId = unit.userLoginId, - isParent = isParent, - className = className, - classId = classId, - studentId = studentId, - symbol = symbol.symbol, - loginType = user.loginType?.name.orEmpty(), - schoolName = unit.schoolName, - schoolShortName = unit.schoolShortName, - schoolSymbol = unit.schoolId, - studentName = "$studentName $studentSurname", - loginMode = user.loginMode.name, - scrapperBaseUrl = user.scrapperBaseUrl.orEmpty(), - scrapperDomainSuffix = scrapperDomainSuffix, - mobileBaseUrl = symbol.hebeBaseUrl.orEmpty(), - certificateKey = symbol.keyId.orEmpty(), - privateKey = symbol.privatePem.orEmpty(), - password = user.password.orEmpty(), - isCurrent = false, - registrationDate = Instant.now(), - isAuthorized = this.isAuthorized, - isEduOne = this.isEduOne, - ).apply { - avatarColor = colors.random() - }, -) diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt new file mode 100644 index 000000000..a2110d7f5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt @@ -0,0 +1,37 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import java.time.Instant +import io.github.wulkanowy.sdk.pojo.Student as SdkStudent + +fun List.mapToEntities(password: String = "", colors: List) = map { + StudentWithSemesters( + student = Student( + email = it.email, + password = password, + isParent = it.isParent, + symbol = it.symbol, + studentId = it.studentId, + userLoginId = it.userLoginId, + userName = it.userName, + studentName = it.studentName + " " + it.studentSurname, + schoolSymbol = it.schoolSymbol, + schoolShortName = it.schoolShortName, + schoolName = it.schoolName, + className = it.className, + classId = it.classId, + scrapperBaseUrl = it.scrapperBaseUrl, + loginType = it.loginType.name, + isCurrent = false, + registrationDate = Instant.now(), + mobileBaseUrl = it.mobileBaseUrl, + privateKey = it.privateKey, + certificateKey = it.certificateKey, + loginMode = it.loginMode.name, + ).apply { + avatarColor = colors.random() + }, + semesters = it.semesters.mapToEntities(it.studentId) + ) +} 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 index ee525e108..e55aa3cf7 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt @@ -5,10 +5,10 @@ import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.TimetableAdditional import io.github.wulkanowy.data.db.entities.TimetableHeader import io.github.wulkanowy.data.pojos.TimetableFull -import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetableFull +import io.github.wulkanowy.sdk.pojo.TimetableFull as SdkTimetableFull import io.github.wulkanowy.sdk.pojo.TimetableDayHeader as SdkTimetableHeader -import io.github.wulkanowy.sdk.pojo.Lesson as SdkLesson -import io.github.wulkanowy.sdk.pojo.LessonAdditional as SdkTimetableAdditional +import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetable +import io.github.wulkanowy.sdk.pojo.TimetableAdditional as SdkTimetableAdditional fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull( lessons = lessons.mapToEntities(semester), @@ -16,13 +16,13 @@ fun SdkTimetableFull.mapToEntities(semester: Semester) = TimetableFull( headers = headers.mapToEntities(semester) ) -fun List.mapToEntities(semester: Semester) = map { +fun List.mapToEntities(semester: Semester) = map { Timetable( studentId = semester.studentId, diaryId = semester.diaryId, number = it.number, - start = it.start.toInstant(), - end = it.end.toInstant(), + start = it.startZoned.toInstant(), + end = it.endZoned.toInstant(), date = it.date, subject = it.subject, subjectOld = it.subjectOld, @@ -45,8 +45,8 @@ fun List.mapToEntities(semester: Semester) = map { diaryId = semester.diaryId, subject = it.subject, date = it.date, - start = it.start.toInstant(), - end = it.end.toInstant(), + start = it.startZoned.toInstant(), + end = it.endZoned.toInstant(), ) } diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/LoginEvent.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/LoginEvent.kt deleted file mode 100644 index c2b4d2ded..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/LoginEvent.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.data.pojos - -import kotlinx.serialization.Serializable - -@Serializable -data class LoginEvent( - val uuid: String, - val schoolName: String, - val schoolShort: String, - val schoolAddress: String, - val scraperBaseUrl: String, - val symbol: String, - val schoolId: String, - val loginType: String, -) - -@Serializable -data class IntegrityRequest( - val tokenString: String, - val data: T, -) diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt deleted file mode 100644 index dec6ebec1..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/RegisterUser.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.wulkanowy.data.pojos - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.sdk.scrapper.Scrapper - -data class RegisterUser( - val email: String, - val password: String?, - val login: String, // may be the same as email - val scrapperBaseUrl: String?, - val loginType: Scrapper.LoginType?, - val loginMode: Sdk.Mode, - val symbols: List, -) : java.io.Serializable - -data class RegisterSymbol( - val symbol: String, - val error: Throwable?, - val hebeBaseUrl: String?, - val keyId: String?, - val privatePem: String?, - val userName: String, - val schools: List, -) : java.io.Serializable - -data class RegisterUnit( - val userLoginId: Int, - val schoolId: String, - val schoolName: String, - val schoolShortName: String, - val parentIds: List, - val studentIds: List, - val employeeIds: List, - val error: Throwable?, - val students: List, -) : java.io.Serializable - -data class RegisterStudent( - val studentId: Int, - val studentName: String, - val studentSecondName: String, - val studentSurname: String, - val className: String, - val classId: Int, - val isParent: Boolean, - val semesters: List, - val isAuthorized: Boolean, - val isEduOne: Boolean -) : java.io.Serializable diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt index b831ee755..c9655b722 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AdminMessageRepository.kt @@ -1,11 +1,10 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.Resource import io.github.wulkanowy.data.api.AdminMessageService import io.github.wulkanowy.data.db.dao.AdminMessageDao -import io.github.wulkanowy.data.db.entities.AdminMessage +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.networkBoundResource -import kotlinx.coroutines.flow.Flow +import io.github.wulkanowy.utils.AppInfo import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -14,20 +13,34 @@ import javax.inject.Singleton class AdminMessageRepository @Inject constructor( private val adminMessageService: AdminMessageService, private val adminMessageDao: AdminMessageDao, + private val appInfo: AppInfo ) { - private val saveFetchResultMutex = Mutex() - fun getAdminMessages(): Flow>> = - networkBoundResource( - mutex = saveFetchResultMutex, - isResultEmpty = { false }, - query = { adminMessageDao.loadAll() }, - fetch = { adminMessageService.getAdminMessages() }, - shouldFetch = { true }, - saveFetchResult = { oldItems, newItems -> - adminMessageDao.removeOldAndSaveNew(oldItems, newItems) - }, - showSavedOnLoading = false, - ) + suspend fun getAdminMessages(student: Student) = networkBoundResource( + mutex = saveFetchResultMutex, + isResultEmpty = { it == null }, + query = { adminMessageDao.loadAll() }, + fetch = { adminMessageService.getAdminMessages() }, + shouldFetch = { true }, + saveFetchResult = { oldItems, newItems -> + adminMessageDao.removeOldAndSaveNew(oldItems, newItems) + }, + showSavedOnLoading = false, + mapResult = { adminMessages -> + adminMessages.filter { adminMessage -> + val isCorrectRegister = adminMessage.targetRegisterHost?.let { + student.scrapperBaseUrl.contains(it, true) + } ?: true + val isCorrectFlavor = + adminMessage.targetFlavor?.equals(appInfo.buildFlavor, true) ?: true + val isCorrectMaxVersion = + adminMessage.versionMax?.let { it >= appInfo.versionCode } ?: true + val isCorrectMinVersion = + adminMessage.versionMin?.let { it <= appInfo.versionCode } ?: true + + isCorrectRegister && isCorrectFlavor && isCorrectMaxVersion && isCorrectMinVersion + }.maxByOrNull { it.id } + } + ) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt index bec2797db..cbaa12bd3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt @@ -19,6 +19,7 @@ class AppCreatorRepository @Inject constructor( ) { @OptIn(ExperimentalSerializationApi::class) + @Suppress("BlockingMethodInNonBlockingContext") suspend fun getAppCreators() = withContext(dispatchers.io) { val inputStream = context.assets.open("contributors.json").buffered() json.decodeFromStream>(inputStream) 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 index 9b94cc103..fd5d8bd16 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.AttendanceDao import io.github.wulkanowy.data.db.dao.TimetableDao import io.github.wulkanowy.data.db.entities.Attendance @@ -8,14 +7,13 @@ 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.networkBoundResource +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.monday -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.utils.* +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.withContext import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime @@ -26,7 +24,7 @@ import javax.inject.Singleton class AttendanceRepository @Inject constructor( private val attendanceDb: AttendanceDao, private val timetableDb: TimetableDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -54,21 +52,23 @@ class AttendanceRepository @Inject constructor( attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) }, fetch = { - val lessons = timetableDb.load( - semester.diaryId, semester.studentId, start.monday, end.sunday - ) - wulkanowySdkFactory.create(student, semester) - .getAttendance(start.monday, end.sunday) + val lessons = withContext(Dispatchers.IO) { + timetableDb.load( + semester.diaryId, semester.studentId, start.monday, end.sunday + ) + } + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getAttendance(start.monday, end.sunday, semester.semesterId) .mapToEntities(semester, lessons) }, saveFetchResult = { old, new -> + attendanceDb.deleteAll(old uniqueSubtract new) val attendanceToAdd = (new uniqueSubtract old).map { newAttendance -> newAttendance.apply { if (notify) isNotified = false } } - attendanceDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = attendanceToAdd, - ) + attendanceDb.insertAll(attendanceToAdd) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) }, filterResult = { it.filter { item -> item.date in start..end } } @@ -87,10 +87,8 @@ class AttendanceRepository @Inject constructor( } suspend fun excuseForAbsence( - student: Student, - semester: Semester, - absenceList: List, - reason: String? = null + student: Student, semester: Semester, + absenceList: List, reason: String? = null ) { val items = absenceList.map { attendance -> Absent( @@ -98,7 +96,8 @@ class AttendanceRepository @Inject constructor( timeId = attendance.timeId ) } - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .excuseForAbsence(items, 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 index 78c98169b..8e0709135 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt @@ -1,15 +1,14 @@ package io.github.wulkanowy.data.repositories -import androidx.room.withTransaction -import io.github.wulkanowy.data.WulkanowySdkFactory -import io.github.wulkanowy.data.db.AppDatabase 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.data.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.sync.Mutex import javax.inject.Inject @@ -18,9 +17,8 @@ import javax.inject.Singleton @Singleton class AttendanceSummaryRepository @Inject constructor( private val attendanceDb: AttendanceSummaryDao, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, - private val appDatabase: AppDatabase, - private val wulkanowySdkFactory: WulkanowySdkFactory, ) { private val saveFetchResultMutex = Mutex() @@ -41,15 +39,14 @@ class AttendanceSummaryRepository @Inject constructor( }, query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getAttendanceSummary(subjectId) .mapToEntities(semester, subjectId) }, saveFetchResult = { old, new -> - appDatabase.withTransaction { - attendanceDb.deleteAll(old uniqueSubtract new) - attendanceDb.insertAll(new uniqueSubtract old) - } + 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 index 45a36f55c..8f393cadb 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt @@ -1,16 +1,12 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource -import io.github.wulkanowy.utils.AutoRefreshHelper -import io.github.wulkanowy.utils.getRefreshKey -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.* import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject @@ -19,7 +15,7 @@ import javax.inject.Singleton @Singleton class CompletedLessonsRepository @Inject constructor( private val completedLessonsDb: CompletedLessonsDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -51,15 +47,14 @@ class CompletedLessonsRepository @Inject constructor( ) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getCompletedLessons(start.monday, end.sunday) .mapToEntities(semester) }, saveFetchResult = { old, new -> - completedLessonsDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + 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 index 58ce0091a..83204cab0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt @@ -1,14 +1,15 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.ConferenceDao import io.github.wulkanowy.data.db.entities.Conference 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.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex @@ -19,7 +20,7 @@ import javax.inject.Singleton @Singleton class ConferenceRepository @Inject constructor( private val conferenceDb: ConferenceDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -44,18 +45,19 @@ class ConferenceRepository @Inject constructor( conferenceDb.loadAll(semester.diaryId, student.studentId, startDate) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getConferences() .mapToEntities(semester) .filter { it.date >= startDate } }, saveFetchResult = { old, new -> - conferenceDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - if (notify) it.isNotified = false - }, - ) + val conferencesToSave = (new uniqueSubtract old).onEach { + if (notify) it.isNotified = false + } + + conferenceDb.deleteAll(old uniqueSubtract new) + conferenceDb.insertAll(conferencesToSave) 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 index 89dbcd5ce..faa80b93e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt @@ -1,17 +1,13 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.ExamDao import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.data.networkBoundResource -import io.github.wulkanowy.utils.AutoRefreshHelper -import io.github.wulkanowy.utils.endExamsDay -import io.github.wulkanowy.utils.getRefreshKey -import io.github.wulkanowy.utils.startExamsDay -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex import java.time.LocalDate @@ -21,7 +17,7 @@ import javax.inject.Singleton @Singleton class ExamRepository @Inject constructor( private val examDb: ExamDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -54,32 +50,31 @@ class ExamRepository @Inject constructor( ) }, fetch = { - wulkanowySdkFactory.create(student, semester) - .getExams(start.startExamsDay, start.endExamsDay) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getExams(start.startExamsDay, start.endExamsDay, semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - examDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - if (notify) it.isNotified = false - }, - ) + val examsToSave = (new uniqueSubtract old).onEach { + if (notify) it.isNotified = false + } + + examDb.deleteAll(old uniqueSubtract new) + examDb.insertAll(examsToSave) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) }, filterResult = { it.filter { item -> item.date in start..end } } ) - fun getExamsFromDatabase( - semester: Semester, - start: LocalDate, - end: LocalDate - ): Flow> = examDb.loadAll( - diaryId = semester.diaryId, - studentId = semester.studentId, - from = start, - end = end, - ) + fun getExamsFromDatabase(semester: Semester, start: LocalDate): Flow> { + return examDb.loadAll( + diaryId = semester.diaryId, + studentId = semester.studentId, + from = start.startExamsDay, + end = start.endExamsDay + ) + } suspend fun updateExam(exam: List) = examDb.updateAll(exam) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt index e899f900d..f5f895d82 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt @@ -1,20 +1,15 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.GradeDao -import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao import io.github.wulkanowy.data.db.dao.GradeSummaryDao import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive 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.data.networkBoundResource -import io.github.wulkanowy.utils.AutoRefreshHelper -import io.github.wulkanowy.utils.getRefreshKey -import io.github.wulkanowy.utils.toLocalDate -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map @@ -27,13 +22,14 @@ import javax.inject.Singleton class GradeRepository @Inject constructor( private val gradeDb: GradeDao, private val gradeSummaryDb: GradeSummaryDao, - private val gradeDescriptiveDb: GradeDescriptiveDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { private val saveFetchResultMutex = Mutex() + private val cacheKey = "grade" + fun getGrades( student: Student, semester: Semester, @@ -45,53 +41,30 @@ class GradeRepository @Inject constructor( //When details is empty and summary is not, app will not use summary cache - edge case it.first.isEmpty() }, - shouldFetch = { (details, summaries, descriptive) -> - val isExpired = - refreshHelper.shouldBeRefreshed(getRefreshKey(GRADE_CACHE_KEY, semester)) - details.isEmpty() || (summaries.isEmpty() && descriptive.isEmpty()) || forceRefresh || isExpired + shouldFetch = { (details, summaries) -> + val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, semester)) + details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired }, query = { val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId) val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) - val descriptiveFlow = - gradeDescriptiveDb.loadAll(semester.semesterId, semester.studentId) - - combine(detailsFlow, summaryFlow, descriptiveFlow) { details, summaries, descriptive -> - Triple(details, summaries, descriptive) - } + detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries } }, fetch = { - val (details, summary, descriptive) = wulkanowySdkFactory.create(student, semester) + val (details, summary) = sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getGrades(semester.semesterId) - Triple( - details.mapToEntities(semester), - summary.mapToEntities(semester), - descriptive.mapToEntities(semester) - ) + details.mapToEntities(semester) to summary.mapToEntities(semester) }, - saveFetchResult = { (oldDetails, oldSummary, oldDescriptive), (newDetails, newSummary, newDescriptive) -> + saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) -> refreshGradeDetails(student, oldDetails, newDetails, notify) refreshGradeSummaries(oldSummary, newSummary, notify) - refreshGradeDescriptions(oldDescriptive, newDescriptive, notify) - refreshHelper.updateLastRefreshTimestamp(getRefreshKey(GRADE_CACHE_KEY, semester)) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) } ) - private suspend fun refreshGradeDescriptions( - old: List, - new: List, - notify: Boolean - ) { - gradeDescriptiveDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - if (notify) it.isNotified = false - }, - ) - } - private suspend fun refreshGradeDetails( student: Student, oldGrades: List, @@ -100,16 +73,13 @@ class GradeRepository @Inject constructor( ) { val notifyBreakDate = oldGrades.maxByOrNull { it.date }?.date ?: student.registrationDate.toLocalDate() - - gradeDb.removeOldAndSaveNew( - oldItems = oldGrades uniqueSubtract newDetails, - newItems = (newDetails uniqueSubtract oldGrades).onEach { - if (it.date >= notifyBreakDate) it.apply { - isRead = false - if (notify) isNotified = false - } - }, - ) + gradeDb.deleteAll(oldGrades uniqueSubtract newDetails) + gradeDb.insertAll((newDetails uniqueSubtract oldGrades).onEach { + if (it.date >= notifyBreakDate) it.apply { + isRead = false + if (notify) isNotified = false + } + }) } private suspend fun refreshGradeSummaries( @@ -117,43 +87,31 @@ class GradeRepository @Inject constructor( newSummary: List, notify: Boolean ) { - gradeSummaryDb.removeOldAndSaveNew( - oldItems = oldSummaries uniqueSubtract newSummary, - newItems = (newSummary uniqueSubtract oldSummaries).onEach { summary -> - getGradeSummaryWithUpdatedNotificationState( - summary = summary, - oldSummary = oldSummaries.find { it.subject == summary.subject }, - notify = notify, - ) - }, - ) - } + gradeSummaryDb.deleteAll(oldSummaries uniqueSubtract newSummary) + gradeSummaryDb.insertAll((newSummary uniqueSubtract oldSummaries).onEach { summary -> + val oldSummary = oldSummaries.find { old -> old.subject == summary.subject } + summary.isPredictedGradeNotified = when { + summary.predictedGrade.isEmpty() -> true + notify && oldSummary?.predictedGrade != summary.predictedGrade -> false + else -> true + } + summary.isFinalGradeNotified = when { + summary.finalGrade.isEmpty() -> true + notify && oldSummary?.finalGrade != summary.finalGrade -> false + else -> true + } - private fun getGradeSummaryWithUpdatedNotificationState( - summary: GradeSummary, - oldSummary: GradeSummary?, - notify: Boolean, - ) { - summary.isPredictedGradeNotified = when { - summary.predictedGrade.isEmpty() -> true - notify && oldSummary?.predictedGrade != summary.predictedGrade -> false - else -> true - } - summary.isFinalGradeNotified = when { - summary.finalGrade.isEmpty() -> true - notify && oldSummary?.finalGrade != summary.finalGrade -> false - else -> true - } - summary.predictedGradeLastChange = when { - oldSummary == null -> Instant.now() - summary.predictedGrade != oldSummary.predictedGrade -> Instant.now() - else -> oldSummary.predictedGradeLastChange - } - summary.finalGradeLastChange = when { - oldSummary == null -> Instant.now() - summary.finalGrade != oldSummary.finalGrade -> Instant.now() - else -> oldSummary.finalGradeLastChange - } + summary.predictedGradeLastChange = when { + oldSummary == null -> Instant.now() + summary.predictedGrade != oldSummary.predictedGrade -> Instant.now() + else -> oldSummary.predictedGradeLastChange + } + summary.finalGradeLastChange = when { + oldSummary == null -> Instant.now() + summary.finalGrade != oldSummary.finalGrade -> Instant.now() + else -> oldSummary.finalGradeLastChange + } + }) } fun getUnreadGrades(semester: Semester): Flow> { @@ -174,10 +132,6 @@ class GradeRepository @Inject constructor( return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) } - fun getGradesDescriptiveFromDatabase(semester: Semester): Flow> { - return gradeDescriptiveDb.loadAll(semester.semesterId, semester.studentId) - } - suspend fun updateGrade(grade: Grade) { return gradeDb.updateAll(listOf(grade)) } @@ -189,13 +143,4 @@ class GradeRepository @Inject constructor( suspend fun updateGradesSummary(gradesSummary: List) { return gradeSummaryDb.updateAll(gradesSummary) } - - suspend fun updateGradesDescriptive(gradesDescriptive: List) { - return gradeDescriptiveDb.updateAll(gradesDescriptive) - } - - private companion object { - - private const val GRADE_CACHE_KEY = "grade" - } } 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 index f120d34f3..9fa06c497 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao @@ -13,11 +12,13 @@ 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.data.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.sync.Mutex -import java.util.Locale +import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -26,7 +27,7 @@ class GradeStatisticsRepository @Inject constructor( private val gradePartialStatisticsDb: GradePartialStatisticsDao, private val gradePointsStatisticsDb: GradePointsStatisticsDao, private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -54,15 +55,14 @@ class GradeStatisticsRepository @Inject constructor( }, query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getGradesPartialStatistics(semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - gradePartialStatisticsDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + gradePartialStatisticsDb.deleteAll(old uniqueSubtract new) + gradePartialStatisticsDb.insertAll(new uniqueSubtract old) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(partialCacheKey, semester)) }, mapResult = { items -> @@ -79,7 +79,6 @@ class GradeStatisticsRepository @Inject constructor( ) listOf(summaryItem) + items } - else -> items.filter { it.subject == subjectName } }.mapPartialToStatisticItems() } @@ -101,15 +100,14 @@ class GradeStatisticsRepository @Inject constructor( }, query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getGradesSemesterStatistics(semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - gradeSemesterStatisticsDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + gradeSemesterStatisticsDb.deleteAll(old uniqueSubtract new) + gradeSemesterStatisticsDb.insertAll(new uniqueSubtract old) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(semesterCacheKey, semester)) }, mapResult = { items -> @@ -139,7 +137,6 @@ class GradeStatisticsRepository @Inject constructor( } listOf(summaryItem) + itemsWithAverage } - else -> itemsWithAverage.filter { it.subject == subjectName } }.mapSemesterToStatisticItems() } @@ -159,15 +156,14 @@ class GradeStatisticsRepository @Inject constructor( }, query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getGradesPointsStatistics(semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - gradePointsStatisticsDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + gradePointsStatisticsDb.deleteAll(old uniqueSubtract new) + gradePointsStatisticsDb.insertAll(new uniqueSubtract old) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(pointsCacheKey, semester)) }, mapResult = { items -> 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 index 7893ef631..f564824de 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt @@ -1,17 +1,13 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource -import io.github.wulkanowy.utils.AutoRefreshHelper -import io.github.wulkanowy.utils.getRefreshKey -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.* import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject @@ -20,7 +16,7 @@ import javax.inject.Singleton @Singleton class HomeworkRepository @Inject constructor( private val homeworkDb: HomeworkDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -53,19 +49,20 @@ class HomeworkRepository @Inject constructor( ) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getHomework(start.monday, end.sunday) .mapToEntities(semester) }, saveFetchResult = { old, new -> + val homeWorkToSave = (new uniqueSubtract old).onEach { + if (notify) it.isNotified = false + } val filteredOld = old.filterNot { it.isAddedByUser } - homeworkDb.removeOldAndSaveNew( - oldItems = filteredOld uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - if (notify) it.isNotified = false - }, - ) + homeworkDb.deleteAll(filteredOld uniqueSubtract new) + homeworkDb.insertAll(homeWorkToSave) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) } ) 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 index 3636cb51e..87e8410f1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt @@ -1,11 +1,12 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.sync.Mutex @@ -17,7 +18,7 @@ import javax.inject.Singleton @Singleton class LuckyNumberRepository @Inject constructor( private val luckyNumberDb: LuckyNumberDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk ) { private val saveFetchResultMutex = Mutex() @@ -32,18 +33,14 @@ class LuckyNumberRepository @Inject constructor( shouldFetch = { it == null || forceRefresh }, query = { luckyNumberDb.load(student.studentId, now()) }, fetch = { - wulkanowySdkFactory.create(student) - .getLuckyNumber(student.schoolShortName) - ?.mapToEntity(student) + sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student) }, - saveFetchResult = { oldLuckyNumber, newLuckyNumber -> - newLuckyNumber ?: return@networkBoundResource - - if (newLuckyNumber != oldLuckyNumber) { - luckyNumberDb.removeOldAndSaveNew( - oldItems = listOfNotNull(oldLuckyNumber), - newItems = listOf(newLuckyNumber.apply { if (notify) isNotified = false }), - ) + saveFetchResult = { old, new -> + if (new != old) { + old?.let { luckyNumberDb.deleteAll(listOfNotNull(it)) } + luckyNumberDb.insertAll(listOfNotNull((new?.apply { + if (notify) isNotified = false + }))) } } ) 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 index ede2a0fde..f95b8dbec 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt @@ -3,39 +3,29 @@ package io.github.wulkanowy.data.repositories import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R -import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.WulkanowySdkFactory +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.dao.MailboxDao import io.github.wulkanowy.data.db.dao.MessageAttachmentDao import io.github.wulkanowy.data.db.dao.MessagesDao -import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao -import io.github.wulkanowy.data.db.entities.Mailbox -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor -import io.github.wulkanowy.data.db.entities.MutedMessageSender -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.* import io.github.wulkanowy.data.enums.MessageFolder 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.data.mappers.mapFromEntities import io.github.wulkanowy.data.mappers.mapToEntities -import io.github.wulkanowy.data.networkBoundResource -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceSuccess import io.github.wulkanowy.data.pojos.MessageDraft -import io.github.wulkanowy.data.toFirstResult -import io.github.wulkanowy.data.waitForResult import io.github.wulkanowy.domain.messages.GetMailboxByStudentUseCase +import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.pojo.Folder import io.github.wulkanowy.utils.AutoRefreshHelper import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.sync.Mutex +import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import timber.log.Timber @@ -45,9 +35,8 @@ import javax.inject.Singleton @Singleton class MessageRepository @Inject constructor( private val messagesDb: MessagesDao, - private val mutedMessageSendersDao: MutedMessageSendersDao, private val messageAttachmentDao: MessageAttachmentDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, @ApplicationContext private val context: Context, private val refreshHelper: AutoRefreshHelper, private val sharedPrefProvider: SharedPrefProvider, @@ -55,6 +44,7 @@ class MessageRepository @Inject constructor( private val mailboxDao: MailboxDao, private val getMailboxByStudentUseCase: GetMailboxByStudentUseCase, ) { + private val saveFetchResultMutex = Mutex() private val messagesCacheKey = "message" @@ -66,7 +56,7 @@ class MessageRepository @Inject constructor( folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false, - ): Flow>> = networkBoundResource( + ): Flow>> = networkBoundResource( mutex = saveFetchResultMutex, isResultEmpty = { it.isEmpty() }, shouldFetch = { @@ -77,30 +67,21 @@ class MessageRepository @Inject constructor( }, query = { if (mailbox == null) { - messagesDb.loadMessagesWithMutedAuthor(folder.id, student.email) - } else messagesDb.loadMessagesWithMutedAuthor(mailbox.globalKey, folder.id) + messagesDb.loadAll(folder.id, student.email) + } else messagesDb.loadAll(mailbox.globalKey, folder.id) }, fetch = { - wulkanowySdkFactory.create(student) - .getMessages( - folder = Folder.valueOf(folder.name), - mailboxKey = mailbox?.globalKey, - ) - .mapToEntities( - student = student, - mailbox = mailbox, - allMailboxes = mailboxDao.loadAll(student.email) - ) + sdk.init(student).getMessages( + folder = Folder.valueOf(folder.name), + mailboxKey = mailbox?.globalKey, + ).mapToEntities(student, mailbox, mailboxDao.loadAll(student.email)) }, - saveFetchResult = { oldWithAuthors, new -> - val old = oldWithAuthors.map { it.message } - messagesDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - val muted = isMuted(it.correspondents) - it.isNotified = !notify || muted - }, - ) + saveFetchResult = { old, new -> + messagesDb.deleteAll(old uniqueSubtract new) + messagesDb.insertAll((new uniqueSubtract old).onEach { + it.isNotified = !notify + }) + refreshHelper.updateLastRefreshTimestamp( getRefreshKey(messagesCacheKey, mailbox, folder) ) @@ -116,25 +97,20 @@ class MessageRepository @Inject constructor( shouldFetch = { checkNotNull(it) { "This message no longer exist!" } Timber.d("Message content in db empty: ${it.message.content.isBlank()}") - (it.message.unread && markAsRead) || it.message.content.isBlank() + it.message.unread || it.message.content.isBlank() + }, + query = { + messagesDb.loadMessageWithAttachment(message.messageGlobalKey) }, - query = { messagesDb.loadMessageWithAttachment(message.messageGlobalKey) }, fetch = { - wulkanowySdkFactory.create(student) - .getMessageDetails( - messageKey = it!!.message.messageGlobalKey, - markAsRead = message.unread && markAsRead, - ) + sdk.init(student).getMessageDetails(it!!.message.messageGlobalKey, markAsRead) }, saveFetchResult = { old, new -> checkNotNull(old) { "Fetched message no longer exist!" } messagesDb.updateAll( listOf(old.message.apply { id = message.id - unread = when { - markAsRead -> false - else -> unread - } + unread = !markAsRead sender = new.sender recipients = new.recipients.singleOrNull() ?: "Wielu adresatów" content = content.ifBlank { new.content } @@ -144,7 +120,7 @@ class MessageRepository @Inject constructor( items = new.attachments.mapToEntities(message.messageGlobalKey), ) - Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read: $markAsRead") + Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read") } ) @@ -163,36 +139,22 @@ class MessageRepository @Inject constructor( subject: String, content: String, recipients: List, - mailbox: Mailbox, + mailboxId: String, ) { - wulkanowySdkFactory.create(student) - .sendMessage( - subject = subject, - content = content, - recipients = recipients.mapFromEntities(), - mailboxId = mailbox.globalKey, - ) - refreshFolders(student, mailbox, listOf(SENT)) + sdk.init(student).sendMessage( + subject = subject, + content = content, + recipients = recipients.mapFromEntities(), + mailboxId = mailboxId, + ) } - suspend fun restoreMessages(student: Student, mailbox: Mailbox?, messages: List) { - wulkanowySdkFactory.create(student) - .restoreMessages(messages = messages.map { it.messageGlobalKey }) - - refreshFolders(student, mailbox) - } - - suspend fun deleteMessage(student: Student, message: Message) { - deleteMessages(student, listOf(message)) - } - - suspend fun deleteMessages(student: Student, messages: List) { + suspend fun deleteMessages(student: Student, mailbox: Mailbox?, messages: List) { val firstMessage = messages.first() - wulkanowySdkFactory.create(student) - .deleteMessages( - messages = messages.map { it.messageGlobalKey }, - removeForever = firstMessage.folderId == TRASHED.id, - ) + sdk.init(student).deleteMessages( + messages = messages.map { it.messageGlobalKey }, + removeForever = firstMessage.folderId == TRASHED.id, + ) if (firstMessage.folderId != TRASHED.id) { val deletedMessages = messages.map { @@ -206,24 +168,18 @@ class MessageRepository @Inject constructor( } messagesDb.updateAll(deletedMessages) - } else { - messagesDb.deleteAll(messages) - } + } else messagesDb.deleteAll(messages) + + getMessages( + student = student, + mailbox = mailbox, + folder = TRASHED, + forceRefresh = true, + ).first() } - private suspend fun refreshFolders( - student: Student, - mailbox: Mailbox?, - folders: List = MessageFolder.entries - ) { - folders.forEach { - getMessages( - student = student, - mailbox = mailbox, - folder = it, - forceRefresh = true, - ).toFirstResult() - } + suspend fun deleteMessage(student: Student, mailbox: Mailbox, message: Message) { + deleteMessages(student, mailbox, listOf(message)) } suspend fun getMailboxes(student: Student, forceRefresh: Boolean) = networkBoundResource( @@ -237,9 +193,7 @@ class MessageRepository @Inject constructor( }, query = { mailboxDao.loadAll(student.email, student.symbol, student.schoolSymbol) }, fetch = { - wulkanowySdkFactory.create(student) - .getMailboxes() - .mapToEntities(student) + sdk.init(student).getMailboxes().mapToEntities(student) }, saveFetchResult = { old, new -> mailboxDao.deleteAll(old uniqueSubtract new) @@ -269,18 +223,4 @@ class MessageRepository @Inject constructor( context.getString(R.string.pref_key_message_draft), value?.let { json.encodeToString(it) } ) - - private suspend fun isMuted(author: String): Boolean { - return mutedMessageSendersDao.checkMute(author) - } - - suspend fun muteMessage(author: String) { - if (isMuted(author)) return - mutedMessageSendersDao.insertMute(MutedMessageSender(author)) - } - - suspend fun unmuteMessage(author: String) { - if (!isMuted(author)) return - mutedMessageSendersDao.deleteMute(author) - } } 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 index 1303d0e7a..07c6959e3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.MobileDeviceDao import io.github.wulkanowy.data.db.entities.MobileDevice import io.github.wulkanowy.data.db.entities.Semester @@ -9,8 +8,10 @@ import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken import io.github.wulkanowy.data.networkBoundResource 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.uniqueSubtract import kotlinx.coroutines.sync.Mutex import javax.inject.Inject @@ -19,7 +20,7 @@ import javax.inject.Singleton @Singleton class MobileDeviceRepository @Inject constructor( private val mobileDb: MobileDeviceDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -38,30 +39,32 @@ class MobileDeviceRepository @Inject constructor( val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student)) it.isEmpty() || forceRefresh || isExpired }, - query = { mobileDb.loadAll(student.studentId) }, + query = { mobileDb.loadAll(student.userLoginId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getRegisteredDevices() .mapToEntities(student) }, saveFetchResult = { old, new -> - mobileDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + mobileDb.deleteAll(old uniqueSubtract new) + mobileDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student)) } ) suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .unregisterDevice(device.deviceId) mobileDb.deleteAll(listOf(device)) } suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken { - return wulkanowySdkFactory.create(student, semester) + return sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, 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 index 9551e01eb..e5d7bc5cb 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt @@ -1,16 +1,13 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource -import io.github.wulkanowy.utils.AutoRefreshHelper -import io.github.wulkanowy.utils.getRefreshKey -import io.github.wulkanowy.utils.toLocalDate -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex import javax.inject.Inject @@ -19,7 +16,7 @@ import javax.inject.Singleton @Singleton class NoteRepository @Inject constructor( private val noteDb: NoteDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -43,21 +40,20 @@ class NoteRepository @Inject constructor( }, query = { noteDb.loadAll(student.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) - .getNotes() + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getNotes(semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - val notesToAdd = (new uniqueSubtract old).onEach { + 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 } - } - noteDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = notesToAdd, - ) + }) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) } ) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt index 64e60a60b..afc262868 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt @@ -2,28 +2,21 @@ package io.github.wulkanowy.data.repositories import android.content.Context import android.content.SharedPreferences -import androidx.annotation.StringRes import androidx.core.content.edit import com.fredporciuncula.flow.preferences.FlowSharedPreferences import com.fredporciuncula.flow.preferences.Preference -import com.fredporciuncula.flow.preferences.Serializer import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R -import io.github.wulkanowy.data.enums.AppTheme -import io.github.wulkanowy.data.enums.GradeColorTheme -import io.github.wulkanowy.data.enums.GradeExpandMode -import io.github.wulkanowy.data.enums.GradeSortingMode -import io.github.wulkanowy.data.enums.TimetableGapsMode -import io.github.wulkanowy.data.enums.TimetableMode +import io.github.wulkanowy.data.enums.* import io.github.wulkanowy.ui.modules.dashboard.DashboardItem import io.github.wulkanowy.ui.modules.grade.GradeAverageMode -import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import java.time.Instant -import java.util.UUID +import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -35,35 +28,29 @@ class PreferencesRepository @Inject constructor( private val json: Json, ) { + val startMenuIndex: Int + get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt() + val isShowPresent: Boolean get() = getBoolean( R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present ) - private val gradeAverageModePref: Preference - get() = getObjectFlow( - R.string.pref_key_grade_average_mode, - R.string.pref_default_grade_average_mode, - object : Serializer { - override fun serialize(value: GradeAverageMode) = value.value - override fun deserialize(serialized: String) = - GradeAverageMode.getByValue(serialized) - }, + val gradeAverageMode: GradeAverageMode + get() = GradeAverageMode.getByValue( + getString( + R.string.pref_key_grade_average_mode, + R.string.pref_default_grade_average_mode + ) ) - val gradeAverageModeFlow: Flow - get() = gradeAverageModePref.asFlow() - - private val gradeAverageForceCalcPref: Preference - get() = flowSharedPref.getBoolean( - context.getString(R.string.pref_key_grade_average_force_calc), - context.resources.getBoolean(R.bool.pref_default_grade_average_force_calc) + val gradeAverageForceCalc: Boolean + get() = getBoolean( + R.string.pref_key_grade_average_force_calc, + R.bool.pref_default_grade_average_force_calc ) - val gradeAverageForceCalcFlow: Flow - get() = gradeAverageForceCalcPref.asFlow() - val gradeExpandMode: GradeExpandMode get() = GradeExpandMode.getByValue( getString( @@ -153,24 +140,12 @@ class PreferencesRepository @Inject constructor( R.string.pref_default_grade_modifier_plus ).toDouble() - val gradePlusModifierFlow: Flow - get() = getStringFlow( - R.string.pref_key_grade_modifier_plus, - R.string.pref_default_grade_modifier_plus - ).asFlow().map { it.toDouble() } - val gradeMinusModifier: Double get() = getString( R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus ).toDouble() - val gradeMinusModifierFlow: Flow - get() = getStringFlow( - R.string.pref_key_grade_modifier_minus, - R.string.pref_default_grade_modifier_minus - ).asFlow().map { it.toDouble() } - val fillMessageContent: Boolean get() = getBoolean( R.string.pref_key_fill_message_content, @@ -199,25 +174,30 @@ class PreferencesRepository @Inject constructor( ) ) - val showTimetableGaps: TimetableGapsMode - get() = TimetableGapsMode.getByValue( - getString( - R.string.pref_key_timetable_show_gaps, - R.string.pref_default_timetable_show_gaps - ) + val showTimetableTimers: Boolean + get() = getBoolean( + R.string.pref_key_timetable_show_timers, + R.bool.pref_default_timetable_show_timers ) + var isHomeworkFullscreen: Boolean + get() = getBoolean( + R.string.pref_key_homework_fullscreen, + R.bool.pref_default_homework_fullscreen + ) + set(value) = sharedPref.edit().putBoolean("homework_fullscreen", value).apply() + val showSubjectsWithoutGrades: Boolean get() = getBoolean( R.string.pref_key_subjects_without_grades, R.bool.pref_default_subjects_without_grades ) - val isOptionalArithmeticAverageFlow: Flow - get() = flowSharedPref.getBoolean( - context.getString(R.string.pref_key_optional_arithmetic_average), - context.resources.getBoolean(R.bool.pref_default_optional_arithmetic_average) - ).asFlow() + val isOptionalArithmeticAverage: Boolean + get() = getBoolean( + R.string.pref_key_optional_arithmetic_average, + R.bool.pref_default_optional_arithmetic_average + ) var lasSyncDate: Instant? get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date) @@ -308,6 +288,19 @@ class PreferencesRepository @Inject constructor( get() = sharedPref.getBoolean(PREF_KEY_APP_SUPPORT_SHOWN, false) set(value) = sharedPref.edit { putBoolean(PREF_KEY_APP_SUPPORT_SHOWN, value) } + var isAgreeToProcessData: Boolean + get() = getBoolean( + R.string.pref_key_ads_consent_data_processing, + R.bool.pref_default_ads_consent_data_processing + ) + set(value) = sharedPref.edit { + putBoolean(context.getString(R.string.pref_key_ads_consent_data_processing), value) + } + + var isPersonalizedAdsEnabled: Boolean + get() = sharedPref.getBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, false) + set(value) = sharedPref.edit { putBoolean(PREF_KEY_PERSONALIZED_ADS_ENABLED, value) } + val isAdsEnabledFlow = flowSharedPref.getBoolean( context.getString(R.string.pref_key_ads_enabled), context.resources.getBoolean(R.bool.pref_default_ads_enabled) @@ -322,26 +315,6 @@ class PreferencesRepository @Inject constructor( putBoolean(context.getString(R.string.pref_key_ads_enabled), value) } - var appMenuItemOrder: List - get() { - val value = sharedPref.getString(PREF_KEY_APP_MENU_ITEM_ORDER, null) - ?: return AppMenuItem.defaultAppMenuItemList - - return json.decodeFromString(value) - } - set(value) = sharedPref.edit { - putString( - PREF_KEY_APP_MENU_ITEM_ORDER, - json.encodeToString(value) - ) - } - - var isIncognitoMode: Boolean - get() = getBoolean(R.string.pref_key_incognito_moge, R.bool.pref_default_incognito_mode) - set(value) = sharedPref.edit { - putBoolean(context.getString(R.string.pref_key_incognito_moge), value) - } - var installationId: String get() = sharedPref.getString(PREF_KEY_INSTALLATION_ID, null).orEmpty() private set(value) = sharedPref.edit { putString(PREF_KEY_INSTALLATION_ID, value) } @@ -357,21 +330,6 @@ class PreferencesRepository @Inject constructor( private fun getLong(id: String, default: Int) = sharedPref.getLong(id, context.resources.getString(default).toLong()) - private fun getStringFlow(id: Int, default: Int) = - flowSharedPref.getString(context.getString(id), context.getString(default)) - - private fun getObjectFlow( - @StringRes id: Int, - @StringRes default: Int, - serializer: Serializer - ): Preference = flowSharedPref.getObject( - key = context.getString(id), - serializer = serializer, - defaultValue = serializer.deserialize( - flowSharedPref.getString(context.getString(default)).get() - ) - ) - private fun getString(id: Int, default: Int) = getString(context.getString(id), default) private fun getString(id: String, default: Int) = @@ -383,13 +341,13 @@ class PreferencesRepository @Inject constructor( sharedPref.getBoolean(id, context.resources.getBoolean(default)) private companion object { - private const val PREF_KEY_APP_MENU_ITEM_ORDER = "app_menu_item_order" private const val PREF_KEY_INSTALLATION_ID = "installation_id" private const val PREF_KEY_DASHBOARD_ITEMS_POSITION = "dashboard_items_position" private const val PREF_KEY_IN_APP_REVIEW_COUNT = "in_app_review_count" private const val PREF_KEY_IN_APP_REVIEW_DATE = "in_app_review_date" private const val PREF_KEY_IN_APP_REVIEW_DONE = "in_app_review_done" private const val PREF_KEY_APP_SUPPORT_SHOWN = "app_support_shown" + private const val PREF_KEY_PERSONALIZED_ADS_ENABLED = "personalized_ads_enabled" private const val PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS = "admin_message_dismissed_ids" } } 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 index 8233d932e..79984ce6d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt @@ -1,15 +1,12 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.RecipientDao -import io.github.wulkanowy.data.db.entities.Mailbox -import io.github.wulkanowy.data.db.entities.MailboxType -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.* 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.uniqueSubtract import javax.inject.Inject import javax.inject.Singleton @@ -17,22 +14,19 @@ import javax.inject.Singleton @Singleton class RecipientRepository @Inject constructor( private val recipientDb: RecipientDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { private val cacheKey = "recipient" suspend fun refreshRecipients(student: Student, mailbox: Mailbox, type: MailboxType) { - val new = wulkanowySdkFactory.create(student) - .getRecipients(mailbox.globalKey) + val new = sdk.init(student).getRecipients(mailbox.globalKey) .mapToEntities(mailbox.globalKey) val old = recipientDb.loadAll(type, mailbox.globalKey) - recipientDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + recipientDb.deleteAll(old uniqueSubtract new) + recipientDb.insertAll(new uniqueSubtract old) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student)) } @@ -60,7 +54,7 @@ class RecipientRepository @Inject constructor( ): List { mailbox ?: return emptyList() - return wulkanowySdkFactory.create(student) + return sdk.init(student) .getMessageReplayDetails(message.messageGlobalKey) .sender .let(::listOf) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt index b554bda0f..5940f477b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt @@ -1,23 +1,17 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory +import io.github.wulkanowy.sdk.Sdk import javax.inject.Inject import javax.inject.Singleton @Singleton -class RecoverRepository @Inject constructor( - private val wulkanowySdkFactory: WulkanowySdkFactory -) { +class RecoverRepository @Inject constructor(private val sdk: Sdk) { - suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair = - wulkanowySdkFactory.create() - .getPasswordResetCaptchaCode(host, symbol) + suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair { + return sdk.getPasswordResetCaptchaCode(host, symbol) + } suspend fun sendRecoverRequest( - url: String, - symbol: String, - email: String, - reCaptchaResponse: String - ): String = wulkanowySdkFactory.create() - .sendPasswordResetRequest(url, symbol, email, reCaptchaResponse) + url: String, symbol: String, email: String, reCaptchaResponse: String + ): String = sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt index 78d956993..4c42d092f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolAnnouncementRepository.kt @@ -1,13 +1,14 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao import io.github.wulkanowy.data.db.entities.SchoolAnnouncement import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.data.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex @@ -17,7 +18,7 @@ import javax.inject.Singleton @Singleton class SchoolAnnouncementRepository @Inject constructor( private val schoolAnnouncementDb: SchoolAnnouncementDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -37,27 +38,26 @@ class SchoolAnnouncementRepository @Inject constructor( it.isEmpty() || forceRefresh || isExpired }, query = { - schoolAnnouncementDb.loadAll(student.studentId) + schoolAnnouncementDb.loadAll(student.userLoginId) }, fetch = { - val sdk = wulkanowySdkFactory.create(student) - val lastAnnouncements = sdk.getLastAnnouncements().mapToEntities(student) - val directorInformation = sdk.getDirectorInformation().mapToEntities(student) - lastAnnouncements + directorInformation + sdk.init(student) + .getDirectorInformation() + .mapToEntities(student) }, saveFetchResult = { old, new -> - schoolAnnouncementDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = (new uniqueSubtract old).onEach { - if (notify) it.isNotified = false - }, - ) + val schoolAnnouncementsToSave = (new uniqueSubtract old).onEach { + if (notify) it.isNotified = false + } + + schoolAnnouncementDb.deleteAll(old uniqueSubtract new) + schoolAnnouncementDb.insertAll(schoolAnnouncementsToSave) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student)) } ) fun getSchoolAnnouncementFromDatabase(student: Student): Flow> { - return schoolAnnouncementDb.loadAll(student.studentId) + return schoolAnnouncementDb.loadAll(student.userLoginId) } suspend fun updateSchoolAnnouncement(schoolAnnouncement: List) = 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 index c48abb6f8..7972ed084 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt @@ -1,13 +1,14 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource +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 kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -15,7 +16,7 @@ import javax.inject.Singleton @Singleton class SchoolRepository @Inject constructor( private val schoolDb: SchoolDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -38,16 +39,17 @@ class SchoolRepository @Inject constructor( }, query = { schoolDb.load(semester.studentId, semester.classId) }, fetch = { - wulkanowySdkFactory.create(student, semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .getSchool() .mapToEntity(semester) }, saveFetchResult = { old, new -> if (old != null && new != old) { - schoolDb.removeOldAndSaveNew( - oldItems = listOf(old), - newItems = listOf(new) - ) + with(schoolDb) { + deleteAll(listOf(old)) + insertAll(listOf(new)) + } } else if (old == null) { schoolDb.insertAll(listOf(new)) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt deleted file mode 100644 index 4a16d6f13..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolsRepository.kt +++ /dev/null @@ -1,62 +0,0 @@ -package io.github.wulkanowy.data.repositories - -import io.github.wulkanowy.data.WulkanowySdkFactory -import io.github.wulkanowy.data.api.SchoolsService -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.pojos.IntegrityRequest -import io.github.wulkanowy.data.pojos.LoginEvent -import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.utils.IntegrityHelper -import io.github.wulkanowy.utils.getCurrentOrLast -import kotlinx.coroutines.withTimeout -import timber.log.Timber -import java.util.UUID -import javax.inject.Inject -import javax.inject.Singleton -import kotlin.time.Duration.Companion.seconds - -@Singleton -class SchoolsRepository @Inject constructor( - private val integrityHelper: IntegrityHelper, - private val schoolsService: SchoolsService, - private val wulkanowySdkFactory: WulkanowySdkFactory, -) { - - suspend fun logSchoolLogin(loginData: LoginData, students: List) { - students.forEach { - runCatching { - withTimeout(10.seconds) { - logLogin(loginData, it.student, it.semesters.getCurrentOrLast()) - } - } - .onFailure { Timber.e(it) } - } - } - - private suspend fun logLogin(loginData: LoginData, student: Student, semester: Semester) { - val requestId = UUID.randomUUID().toString() - val token = integrityHelper.getIntegrityToken(requestId) ?: return - val updatedStudent = student.copy(password = loginData.password) - - val schoolInfo = wulkanowySdkFactory.create(updatedStudent, semester) - .getSchool() - - schoolsService.logLoginEvent( - IntegrityRequest( - tokenString = token, - data = LoginEvent( - uuid = requestId, - schoolAddress = schoolInfo.address, - schoolName = schoolInfo.name, - schoolShort = student.schoolShortName, - scraperBaseUrl = student.scrapperBaseUrl, - loginType = student.loginType, - symbol = student.symbol, - schoolId = student.schoolSymbol, - ) - ) - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt index 92d44650f..96f019223 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt @@ -1,15 +1,11 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.isCurrent -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.utils.* import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject @@ -18,8 +14,8 @@ import javax.inject.Singleton @Singleton class SemesterRepository @Inject constructor( private val semesterDb: SemesterDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, - private val dispatchers: DispatchersProvider, + private val sdk: Sdk, + private val dispatchers: DispatchersProvider ) { suspend fun getSemesters( @@ -44,36 +40,27 @@ class SemesterRepository @Inject constructor( val isNoSemesters = semesters.isEmpty() val isRefreshOnModeChangeRequired = when { - Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE -> { - semesters.firstOrNull { it.isCurrent() }?.let { + Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> { + semesters.firstOrNull { it.isCurrent }?.let { 0 == it.diaryId && 0 == it.kindergartenDiaryId } == true } - else -> false } val isRefreshOnNoCurrentAppropriate = - refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent() } + refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent } return forceRefresh || isNoSemesters || isRefreshOnModeChangeRequired || isRefreshOnNoCurrentAppropriate } private suspend fun refreshSemesters(student: Student) { - val new = wulkanowySdkFactory.create(student) - .getSemesters() - .mapToEntities(student.studentId) - - if (new.isEmpty()) { - Timber.i("Empty semester list from SDK!") - return - } + val new = sdk.init(student).getSemesters().mapToEntities(student.studentId) + if (new.isEmpty()) return Timber.i("Empty semester list!") val old = semesterDb.loadAll(student.studentId, student.classId) - semesterDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + semesterDb.deleteAll(old.uniqueSubtract(new)) + semesterDb.insertSemesters(new.uniqueSubtract(old)) } suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt index db4c0aebb..efc82a772 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt @@ -1,11 +1,12 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.StudentInfoDao 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.data.networkBoundResource +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -13,7 +14,7 @@ import javax.inject.Singleton @Singleton class StudentInfoRepository @Inject constructor( private val studentInfoDao: StudentInfoDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk ) { private val saveFetchResultMutex = Mutex() @@ -28,16 +29,16 @@ class StudentInfoRepository @Inject constructor( shouldFetch = { it == null || forceRefresh }, query = { studentInfoDao.loadStudentInfo(student.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) - .getStudentInfo() - .mapToEntity(semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getStudentInfo().mapToEntity(semester) }, saveFetchResult = { old, new -> if (old != null && new != old) { - studentInfoDao.removeOldAndSaveNew( - oldItems = listOf(old), - newItems = listOf(new), - ) + with(studentInfoDao) { + deleteAll(listOf(old)) + insertAll(listOf(new)) + } } else if (old == null) { studentInfoDao.insertAll(listOf(new)) } 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 index df47d7a63..f006b7d28 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt @@ -1,95 +1,83 @@ package io.github.wulkanowy.data.repositories +import android.content.Context import androidx.room.withTransaction -import io.github.wulkanowy.data.WulkanowySdkFactory +import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.dao.StudentDao -import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentIsAuthorized -import io.github.wulkanowy.data.db.entities.StudentName import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.data.mappers.mapToEntities -import io.github.wulkanowy.data.mappers.mapToPojo -import io.github.wulkanowy.data.pojos.RegisterUser import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.DispatchersProvider -import io.github.wulkanowy.utils.security.Scrambler +import io.github.wulkanowy.utils.security.decrypt +import io.github.wulkanowy.utils.security.encrypt import kotlinx.coroutines.withContext -import timber.log.Timber 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 wulkanowySdkFactory: WulkanowySdkFactory, - private val appDatabase: AppDatabase, - private val scrambler: Scrambler, + private val sdk: Sdk, + private val appInfo: AppInfo, + private val appDatabase: AppDatabase ) { + suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty() + suspend fun isCurrentStudentSet() = studentDb.loadCurrent()?.isCurrent ?: false suspend fun getStudentsApi( pin: String, symbol: String, token: String - ): RegisterUser = wulkanowySdkFactory.create() - .getStudentsFromHebe(token, pin, symbol, "") - .mapToPojo(null) - .also { it.logErrors() } + ): List = + sdk.getStudentsFromMobileApi(token, pin, symbol, "") + .mapToEntities(colors = appInfo.defaultColorsForAvatar) - suspend fun getUserSubjectsFromScrapper( + suspend fun getStudentsScrapper( email: String, password: String, scrapperBaseUrl: String, - domainSuffix: String, symbol: String - ): RegisterUser = wulkanowySdkFactory.create() - .getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, domainSuffix, symbol) - .mapToPojo(password) - .also { it.logErrors() } + ): List = + sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol) + .mapToEntities(password, appInfo.defaultColorsForAvatar) suspend fun getStudentsHybrid( email: String, password: String, scrapperBaseUrl: String, symbol: String - ): RegisterUser = wulkanowySdkFactory.create() - .getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol) - .mapToPojo(password) - .also { it.logErrors() } + ): List = + sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol) + .mapToEntities(password, appInfo.defaultColorsForAvatar) - suspend fun getSavedStudents(decryptPass: Boolean = true): List { - return studentDb.loadStudentsWithSemesters().map { (student, semesters) -> - StudentWithSemesters( - student = student.apply { - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) { + suspend fun getSavedStudents(decryptPass: Boolean = true) = + studentDb.loadStudentsWithSemesters() + .map { + it.apply { + if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { student.password = withContext(dispatchers.io) { - scrambler.decrypt(student.password) + decrypt(student.password) } } - }, - semesters = semesters, - ) - } - } + } + } - suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true): StudentWithSemesters? = - studentDb.loadStudentWithSemestersById(id).let { res -> - StudentWithSemesters( - student = res.keys.firstOrNull() ?: return null, - semesters = res.values.first(), - ) - }.apply { - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) { + suspend fun getSavedStudentById(id: Long, decryptPass: Boolean = true) = + studentDb.loadStudentWithSemestersById(id)?.apply { + if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { student.password = withContext(dispatchers.io) { - scrambler.decrypt(student.password) + decrypt(student.password) } } } @@ -97,60 +85,20 @@ class StudentRepository @Inject constructor( suspend fun getStudentById(id: Long, decryptPass: Boolean = true): Student { val student = studentDb.loadById(id) ?: throw NoCurrentStudentException() - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) { + if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { student.password = withContext(dispatchers.io) { - scrambler.decrypt(student.password) + decrypt(student.password) } } return student } - suspend fun updateCurrentStudentAuthStatus() { - Timber.i("Check isAuthorized: started") - val student = getCurrentStudent() - if (student.isAuthorized) { - Timber.i("Check isAuthorized: already authorized") - return - } - - val initializedSdk = wulkanowySdkFactory.create(student) - val newCurrentStudent = runCatching { initializedSdk.getCurrentStudent() } - .onFailure { Timber.e(it, "Check isAuthorized: error occurred") } - .getOrNull() - - if (newCurrentStudent == null) { - Timber.d("Check isAuthorized: current user is null") - return - } - - val currentStudentSemesters = semesterDb.loadAll(student.studentId, student.classId) - if (currentStudentSemesters.isEmpty()) { - Timber.d("Check isAuthorized: apply empty semesters workaround") - semesterDb.insertSemesters( - items = newCurrentStudent.semesters.mapToEntities(student.studentId), - ) - } - - if (!newCurrentStudent.isAuthorized) { - Timber.i("Check isAuthorized: authorization required") - throw NoAuthorizationException() - } - - val studentIsAuthorized = StudentIsAuthorized( - id = student.id, - isAuthorized = true - ) - - Timber.i("Check isAuthorized: already authorized, update local status") - studentDb.update(studentIsAuthorized) - } - suspend fun getCurrentStudent(decryptPass: Boolean = true): Student { val student = studentDb.loadCurrent() ?: throw NoCurrentStudentException() - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.HEBE) { + if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { student.password = withContext(dispatchers.io) { - scrambler.decrypt(student.password) + decrypt(student.password) } } return student @@ -161,9 +109,9 @@ class StudentRepository @Inject constructor( val students = studentsWithSemesters.map { it.student } .map { it.apply { - if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.HEBE) { + if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) { password = withContext(dispatchers.io) { - scrambler.encrypt(password) + encrypt(password, context) } } } @@ -192,50 +140,4 @@ class StudentRepository @Inject constructor( suspend fun isOneUniqueStudent() = getSavedStudents(false) .distinctBy { it.student.studentName }.size == 1 - - suspend fun authorizePermission(student: Student, semester: Semester, pesel: String) = - wulkanowySdkFactory.create(student, semester) - .authorizePermission(pesel) - - suspend fun refreshStudentAfterAuthorize(student: Student, semester: Semester) { - val wulkanowySdk = wulkanowySdkFactory.create(student, semester) - val newCurrentApiStudent = runCatching { wulkanowySdk.getCurrentStudent() } - .onFailure { Timber.e(it, "Can't find student with id ${student.studentId}") } - .getOrNull() ?: return - - val studentName = StudentName( - studentName = "${newCurrentApiStudent.studentName} ${newCurrentApiStudent.studentSurname}" - ).apply { id = student.id } - - studentDb.update(studentName) - semesterDb.removeOldAndSaveNew( - oldItems = semesterDb.loadAll(student.studentId, semester.classId), - newItems = newCurrentApiStudent.semesters.mapToEntities(newCurrentApiStudent.studentId) - ) - } - - suspend fun deleteStudentsAssociatedWithAccount(student: Student) { - studentDb.deleteByEmailAndUserName(student.email, student.userName) - } - - suspend fun clearAll() { - withContext(dispatchers.io) { - scrambler.clearKeyPair() - appDatabase.clearAllTables() - } - } - - private fun RegisterUser.logErrors() { - val symbolsErrors = symbols.filter { it.error != null } - .map { it.error } - val unitsErrors = symbols.flatMap { it.schools } - .filter { it.error != null } - .map { it.error } - - (symbolsErrors + unitsErrors).forEach { error -> - Timber.e(error, "Error occurred while fetching students") - } - } } - -class NoAuthorizationException : Exception() 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 index 573c7c149..3926122b3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt @@ -1,13 +1,14 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.sync.Mutex import javax.inject.Inject @@ -16,7 +17,7 @@ import javax.inject.Singleton @Singleton class SubjectRepository @Inject constructor( private val subjectDao: SubjectDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -37,15 +38,14 @@ class SubjectRepository @Inject constructor( }, query = { subjectDao.loadAll(semester.diaryId, semester.studentId) }, fetch = { - wulkanowySdkFactory.create(student, semester) - .getSubjects() - .mapToEntities(semester) + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getSubjects().mapToEntities(semester) }, saveFetchResult = { old, new -> - subjectDao.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old - ) + subjectDao.deleteAll(old uniqueSubtract new) + subjectDao.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) } ) 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 index a5a6e3f9c..acd71e1f4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt @@ -1,13 +1,14 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory 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.data.networkBoundResource +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.uniqueSubtract import kotlinx.coroutines.sync.Mutex import javax.inject.Inject @@ -16,7 +17,7 @@ import javax.inject.Singleton @Singleton class TeacherRepository @Inject constructor( private val teacherDb: TeacherDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val refreshHelper: AutoRefreshHelper, ) { @@ -37,15 +38,15 @@ class TeacherRepository @Inject constructor( }, query = { teacherDb.loadAll(semester.studentId, semester.classId) }, fetch = { - wulkanowySdkFactory.create(student, semester) - .getTeachers() + sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getTeachers(semester.semesterId) .mapToEntities(semester) }, saveFetchResult = { old, new -> - teacherDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + teacherDb.deleteAll(old uniqueSubtract new) + teacherDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) } ) 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 index 335789991..3145c2a23 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt @@ -1,27 +1,18 @@ package io.github.wulkanowy.data.repositories -import io.github.wulkanowy.data.WulkanowySdkFactory import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao import io.github.wulkanowy.data.db.dao.TimetableDao import io.github.wulkanowy.data.db.dao.TimetableHeaderDao -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.db.entities.TimetableHeader +import io.github.wulkanowy.data.db.entities.* import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.data.networkBoundResource import io.github.wulkanowy.data.pojos.TimetableFull +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.monday -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract +import io.github.wulkanowy.utils.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.sync.Mutex -import java.time.Instant import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -31,7 +22,7 @@ class TimetableRepository @Inject constructor( private val timetableDb: TimetableDao, private val timetableAdditionalDb: TimetableAdditionalDao, private val timetableHeaderDb: TimetableHeaderDao, - private val wulkanowySdkFactory: WulkanowySdkFactory, + private val sdk: Sdk, private val schedulerHelper: TimetableNotificationSchedulerHelper, private val refreshHelper: AutoRefreshHelper, ) { @@ -72,8 +63,9 @@ class TimetableRepository @Inject constructor( }, query = { getFullTimetableFromDatabase(student, semester, start, end) }, fetch = { - val timetableFull = wulkanowySdkFactory.create(student, semester) - .getTimetable(start.monday, end.sunday) + val timetableFull = sdk.init(student) + .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) + .getTimetableFull(start.monday, end.sunday) timetableFull.mapToEntities(semester) }, @@ -128,12 +120,12 @@ class TimetableRepository @Inject constructor( } } - suspend fun getTimetableFromDatabase( + fun getTimetableFromDatabase( semester: Semester, - start: LocalDate, + from: LocalDate, end: LocalDate - ): List { - return timetableDb.load(semester.diaryId, semester.studentId, start, end) + ): Flow> { + return timetableDb.loadAll(semester.diaryId, semester.studentId, from, end) } suspend fun updateTimetable(timetable: List) { @@ -151,10 +143,8 @@ class TimetableRepository @Inject constructor( new.apply { if (notify) isNotified = false } } - timetableDb.removeOldAndSaveNew( - oldItems = lessonsToRemove, - newItems = lessonsToAdd, - ) + timetableDb.deleteAll(lessonsToRemove) + timetableDb.insertAll(lessonsToAdd) schedulerHelper.cancelScheduled(lessonsToRemove, student) schedulerHelper.scheduleNotifications(lessonsToAdd, student) @@ -165,22 +155,13 @@ class TimetableRepository @Inject constructor( new: List ) { val oldFiltered = old.filter { !it.isAddedByUser } - timetableAdditionalDb.removeOldAndSaveNew( - oldItems = oldFiltered uniqueSubtract new, - newItems = new uniqueSubtract old, - ) + timetableAdditionalDb.deleteAll(oldFiltered uniqueSubtract new) + timetableAdditionalDb.insertAll(new uniqueSubtract old) } private suspend fun refreshDayHeaders(old: List, new: List) { - timetableHeaderDb.removeOldAndSaveNew( - oldItems = old uniqueSubtract new, - newItems = new uniqueSubtract old, - ) - } - - fun getLastRefreshTimestamp(semester: Semester, start: LocalDate, end: LocalDate): Instant { - val refreshKey = getRefreshKey(cacheKey, semester, start, end) - return refreshHelper.getLastRefreshTimestamp(refreshKey) + timetableHeaderDb.deleteAll(old uniqueSubtract new) + timetableHeaderDb.insertAll(new uniqueSubtract old) } suspend fun saveAdditionalList(additionalList: List) = diff --git a/app/src/main/java/io/github/wulkanowy/domain/adminmessage/GetAppropriateAdminMessageUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/adminmessage/GetAppropriateAdminMessageUseCase.kt deleted file mode 100644 index b55bf899d..000000000 --- a/app/src/main/java/io/github/wulkanowy/domain/adminmessage/GetAppropriateAdminMessageUseCase.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.domain.adminmessage - -import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.db.entities.AdminMessage -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.enums.MessageType -import io.github.wulkanowy.data.mapResourceData -import io.github.wulkanowy.data.repositories.AdminMessageRepository -import io.github.wulkanowy.data.repositories.PreferencesRepository -import io.github.wulkanowy.utils.AppInfo -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject - -class GetAppropriateAdminMessageUseCase @Inject constructor( - private val adminMessageRepository: AdminMessageRepository, - private val preferencesRepository: PreferencesRepository, - private val appInfo: AppInfo -) { - - operator fun invoke(student: Student, type: MessageType): Flow> { - return invoke(student.scrapperBaseUrl, type) - } - - operator fun invoke(scrapperBaseUrl: String, type: MessageType): Flow> { - return adminMessageRepository.getAdminMessages().mapResourceData { adminMessages -> - adminMessages - .asSequence() - .filter { it.isNotDismissed() } - .filter { it.isVersionMatch() } - .filter { it.isRegisterHostMatch(scrapperBaseUrl) } - .filter { it.isFlavorMatch() } - .filter { it.isTypeMatch(type) } - .maxByOrNull { it.id } - } - } - - private fun AdminMessage.isNotDismissed(): Boolean { - return id !in preferencesRepository.dismissedAdminMessageIds - } - - private fun AdminMessage.isRegisterHostMatch(scrapperBaseUrl: String): Boolean { - return targetRegisterHost?.let { - scrapperBaseUrl.contains(it, true) - } ?: true - } - - private fun AdminMessage.isFlavorMatch(): Boolean { - return targetFlavor?.equals(appInfo.buildFlavor, true) ?: true - } - - private fun AdminMessage.isVersionMatch(): Boolean { - val isCorrectMaxVersion = versionMax?.let { it >= appInfo.versionCode } ?: true - val isCorrectMinVersion = versionMin?.let { it <= appInfo.versionCode } ?: true - - return isCorrectMaxVersion && isCorrectMinVersion - } - - private fun AdminMessage.isTypeMatch(messageType: MessageType): Boolean { - if (messageType in types) return true - if (MessageType.GENERAL_MESSAGE in types) return true - - return false - } -} diff --git a/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt index 669514aae..a696d9b2f 100644 --- a/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt +++ b/app/src/main/java/io/github/wulkanowy/domain/messages/GetMailboxByStudentUseCase.kt @@ -17,11 +17,8 @@ class GetMailboxByStudentUseCase @Inject constructor( private fun List.filterByStudent(student: Student): Mailbox? { val normalizedStudentName = student.studentName.normalizeStudentName() - return singleOrNull { + return find { it.studentName.normalizeStudentName() == normalizedStudentName - } ?: singleOrNull { - it.studentName.normalizeStudentName() == normalizedStudentName - && it.schoolNameShort == student.schoolShortName } ?: singleOrNull { it.studentName.getFirstAndLastPart() == normalizedStudentName.getFirstAndLastPart() } ?: singleOrNull { diff --git a/app/src/main/java/io/github/wulkanowy/domain/timetable/IsStudentHasLessonsOnWeekendUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/timetable/IsStudentHasLessonsOnWeekendUseCase.kt deleted file mode 100644 index ffd005740..000000000 --- a/app/src/main/java/io/github/wulkanowy/domain/timetable/IsStudentHasLessonsOnWeekendUseCase.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.domain.timetable - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.TimetableRepository -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.sunday -import java.time.LocalDate -import javax.inject.Inject - -class IsStudentHasLessonsOnWeekendUseCase @Inject constructor( - private val timetableRepository: TimetableRepository, - private val isWeekendHasLessonsUseCase: IsWeekendHasLessonsUseCase, -) { - - suspend operator fun invoke( - semester: Semester, - currentDate: LocalDate = LocalDate.now(), - ): Boolean { - val lessons = timetableRepository.getTimetableFromDatabase( - semester = semester, - start = currentDate.monday, - end = currentDate.sunday, - ) - return isWeekendHasLessonsUseCase(lessons) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/domain/timetable/IsWeekendHasLessonsUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/timetable/IsWeekendHasLessonsUseCase.kt deleted file mode 100644 index 908c9df78..000000000 --- a/app/src/main/java/io/github/wulkanowy/domain/timetable/IsWeekendHasLessonsUseCase.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.domain.timetable - -import io.github.wulkanowy.data.db.entities.Timetable -import java.time.DayOfWeek -import javax.inject.Inject - -class IsWeekendHasLessonsUseCase @Inject constructor() { - - operator fun invoke( - lessons: List, - ): Boolean = lessons.any { - it.date.dayOfWeek in listOf( - DayOfWeek.SATURDAY, - DayOfWeek.SUNDAY, - ) - } -} 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 aae7882f1..42078d03f 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 @@ -65,6 +65,8 @@ class TimetableNotificationSchedulerHelper @Inject constructor( range = lesson.start..lesson.end, requestCode = getRequestCode(lesson.start, studentId) ) + + Timber.d("TimetableNotification canceled: type 1 & 2, subject: ${lesson.subject}, start: ${lesson.start}, student: $studentId") } } } 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 e0a136f98..c1bed4dd3 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 @@ -4,12 +4,18 @@ import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.O import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.asFlow -import androidx.work.* import androidx.work.BackoffPolicy.EXPONENTIAL +import androidx.work.Constraints +import androidx.work.Data import androidx.work.ExistingPeriodicWorkPolicy.KEEP -import androidx.work.ExistingPeriodicWorkPolicy.UPDATE +import androidx.work.ExistingPeriodicWorkPolicy.REPLACE +import androidx.work.ExistingWorkPolicy import androidx.work.NetworkType.CONNECTED import androidx.work.NetworkType.UNMETERED +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.PeriodicWorkRequestBuilder +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.PreferencesRepository @@ -54,7 +60,7 @@ class SyncManager @Inject constructor( val serviceInterval = preferencesRepository.servicesInterval workManager.enqueueUniquePeriodicWork( - SyncWorker::class.java.simpleName, if (restart) UPDATE else KEEP, + SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP, PeriodicWorkRequestBuilder(serviceInterval, MINUTES) .setInitialDelay(10, MINUTES) .setBackoffCriteria(EXPONENTIAL, 30, MINUTES) 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 bcbc23ef2..5dddd9a78 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 @@ -17,7 +17,6 @@ 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.sdk.scrapper.exception.FeatureUnavailableException import io.github.wulkanowy.services.sync.channels.DebugChannel import io.github.wulkanowy.services.sync.works.Work import io.github.wulkanowy.utils.DispatchersProvider @@ -49,7 +48,6 @@ class SyncWorker @AssistedInject constructor( val semester = semesterRepository.getCurrentSemester(student, true) student to semester } catch (e: Throwable) { - Timber.e(e) return@withContext getResultFromErrors(listOf(e)) } @@ -61,7 +59,7 @@ class SyncWorker @AssistedInject constructor( null } catch (e: Throwable) { Timber.w("${work::class.java.simpleName} result: An exception ${e.message} occurred") - if (e is FeatureDisabledException || e is FeatureNotAvailableException || e is FeatureUnavailableException) { + if (e is FeatureDisabledException || e is FeatureNotAvailableException) { null } else { Timber.e(e) diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewGradeNotification.kt b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewGradeNotification.kt index 7f90bbddc..9b49ed178 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewGradeNotification.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewGradeNotification.kt @@ -4,12 +4,12 @@ import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.pojos.GroupNotificationData import io.github.wulkanowy.data.pojos.NotificationData import io.github.wulkanowy.ui.modules.Destination +import io.github.wulkanowy.ui.modules.splash.SplashActivity import io.github.wulkanowy.utils.getPlural import javax.inject.Inject @@ -88,28 +88,4 @@ class NewGradeNotification @Inject constructor( appNotificationManager.sendMultipleNotifications(groupNotificationData, student) } - - suspend fun notifyDescriptive(items: List, student: Student) { - val notificationDataList = items.map { - NotificationData( - title = context.getPlural(R.plurals.grade_new_items_descriptive, 1), - content = "${it.subject}: ${it.description}", - destination = Destination.Grade, - ) - } - - val groupNotificationData = GroupNotificationData( - notificationDataList = notificationDataList, - title = context.getPlural(R.plurals.grade_new_items_descriptive, items.size), - content = context.getPlural( - R.plurals.grade_notify_new_items_descriptive, - items.size, - items.size - ), - destination = Destination.Grade, - type = NotificationType.NEW_GRADE_DESCRIPTIVE - ) - - appNotificationManager.sendMultipleNotifications(groupNotificationData, student) - } } diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NotificationType.kt b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NotificationType.kt index 4e7f27351..023ae2e4c 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NotificationType.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NotificationType.kt @@ -37,10 +37,6 @@ enum class NotificationType( channel = NewGradesChannel.CHANNEL_ID, icon = R.drawable.ic_stat_grade, ), - NEW_GRADE_DESCRIPTIVE( - channel = NewGradesChannel.CHANNEL_ID, - icon = R.drawable.ic_stat_grade, - ), NEW_HOMEWORK( channel = NewHomeworkChannel.CHANNEL_ID, icon = R.drawable.ic_more_homework, 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 4fc097492..657f69638 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 @@ -16,24 +16,17 @@ class AttendanceWork @Inject constructor( ) : Work { override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) { - val startDate = now().previousOrSameSchoolDay - val endDate = startDate.plusDays(7) - attendanceRepository.getAttendance( student = student, semester = semester, - start = startDate, - end = endDate, + start = now().previousOrSameSchoolDay, + end = now().previousOrSameSchoolDay, forceRefresh = true, notify = notify, ) .waitForResult() - attendanceRepository.getAttendanceFromDatabase( - semester = semester, - start = startDate, - end = endDate, - ) + attendanceRepository.getAttendanceFromDatabase(semester, now().minusDays(7), now()) .first() .filterNot { it.isNotified } .let { 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 4b0b1bdb3..7071bce20 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 @@ -5,8 +5,6 @@ import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.repositories.ExamRepository import io.github.wulkanowy.data.waitForResult import io.github.wulkanowy.services.sync.notifications.NewExamNotification -import io.github.wulkanowy.utils.endExamsDay -import io.github.wulkanowy.utils.startExamsDay import kotlinx.coroutines.flow.first import java.time.LocalDate.now import javax.inject.Inject @@ -17,24 +15,16 @@ class ExamWork @Inject constructor( ) : Work { override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) { - val startDate = now().startExamsDay - val endDate = startDate.endExamsDay - examRepository.getExams( student = student, semester = semester, - start = startDate, - end = endDate, + start = now(), + end = now(), forceRefresh = true, notify = notify, ).waitForResult() - examRepository.getExamsFromDatabase( - semester = semester, - start = startDate, - end = endDate, - ) - .first() + examRepository.getExamsFromDatabase(semester, now()).first() .filter { !it.isNotified }.let { if (it.isNotEmpty()) newExamNotification.notify(it, student) 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 b62ad94b9..ba21b8600 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 @@ -45,15 +45,5 @@ class GradeWork @Inject constructor( grade.isFinalGradeNotified = true }) } - - gradeRepository.getGradesDescriptiveFromDatabase(semester).first() - .filter { !it.isNotified } - .let { - if (it.isNotEmpty()) newGradeNotification.notifyDescriptive(it, student) - - gradeRepository.updateGradesDescriptive(it.onEach { grade -> - grade.isNotified = true - }) - } } } 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 ddff3af7c..4cfe27d0d 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 @@ -5,9 +5,7 @@ import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.repositories.HomeworkRepository import io.github.wulkanowy.data.waitForResult import io.github.wulkanowy.services.sync.notifications.NewHomeworkNotification -import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.sunday import kotlinx.coroutines.flow.first import java.time.LocalDate.now import javax.inject.Inject @@ -18,24 +16,16 @@ class HomeworkWork @Inject constructor( ) : Work { override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) { - val startDate = now().nextOrSameSchoolDay.monday - val endDate = startDate.sunday - homeworkRepository.getHomework( student = student, semester = semester, - start = startDate, - end = endDate, + start = now().nextOrSameSchoolDay, + end = now().nextOrSameSchoolDay, forceRefresh = true, notify = notify, ).waitForResult() - homeworkRepository.getHomeworkFromDatabase( - semester = semester, - start = startDate, - end = endDate - ) - .first() + homeworkRepository.getHomeworkFromDatabase(semester, now(), now().plusDays(7)).first() .filter { !it.isNotified }.let { if (it.isNotEmpty()) newHomeworkNotification.notify(it, student) 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 2d10d925c..29b1f13c7 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 @@ -6,6 +6,7 @@ import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.data.waitForResult import io.github.wulkanowy.services.sync.notifications.ChangeTimetableNotification import io.github.wulkanowy.utils.nextOrSameSchoolDay +import kotlinx.coroutines.flow.first import java.time.LocalDate.now import javax.inject.Inject @@ -15,24 +16,18 @@ class TimetableWork @Inject constructor( ) : Work { override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) { - val startDate = now().nextOrSameSchoolDay - val endDate = startDate.plusDays(7) - timetableRepository.getTimetable( student = student, semester = semester, - start = startDate, - end = endDate, + start = now().nextOrSameSchoolDay, + end = now().nextOrSameSchoolDay, forceRefresh = true, notify = notify, ) .waitForResult() - timetableRepository.getTimetableFromDatabase( - semester = semester, - start = startDate, - end = endDate, - ) + timetableRepository.getTimetableFromDatabase(semester, now(), now().plusDays(7)) + .first() .filterNot { it.isNotified } .let { if (it.isNotEmpty()) changeTimetableNotification.notify(it, student) 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 ffdb07ecd..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 @@ -25,21 +25,13 @@ class TimetableWidgetService : RemoteViewsService() { lateinit var semesterRepo: SemesterRepository @Inject - lateinit var sharedPref: SharedPrefProvider + lateinit var prefRepository: PreferencesRepository @Inject - lateinit var prefRepository: PreferencesRepository + lateinit var sharedPref: SharedPrefProvider override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory { Timber.d("TimetableWidgetFactory created") - return TimetableWidgetFactory( - timetableRepository = timetableRepo, - studentRepository = studentRepo, - semesterRepository = semesterRepo, - sharedPref = sharedPref, - prefRepository = prefRepository, - context = applicationContext, - intent = intent, - ) + return TimetableWidgetFactory(timetableRepo, studentRepo, semesterRepo, prefRepository, sharedPref, applicationContext, intent) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt index 922c35365..075557a5c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt @@ -1,25 +1,20 @@ package io.github.wulkanowy.ui.base import android.app.ActivityManager -import android.os.Build import android.os.Bundle import android.view.View import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.viewbinding.ViewBinding -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar.LENGTH_LONG import io.github.wulkanowy.R -import io.github.wulkanowy.ui.modules.auth.AuthDialog -import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.utils.FragmentLifecycleLogger import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.openInternetBrowser -import timber.log.Timber -import java.time.Instant import javax.inject.Inject abstract class BaseActivity, VB : ViewBinding> : @@ -35,37 +30,24 @@ abstract class BaseActivity, VB : ViewBinding> : protected var messageContainer: View? = null - protected var messageAnchor: View? = null - abstract var presenter: T - private var lastDialogOpenTime = mutableMapOf() - override fun onCreate(savedInstanceState: Bundle?) { inject() themeManager.applyActivityTheme(this) super.onCreate(savedInstanceState) supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true) - applyCustomTaskDescription() - } - @Suppress("DEPRECATION") - private fun applyCustomTaskDescription() { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) return - try { - val newColor = getThemeAttrColor(R.attr.colorSurface) - val taskDescription = ActivityManager.TaskDescription(null, null, newColor) - setTaskDescription(taskDescription) - } catch (e: Exception) { - Timber.e(e) - } + @Suppress("DEPRECATION") + setTaskDescription( + ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface)) + ) } override fun showError(text: String, error: Throwable) { if (messageContainer != null) { Snackbar.make(messageContainer!!, text, LENGTH_LONG) .setAction(R.string.all_details) { showErrorDetailsDialog(error) } - .apply { messageAnchor?.let { anchorView = it } } .show() } else showMessage(text) } @@ -75,48 +57,23 @@ abstract class BaseActivity, VB : ViewBinding> : } override fun showMessage(text: String) { - if (messageContainer != null) { - Snackbar.make(messageContainer!!, text, LENGTH_LONG) - .apply { messageAnchor?.let { anchorView = it } } - .show() - } else Toast.makeText(this, text, Toast.LENGTH_LONG).show() + if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show() + else Toast.makeText(this, text, Toast.LENGTH_LONG).show() } - override fun showExpiredCredentialsDialog() { - if (!shouldShowDialog(DIALOG_ERROR_BAD_CREDENTIALS)) return - - MaterialAlertDialogBuilder(this) - .setTitle(R.string.main_expired_credentials_title) - .setMessage(R.string.main_expired_credentials_description) - .setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onConfirmExpiredCredentialsSelected() } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - - override fun onCaptchaVerificationRequired(url: String?) { - CaptchaDialog.newInstance(url).show(supportFragmentManager, "captcha_dialog") - } - - override fun showDecryptionFailedDialog() { - if (!shouldShowDialog(DIALOG_ERROR_DECRYPTION_FAILED)) return - - MaterialAlertDialogBuilder(this) + override fun showExpiredDialog() { + AlertDialog.Builder(this) .setTitle(R.string.main_session_expired) .setMessage(R.string.main_session_relogin) - .setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onConfirmDecryptionFailedSelected() } + .setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() } .setNegativeButton(android.R.string.cancel) { _, _ -> } .show() } - override fun showAuthDialog() { - AuthDialog.newInstance().show(supportFragmentManager, "auth_dialog") - } - override fun showChangePasswordSnackbar(redirectUrl: String) { messageContainer?.let { Snackbar.make(it, R.string.error_password_change_required, LENGTH_LONG) .setAction(R.string.all_change) { openInternetBrowser(redirectUrl) } - .apply { messageAnchor?.let { anchorView = it } } .show() } } @@ -136,21 +93,4 @@ abstract class BaseActivity, VB : ViewBinding> : protected open fun inject() { throw UnsupportedOperationException() } - - private fun shouldShowDialog(name: String): Boolean { - val lastOpenTime = lastDialogOpenTime[name] - val now = Instant.now() - - if (lastOpenTime != null && now.isBefore(lastOpenTime.plusSeconds(1))) { - Timber.i("Dialog $name was shown less than a second ago. Skip") - return false - } - lastDialogOpenTime[name] = Instant.now() - return true - } - - companion object { - private const val DIALOG_ERROR_BAD_CREDENTIALS = "dialog_error_bad_credentials" - private const val DIALOG_ERROR_DECRYPTION_FAILED = "dialog_error_decryption_failed" - } } 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 e63887b8f..25a53395d 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 @@ -1,13 +1,8 @@ package io.github.wulkanowy.ui.base -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.DialogFragment import androidx.viewbinding.ViewBinding -import com.google.android.material.elevation.SurfaceColors import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.lifecycleAwareVariable import javax.inject.Inject @@ -27,16 +22,8 @@ abstract class BaseDialogFragment : DialogFragment(), BaseView Toast.makeText(context, text, Toast.LENGTH_LONG).show() } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun openClearLoginView() { @@ -47,25 +34,10 @@ abstract class BaseDialogFragment : DialogFragment(), BaseView (activity as? BaseActivity<*, *>)?.showChangePasswordSnackbar(redirectUrl) } - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() - } - override fun showErrorDetailsDialog(error: Throwable) { ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - view.setBackgroundColor(SurfaceColors.SURFACE_3.getColor(requireContext())) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = binding.root - override fun onResume() { super.onResume() analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName) diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt index ba346131c..dbc5af3a9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt @@ -38,20 +38,8 @@ abstract class BaseFragment(@LayoutRes layoutId: Int) : Fragme } } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() - } - - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun openClearLoginView() { 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 d4cb20cac..15c069f54 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,15 +1,10 @@ package io.github.wulkanowy.ui.base import io.github.wulkanowy.data.repositories.StudentRepository -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancelChildren +import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.launch import timber.log.Timber open class BasePresenter( @@ -28,38 +23,19 @@ open class BasePresenter( this.view = view errorHandler.apply { showErrorMessage = view::showError - onExpiredCredentials = view::showExpiredCredentialsDialog - onCaptchaVerificationRequired = view::onCaptchaVerificationRequired - onDecryptionFailed = view::showDecryptionFailedDialog + onSessionExpired = view::showExpiredDialog onNoCurrentStudent = view::openClearLoginView onPasswordChangeRequired = view::showChangePasswordSnackbar - onAuthorizationRequired = view::showAuthDialog } } - fun onConfirmDecryptionFailedSelected() { - Timber.i("Attempt to clear all data") - - presenterScope.launch { - runCatching { studentRepository.clearAll() } - .onFailure { - Timber.i("Clear data result: An exception occurred") - errorHandler.dispatch(it) - } - .onSuccess { - Timber.i("Clear data result: Open login view") - view?.openClearLoginView() - } - } - } - - fun onConfirmExpiredCredentialsSelected() { - Timber.i("Attempt to delete students associated with the account and switch to new student") + fun onExpiredLoginSelected() { + Timber.i("Attempt to switch the student after the session expires") presenterScope.launch { runCatching { val student = studentRepository.getCurrentStudent(false) - studentRepository.deleteStudentsAssociatedWithAccount(student) + studentRepository.logoutStudent(student) val students = studentRepository.getSavedStudents(false) if (students.isNotEmpty()) { @@ -68,11 +44,11 @@ open class BasePresenter( } } .onFailure { - Timber.i("Delete students result: An exception occurred") + Timber.i("Switch student result: An exception occurred") errorHandler.dispatch(it) } .onSuccess { - Timber.i("Delete students result: Open login view") + Timber.i("Switch student result: Open login view") view?.openClearLoginView() } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt index 88d5754f8..d3165ea44 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt @@ -6,13 +6,7 @@ interface BaseView { fun showMessage(text: String) - fun showExpiredCredentialsDialog() - - fun onCaptchaVerificationRequired(url: String?) - - fun showDecryptionFailedDialog() - - fun showAuthDialog() + fun showExpiredDialog() fun openClearLoginView() 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 679d904a3..e979fa8af 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 @@ -4,13 +4,13 @@ import android.app.Dialog import android.content.ClipData import android.content.ClipboardManager import android.os.Bundle -import android.view.View import android.widget.Toast import android.widget.Toast.LENGTH_LONG import androidx.appcompat.app.AlertDialog import androidx.core.content.getSystemService import androidx.core.os.bundleOf import androidx.core.view.isGone +import androidx.fragment.app.DialogFragment import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -20,7 +20,7 @@ import io.github.wulkanowy.utils.* import javax.inject.Inject @AndroidEntryPoint -class ErrorDialog : BaseDialogFragment() { +class ErrorDialog : DialogFragment() { @Inject lateinit var appInfo: AppInfo @@ -28,8 +28,6 @@ class ErrorDialog : BaseDialogFragment() { @Inject lateinit var preferencesRepository: PreferencesRepository - private lateinit var error: Throwable - companion object { private const val ARGUMENT_KEY = "error" @@ -38,31 +36,32 @@ class ErrorDialog : BaseDialogFragment() { } } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - error = requireArguments().serializable(ARGUMENT_KEY) + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val error = requireArguments().getSerializable(ARGUMENT_KEY) as Throwable + + val binding = DialogErrorBinding.inflate(layoutInflater) + binding.bindErrorDetails(error) + + return getAlertDialog(binding, error).apply { + enableReportButtonIfErrorIsReportable(error) + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + private fun getAlertDialog(binding: DialogErrorBinding, error: Throwable): AlertDialog { return MaterialAlertDialogBuilder(requireContext()).apply { val errorStacktrace = error.stackTraceToString() setTitle(R.string.all_details) - setView(DialogErrorBinding.inflate(layoutInflater).apply { binding = this }.root) + setView(binding.root) setNeutralButton(R.string.about_feedback) { _, _ -> openConfirmDialog { openEmailClient(errorStacktrace) } } setNegativeButton(android.R.string.cancel) { _, _ -> } setPositiveButton(android.R.string.copy) { _, _ -> copyErrorToClipboard(errorStacktrace) } - }.create().apply { - setOnShowListener { - getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported() - } - } + }.create() } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - with(binding) { + private fun DialogErrorBinding.bindErrorDetails(error: Throwable) { + return with(this) { errorDialogHumanizedMessage.text = resources.getErrorString(error) errorDialogErrorMessage.text = error.localizedMessage errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank() @@ -71,6 +70,12 @@ class ErrorDialog : BaseDialogFragment() { } } + private fun AlertDialog.enableReportButtonIfErrorIsReportable(error: Throwable) { + setOnShowListener { + getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported() + } + } + private fun copyErrorToClipboard(errorStacktrace: String) { val clip = ClipData.newPlainText("Error details", errorStacktrace) requireActivity().getSystemService()?.setPrimaryClip(clip) @@ -78,7 +83,7 @@ class ErrorDialog : BaseDialogFragment() { } private fun openConfirmDialog(callback: () -> Unit) { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.dialog_error_check_update) .setMessage(R.string.dialog_error_check_update_message) .setNeutralButton(R.string.about_feedback) { _, _ -> callback() } @@ -108,4 +113,8 @@ class ErrorDialog : BaseDialogFragment() { } ) } + + private fun showMessage(text: String) { + Toast.makeText(requireContext(), text, LENGTH_LONG).show() + } } 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 00a2ab225..afe200e9a 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 @@ -3,8 +3,6 @@ package io.github.wulkanowy.ui.base import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.github.wulkanowy.data.repositories.NoAuthorizationException -import io.github.wulkanowy.sdk.scrapper.exception.CloudflareVerificationException import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException import io.github.wulkanowy.utils.getErrorString @@ -16,45 +14,30 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> } - var onExpiredCredentials: () -> Unit = {} - - var onDecryptionFailed: () -> Unit = {} + var onSessionExpired: () -> Unit = {} var onNoCurrentStudent: () -> Unit = {} var onPasswordChangeRequired: (String) -> Unit = {} - var onAuthorizationRequired: () -> Unit = {} - - var onCaptchaVerificationRequired: (url: String?) -> Unit = {} - fun dispatch(error: Throwable) { Timber.e(error, "An exception occurred while the Wulkanowy was running") proceed(error) } protected open fun proceed(error: Throwable) { - showDefaultMessage(error) + showErrorMessage(context.resources.getErrorString(error), error) when (error) { is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl) - is ScramblerException -> onDecryptionFailed() - is BadCredentialsException -> onExpiredCredentials() + is ScramblerException, is BadCredentialsException -> onSessionExpired() is NoCurrentStudentException -> onNoCurrentStudent() - is NoAuthorizationException -> onAuthorizationRequired() - is CloudflareVerificationException -> onCaptchaVerificationRequired(error.originalUrl) } } - fun showDefaultMessage(error: Throwable) { - showErrorMessage(context.resources.getErrorString(error), error) - } - open fun clear() { showErrorMessage = { _, _ -> } - onExpiredCredentials = {} - onDecryptionFailed = {} + onSessionExpired = {} onNoCurrentStudent = {} onPasswordChangeRequired = {} - onAuthorizationRequired = {} } } 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 f42f315ce..2d83bbbf9 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 @@ -1,19 +1,17 @@ package io.github.wulkanowy.ui.base -import android.content.pm.PackageInfo -import android.content.pm.PackageManager import android.content.pm.PackageManager.GET_ACTIVITIES -import android.os.Build import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate -import com.google.android.material.color.DynamicColors +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.enums.AppTheme import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity +import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity import javax.inject.Inject import javax.inject.Singleton @@ -27,40 +25,31 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer when (activity) { is MainActivity -> activity.setTheme(R.style.WulkanowyTheme_Black) is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black) + is SendMessageActivity -> activity.setTheme(R.style.WulkanowyTheme_MessageSend_Black) } } - } else if (activity is TimetableWidgetConfigureActivity || activity is LuckyNumberWidgetConfigureActivity) { - DynamicColors.applyToActivityIfAvailable(activity) } } fun applyDefaultTheme() { AppCompatDelegate.setDefaultNightMode( when (preferencesRepository.appTheme) { - AppTheme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO - AppTheme.DARK, AppTheme.BLACK -> AppCompatDelegate.MODE_NIGHT_YES - AppTheme.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + AppTheme.LIGHT -> MODE_NIGHT_NO + AppTheme.DARK, AppTheme.BLACK -> MODE_NIGHT_YES + AppTheme.SYSTEM -> MODE_NIGHT_FOLLOW_SYSTEM } ) } - private fun isThemeApplicable(activity: AppCompatActivity): Boolean = - getPackageInfo(activity) + private fun isThemeApplicable(activity: AppCompatActivity) = + activity.packageManager + .getPackageInfo(activity.packageName, GET_ACTIVITIES) .activities .singleOrNull { it.name == activity::class.java.canonicalName } ?.theme .let { it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar || it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black + || it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black } - - @Suppress("DEPRECATION") - private fun getPackageInfo(activity: AppCompatActivity): PackageInfo { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - activity.packageManager.getPackageInfo( - activity.packageName, - PackageManager.PackageInfoFlags.of(GET_ACTIVITIES.toLong()) - ) - } else activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES) - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt index f0969fac4..561419a05 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/Destination.kt @@ -9,14 +9,11 @@ import io.github.wulkanowy.ui.modules.exam.ExamFragment import io.github.wulkanowy.ui.modules.grade.GradeFragment import io.github.wulkanowy.ui.modules.homework.HomeworkFragment import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment -import io.github.wulkanowy.ui.modules.luckynumber.history.LuckyNumberHistoryFragment import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.note.NoteFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment +import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment -import io.github.wulkanowy.ui.modules.settings.SettingsFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import kotlinx.serialization.Serializable import java.time.LocalDate @@ -42,13 +39,10 @@ sealed class Destination { NOTE(Note), CONFERENCE(Conference), SCHOOL_ANNOUNCEMENT(SchoolAnnouncement), - SCHOOL_AND_TEACHERS(SchoolAndTeachers), - LUCKY_NUMBER(LuckyNumber), - LUCKY_NUMBER_HISTORY(LuckyNumberHistory), + SCHOOL(School), + LUCKY_NUMBER(More), MORE(More), - MESSAGE(Message), - MOBILE_DEVICE(MobileDevice), - SETTINGS(Settings); + MESSAGE(Message); } @Serializable @@ -109,9 +103,9 @@ sealed class Destination { } @Serializable - object SchoolAndTeachers : Destination() { - override val destinationType get() = Type.SCHOOL_AND_TEACHERS - override val destinationFragment get() = SchoolAndTeachersFragment.newInstance() + object School : Destination() { + override val destinationType get() = Type.SCHOOL + override val destinationFragment get() = SchoolFragment.newInstance() } @Serializable @@ -120,12 +114,6 @@ sealed class Destination { override val destinationFragment get() = LuckyNumberFragment.newInstance() } - @Serializable - object LuckyNumberHistory : Destination() { - override val destinationType get() = Type.LUCKY_NUMBER_HISTORY - override val destinationFragment get() = LuckyNumberHistoryFragment.newInstance() - } - @Serializable object More : Destination() { override val destinationType get() = Type.MORE @@ -137,16 +125,4 @@ sealed class Destination { override val destinationType get() = Type.MESSAGE override val destinationFragment get() = MessageFragment.newInstance() } - - @Serializable - object MobileDevice : Destination() { - override val destinationType get() = Type.MOBILE_DEVICE - override val destinationFragment get() = MobileDeviceFragment.newInstance() - } - - @Serializable - object Settings : Destination() { - override val destinationType get() = Type.SETTINGS - override val destinationFragment get() = SettingsFragment.newInstance() - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt index f115372a5..051c93c95 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt @@ -34,7 +34,6 @@ class AccountFragment : BaseFragment(R.layout.fragment_a override val titleStringId = R.string.account_title - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt index d6bc6154b..c3137ec58 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt @@ -6,10 +6,8 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog -import androidx.core.os.bundleOf import androidx.core.view.get import androidx.core.view.isVisible -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student @@ -23,7 +21,6 @@ import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoFragment import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.nickOrName -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -40,12 +37,12 @@ class AccountDetailsFragment : private const val ARGUMENT_KEY = "Data" - fun newInstance(student: Student) = AccountDetailsFragment().apply { - arguments = bundleOf(ARGUMENT_KEY to student) - } + fun newInstance(student: Student) = + AccountDetailsFragment().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, student) } + } } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -54,7 +51,7 @@ class AccountDetailsFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentAccountDetailsBinding.bind(view) - presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY)) + presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student) } override fun initView() { @@ -115,7 +112,7 @@ class AccountDetailsFragment : override fun showLogoutConfirmDialog() { context?.let { - MaterialAlertDialogBuilder(it) + AlertDialog.Builder(it) .setTitle(R.string.account_logout_student) .setMessage(R.string.account_confirm) .setPositiveButton(R.string.account_logout) { _, _ -> presenter.onLogoutConfirm() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt index 4229579c0..21a7a492d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt @@ -1,16 +1,14 @@ package io.github.wulkanowy.ui.modules.account.accountedit -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf +import android.view.ViewGroup import androidx.recyclerview.widget.GridLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.DialogAccountEditBinding import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -26,21 +24,28 @@ class AccountEditDialog : BaseDialogFragment(), Accoun private const val ARGUMENT_KEY = "student_with_semesters" - fun newInstance(student: Student) = AccountEditDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to student) - } + fun newInstance(student: Student) = + AccountEditDialog().apply { + arguments = Bundle().apply { + putSerializable(ARGUMENT_KEY, student) + } + } } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogAccountEditBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View = DialogAccountEditBinding.inflate(inflater).apply { binding = this }.root + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this, requireArguments().serializable(ARGUMENT_KEY)) + presenter.onAttachView(this, requireArguments()[ARGUMENT_KEY] as Student) } override fun initView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt index 2d2dccec4..4279102e1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt @@ -1,11 +1,10 @@ package io.github.wulkanowy.ui.modules.account.accountquick -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf +import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.DialogAccountQuickBinding @@ -14,7 +13,6 @@ import io.github.wulkanowy.ui.modules.account.AccountAdapter import io.github.wulkanowy.ui.modules.account.AccountFragment import io.github.wulkanowy.ui.modules.account.AccountItem import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -32,23 +30,27 @@ class AccountQuickDialog : BaseDialogFragment(), Acco fun newInstance(studentsWithSemesters: List) = AccountQuickDialog().apply { - arguments = bundleOf(STUDENTS_ARGUMENT_KEY to studentsWithSemesters.toTypedArray()) + arguments = Bundle().apply { + putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray()) + } } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView( - DialogAccountQuickBinding.inflate(layoutInflater) - .apply { binding = this }.root - ) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogAccountQuickBinding.inflate(inflater).apply { binding = this }.root + + @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - val studentsWithSemesters = requireArguments() - .serializable>(STUDENTS_ARGUMENT_KEY).toList() + val studentsWithSemesters = + (requireArguments()[STUDENTS_ARGUMENT_KEY] as Array).toList() presenter.onAttachView(this, studentsWithSemesters) } 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 f5689ec8d..39f376f65 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 @@ -1,7 +1,5 @@ package io.github.wulkanowy.ui.modules.attendance -import android.content.res.ColorStateList -import android.graphics.Typeface import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -12,7 +10,6 @@ import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.enums.SentExcuseStatus import io.github.wulkanowy.databinding.ItemAttendanceBinding import io.github.wulkanowy.utils.descriptionRes -import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.isExcusableOrNotExcused import javax.inject.Inject @@ -34,43 +31,15 @@ class AttendanceAdapter @Inject constructor() : ) override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val context = holder.binding.root.context val item = items[position] with(holder.binding) { attendanceItemNumber.text = item.number.toString() - attendanceItemSubject.text = item.subject - .ifBlank { context.getString(R.string.all_no_data) } - attendanceItemDescription.setText(item.descriptionRes) - - attendanceItemDescription.setTextColor( - context.getThemeAttrColor( - when { - item.absence && !item.excused -> R.attr.colorAttendanceAbsence - item.lateness && !item.excused -> R.attr.colorAttendanceLateness - else -> android.R.attr.textColorSecondary - } - ) - ) - - if (item.exemption || item.excused) { - attendanceItemDescription.setTypeface(null, Typeface.BOLD) - } else { - attendanceItemDescription.setTypeface(null, Typeface.NORMAL) + attendanceItemSubject.text = item.subject.ifBlank { + root.context.getString(R.string.all_no_data) } - - attendanceItemAlert.isVisible = - item.let { (it.absence && !it.excused) || (it.lateness && !it.excused) } - - attendanceItemAlert.imageTintList = ColorStateList.valueOf( - context.getThemeAttrColor( - when { - item.absence && !item.excused -> R.attr.colorAttendanceAbsence - item.lateness && !item.excused -> R.attr.colorAttendanceLateness - else -> android.R.attr.colorPrimary - } - ) - ) + attendanceItemDescription.setText(item.descriptionRes) + attendanceItemAlert.isVisible = item.let { it.absence && !it.excused } attendanceItemNumber.visibility = View.GONE attendanceItemExcuseInfo.visibility = View.GONE attendanceItemExcuseCheckbox.visibility = View.GONE @@ -85,12 +54,10 @@ class AttendanceAdapter @Inject constructor() : attendanceItemExcuseInfo.visibility = View.VISIBLE attendanceItemAlert.visibility = View.INVISIBLE } - SentExcuseStatus.DENIED -> { attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_denied) attendanceItemExcuseInfo.visibility = View.VISIBLE } - else -> { if (item.isExcusableOrNotExcused && excuseActionMode) { attendanceItemNumber.visibility = View.GONE diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt index 635033132..9b5c63e4c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt @@ -1,22 +1,19 @@ package io.github.wulkanowy.ui.modules.attendance -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.databinding.DialogAttendanceBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.utils.descriptionRes -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.serializable +import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.toFormattedString -@AndroidEntryPoint -class AttendanceDialog : BaseDialogFragment() { +class AttendanceDialog : DialogFragment() { + + private var binding: DialogAttendanceBinding by lifecycleAwareVariable() private lateinit var attendance: Attendance @@ -25,20 +22,23 @@ class AttendanceDialog : BaseDialogFragment() { private const val ARGUMENT_KEY = "Item" fun newInstance(exam: Attendance) = AttendanceDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to exam) + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - attendance = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + attendance = getSerializable(ARGUMENT_KEY) as Attendance + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogAttendanceBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogAttendanceBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -46,16 +46,6 @@ class AttendanceDialog : BaseDialogFragment() { with(binding) { attendanceDialogSubjectValue.text = attendance.subject attendanceDialogDescriptionValue.setText(attendance.descriptionRes) - attendanceDialogDescriptionValue.setTextColor( - root.context.getThemeAttrColor( - when { - attendance.absence && !attendance.excused -> R.attr.colorAttendanceAbsence - attendance.lateness && !attendance.excused -> R.attr.colorAttendanceLateness - else -> android.R.attr.textColorSecondary - } - ) - ) - attendanceDialogDateValue.text = attendance.date.toFormattedString() attendanceDialogNumberValue.text = attendance.number.toString() attendanceDialogClose.setOnClickListener { dismiss() } 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 6e842b4d7..6354b5e04 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 @@ -4,10 +4,10 @@ import android.content.DialogInterface.BUTTON_POSITIVE import android.os.Bundle import android.view.* import android.view.View.* +import androidx.appcompat.app.AlertDialog import androidx.appcompat.view.ActionMode import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Attendance @@ -84,7 +84,6 @@ class AttendanceFragment : BaseFragment(R.layout.frag } } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -124,7 +123,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() } - attendanceNavContainer.elevation = requireContext().dpToPx(3f) + attendanceNavContainer.elevation = requireContext().dpToPx(8f) } } @@ -148,10 +147,6 @@ class AttendanceFragment : BaseFragment(R.layout.frag binding.attendanceNavDate.text = date } - override fun showNavigation(show: Boolean) { - binding.attendanceNavContainer.isVisible = show - } - override fun clearData() { with(attendanceAdapter) { items = emptyList() @@ -232,7 +227,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag override fun showExcuseDialog() { val dialogBinding = DialogExcuseBinding.inflate(LayoutInflater.from(context)) - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.attendance_excuse_title) .setView(dialogBinding.root) .setNegativeButton(android.R.string.cancel) { _, _ -> } @@ -285,9 +280,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - presenter.currentDate?.let { - outState.putLong(SAVED_DATE_KEY, it.toEpochDay()) - } + outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) } override fun onDestroyView() { 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 82fe69cb7..26bfaf19f 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,7 +3,6 @@ package io.github.wulkanowy.ui.modules.attendance import android.annotation.SuppressLint import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.repositories.AttendanceRepository import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.SemesterRepository @@ -11,10 +10,10 @@ 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.* -import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.onEach import timber.log.Timber -import java.time.DayOfWeek import java.time.LocalDate import java.time.LocalDate.now import java.time.LocalDate.ofEpochDay @@ -29,10 +28,9 @@ class AttendancePresenter @Inject constructor( private val analytics: AnalyticsHelper ) : BasePresenter(errorHandler, studentRepository) { - private var initialDate: LocalDate? = null - private var isWeekendHasLessons: Boolean = false + private var baseDate: LocalDate = now().previousOrSameSchoolDay - var currentDate: LocalDate? = null + lateinit var currentDate: LocalDate private set private lateinit var lastError: Throwable @@ -46,34 +44,27 @@ class AttendancePresenter @Inject constructor( view.initView() Timber.i("Attendance view was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - currentDate = date?.let(::ofEpochDay) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) loadData() + if (currentDate.isHolidays) setBaseDateOnHolidays() } fun onPreviousDay() { - val date = if (isWeekendHasLessons) { - currentDate?.minusDays(1) - } else currentDate?.previousSchoolDay - view?.finishActionMode() attendanceToExcuseList.clear() - reloadView(date ?: return) + reloadView(currentDate.previousSchoolDay) loadData() } fun onNextDay() { - val date = if (isWeekendHasLessons) { - currentDate?.plusDays(1) - } else currentDate?.nextSchoolDay - view?.finishActionMode() attendanceToExcuseList.clear() - reloadView(date ?: return) + reloadView(currentDate.nextSchoolDay) loadData() } fun onPickDate() { - view?.showDatePickerDialog(currentDate ?: return) + view?.showDatePickerDialog(currentDate) } fun onDateSet(year: Int, month: Int, day: Int) { @@ -102,8 +93,10 @@ class AttendancePresenter @Inject constructor( Timber.i("Attendance view is reselected") view?.let { view -> if (view.currentStackSize == 1) { - if (currentDate != initialDate) { - reloadView(initialDate ?: return) + baseDate = now().previousOrSameSchoolDay + + if (currentDate != baseDate) { + reloadView(baseDate) loadData() } else if (!view.isViewEmpty) { view.resetView() @@ -195,6 +188,19 @@ class AttendancePresenter @Inject constructor( return true } + private fun setBaseDateOnHolidays() { + flow { + val student = studentRepository.getCurrentStudent() + emit(semesterRepository.getCurrentSemester(student)) + }.catch { + Timber.i("Loading semester result: An exception occurred") + }.onEach { + baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) + currentDate = baseDate + reloadNavigation() + }.launch("holidays") + } + private fun loadData(forceRefresh: Boolean = false) { Timber.i("Loading attendance data started") @@ -205,13 +211,11 @@ class AttendancePresenter @Inject constructor( isParent = student.isParent val semester = semesterRepository.getCurrentSemester(student) - - checkInitialAndCurrentDate(semester) attendanceRepository.getAttendance( student = student, semester = semester, - start = currentDate ?: now(), - end = currentDate ?: now(), + start = currentDate, + end = currentDate, forceRefresh = forceRefresh ) } @@ -227,8 +231,6 @@ class AttendancePresenter @Inject constructor( }.sortedBy { item -> item.number } } .onResourceData { - isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessons(it) - view?.run { enableSwipe(true) showProgress(false) @@ -236,7 +238,6 @@ class AttendancePresenter @Inject constructor( showEmpty(it.isEmpty()) showContent(it.isNotEmpty()) updateData(it) - reloadNavigation() } } .onResourceIntermediate { view?.showRefresh(true) } @@ -262,41 +263,6 @@ class AttendancePresenter @Inject constructor( .launch() } - private suspend fun checkInitialAndCurrentDate(semester: Semester) { - if (initialDate == null) { - val lessons = attendanceRepository.getAttendanceFromDatabase( - semester = semester, - start = now().monday, - end = now().sunday, - ).firstOrNull().orEmpty() - isWeekendHasLessons = isWeekendHasLessons(lessons) - initialDate = getInitialDate(semester) - } - - if (currentDate == null) { - currentDate = initialDate - } - } - - private fun isWeekendHasLessons( - lessons: List, - ): Boolean = lessons.any { - it.date.dayOfWeek in listOf( - DayOfWeek.SATURDAY, - DayOfWeek.SUNDAY, - ) - } - - private fun getInitialDate(semester: Semester): LocalDate { - val now = now() - - return when { - now.isHolidays -> now.getLastSchoolDayIfHoliday(semester.schoolYear) - isWeekendHasLessons -> now - else -> now.previousOrSameSchoolDay - } - } - private fun excuseAbsence(reason: String?, toExcuseList: List) { resourceFlow { val student = studentRepository.getCurrentStudent() @@ -310,7 +276,6 @@ class AttendancePresenter @Inject constructor( showContent(false) showExcuseButton(false) } - is Resource.Success -> { Timber.i("Excusing for absence result: Success") analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size) @@ -323,7 +288,6 @@ class AttendancePresenter @Inject constructor( } loadData(forceRefresh = true) } - is Resource.Error -> { Timber.i("Excusing for absence result: An exception occurred") errorHandler.dispatch(it.error) @@ -347,7 +311,7 @@ class AttendancePresenter @Inject constructor( private fun reloadView(date: LocalDate) { currentDate = date - Timber.i("Reload attendance view with the date ${currentDate?.toFormattedString()}") + Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) enableSwipe(false) @@ -362,13 +326,10 @@ class AttendancePresenter @Inject constructor( @SuppressLint("DefaultLocale") private fun reloadNavigation() { - val currentDate = currentDate ?: return - view?.apply { showPreButton(!currentDate.minusDays(1).isHolidays) showNextButton(!currentDate.plusDays(1).isHolidays) updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise()) - showNavigation(true) } } } 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 2629c217e..b0123065a 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 @@ -40,8 +40,6 @@ interface AttendanceView : BaseView { fun showContent(show: Boolean) - fun showNavigation(show: Boolean) - fun showPreButton(show: Boolean) fun showNextButton(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt deleted file mode 100644 index 0f7c4234e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthDialog.kt +++ /dev/null @@ -1,86 +0,0 @@ -package io.github.wulkanowy.ui.modules.auth - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.text.parseAsHtml -import androidx.core.view.isVisible -import androidx.core.widget.doOnTextChanged -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.DialogAuthBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import javax.inject.Inject - -@AndroidEntryPoint -class AuthDialog : BaseDialogFragment(), AuthView { - - @Inject - lateinit var presenter: AuthPresenter - - companion object { - fun newInstance() = AuthDialog() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, R.style.FullScreenDialogStyle) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return DialogAuthBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - presenter.onAttachView(this) - - binding.authInput.doOnTextChanged { text, _, _, _ -> - presenter.onPeselChange(text?.toString()) - } - - binding.authButton.setOnClickListener { presenter.authorize() } - binding.authSuccessButton.setOnClickListener { - activity?.recreate() - dismiss() - } - binding.authButtonSkip.setOnClickListener { dismiss() } - } - - override fun enableAuthButton(isEnabled: Boolean) { - binding.authButton.isEnabled = isEnabled - } - - override fun showProgress(show: Boolean) { - binding.authProgress.isVisible = show - } - - override fun showPeselError(show: Boolean) { - binding.authInputLayout.error = getString(R.string.auth_api_error).takeIf { show } - } - - override fun showInvalidPeselError(show: Boolean) { - binding.authInputLayout.error = getString(R.string.auth_invalid_error).takeIf { show } - } - - override fun showSuccess(show: Boolean) { - binding.authSuccess.isVisible = show - } - - override fun showContent(show: Boolean) { - binding.authForm.isVisible = show - } - - override fun showDescriptionWithName(name: String) { - binding.authDescription.text = getString(R.string.auth_description, name).parseAsHtml() - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt deleted file mode 100644 index 5c597eeb4..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthPresenter.kt +++ /dev/null @@ -1,107 +0,0 @@ -package io.github.wulkanowy.ui.modules.auth - -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 kotlinx.coroutines.launch -import timber.log.Timber -import javax.inject.Inject - -class AuthPresenter @Inject constructor( - private val semesterRepository: SemesterRepository, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository) { - - private var pesel: String = "" - - override fun onAttachView(view: AuthView) { - super.onAttachView(view) - view.enableAuthButton(pesel.length == 11) - view.showSuccess(false) - view.showProgress(false) - - loadName() - } - - private fun loadName() { - presenterScope.launch { - runCatching { studentRepository.getCurrentStudent(false) } - .onSuccess { view?.showDescriptionWithName(it.studentName) } - .onFailure { errorHandler.dispatch(it) } - } - } - - fun onPeselChange(newPesel: String?) { - pesel = newPesel.orEmpty() - - view?.enableAuthButton(pesel.length == 11) - view?.showPeselError(false) - view?.showInvalidPeselError(false) - } - - fun authorize() { - presenterScope.launch { - view?.showProgress(true) - view?.showContent(false) - - if (!isValidPESEL(pesel)) { - view?.showInvalidPeselError(true) - view?.showProgress(false) - view?.showContent(true) - return@launch - } - - runCatching { - val student = studentRepository.getCurrentStudent() - val semester = semesterRepository.getCurrentSemester(student) - - val isSuccess = studentRepository.authorizePermission(student, semester, pesel) - Timber.d("Auth succeed: $isSuccess") - if (isSuccess) { - studentRepository.refreshStudentAfterAuthorize(student, semester) - } - isSuccess - } - .onFailure { - errorHandler.dispatch(it) - view?.showProgress(false) - view?.showContent(true) - } - .onSuccess { - Timber.d("Auth fully succeed: $it") - if (it) { - view?.showSuccess(true) - view?.showContent(false) - view?.showPeselError(false) - } else { - view?.showSuccess(false) - view?.showContent(true) - view?.showPeselError(true) - } - } - - view?.showProgress(false) - } - } - - private fun isValidPESEL(peselString: String): Boolean { - if (peselString.length != 11) { - return false - } - - val weights = intArrayOf(1, 3, 7, 9, 1, 3, 7, 9, 1, 3) - var sum = 0 - - for (i in 0 until 10) { - sum += weights[i] * Character.getNumericValue(peselString[i]) - } - - sum %= 10 - sum = 10 - sum - sum %= 10 - - return sum == Character.getNumericValue(peselString[10]) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt deleted file mode 100644 index d7e1917c2..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/auth/AuthView.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.ui.modules.auth - -import io.github.wulkanowy.ui.base.BaseView - -interface AuthView : BaseView { - - fun enableAuthButton(isEnabled: Boolean) - - fun showProgress(show: Boolean) - - fun showPeselError(show: Boolean) - - fun showInvalidPeselError(show: Boolean) - - fun showSuccess(show: Boolean) - - fun showContent(show: Boolean) - - fun showDescriptionWithName(name: String) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt deleted file mode 100644 index ce2173d28..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/captcha/CaptchaDialog.kt +++ /dev/null @@ -1,91 +0,0 @@ -package io.github.wulkanowy.ui.modules.captcha - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.webkit.WebView -import android.webkit.WebViewClient -import androidx.core.os.bundleOf -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.data.WulkanowySdkFactory -import io.github.wulkanowy.databinding.DialogCaptchaBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.WebkitCookieManagerProxy -import timber.log.Timber -import javax.inject.Inject - -@AndroidEntryPoint -class CaptchaDialog : BaseDialogFragment() { - - @Inject - lateinit var wulkanowySdkFactory: WulkanowySdkFactory - - @Inject - lateinit var webkitCookieManagerProxy: WebkitCookieManagerProxy - - private var webView: WebView? = null - - companion object { - const val CAPTCHA_SUCCESS = "captcha_success" - private const val CAPTCHA_URL = "captcha_url" - private const val CAPTCHA_CHECK_JS = "document.getElementById('challenge-running') == null" - - fun newInstance(url: String?): CaptchaDialog { - return CaptchaDialog().apply { - arguments = bundleOf(CAPTCHA_URL to url) - } - } - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View = DialogCaptchaBinding.inflate(inflater).apply { binding = this }.root - - @SuppressLint("SetJavaScriptEnabled") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - isCancelable = false - binding.captchaRefresh.setOnClickListener { - binding.captchaWebview.loadUrl(arguments?.getString(CAPTCHA_URL).orEmpty()) - } - binding.captchaClose.setOnClickListener { dismiss() } - - with(binding.captchaWebview) { - webView = this - with(settings) { - javaScriptEnabled = true - userAgentString = wulkanowySdkFactory.create().userAgent - } - - webViewClient = object : WebViewClient() { - override fun onPageFinished(view: WebView?, url: String?) { - view?.evaluateJavascript(CAPTCHA_CHECK_JS) { - if (it == "true") { - onChallengeAccepted() - } - } - } - } - - loadUrl(arguments?.getString(CAPTCHA_URL).orEmpty()) - } - } - - private fun onChallengeAccepted() { - runCatching { parentFragmentManager.setFragmentResult(CAPTCHA_SUCCESS, bundleOf()) } - .onFailure { Timber.e(it) } - showMessage(getString(R.string.captcha_verified_message)) - dismissAllowingStateLoss() - } - - override fun onDestroy() { - webkitCookieManagerProxy.webkitCookieManager?.flush() - webView?.destroy() - super.onDestroy() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt index c532377e1..477b762b9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceDialog.kt @@ -1,20 +1,19 @@ package io.github.wulkanowy.ui.modules.conference -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf +import android.view.ViewGroup import androidx.core.view.isVisible -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.Conference import io.github.wulkanowy.databinding.DialogConferenceBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.serializable +import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.toFormattedString -@AndroidEntryPoint -class ConferenceDialog : BaseDialogFragment() { +class ConferenceDialog : DialogFragment() { + + private var binding: DialogConferenceBinding by lifecycleAwareVariable() private lateinit var conference: Conference @@ -23,20 +22,23 @@ class ConferenceDialog : BaseDialogFragment() { private const val ARGUMENT_KEY = "item" fun newInstance(conference: Conference) = ConferenceDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to conference) + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, conference) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - conference = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.let { + conference = it.getSerializable(ARGUMENT_KEY) as Conference + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogConferenceBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogConferenceBinding.inflate(inflater).also { binding = it }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -55,4 +57,4 @@ class ConferenceDialog : BaseDialogFragment() { conferenceDialogAgendaTitle.isVisible = conference.agenda.isNotBlank() } } -} +} \ No newline at end of file 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 index 0cd3150c7..b9642b1c7 100644 --- 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 @@ -16,7 +16,7 @@ import javax.inject.Inject @AndroidEntryPoint class ConferenceFragment : BaseFragment(R.layout.fragment_conference), - ConferenceView, MainView.TitledView, MainView.MainChildView { + ConferenceView, MainView.TitledView { @Inject lateinit var presenter: ConferencePresenter @@ -109,14 +109,6 @@ class ConferenceFragment : BaseFragment(R.layout.frag (activity as? MainActivity)?.showDialogFragment(ConferenceDialog.newInstance(conference)) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onFragmentReselected() - } - - override fun resetView() { - binding.conferenceRecycler.smoothScrollToPosition(0) - } - 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 index 1178c7200..f53648930 100644 --- 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 @@ -96,11 +96,4 @@ class ConferencePresenter @Inject constructor( .onResourceError(errorHandler::dispatch) .launch() } - - fun onFragmentReselected() { - Timber.i("Conference is reselected") - if (view?.isViewEmpty == false) { - view?.resetView() - } - } } 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 index 3299a1f08..4f73394df 100644 --- 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 @@ -28,6 +28,4 @@ interface ConferenceView : BaseView { fun showContent(show: Boolean) fun openConferenceDialog(conference: Conference) - - fun resetView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt index b7a0796c5..de0b4a6c9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardFragment.kt @@ -11,17 +11,14 @@ import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.databinding.FragmentDashboardBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.account.accountdetails.AccountDetailsFragment import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment -import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog.Companion.CAPTCHA_SUCCESS import io.github.wulkanowy.ui.modules.conference.ConferenceFragment import io.github.wulkanowy.ui.modules.dashboard.adapters.DashboardAdapter -import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder import io.github.wulkanowy.ui.modules.exam.ExamFragment import io.github.wulkanowy.ui.modules.grade.GradeFragment import io.github.wulkanowy.ui.modules.homework.HomeworkFragment @@ -32,12 +29,7 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment -import io.github.wulkanowy.utils.capitalise -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.getErrorString -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.toFormattedString +import io.github.wulkanowy.utils.* import java.time.LocalDate import javax.inject.Inject @@ -64,15 +56,11 @@ class DashboardFragment : BaseFragment(R.layout.fragme return ((recyclerWidth - margin) / resources.displayMetrics.density).toInt() } - override val isViewEmpty - get() = dashboardAdapter.itemCount == 0 - companion object { fun newInstance() = DashboardFragment() } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -82,13 +70,6 @@ class DashboardFragment : BaseFragment(R.layout.fragme super.onViewCreated(view, savedInstanceState) binding = FragmentDashboardBinding.bind(view) presenter.onAttachView(this) - initializeCaptchaResultObserver() - } - - private fun initializeCaptchaResultObserver() { - childFragmentManager.setFragmentResultListener(CAPTCHA_SUCCESS, this) { _, _ -> - presenter.onRetryAfterCaptcha() - } } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -166,7 +147,7 @@ class DashboardFragment : BaseFragment(R.layout.fragme val values = requireContext().resources.getStringArray(R.array.dashboard_tile_values) val selectedItemsState = values.map { value -> selectedItems.any { it.name == value } } - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.pref_dashboard_appearance_tiles_title) .setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { _, _, _ -> } .setPositiveButton(android.R.string.ok) { dialog, _ -> @@ -199,17 +180,8 @@ class DashboardFragment : BaseFragment(R.layout.fragme binding.dashboardRecycler.isVisible = show } - override fun showErrorView(show: Boolean, adminMessageItem: DashboardItem.AdminMessages?) { + override fun showErrorView(show: Boolean) { binding.dashboardErrorContainer.isVisible = show - binding.dashboardErrorAdminMessage.root.isVisible = adminMessageItem != null - - if (adminMessageItem != null) { - AdminMessageViewHolder( - binding = binding.dashboardErrorAdminMessage, - onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, - onAdminMessageClickListener = presenter::onAdminMessageSelected, - ).bind(adminMessageItem.adminMessage) - } } override fun setErrorDetails(error: Throwable) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardItemMoveCallback.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardItemMoveCallback.kt index f033b5947..9c15acc35 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardItemMoveCallback.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardItemMoveCallback.kt @@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.modules.dashboard import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.ui.modules.dashboard.adapters.DashboardAdapter -import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder import java.util.* class DashboardItemMoveCallback( @@ -56,5 +55,5 @@ class DashboardItemMoveCallback( } private val RecyclerView.ViewHolder.isAdminMessageOrAccountItem: Boolean - get() = this is AdminMessageViewHolder || this is DashboardAdapter.AccountViewHolder + get() = this is DashboardAdapter.AdminMessageViewHolder || this is DashboardAdapter.AccountViewHolder } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt index 3fec62562..22b0d267e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt @@ -1,48 +1,17 @@ package io.github.wulkanowy.ui.modules.dashboard -import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.dataOrNull +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.AdminMessage import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.enums.MessageFolder -import io.github.wulkanowy.data.enums.MessageType -import io.github.wulkanowy.data.errorOrNull -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.mapResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository -import io.github.wulkanowy.data.repositories.ConferenceRepository -import io.github.wulkanowy.data.repositories.ExamRepository -import io.github.wulkanowy.data.repositories.GradeRepository -import io.github.wulkanowy.data.repositories.HomeworkRepository -import io.github.wulkanowy.data.repositories.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.MessageRepository -import io.github.wulkanowy.data.repositories.PreferencesRepository -import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository -import io.github.wulkanowy.data.repositories.SemesterRepository -import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.data.repositories.TimetableRepository -import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase -import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase +import io.github.wulkanowy.data.repositories.* import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AdsHelper import io.github.wulkanowy.utils.calculatePercentage import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.sunday -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.emitAll -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.filterNot -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.merge -import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber import java.time.Instant @@ -58,13 +27,12 @@ class DashboardPresenter @Inject constructor( private val messageRepository: MessageRepository, private val attendanceSummaryRepository: AttendanceSummaryRepository, private val timetableRepository: TimetableRepository, - private val isStudentHasLessonsOnWeekendUseCase: IsStudentHasLessonsOnWeekendUseCase, private val homeworkRepository: HomeworkRepository, private val examRepository: ExamRepository, private val conferenceRepository: ConferenceRepository, private val preferencesRepository: PreferencesRepository, private val schoolAnnouncementRepository: SchoolAnnouncementRepository, - private val getAppropriateAdminMessageUseCase: GetAppropriateAdminMessageUseCase, + private val adminMessageRepository: AdminMessageRepository, private val adsHelper: AdsHelper ) : BasePresenter(errorHandler, studentRepository) { @@ -78,11 +46,6 @@ class DashboardPresenter @Inject constructor( private val firstLoadedItemList = mutableListOf() - private val selectedDashboardTiles - get() = preferencesRepository.selectedDashboardTiles - .filterNot { it == DashboardItem.Tile.ADS && !adsHelper.canShowAd } - .toSet() - private lateinit var lastError: Throwable override fun onAttachView(view: DashboardView) { @@ -94,19 +57,10 @@ class DashboardPresenter @Inject constructor( showContent(false) } - val selectedDashboardTilesFlow = preferencesRepository.selectedDashboardTilesFlow - .map { selectedDashboardTiles } - val isAdsEnabledFlow = preferencesRepository.isAdsEnabledFlow - .filter { (adsHelper.canShowAd && it) || !it } - .map { selectedDashboardTiles } - val isMobileAdsSdkInitializedFlow = adsHelper.isMobileAdsSdkInitialized - .filter { it } - .map { selectedDashboardTiles } - merge( - selectedDashboardTilesFlow, - isAdsEnabledFlow, - isMobileAdsSdkInitializedFlow + preferencesRepository.selectedDashboardTilesFlow, + preferencesRepository.isAdsEnabledFlow + .map { preferencesRepository.selectedDashboardTiles } ) .onEach { loadData(tilesToLoad = it) } .launch("dashboard_pref") @@ -115,7 +69,7 @@ class DashboardPresenter @Inject constructor( fun onAdminMessageDismissed(adminMessage: AdminMessage) { preferencesRepository.dismissedAdminMessageIds += adminMessage.id - loadData(selectedDashboardTiles) + loadData(preferencesRepository.selectedDashboardTiles) } fun onDragAndDropEnd(list: List) { @@ -205,23 +159,19 @@ class DashboardPresenter @Inject constructor( DashboardItem.Type.ACCOUNT -> { updateData(DashboardItem.Account(student), forceRefresh) } - DashboardItem.Type.HORIZONTAL_GROUP -> { loadHorizontalGroup(student, forceRefresh) } - DashboardItem.Type.LESSONS -> loadLessons(student, forceRefresh) DashboardItem.Type.GRADES -> loadGrades(student, forceRefresh) DashboardItem.Type.HOMEWORK -> loadHomework(student, forceRefresh) DashboardItem.Type.ANNOUNCEMENTS -> { loadSchoolAnnouncements(student, forceRefresh) } - DashboardItem.Type.EXAMS -> loadExams(student, forceRefresh) DashboardItem.Type.CONFERENCES -> { loadConferences(student, forceRefresh) } - DashboardItem.Type.ADS -> loadAds(forceRefresh) DashboardItem.Type.ADMIN_MESSAGE -> loadAdminMessage(student, forceRefresh) } @@ -231,7 +181,7 @@ class DashboardPresenter @Inject constructor( fun onSwipeRefresh() { Timber.i("Force refreshing the dashboard") - loadData(selectedDashboardTiles, forceRefresh = true) + loadData(preferencesRepository.selectedDashboardTiles, forceRefresh = true) } fun onRetry() { @@ -239,15 +189,7 @@ class DashboardPresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(selectedDashboardTiles, forceRefresh = true) - } - - fun onRetryAfterCaptcha() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(selectedDashboardTiles, forceRefresh = true) + loadData(preferencesRepository.selectedDashboardTiles, forceRefresh = true) } fun onViewReselected() { @@ -268,7 +210,7 @@ class DashboardPresenter @Inject constructor( } fun onDashboardTileSettingsSelected(): Boolean { - view?.showDashboardTileSettings(selectedDashboardTiles.toList()) + view?.showDashboardTileSettings(preferencesRepository.selectedDashboardTiles.toList()) return true } @@ -284,7 +226,7 @@ class DashboardPresenter @Inject constructor( private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) { flow { - val selectedTiles = selectedDashboardTiles + val selectedTiles = preferencesRepository.selectedDashboardTiles val flowSuccess = flowOf(Resource.Success(null)) val luckyNumberFlow = luckyNumberRepository.getLuckyNumber(student, forceRefresh) @@ -304,7 +246,6 @@ class DashboardPresenter @Inject constructor( forceRefresh = forceRefresh ) } - .mapResourceData { it.map { messageWithAuthor -> messageWithAuthor.message } } .onResourceError { errorHandler.dispatch(it) } .takeIf { DashboardItem.Tile.MESSAGES in selectedTiles } ?: flowSuccess @@ -328,7 +269,7 @@ class DashboardPresenter @Inject constructor( ) { luckyNumberResource, messageResource, attendanceResource -> val resList = listOf(luckyNumberResource, messageResource, attendanceResource) - resList to DashboardItem.HorizontalGroup( + DashboardItem.HorizontalGroup( isLoading = resList.any { it is Resource.Loading }, error = resList.map { it.errorOrNull }.let { errors -> if (errors.all { it != null }) { @@ -353,9 +294,9 @@ class DashboardPresenter @Inject constructor( ) }) } - .filterNot { (_, it) -> it.isLoading && forceRefresh } + .filterNot { it.isLoading && forceRefresh } .distinctUntilChanged() - .onEach { (_, it) -> + .onEach { updateData(it, forceRefresh) if (it.isLoading) { @@ -373,7 +314,7 @@ class DashboardPresenter @Inject constructor( ) errorHandler.dispatch(it) } - .launchWithUniqueRefreshJob("horizontal_group", forceRefresh) + .launch("horizontal_group ${if (forceRefresh) "-forceRefresh" else ""}") } private fun loadGrades(student: Student, forceRefresh: Boolean) { @@ -407,14 +348,13 @@ class DashboardPresenter @Inject constructor( subjectWithGrades = it.dataOrNull, gradeTheme = preferencesRepository.gradeColorTheme, isLoading = true - ), false + ), forceRefresh ) if (!it.dataOrNull.isNullOrEmpty()) { firstLoadedItemList += DashboardItem.Type.GRADES } } - is Resource.Success -> { Timber.i("Loading dashboard grades result: Success") updateData( @@ -425,7 +365,6 @@ class DashboardPresenter @Inject constructor( forceRefresh ) } - is Resource.Error -> { Timber.i("Loading dashboard grades result: An exception occurred") errorHandler.dispatch(it.error) @@ -439,17 +378,14 @@ class DashboardPresenter @Inject constructor( private fun loadLessons(student: Student, forceRefresh: Boolean) { flatResourceFlow { val semester = semesterRepository.getCurrentSemester(student) - val date = when (isStudentHasLessonsOnWeekendUseCase(semester)) { - true -> LocalDate.now() - else -> LocalDate.now().nextOrSameSchoolDay - } + val date = LocalDate.now().nextOrSameSchoolDay timetableRepository.getTimetable( student = student, semester = semester, start = date, - end = date.sunday, - forceRefresh = forceRefresh, + end = date.plusDays(1), + forceRefresh = forceRefresh ) } .onEach { @@ -459,21 +395,19 @@ class DashboardPresenter @Inject constructor( if (forceRefresh) return@onEach updateData( DashboardItem.Lessons(it.dataOrNull, isLoading = true), - false + forceRefresh ) if (!it.dataOrNull?.lessons.isNullOrEmpty()) { firstLoadedItemList += DashboardItem.Type.LESSONS } } - is Resource.Success -> { Timber.i("Loading dashboard lessons result: Success") updateData( DashboardItem.Lessons(it.data), forceRefresh ) } - is Resource.Error -> { Timber.i("Loading dashboard lessons result: An exception occurred") errorHandler.dispatch(it.error) @@ -516,19 +450,17 @@ class DashboardPresenter @Inject constructor( val data = it.dataOrNull.orEmpty() updateData( DashboardItem.Homework(data, isLoading = true), - false + forceRefresh ) if (data.isNotEmpty()) { firstLoadedItemList += DashboardItem.Type.HOMEWORK } } - is Resource.Success -> { Timber.i("Loading dashboard homework result: Success") updateData(DashboardItem.Homework(it.data), forceRefresh) } - is Resource.Error -> { Timber.i("Loading dashboard homework result: An exception occurred") errorHandler.dispatch(it.error) @@ -550,19 +482,17 @@ class DashboardPresenter @Inject constructor( if (forceRefresh) return@onEach updateData( DashboardItem.Announcements(it.dataOrNull.orEmpty(), isLoading = true), - false + forceRefresh ) if (!it.dataOrNull.isNullOrEmpty()) { firstLoadedItemList += DashboardItem.Type.ANNOUNCEMENTS } } - is Resource.Success -> { Timber.i("Loading dashboard announcements result: Success") updateData(DashboardItem.Announcements(it.data), forceRefresh) } - is Resource.Error -> { Timber.i("Loading dashboard announcements result: An exception occurred") errorHandler.dispatch(it.error) @@ -593,19 +523,17 @@ class DashboardPresenter @Inject constructor( if (forceRefresh) return@onEach updateData( DashboardItem.Exams(it.dataOrNull.orEmpty(), isLoading = true), - false + forceRefresh ) if (!it.dataOrNull.isNullOrEmpty()) { firstLoadedItemList += DashboardItem.Type.EXAMS } } - is Resource.Success -> { Timber.i("Loading dashboard exams result: Success") updateData(DashboardItem.Exams(it.data), forceRefresh) } - is Resource.Error -> { Timber.i("Loading dashboard exams result: An exception occurred") errorHandler.dispatch(it.error) @@ -634,19 +562,17 @@ class DashboardPresenter @Inject constructor( if (forceRefresh) return@onEach updateData( DashboardItem.Conferences(it.dataOrNull.orEmpty(), isLoading = true), - false + forceRefresh ) if (!it.dataOrNull.isNullOrEmpty()) { firstLoadedItemList += DashboardItem.Type.CONFERENCES } } - is Resource.Success -> { Timber.i("Loading dashboard conferences result: Success") updateData(DashboardItem.Conferences(it.data), forceRefresh) } - is Resource.Error -> { Timber.i("Loading dashboard conferences result: An exception occurred") errorHandler.dispatch(it.error) @@ -658,20 +584,19 @@ class DashboardPresenter @Inject constructor( } private fun loadAdminMessage(student: Student, forceRefresh: Boolean) { - flatResourceFlow { - getAppropriateAdminMessageUseCase( - student = student, - type = MessageType.DASHBOARD_MESSAGE, - ) - } + flatResourceFlow { adminMessageRepository.getAdminMessages(student) } + .filter { + val data = it.dataOrNull ?: return@filter true + val isDismissed = data.id in preferencesRepository.dismissedAdminMessageIds + !isDismissed + } .onEach { when (it) { is Resource.Loading -> { Timber.i("Loading dashboard admin message data started") if (forceRefresh) return@onEach - updateData(DashboardItem.AdminMessages(), false) + updateData(DashboardItem.AdminMessages(), forceRefresh) } - is Resource.Success -> { Timber.i("Loading dashboard admin message result: Success") updateData( @@ -679,10 +604,9 @@ class DashboardPresenter @Inject constructor( forceRefresh = forceRefresh ) } - is Resource.Error -> { Timber.i("Loading dashboard admin message result: An exception occurred") - Timber.e(it.error) + errorHandler.dispatch(it.error) updateData( dashboardItem = DashboardItem.AdminMessages( adminMessage = null, @@ -699,7 +623,7 @@ class DashboardPresenter @Inject constructor( private fun loadAds(forceRefresh: Boolean) { presenterScope.launch { if (!forceRefresh) { - updateData(DashboardItem.Ads(), false) + updateData(DashboardItem.Ads(), forceRefresh) } val dashboardAdItem = @@ -820,13 +744,11 @@ class DashboardPresenter @Inject constructor( val filteredItems = itemsLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT || it.type == DashboardItem.Type.ADMIN_MESSAGE } - val dataLoadedAdminMessageItem = - itemsLoadedList.find { it.type == DashboardItem.Type.ADMIN_MESSAGE && it.isDataLoaded } as DashboardItem.AdminMessages? val isAccountItemError = itemsLoadedList.find { it.type == DashboardItem.Type.ACCOUNT }?.error != null val isGeneralError = filteredItems.none { it.error == null } && filteredItems.isNotEmpty() || isAccountItemError - val firstError = itemsLoadedList.firstNotNullOfOrNull { it.error } + val firstError = itemsLoadedList.mapNotNull { it.error }.firstOrNull() val filteredOriginalLoadedList = dashboardItemLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT } @@ -843,7 +765,7 @@ class DashboardPresenter @Inject constructor( showRefresh(false) if ((forceRefresh && wasGeneralError) || !forceRefresh) { showContent(false) - showErrorView(true, dataLoadedAdminMessageItem) + showErrorView(true) setErrorDetails(lastError) } } @@ -871,28 +793,6 @@ class DashboardPresenter @Inject constructor( onEach { if (it is Resource.Success) { cancelJobs(jobName) - } else if (it is Resource.Error) { - cancelJobs(jobName) - } - }.launch(jobName) - } else { - launch(jobName) - } - } - - @JvmName("launchWithUniqueRefreshJobHorizontalGroup") - private fun Flow>, *>>.launchWithUniqueRefreshJob( - name: String, - forceRefresh: Boolean - ) { - val jobName = if (forceRefresh) "$name-forceRefresh" else name - - if (forceRefresh) { - onEach { (resources, _) -> - if (resources.all { it is Resource.Success<*> }) { - cancelJobs(jobName) - } else if (resources.any { it is Resource.Error<*> }) { - cancelJobs(jobName) } }.launch(jobName) } else { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardView.kt index 56a0a773a..767885434 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardView.kt @@ -6,8 +6,6 @@ interface DashboardView : BaseView { val tileWidth: Int - val isViewEmpty: Boolean - fun initView() fun updateData(data: List) @@ -20,7 +18,7 @@ interface DashboardView : BaseView { fun showRefresh(show: Boolean) - fun showErrorView(show: Boolean, adminMessageItem: DashboardItem.AdminMessages? = null) + fun showErrorView(show: Boolean) fun setErrorDetails(error: Throwable) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardAdapter.kt index 7c74cae80..2c06e45fd 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/adapters/DashboardAdapter.kt @@ -1,6 +1,8 @@ package io.github.wulkanowy.ui.modules.dashboard.adapters import android.annotation.SuppressLint +import android.content.res.ColorStateList +import android.graphics.Color import android.graphics.Typeface import android.os.Handler import android.os.Looper @@ -22,7 +24,6 @@ import io.github.wulkanowy.data.db.entities.TimetableHeader import io.github.wulkanowy.data.enums.GradeColorTheme import io.github.wulkanowy.databinding.* import io.github.wulkanowy.ui.modules.dashboard.DashboardItem -import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder import io.github.wulkanowy.utils.* import timber.log.Timber import java.time.Duration @@ -108,9 +109,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter AdminMessageViewHolder( - ItemDashboardAdminMessageBinding.inflate(inflater, parent, false), - onAdminMessageDismissClickListener = onAdminMessageDismissClickListener, - onAdminMessageClickListener = onAdminMessageClickListener, + ItemDashboardAdminMessageBinding.inflate(inflater, parent, false) ) DashboardItem.Type.ADS.ordinal -> AdsViewHolder( ItemDashboardAdsBinding.inflate(inflater, parent, false) @@ -129,7 +128,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter bindAnnouncementsViewHolder(holder, position) is ExamsViewHolder -> bindExamsViewHolder(holder, position) is ConferencesViewHolder -> bindConferencesViewHolder(holder, position) - is AdminMessageViewHolder -> holder.bind((items[position] as DashboardItem.AdminMessages).adminMessage) + is AdminMessageViewHolder -> bindAdminMessage(holder, position) is AdsViewHolder -> bindAdsViewHolder(holder, position) } } @@ -734,6 +733,38 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter { + context.getThemeAttrColor(R.attr.colorPrimary) to + context.getThemeAttrColor(R.attr.colorOnPrimary) + } + "MEDIUM" -> { + context.getThemeAttrColor(R.attr.colorMessageMedium) to Color.BLACK + } + else -> null to context.getThemeAttrColor(R.attr.colorOnSurface) + } + + with(adminMessageViewHolder.binding) { + dashboardAdminMessageItemTitle.text = item.title + dashboardAdminMessageItemTitle.setTextColor(textColor) + dashboardAdminMessageItemDescription.text = item.content + dashboardAdminMessageItemDescription.setTextColor(textColor) + dashboardAdminMessageItemIcon.setColorFilter(textColor) + dashboardAdminMessageItemDismiss.isVisible = item.isDismissible + dashboardAdminMessageItemDismiss.setOnClickListener { + onAdminMessageDismissClickListener(item) + } + + root.setCardBackgroundColor(backgroundColor?.let { ColorStateList.valueOf(it) }) + item.destinationUrl?.let { url -> + root.setOnClickListener { onAdminMessageClickListener(url) } + } + } + } + private fun bindAdsViewHolder(adsViewHolder: AdsViewHolder, position: Int) { val item = (items[position] as DashboardItem.Ads).adBanner ?: return val binding = adsViewHolder.binding @@ -787,6 +818,9 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter() { @@ -39,9 +37,7 @@ class DashboardGradesAdapter : RecyclerView.Adapter Unit, - private val onAdminMessageClickListener: (String?) -> Unit, -) : RecyclerView.ViewHolder(binding.root) { - - fun bind(item: AdminMessage?) { - item ?: return - - val context = binding.root.context - val (backgroundColor, textColor) = when (item.priority) { - "HIGH" -> { - context.getThemeAttrColor(R.attr.colorMessageHigh) to - context.getThemeAttrColor(R.attr.colorOnMessageHigh) - } - - "MEDIUM" -> { - context.getThemeAttrColor(R.attr.colorMessageMedium) to Color.BLACK - } - - else -> null to context.getThemeAttrColor(R.attr.colorOnSurface) - } - - with(binding) { - dashboardAdminMessageItemTitle.text = item.title - dashboardAdminMessageItemTitle.setTextColor(textColor) - dashboardAdminMessageItemDescription.text = item.content - dashboardAdminMessageItemDescription.setTextColor(textColor) - dashboardAdminMessageItemIcon.setColorFilter(textColor) - dashboardAdminMessageItemDismiss.isVisible = item.isOkVisible - dashboardAdminMessageItemClose.isVisible = item.isXVisible - dashboardAdminMessageItemDismiss.setTextColor(textColor) - dashboardAdminMessageItemClose.imageTintList = ColorStateList.valueOf(textColor) - dashboardAdminMessageItemDismiss.setOnClickListener { - onAdminMessageDismissClickListener(item) - } - dashboardAdminMessageItemClose.setOnClickListener { - onAdminMessageDismissClickListener(item) - } - - root.setCardBackgroundColor(backgroundColor?.let { ColorStateList.valueOf(it) }) - item.destinationUrl?.let { url -> - root.setOnClickListener { onAdminMessageClickListener(url) } - } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugFragment.kt index 9db01a307..000916b17 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugFragment.kt @@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.modules.debug import android.os.Bundle import android.view.View -import android.webkit.CookieManager import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -59,10 +58,6 @@ class DebugFragment : BaseFragment(R.layout.fragment_debug (activity as? MainActivity)?.pushView(NotificationDebugFragment.newInstance()) } - override fun clearWebkitCookies() { - CookieManager.getInstance().removeAllCookies(null) - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugPresenter.kt index 816b59858..67ac88861 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugPresenter.kt @@ -15,7 +15,6 @@ class DebugPresenter @Inject constructor( val items = listOf( DebugItem(R.string.logviewer_title), DebugItem(R.string.notification_debug_title), - DebugItem(R.string.debug_cookies_clear), ) override fun onAttachView(view: DebugView) { @@ -32,7 +31,6 @@ class DebugPresenter @Inject constructor( when (item.title) { R.string.logviewer_title -> view?.openLogViewer() R.string.notification_debug_title -> view?.openNotificationsDebug() - R.string.debug_cookies_clear -> view?.clearWebkitCookies() else -> Timber.d("Unknown debug item: $item") } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugView.kt index 792d63d9e..9396ec6ac 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/DebugView.kt @@ -11,6 +11,4 @@ interface DebugView : BaseView { fun openLogViewer() fun openNotificationsDebug() - - fun clearWebkitCookies() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/logviewer/LogViewerFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/logviewer/LogViewerFragment.kt index 929e72645..1e11c874b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/logviewer/LogViewerFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/logviewer/LogViewerFragment.kt @@ -1,7 +1,9 @@ package io.github.wulkanowy.ui.modules.debug.logviewer import android.content.Intent -import android.content.Intent.* +import android.content.Intent.EXTRA_EMAIL +import android.content.Intent.EXTRA_STREAM +import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION import android.os.Bundle import android.view.Menu import android.view.MenuInflater @@ -34,7 +36,6 @@ class LogViewerFragment : BaseFragment(R.layout.fragme fun newInstance() = LogViewerFragment() } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/NotificationDebugPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/NotificationDebugPresenter.kt index cdd186b94..d0dfcd696 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/NotificationDebugPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/NotificationDebugPresenter.kt @@ -18,7 +18,6 @@ import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.debug.notification.mock.debugAttendanceItems import io.github.wulkanowy.ui.modules.debug.notification.mock.debugConferenceItems import io.github.wulkanowy.ui.modules.debug.notification.mock.debugExamItems -import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeDescriptiveItems import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeDetailsItems import io.github.wulkanowy.ui.modules.debug.notification.mock.debugGradeSummaryItems import io.github.wulkanowy.ui.modules.debug.notification.mock.debugHomeworkItems @@ -56,14 +55,6 @@ class NotificationDebugPresenter @Inject constructor( NotificationDebugItem(R.string.grade_summary_final_grade) { n -> withStudent { newGradeNotification.notifyFinal(debugGradeSummaryItems.take(n), it) } }, - NotificationDebugItem(R.string.grade_summary_descriptive) { n -> - withStudent { - newGradeNotification.notifyDescriptive( - debugGradeDescriptiveItems.take(n), - it - ) - } - }, NotificationDebugItem(R.string.homework_title) { n -> withStudent { newHomeworkNotification.notify(debugHomeworkItems.take(n), it) } }, diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/gradeDescriptive.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/gradeDescriptive.kt deleted file mode 100644 index d5a0c089b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/gradeDescriptive.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.ui.modules.debug.notification.mock - -import io.github.wulkanowy.data.db.entities.GradeDescriptive - -val debugGradeDescriptiveItems = listOf( - generateGradeDescriptive( - "Matematyka", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive("Fizyka", "Lorem ipsum dolor sit amet, consectetur adipiscing elit."), - generateGradeDescriptive( - "Geografia", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive( - "Sieci komputerowe", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive( - "Systemy operacyjne", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive( - "Język polski", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive( - "Język angielski", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive("Religia", "Lorem ipsum dolor sit amet, consectetur adipiscing elit."), - generateGradeDescriptive( - "Język niemiecki", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), - generateGradeDescriptive( - "Wychowanie fizyczne", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ), -) - -private fun generateGradeDescriptive(subject: String, description: String) = - GradeDescriptive( - semesterId = 0, - studentId = 0, - subject = subject, - description = description - ) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/schoolAnnouncement.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/schoolAnnouncement.kt index 9b21f08e6..e2dc5cd84 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/schoolAnnouncement.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/schoolAnnouncement.kt @@ -19,6 +19,6 @@ val debugSchoolAnnouncementItems = listOf( private fun generateAnnouncement(subject: String, content: String) = SchoolAnnouncement( subject = subject, content = content, - studentId = 0, + userLoginId = 0, date = LocalDate.now() ) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt index d452d74a5..41adc008a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt @@ -1,22 +1,21 @@ package io.github.wulkanowy.ui.modules.exam -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.databinding.DialogExamBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment +import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.openCalendarEventAdd -import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.toFormattedString import java.time.LocalTime -@AndroidEntryPoint -class ExamDialog : BaseDialogFragment() { +class ExamDialog : DialogFragment() { + + private var binding: DialogExamBinding by lifecycleAwareVariable() private lateinit var exam: Exam @@ -25,20 +24,23 @@ class ExamDialog : BaseDialogFragment() { private const val ARGUMENT_KEY = "Item" fun newInstance(exam: Exam) = ExamDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to exam) + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - exam = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + exam = getSerializable(ARGUMENT_KEY) as Exam + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogExamBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogExamBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) 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 0123e2340..ddd0e4a19 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 @@ -2,7 +2,9 @@ package io.github.wulkanowy.ui.modules.exam import android.os.Bundle import android.view.View -import android.view.View.* +import android.view.View.GONE +import android.view.View.INVISIBLE +import android.view.View.VISIBLE import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -18,7 +20,7 @@ import javax.inject.Inject @AndroidEntryPoint class ExamFragment : BaseFragment(R.layout.fragment_exam), ExamView, - MainView.TitledView, MainView.MainChildView { + MainView.TitledView { @Inject lateinit var presenter: ExamPresenter @@ -62,7 +64,7 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam), examPreviousButton.setOnClickListener { presenter.onPreviousWeek() } examNextButton.setOnClickListener { presenter.onNextWeek() } - examNavContainer.elevation = requireContext().dpToPx(3f) + examNavContainer.elevation = requireContext().dpToPx(8f) } } @@ -124,14 +126,6 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam), (activity as? MainActivity)?.showDialogFragment(ExamDialog.newInstance(exam)) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun resetView() { - binding.examRecycler.smoothScrollToPosition(0) - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) 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 858140728..99b0bcb87 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 @@ -175,17 +175,4 @@ class ExamPresenter @Inject constructor( ) } } - - fun onViewReselected() { - Timber.i("Exam view is reselected") - - baseDate = now().nextOrSameSchoolDay - - if (currentDate != baseDate) { - reloadView(baseDate) - loadData() - } else if (view?.isViewEmpty == false) { - view?.resetView() - } - } } 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 677fac40e..45b9e788c 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 @@ -34,6 +34,4 @@ interface ExamView : BaseView { fun showPreButton(show: Boolean) fun showExamDialog(exam: Exam) - - 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 8da59eaf4..b6733d4f2 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,113 +1,81 @@ package io.github.wulkanowy.ui.modules.grade -import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.dataOrNull +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive 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.errorOrNull -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.mapData -import io.github.wulkanowy.data.mapResourceData 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 -import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ONE_SEMESTER +import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.* import io.github.wulkanowy.utils.calcAverage import io.github.wulkanowy.utils.changeModifier -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.flatMapLatest import javax.inject.Inject -@OptIn(ExperimentalCoroutinesApi::class) +@OptIn(FlowPreview::class) class GradeAverageProvider @Inject constructor( private val semesterRepository: SemesterRepository, private val gradeRepository: GradeRepository, private val preferencesRepository: PreferencesRepository ) { - private data class AverageCalcParams( - val gradeAverageMode: GradeAverageMode, - val forceAverageCalc: Boolean, - val isOptionalArithmeticAverage: Boolean, - val plusModifier: Double, - val minusModifier: Double, - ) + private val plusModifier get() = preferencesRepository.gradePlusModifier - fun getGradesDetailsWithAverage( - student: Student, - semesterId: Int, - forceRefresh: Boolean - ): Flow>> = combine( - flow = preferencesRepository.gradeAverageModeFlow, - flow2 = preferencesRepository.gradeAverageForceCalcFlow, - flow3 = preferencesRepository.isOptionalArithmeticAverageFlow, - flow4 = preferencesRepository.gradePlusModifierFlow, - flow5 = preferencesRepository.gradeMinusModifierFlow, - ) { gradeAverageMode, forceAverageCalc, isOptionalArithmeticAverage, plusModifier, minusModifier -> - AverageCalcParams( - gradeAverageMode = gradeAverageMode, - forceAverageCalc = forceAverageCalc, - isOptionalArithmeticAverage = isOptionalArithmeticAverage, - plusModifier = plusModifier, - minusModifier = minusModifier, - ) - }.flatMapLatest { params -> + private val minusModifier get() = preferencesRepository.gradeMinusModifier + + private val isOptionalArithmeticAverage get() = preferencesRepository.isOptionalArithmeticAverage + + fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean) = flatResourceFlow { val semesters = semesterRepository.getSemesters(student) - when (params.gradeAverageMode) { + + when (preferencesRepository.gradeAverageMode) { ONE_SEMESTER -> getGradeSubjects( student = student, - semester = semesters.first { it.semesterId == semesterId }, - forceRefresh = forceRefresh, - params = params, + semester = semesters.single { it.semesterId == semesterId }, + forceRefresh = forceRefresh ) - BOTH_SEMESTERS -> calculateCombinedAverage( student = student, semesters = semesters, semesterId = semesterId, forceRefresh = forceRefresh, - config = params, + averageMode = BOTH_SEMESTERS ) - ALL_YEAR -> calculateCombinedAverage( student = student, semesters = semesters, semesterId = semesterId, forceRefresh = forceRefresh, - config = params, + averageMode = ALL_YEAR ) } - } - }.distinctUntilChanged() + }.distinctUntilChanged() private fun calculateCombinedAverage( student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean, - config: AverageCalcParams, + averageMode: GradeAverageMode ): Flow>> { + val isGradeAverageForceCalc = preferencesRepository.gradeAverageForceCalc val selectedSemester = semesters.single { it.semesterId == semesterId } val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } val selectedSemesterGradeSubjects = - getGradeSubjects(student, selectedSemester, forceRefresh, config) + getGradeSubjects(student, selectedSemester, forceRefresh) if (selectedSemester == firstSemester) return selectedSemesterGradeSubjects - val firstSemesterGradeSubjects = - getGradeSubjects(student, firstSemester, forceRefresh, config) + val firstSemesterGradeSubjects = getGradeSubjects(student, firstSemester, forceRefresh) return selectedSemesterGradeSubjects.combine(firstSemesterGradeSubjects) { secondSemesterGradeSubject, firstSemesterGradeSubject -> if (firstSemesterGradeSubject.errorOrNull != null) { @@ -123,21 +91,21 @@ class GradeAverageProvider @Inject constructor( val firstSemesterSubject = firstSemesterGradeSubject.dataOrNull.orEmpty() .singleOrNull { it.subject == secondSemesterSubject.subject } - val updatedAverage = if (config.gradeAverageMode == ALL_YEAR) { + val updatedAverage = if (averageMode == ALL_YEAR) { calculateAllYearAverage( student = student, isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, + isGradeAverageForceCalc = isGradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, - firstSemesterSubject = firstSemesterSubject, - config = config, + firstSemesterSubject = firstSemesterSubject ) } else { calculateBothSemestersAverage( student = student, isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, + isGradeAverageForceCalc = isGradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, - firstSemesterSubject = firstSemesterSubject, - config = config + firstSemesterSubject = firstSemesterSubject ) } secondSemesterSubject.copy(average = updatedAverage) @@ -149,17 +117,17 @@ class GradeAverageProvider @Inject constructor( private fun calculateAllYearAverage( student: Student, isAnyVulcanAverage: Boolean, + isGradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, - firstSemesterSubject: GradeSubject?, - config: AverageCalcParams, - ) = if (!isAnyVulcanAverage || config.forceAverageCalc) { - val updatedSecondSemesterGrades = secondSemesterSubject.grades - .updateModifiers(student, config) - val updatedFirstSemesterGrades = firstSemesterSubject?.grades - ?.updateModifiers(student, config).orEmpty() + firstSemesterSubject: GradeSubject? + ) = if (!isAnyVulcanAverage || isGradeAverageForceCalc) { + val updatedSecondSemesterGrades = + secondSemesterSubject.grades.updateModifiers(student) + val updatedFirstSemesterGrades = + firstSemesterSubject?.grades?.updateModifiers(student).orEmpty() (updatedSecondSemesterGrades + updatedFirstSemesterGrades).calcAverage( - isOptionalArithmeticAverage = config.isOptionalArithmeticAverage, + isOptionalArithmeticAverage ) } else { secondSemesterSubject.average @@ -168,117 +136,66 @@ class GradeAverageProvider @Inject constructor( private fun calculateBothSemestersAverage( student: Student, isAnyVulcanAverage: Boolean, + isGradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, - firstSemesterSubject: GradeSubject?, - config: AverageCalcParams, - ): Double { - return if (!isAnyVulcanAverage || config.forceAverageCalc) { - val isSecondSemesterHasWeightGrade = secondSemesterSubject.grades - .any { it.weightValue > .0 } - val isSecondSemesterHasArithmeticGrade = secondSemesterSubject.grades - .all { it.weightValue == .0 } && config.isOptionalArithmeticAverage - val isSecondSemesterHaveAverage = - isSecondSemesterHasWeightGrade || isSecondSemesterHasArithmeticGrade + firstSemesterSubject: GradeSubject? + ): Double = if (!isAnyVulcanAverage || isGradeAverageForceCalc) { + val divider = if (secondSemesterSubject.grades.any { it.weightValue > .0 }) 2 else 1 - val divider = if (isSecondSemesterHaveAverage) 2 else 1 - val secondSemesterAverage = secondSemesterSubject.grades - .updateModifiers(student, config) - .calcAverage(isOptionalArithmeticAverage = config.isOptionalArithmeticAverage) - val firstSemesterAverage = firstSemesterSubject?.grades - ?.updateModifiers(student, config) - ?.calcAverage(isOptionalArithmeticAverage = config.isOptionalArithmeticAverage) - ?: secondSemesterAverage + val secondSemesterAverage = secondSemesterSubject.grades.updateModifiers(student) + .calcAverage(isOptionalArithmeticAverage) + val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student) + ?.calcAverage(isOptionalArithmeticAverage) ?: secondSemesterAverage - (secondSemesterAverage + firstSemesterAverage) / divider - } else { - val divider = if (secondSemesterSubject.average > 0) 2 else 1 + (secondSemesterAverage + firstSemesterAverage) / divider + } else { + val divider = if (secondSemesterSubject.average > 0) 2 else 1 - secondSemesterSubject.average.plus( - (firstSemesterSubject?.average ?: secondSemesterSubject.average) - ) / divider - } + (secondSemesterSubject.average + (firstSemesterSubject?.average + ?: secondSemesterSubject.average)) / divider } private fun getGradeSubjects( student: Student, semester: Semester, - forceRefresh: Boolean, - params: AverageCalcParams, + forceRefresh: Boolean ): Flow>> { + val isGradeAverageForceCalc = preferencesRepository.gradeAverageForceCalc + return gradeRepository.getGrades(student, semester, forceRefresh = forceRefresh) .mapResourceData { res -> - val (details, summaries, descriptives) = res + val (details, summaries) = res val isAnyAverage = summaries.any { it.average != .0 } val allGrades = details.groupBy { it.subject } - val descriptiveGradesBySubject = descriptives.associateBy { it.subject } - val items = summaries - .createEmptySummariesByGradesIfNeeded( - student = student, - semester = semester, - grades = allGrades.toList(), - calcAverage = isAnyAverage, - params = params, + val items = summaries.emulateEmptySummaries( + student = student, + semester = semester, + grades = allGrades.toList(), + calcAverage = isAnyAverage + ).map { summary -> + val grades = allGrades[summary.subject].orEmpty() + GradeSubject( + subject = summary.subject, + average = if (!isAnyAverage || isGradeAverageForceCalc) { + grades.updateModifiers(student).calcAverage(isOptionalArithmeticAverage) + } else summary.average, + points = summary.pointsSum, + summary = summary, + grades = grades, + isVulcanAverage = isAnyAverage ) - .createEmptySummariesByDescriptiveGradesIfNeeded( - student = student, - semester = semester, - descriptives = descriptives, - ) - .map { summary -> - val grades = allGrades[summary.subject].orEmpty() - val descriptiveGrade = descriptiveGradesBySubject[summary.subject] - - GradeSubject( - subject = summary.subject, - average = if (!isAnyAverage || params.forceAverageCalc) { - grades.updateModifiers(student, params) - .calcAverage(isOptionalArithmeticAverage = params.isOptionalArithmeticAverage) - } else summary.average, - points = summary.pointsSum, - summary = summary, - grades = grades, - descriptive = descriptiveGrade, - isVulcanAverage = isAnyAverage - ) - } + } items } } - private fun List.createEmptySummariesByDescriptiveGradesIfNeeded( - student: Student, - semester: Semester, - descriptives: List - ): List { - val summarySubjects = this.map { it.subject } - val gradeSummaryToAdd = descriptives.mapNotNull { gradeDescriptive -> - if (gradeDescriptive.subject in summarySubjects) return@mapNotNull null - - GradeSummary( - studentId = student.studentId, - semesterId = semester.semesterId, - position = 0, - subject = gradeDescriptive.subject, - predictedGrade = "", - finalGrade = "", - proposedPoints = "", - finalPoints = "", - pointsSum = "", - average = .0 - ) - } - - return this + gradeSummaryToAdd - } - - private fun List.createEmptySummariesByGradesIfNeeded( + private fun List.emulateEmptySummaries( student: Student, semester: Semester, grades: List>>, - calcAverage: Boolean, - params: AverageCalcParams, + calcAverage: Boolean ): List { if (isNotEmpty() && size > grades.size) return this @@ -294,21 +211,15 @@ class GradeAverageProvider @Inject constructor( proposedPoints = "", finalPoints = "", pointsSum = "", - average = when { - calcAverage -> details - .updateModifiers(student, params) - .calcAverage(isOptionalArithmeticAverage = params.isOptionalArithmeticAverage) - - else -> .0 - } + average = if (calcAverage) details.updateModifiers(student) + .calcAverage(isOptionalArithmeticAverage) else .0 ) } } - private fun List.updateModifiers( - student: Student, - params: AverageCalcParams, - ): List = if (student.loginMode == Sdk.Mode.SCRAPPER.name) { - map { it.changeModifier(params.plusModifier, params.minusModifier) } - } else this + private fun List.updateModifiers(student: Student): List { + return if (student.loginMode == Sdk.Mode.SCRAPPER.name) { + map { it.changeModifier(plusModifier, minusModifier) } + } else this + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt index cc61dc25a..0a8561eec 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt @@ -7,7 +7,7 @@ import android.view.MenuItem import android.view.View import android.view.View.INVISIBLE import android.view.View.VISIBLE -import com.google.android.material.dialog.MaterialAlertDialogBuilder +import androidx.appcompat.app.AlertDialog import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -30,6 +30,14 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade @Inject lateinit var presenter: GradePresenter + private val pagerAdapter by lazy { + BaseFragmentPagerAdapter( + fragmentManager = childFragmentManager, + pagesCount = 3, + lifecycle = lifecycle, + ) + } + private var semesterSwitchMenu: MenuItem? = null companion object { @@ -43,9 +51,6 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade override val currentPageIndex get() = binding.gradeViewPager.currentItem - private var pagerAdapter: BaseFragmentPagerAdapter? = null - - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -64,26 +69,13 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade } override fun initView() { - with(binding) { - gradeErrorRetry.setOnClickListener { presenter.onRetry() } - gradeErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun initTabs(pageCount: Int) { - pagerAdapter = BaseFragmentPagerAdapter( - lifecycle = lifecycle, - pagesCount = pageCount, - fragmentManager = childFragmentManager - ) - with(binding.gradeViewPager) { adapter = pagerAdapter offscreenPageLimit = 3 setOnSelectPageListener(presenter::onPageSelected) } - with(pagerAdapter!!) { + with(pagerAdapter) { containerId = binding.gradeViewPager.id titleFactory = { when (it) { @@ -105,6 +97,11 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade } binding.gradeTabLayout.elevation = requireContext().dpToPx(4f) + + with(binding) { + gradeErrorRetry.setOnClickListener { presenter.onRetry() } + gradeErrorDetails.setOnClickListener { presenter.onDetailsClick() } + } } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -143,7 +140,7 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade val choices = semesters.map { getString(R.string.grade_semester, it.semesterName) } .toTypedArray() - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setSingleChoiceItems(choices, selectedIndex) { dialog, which -> presenter.onSemesterSelected(which) dialog.dismiss() @@ -170,20 +167,19 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade } override fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean) { - (pagerAdapter?.getFragmentInstance(index) as? GradeView.GradeChildView) + (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView) ?.onParentLoadData(semesterId, forceRefresh) } override fun notifyChildParentReselected(index: Int) { - (pagerAdapter?.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentReselected() + (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentReselected() } override fun notifyChildSemesterChange(index: Int) { - (pagerAdapter?.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentChangeSemester() + (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentChangeSemester() } override fun onDestroyView() { - pagerAdapter = null presenter.onDetachView() super.onDestroyView() } 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 8a70b3c19..0ae6521cf 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 @@ -22,8 +22,11 @@ class GradePresenter @Inject constructor( ) : BasePresenter(errorHandler, studentRepository) { private var selectedIndex = 0 + private var schoolYear = 0 - private var availableSemesters = emptyList() + + private var semesters = emptyList() + private val loadedSemesterId = mutableMapOf() private lateinit var lastError: Throwable @@ -37,7 +40,7 @@ class GradePresenter @Inject constructor( } fun onCreateMenu() { - if (availableSemesters.isEmpty()) view?.showSemesterSwitch(false) + if (semesters.isEmpty()) view?.showSemesterSwitch(false) } fun onViewReselected() { @@ -46,8 +49,8 @@ class GradePresenter @Inject constructor( } fun onSemesterSwitch(): Boolean { - if (availableSemesters.isNotEmpty()) { - view?.showSemesterDialog(selectedIndex - 1, availableSemesters.take(2)) + if (semesters.isNotEmpty()) { + view?.showSemesterDialog(selectedIndex - 1, semesters.take(2)) } return true } @@ -80,7 +83,7 @@ class GradePresenter @Inject constructor( } fun onPageSelected(index: Int) { - if (availableSemesters.isNotEmpty()) loadChild(index) + if (semesters.isNotEmpty()) loadChild(index) } fun onRetry() { @@ -98,24 +101,16 @@ class GradePresenter @Inject constructor( private fun loadData() { resourceFlow { val student = studentRepository.getCurrentStudent() - val semesters = semesterRepository.getSemesters(student, refreshOnNoCurrent = true) - - student to semesters + semesterRepository.getSemesters(student, refreshOnNoCurrent = true) } .logResourceStatus("load grade data") - .onResourceData { (student, semesters) -> - val currentSemester = semesters.getCurrentOrLast() - selectedIndex = - if (selectedIndex == 0) currentSemester.semesterName else selectedIndex - schoolYear = currentSemester.schoolYear - availableSemesters = semesters.filter { semester -> - semester.diaryId == currentSemester.diaryId - } - + .onResourceData { + val current = it.getCurrentOrLast() + selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex + schoolYear = current.schoolYear + semesters = it.filter { semester -> semester.diaryId == current.diaryId } + view?.setCurrentSemesterName(current.semesterName, schoolYear) view?.run { - initTabs(if (student.isEduOne == true) 2 else 3) - setCurrentSemesterName(currentSemester.semesterName, schoolYear) - Timber.i("Loading grade data: Attempt load index $currentPageIndex") loadChild(currentPageIndex) showErrorView(false) @@ -136,10 +131,10 @@ class GradePresenter @Inject constructor( } private fun loadChild(index: Int, forceRefresh: Boolean = false) { - Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${availableSemesters.joinToString { it.semesterName.toString() }}") + Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${semesters.joinToString { it.semesterName.toString() }}") val newSelectedSemesterId = try { - availableSemesters.first { it.semesterName == selectedIndex }.semesterId + semesters.first { it.semesterName == selectedIndex }.semesterId } catch (e: NoSuchElementException) { Timber.e(e, "Selected semester no exists") return diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSubject.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSubject.kt index a465551f9..57be55ee3 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSubject.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeSubject.kt @@ -1,7 +1,6 @@ package io.github.wulkanowy.ui.modules.grade import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeDescriptive import io.github.wulkanowy.data.db.entities.GradeSummary data class GradeSubject( @@ -9,7 +8,6 @@ data class GradeSubject( val average: Double, val points: String, val summary: GradeSummary, - val descriptive: GradeDescriptive?, val grades: List, val isVulcanAverage: Boolean ) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt index fc06c4809..104f8505a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt @@ -9,8 +9,6 @@ interface GradeView : BaseView { fun initView() - fun initTabs(pageCount: Int) - fun showContent(show: Boolean) fun showProgress(show: Boolean) 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 15b5db031..e5c3bb63e 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 @@ -1,7 +1,6 @@ package io.github.wulkanowy.ui.modules.grade.details import android.annotation.SuppressLint -import android.content.res.ColorStateList import android.content.res.Resources import android.view.LayoutInflater import android.view.View @@ -18,10 +17,9 @@ import io.github.wulkanowy.databinding.HeaderGradeDetailsBinding import io.github.wulkanowy.databinding.ItemGradeDetailsBinding import io.github.wulkanowy.ui.base.BaseExpandableAdapter import io.github.wulkanowy.utils.getBackgroundColor -import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.toFormattedString import timber.log.Timber -import java.util.* +import java.util.BitSet import javax.inject.Inject class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter() { @@ -205,9 +203,7 @@ class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter grade.description diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt index 39f72f8bc..34594111f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt @@ -1,23 +1,21 @@ package io.github.wulkanowy.ui.modules.grade.details -import android.app.Dialog -import android.content.res.ColorStateList import android.os.Bundle +import android.view.LayoutInflater import android.view.View import android.view.View.GONE -import androidx.core.content.ContextCompat -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.enums.GradeColorTheme import io.github.wulkanowy.databinding.DialogGradeBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.utils.* -@AndroidEntryPoint -class GradeDetailsDialog : BaseDialogFragment() { + +class GradeDetailsDialog : DialogFragment() { + + private var binding: DialogGradeBinding by lifecycleAwareVariable() private lateinit var grade: Grade @@ -29,25 +27,29 @@ class GradeDetailsDialog : BaseDialogFragment() { private const val COLOR_THEME_KEY = "Theme" - fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = GradeDetailsDialog().apply { - arguments = bundleOf( - ARGUMENT_KEY to grade, - COLOR_THEME_KEY to colorTheme - ) - } + fun newInstance(grade: Grade, colorTheme: GradeColorTheme) = + GradeDetailsDialog().apply { + arguments = Bundle().apply { + putSerializable(ARGUMENT_KEY, grade) + putSerializable(COLOR_THEME_KEY, colorTheme) + } + } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - grade = requireArguments().serializable(ARGUMENT_KEY) - gradeColorTheme = requireArguments().serializable(COLOR_THEME_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + grade = getSerializable(ARGUMENT_KEY) as Grade + gradeColorTheme = getSerializable(COLOR_THEME_KEY) as GradeColorTheme + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogGradeBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogGradeBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -55,9 +57,10 @@ class GradeDetailsDialog : BaseDialogFragment() { with(binding) { gradeDialogSubject.text = grade.subject - gradeDialogWeightValue.text = grade.weight - gradeDialogWeightLayout.backgroundTintList = - ColorStateList.valueOf(requireContext().getCompatColor(grade.getGradeColor())) + gradeDialogColorAndWeightValue.run { + text = context.getString(R.string.grade_weight_value, grade.weight) + setBackgroundResource(grade.getGradeColor()) + } gradeDialogDateValue.text = grade.date.toFormattedString() gradeDialogColorValue.text = getString(grade.colorStringId) @@ -71,12 +74,7 @@ class GradeDetailsDialog : BaseDialogFragment() { gradeDialogValue.run { text = grade.entry - backgroundTintList = ColorStateList.valueOf( - ContextCompat.getColor( - requireContext(), - grade.getBackgroundColor(gradeColorTheme) - ) - ) + setBackgroundResource(grade.getBackgroundColor(gradeColorTheme)) } gradeDialogTeacherValue.text = grade.teacher.ifBlank { getString(R.string.all_no_data) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt index 23d767a6f..81f3226ad 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt @@ -5,7 +5,9 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import android.view.View.* +import android.view.View.GONE +import android.view.View.INVISIBLE +import android.view.View.VISIBLE import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -40,7 +42,6 @@ class GradeDetailsFragment : override val isViewEmpty get() = gradeDetailsAdapter.itemCount == 0 - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) 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 d9621f51e..4261c507d 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 @@ -1,22 +1,13 @@ package io.github.wulkanowy.ui.modules.grade.details +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.enums.GradeExpandMode -import io.github.wulkanowy.data.enums.GradeSortingMode.ALPHABETIC -import io.github.wulkanowy.data.enums.GradeSortingMode.AVERAGE -import io.github.wulkanowy.data.enums.GradeSortingMode.DATE -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.onResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceIntermediate -import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.onResourceSuccess +import io.github.wulkanowy.data.enums.GradeSortingMode.* 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.data.resourceFlow import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider @@ -216,20 +207,20 @@ class GradeDetailsPresenter @Inject constructor( AVERAGE -> gradeSubjects.sortedByDescending { it.average } } } - .map { gradeSubject -> - val subItems = gradeSubject.grades + .map { (subject, average, points, _, grades) -> + val subItems = grades .sortedByDescending { it.date } .map { GradeDetailsItem(it, ViewType.ITEM) } val gradeDetailsItems = listOf( GradeDetailsItem( GradeDetailsHeader( - subject = gradeSubject.subject, - average = gradeSubject.average, - pointsSum = gradeSubject.points, + subject = subject, + average = average, + pointsSum = points, grades = subItems ).apply { - newGrades = gradeSubject.grades.filter { grade -> !grade.isRead }.size + newGrades = grades.filter { grade -> !grade.isRead }.size }, ViewType.HEADER ) ) 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 e5f1eba0c..fd0ac5471 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 @@ -22,8 +22,6 @@ import io.github.wulkanowy.databinding.ItemGradeStatisticsHeaderBinding import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding import io.github.wulkanowy.utils.getThemeAttrColor import javax.inject.Inject -import kotlin.math.max -import kotlin.math.roundToInt class GradeStatisticsAdapter @Inject constructor() : RecyclerView.Adapter() { @@ -118,9 +116,7 @@ class GradeStatisticsAdapter @Inject constructor() : } ) - binding.gradeStatisticsTypeSwitch.addOnButtonCheckedListener { _, checkedId, isChecked -> - if (!isChecked) return@addOnButtonCheckedListener - + binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId -> currentDataType = when (checkedId) { R.id.gradeStatisticsTypePartial -> GradeStatisticsItem.DataType.PARTIAL R.id.gradeStatisticsTypeSemester -> GradeStatisticsItem.DataType.SEMESTER @@ -271,7 +267,7 @@ class GradeStatisticsAdapter @Inject constructor() : valueTextSize = 12f valueTextColor = binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary) valueFormatter = object : ValueFormatter() { - override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}" + override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%" } colors = gradePointsColors } @@ -306,20 +302,15 @@ class GradeStatisticsAdapter @Inject constructor() : } xAxis.setDrawLabels(false) xAxis.setDrawGridLines(false) - - val yMaxFromValues = (max(points.others, points.student)).roundToInt() + 30f - val yMaxFromValuesWithMargin = ((yMaxFromValues / 10.0).roundToInt() * 10).toFloat() - val yMax = yMaxFromValuesWithMargin.coerceAtLeast(100f) - val yLabelCount = (yMax / 10).toInt() + 1 with(axisLeft) { axisMinimum = 0f - axisMaximum = yMax - labelCount = yLabelCount + axisMaximum = 100f + labelCount = 11 } with(axisRight) { axisMinimum = 0f - axisMaximum = yMax - labelCount = yLabelCount + axisMaximum = 100f + labelCount = 11 } invalidate() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt index edc384c5e..2af59c011 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt @@ -15,7 +15,6 @@ import io.github.wulkanowy.ui.modules.grade.GradeFragment import io.github.wulkanowy.ui.modules.grade.GradeView import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.setOnItemSelectedListener import javax.inject.Inject @@ -49,8 +48,8 @@ class GradeStatisticsFragment : messageContainer = binding.gradeStatisticsRecycler presenter.onAttachView( view = this, - type = savedInstanceState?.serializable(SAVED_CHART_TYPE), - subjectName = savedInstanceState?.serializable(SAVED_SUBJECT_NAME), + type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType, + subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String, ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt index 95cf97bed..8dcade56e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt @@ -2,16 +2,16 @@ package io.github.wulkanowy.ui.modules.grade.summary import android.annotation.SuppressLint import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup -import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.ItemGradeSummaryBinding import io.github.wulkanowy.databinding.ScrollableHeaderGradeSummaryBinding import io.github.wulkanowy.sdk.scrapper.grades.isGradeValid import io.github.wulkanowy.utils.calcFinalAverage -import io.github.wulkanowy.utils.ifNullOrBlank import java.util.Locale import javax.inject.Inject @@ -24,7 +24,7 @@ class GradeSummaryAdapter @Inject constructor( ITEM(2) } - var items = emptyList() + var items = emptyList() var onCalculatedHelpClickListener: () -> Unit = {} @@ -44,11 +44,9 @@ class GradeSummaryAdapter @Inject constructor( ViewType.HEADER.id -> HeaderViewHolder( ScrollableHeaderGradeSummaryBinding.inflate(inflater, parent, false) ) - ViewType.ITEM.id -> ItemViewHolder( ItemGradeSummaryBinding.inflate(inflater, parent, false) ) - else -> throw IllegalStateException() } } @@ -62,23 +60,19 @@ class GradeSummaryAdapter @Inject constructor( private fun bindHeaderViewHolder(binding: ScrollableHeaderGradeSummaryBinding) { if (items.isEmpty()) return - val gradeSummaries = items - .filter { it.gradeDescriptive == null } - .map { it.gradeSummary } val context = binding.root.context - val finalItemsCount = gradeSummaries.count { isGradeValid(it.finalGrade) } - val calculatedItemsCount = gradeSummaries.count { value -> value.average != 0.0 } - val allItemsCount = gradeSummaries.count { !it.subject.equals("zachowanie", true) } - val finalAverage = gradeSummaries.calcFinalAverage( + val finalItemsCount = items.count { isGradeValid(it.finalGrade) } + val calculatedItemsCount = items.count { value -> value.average != 0.0 } + val allItemsCount = items.count { !it.subject.equals("zachowanie", true) } + val finalAverage = items.calcFinalAverage( preferencesRepository.gradePlusModifier, preferencesRepository.gradeMinusModifier ) - val calculatedAverage = gradeSummaries.filter { value -> value.average != 0.0 } + val calculatedAverage = items.filter { value -> value.average != 0.0 } .map { values -> values.average } .reversed() // fix average precision .average() - .let { if (it.isNaN()) 0.0 else it } with(binding) { gradeSummaryScrollableHeaderFinal.text = formatAverage(finalAverage) @@ -101,28 +95,16 @@ class GradeSummaryAdapter @Inject constructor( } @SuppressLint("SetTextI18n") - private fun bindItemViewHolder(binding: ItemGradeSummaryBinding, item: GradeSummaryItem) { - val (gradeSummary, gradeDescriptive) = item - + private fun bindItemViewHolder(binding: ItemGradeSummaryBinding, item: GradeSummary) { with(binding) { - gradeSummaryItemTitle.text = gradeSummary.subject - gradeSummaryItemPoints.text = gradeSummary.pointsSum - gradeSummaryItemAverage.text = formatAverage(gradeSummary.average, "") - gradeSummaryItemPredicted.text = - "${gradeSummary.predictedGrade} ${gradeSummary.proposedPoints}".trim() - gradeSummaryItemFinal.text = - "${gradeSummary.finalGrade} ${gradeSummary.finalPoints}".trim() - gradeSummaryItemDescriptive.text = gradeDescriptive?.description.ifNullOrBlank { - root.context.getString(R.string.all_no_data) - } + gradeSummaryItemTitle.text = item.subject + gradeSummaryItemPoints.text = item.pointsSum + gradeSummaryItemAverage.text = formatAverage(item.average, "") + gradeSummaryItemPredicted.text = "${item.predictedGrade} ${item.proposedPoints}".trim() + gradeSummaryItemFinal.text = "${item.finalGrade} ${item.finalPoints}".trim() - gradeSummaryItemFinalDivider.isVisible = gradeDescriptive == null - gradeSummaryItemPredictedDivider.isVisible = gradeDescriptive == null - gradeSummaryItemPointsDivider.isVisible = gradeDescriptive == null - gradeSummaryItemPredictedContainer.isVisible = gradeDescriptive == null - gradeSummaryItemFinalContainer.isVisible = gradeDescriptive == null - gradeSummaryItemDescriptiveContainer.isVisible = gradeDescriptive != null - gradeSummaryItemPointsContainer.isVisible = gradeSummary.pointsSum.isNotBlank() + gradeSummaryItemPointsContainer.visibility = + if (item.pointsSum.isBlank()) View.GONE else View.VISIBLE } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt index 35b2edd58..3810902ff 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt @@ -5,10 +5,11 @@ import android.view.View import android.view.View.GONE import android.view.View.INVISIBLE import android.view.View.VISIBLE +import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.databinding.FragmentGradeSummaryBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.grade.GradeFragment @@ -70,7 +71,7 @@ class GradeSummaryFragment : } } - override fun updateData(data: List) { + override fun updateData(data: List) { with(gradeSummaryAdapter) { items = data notifyDataSetChanged() @@ -117,7 +118,7 @@ class GradeSummaryFragment : } override fun showCalculatedAverageHelpDialog() { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.grade_summary_calculated_average_help_dialog_title) .setMessage(R.string.grade_summary_calculated_average_help_dialog_message) .setPositiveButton(R.string.all_close) { _, _ -> } @@ -125,7 +126,7 @@ class GradeSummaryFragment : } override fun showFinalAverageHelpDialog() { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.grade_summary_final_average_help_dialog_title) .setMessage(R.string.grade_summary_final_average_help_dialog_message) .setPositiveButton(R.string.all_close) { _, _ -> } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt deleted file mode 100644 index cf0f1d92e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryItem.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.summary - -import io.github.wulkanowy.data.db.entities.GradeDescriptive -import io.github.wulkanowy.data.db.entities.GradeSummary - -data class GradeSummaryItem( - val gradeSummary: GradeSummary, - val gradeDescriptive: GradeDescriptive? -) 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 d762df02b..4d5a43d8f 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 @@ -1,16 +1,9 @@ package io.github.wulkanowy.ui.modules.grade.summary -import io.github.wulkanowy.data.enums.GradeSortingMode.ALPHABETIC -import io.github.wulkanowy.data.enums.GradeSortingMode.AVERAGE -import io.github.wulkanowy.data.enums.GradeSortingMode.DATE -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.mapResourceData -import io.github.wulkanowy.data.onResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceIntermediate -import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.onResourceSuccess +import io.github.wulkanowy.data.* +import io.github.wulkanowy.data.db.entities.GradeSummary +import io.github.wulkanowy.data.enums.GradeSortingMode +import io.github.wulkanowy.data.enums.GradeSortingMode.* import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter @@ -49,7 +42,7 @@ class GradeSummaryPresenter @Inject constructor( val student = studentRepository.getCurrentStudent() averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh) } - .logResourceStatus("load grade summary") + .logResourceStatus("load grade summary", showData = true) .mapResourceData { createGradeSummaryItems(it) } .onResourceData { view?.run { @@ -135,7 +128,7 @@ class GradeSummaryPresenter @Inject constructor( view?.showFinalAverageHelpDialog() } - private fun createGradeSummaryItems(items: List): List { + private fun createGradeSummaryItems(items: List): List { return items .filter { !checkEmpty(it) } .let { gradeSubjects -> @@ -143,32 +136,21 @@ class GradeSummaryPresenter @Inject constructor( DATE -> gradeSubjects.sortedByDescending { gradeDetailsWithAverage -> gradeDetailsWithAverage.grades.maxByOrNull { it.date }?.date } - ALPHABETIC -> gradeSubjects.sortedBy { gradeDetailsWithAverage -> gradeDetailsWithAverage.subject.lowercase() } - AVERAGE -> gradeSubjects.sortedByDescending { it.average } } } - .map { - val gradeSummary = it.summary.copy(average = it.average) - val descriptive = it.descriptive - GradeSummaryItem( - gradeSummary = gradeSummary, - gradeDescriptive = descriptive, - ) - } - + .map { it.summary.copy(average = it.average) } } private fun checkEmpty(gradeSummary: GradeSubject): Boolean { return gradeSummary.run { summary.finalGrade.isBlank() - && summary.predictedGrade.isBlank() - && average == .0 - && points.isBlank() - && descriptive == null + && summary.predictedGrade.isBlank() + && average == .0 + && points.isBlank() } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt index 36bd61421..156731c31 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.grade.summary +import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.ui.base.BaseView interface GradeSummaryView : BaseView { @@ -12,7 +13,7 @@ interface GradeSummaryView : BaseView { fun initView() - fun updateData(data: List) + fun updateData(data: List) fun resetView() 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 0381acf35..d4eaade2c 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 @@ -21,7 +21,7 @@ import javax.inject.Inject @AndroidEntryPoint class HomeworkFragment : BaseFragment(R.layout.fragment_homework), - HomeworkView, MainView.TitledView, MainView.MainChildView { + HomeworkView, MainView.TitledView { @Inject lateinit var presenter: HomeworkPresenter @@ -67,7 +67,7 @@ class HomeworkFragment : BaseFragment(R.layout.fragment openAddHomeworkButton.setOnClickListener { presenter.onHomeworkAddButtonClicked() } - homeworkNavContainer.elevation = requireContext().dpToPx(3f) + homeworkNavContainer.elevation = requireContext().dpToPx(8f) } } @@ -133,14 +133,6 @@ class HomeworkFragment : BaseFragment(R.layout.fragment (activity as? MainActivity)?.showDialogFragment(HomeworkAddDialog()) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun resetView() { - binding.homeworkRecycler.smoothScrollToPosition(0) - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) 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 6b263e26d..2ac552b41 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 @@ -177,21 +177,8 @@ class HomeworkPresenter @Inject constructor( showNextButton(!currentDate.plusDays(7).isHolidays) updateNavigationWeek( "${currentDate.monday.toFormattedString("dd.MM")} - " + - currentDate.sunday.toFormattedString("dd.MM") + currentDate.sunday.toFormattedString("dd.MM") ) } } - - fun onViewReselected() { - Timber.i("Homework view is reselected") - - baseDate = LocalDate.now().nextOrSameSchoolDay - - if (currentDate != baseDate) { - reloadView(baseDate) - loadData() - } else if (view?.isViewEmpty == false) { - view?.resetView() - } - } } 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 56ba6c89e..7c05ab865 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 @@ -36,6 +36,4 @@ interface HomeworkView : BaseView { fun showHomeworkDialog(homework: Homework) fun showAddHomeworkDialog() - - fun resetView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt index 400d9f46b..c2aff2b13 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/add/HomeworkAddDialog.kt @@ -1,10 +1,10 @@ package io.github.wulkanowy.ui.modules.homework.add -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.core.widget.doOnTextChanged -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.databinding.DialogHomeworkAddBinding @@ -21,15 +21,20 @@ class HomeworkAddDialog : BaseDialogFragment(), Homewo @Inject lateinit var presenter: HomeworkAddPresenter - //todo: move it to presenter + // todo: move it to presenter private var date: LocalDate? = null - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogHomeworkAddBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogHomeworkAddBinding.inflate(inflater).apply { binding = this }.root + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter.onAttachView(this) @@ -98,9 +103,7 @@ class HomeworkAddDialog : BaseDialogFragment(), Homewo rangeEnd = LocalDate.now().lastSchoolDayInSchoolYear, onDateSelected = { date = it - if (isAdded) { - binding.homeworkDialogDate.editText?.setText(date!!.toFormattedString()) - } + binding.homeworkDialogDate.editText?.setText(date!!.toFormattedString()) } ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt index 1ad2a0e32..e03707a5c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt @@ -31,8 +31,14 @@ class HomeworkDetailsAdapter @Inject constructor() : attachments = value?.attachments.orEmpty() } + var isHomeworkFullscreen = false + var onAttachmentClickListener: (url: String) -> Unit = {} + var onFullScreenClickListener = {} + + var onFullScreenExitClickListener = {} + var onDeleteClickListener: (homework: Homework) -> Unit = {} override fun getItemCount() = 1 + if (attachments.isNotEmpty()) attachments.size + 1 else 0 @@ -76,6 +82,18 @@ class HomeworkDetailsAdapter @Inject constructor() : homeworkDialogTeacher.text = homework?.teacher.ifNullOrBlank { noDataString } homeworkDialogContent.text = homework?.content.ifNullOrBlank { noDataString } homeworkDialogDelete.visibility = if (homework?.isAddedByUser == true) VISIBLE else GONE + homeworkDialogFullScreen.visibility = if (isHomeworkFullscreen) GONE else VISIBLE + homeworkDialogFullScreenExit.visibility = if (isHomeworkFullscreen) VISIBLE else GONE + homeworkDialogFullScreen.setOnClickListener { + homeworkDialogFullScreen.visibility = GONE + homeworkDialogFullScreenExit.visibility = VISIBLE + onFullScreenClickListener() + } + homeworkDialogFullScreenExit.setOnClickListener { + homeworkDialogFullScreen.visibility = VISIBLE + homeworkDialogFullScreenExit.visibility = GONE + onFullScreenExitClickListener() + } homeworkDialogDelete.setOnClickListener { onDeleteClickListener(homework!!) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt index 1f9bc881b..f9d463510 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt @@ -1,19 +1,19 @@ package io.github.wulkanowy.ui.modules.homework.details import android.annotation.SuppressLint -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.databinding.DialogHomeworkBinding import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -35,20 +35,23 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew private const val ARGUMENT_KEY = "Item" fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to homework) + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - homework = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + homework = getSerializable(ARGUMENT_KEY) as Homework + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogHomeworkBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogHomeworkBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -64,11 +67,26 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew homeworkDialogClose.setOnClickListener { dismiss() } } + if (presenter.isHomeworkFullscreen) { + dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) + } else { + dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) + } + with(binding.homeworkDialogRecycler) { layoutManager = LinearLayoutManager(context) adapter = detailsAdapter.apply { onAttachmentClickListener = { context.openInternetBrowser(it, ::showMessage) } + onFullScreenClickListener = { + dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) + presenter.isHomeworkFullscreen = true + } + onFullScreenExitClickListener = { + dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) + presenter.isHomeworkFullscreen = false + } onDeleteClickListener = { homework -> presenter.deleteHomework(homework) } + isHomeworkFullscreen = presenter.isHomeworkFullscreen homework = this@HomeworkDetailsDialog.homework } } 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 84933f06b..e76df6bd0 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 @@ -5,6 +5,7 @@ import io.github.wulkanowy.data.logResourceStatus import io.github.wulkanowy.data.onResourceError import io.github.wulkanowy.data.onResourceSuccess 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.data.resourceFlow import io.github.wulkanowy.ui.base.BasePresenter @@ -18,8 +19,15 @@ class HomeworkDetailsPresenter @Inject constructor( studentRepository: StudentRepository, private val homeworkRepository: HomeworkRepository, private val analytics: AnalyticsHelper, + private val preferencesRepository: PreferencesRepository ) : BasePresenter(errorHandler, studentRepository) { + var isHomeworkFullscreen + get() = preferencesRepository.isHomeworkFullscreen + set(value) { + preferencesRepository.isHomeworkFullscreen = value + } + override fun onAttachView(view: HomeworkDetailsView) { super.onAttachView(view) view.initView() 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 88f295788..aac60b56d 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 @@ -2,17 +2,13 @@ package io.github.wulkanowy.ui.modules.login import android.content.Context import android.content.Intent -import android.content.pm.PackageManager -import android.os.Build.VERSION_CODES.TIRAMISU import android.os.Bundle import android.view.MenuItem -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE import androidx.fragment.app.commit import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityLoginBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment @@ -20,10 +16,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.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.notifications.NotificationsFragment -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.InAppUpdateHelper +import io.github.wulkanowy.utils.UpdateHelper import javax.inject.Inject @AndroidEntryPoint @@ -33,10 +26,7 @@ class LoginActivity : BaseActivity(), Logi override lateinit var presenter: LoginPresenter @Inject - lateinit var inAppUpdateHelper: InAppUpdateHelper - - @Inject - lateinit var appInfo: AppInfo + lateinit var updateHelper: UpdateHelper companion object { fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java) @@ -47,10 +37,10 @@ class LoginActivity : BaseActivity(), Logi setContentView(ActivityLoginBinding.inflate(layoutInflater).apply { binding = this }.root) setSupportActionBar(binding.loginToolbar) messageContainer = binding.loginContainer - inAppUpdateHelper.messageContainer = binding.loginContainer + updateHelper.messageContainer = binding.loginContainer presenter.onAttachView(this) - inAppUpdateHelper.checkAndInstallUpdates() + updateHelper.checkAndInstallUpdates(this) if (savedInstanceState == null) { openFragment(LoginFormFragment.newInstance(), clearBackStack = true) @@ -65,7 +55,7 @@ class LoginActivity : BaseActivity(), Logi } override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) onBackPressedDispatcher.onBackPressed() + if (item.itemId == android.R.id.home) onBackPressed() return true } @@ -77,24 +67,8 @@ class LoginActivity : BaseActivity(), Logi openFragment(LoginSymbolFragment.newInstance(loginData)) } - fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) { - openFragment(LoginStudentSelectFragment.newInstance(loginData, registerUser)) - } - - fun navigateToNotifications() { - val isNotificationsPermissionRequired = appInfo.systemVersion >= TIRAMISU - val isPermissionGranted = ContextCompat.checkSelfPermission( - this, "android.permission.POST_NOTIFICATIONS" - ) == PackageManager.PERMISSION_GRANTED - - if (isNotificationsPermissionRequired && !isPermissionGranted) { - openFragment(NotificationsFragment.newInstance(), clearBackStack = true) - } else navigateToFinish() - } - - fun navigateToFinish() { - startActivity(MainActivity.getStartIntent(this)) - finish() + fun navigateToStudentSelect(studentsWithSemesters: List) { + openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters)) } fun onAdvancedLoginClick() { @@ -106,8 +80,6 @@ class LoginActivity : BaseActivity(), Logi } private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) { - supportFragmentManager.popBackStack(fragment::class.java.name, POP_BACK_STACK_INCLUSIVE) - supportFragmentManager.commit { replace(R.id.loginContainer, fragment) setReorderingAllowed(true) @@ -117,6 +89,14 @@ class LoginActivity : BaseActivity(), Logi override fun onResume() { super.onResume() - inAppUpdateHelper.onResume() + updateHelper.onResume(this) + } + + //https://developer.android.com/guide/playcore/in-app-updates#status_callback + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + updateHelper.onActivityResult(requestCode, resultCode) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt index b066cceb9..5d4743589 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginData.kt @@ -6,7 +6,4 @@ data class LoginData( val login: String, val password: String, val baseUrl: String, - val domainSuffix: String, - val defaultSymbol: String, - val userEnteredSymbol: String? = null, ) : Serializable 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 4f709438a..37ab71dce 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 @@ -4,15 +4,13 @@ import android.content.Context import android.database.sqlite.SQLiteConstraintException import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R -import io.github.wulkanowy.sdk.hebe.exception.InvalidPinException -import io.github.wulkanowy.sdk.hebe.exception.InvalidTokenException -import io.github.wulkanowy.sdk.hebe.exception.TokenDeadException -import io.github.wulkanowy.sdk.hebe.exception.UnknownTokenException +import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException +import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException +import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException +import io.github.wulkanowy.sdk.mobile.exception.TokenDeadException import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException import io.github.wulkanowy.ui.base.ErrorHandler import javax.inject.Inject -import io.github.wulkanowy.sdk.hebe.exception.InvalidSymbolException as InvalidHebeSymbolException -import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException as InvalidScrapperSymbolException class LoginErrorHandler @Inject constructor( @ApplicationContext context: Context, @@ -34,11 +32,9 @@ class LoginErrorHandler @Inject constructor( is BadCredentialsException -> onBadCredentials(error.message) is SQLiteConstraintException -> onStudentDuplicate(resources.getString(R.string.login_duplicate_student)) is TokenDeadException -> onInvalidToken(resources.getString(R.string.login_expired_token)) - is UnknownTokenException, is InvalidTokenException -> onInvalidToken(resources.getString(R.string.login_invalid_token)) is InvalidPinException -> onInvalidPin(resources.getString(R.string.login_invalid_pin)) - is InvalidScrapperSymbolException, - is InvalidHebeSymbolException -> onInvalidSymbol(resources.getString(R.string.login_invalid_symbol)) + is InvalidSymbolException -> onInvalidSymbol(resources.getString(R.string.login_invalid_symbol)) else -> super.proceed(error) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt index 13d2c14a7..37dcb38b3 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt @@ -5,11 +5,10 @@ import android.view.View import android.view.View.GONE import android.view.View.VISIBLE import android.widget.ArrayAdapter -import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.ui.base.BaseFragment @@ -35,9 +34,9 @@ class LoginAdvancedFragment : override val formLoginType: String get() = when (binding.loginTypeSwitch.checkedRadioButtonId) { - R.id.loginTypeApi -> Sdk.Mode.HEBE.name - R.id.loginTypeScrapper -> Sdk.Mode.SCRAPPER.name - else -> Sdk.Mode.HYBRID.name + R.id.loginTypeApi -> "API" + R.id.loginTypeScrapper -> "SCRAPPER" + else -> "HYBRID" } override val formUsernameValue: String @@ -56,9 +55,6 @@ class LoginAdvancedFragment : get() = hostValues.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())) .orEmpty() - override val formDomainSuffix: String - get() = binding.loginFormDomainSuffix.text.toString().trim() - override val formHostSymbol: String get() = hostSymbols.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())) .orEmpty() @@ -103,7 +99,7 @@ class LoginAdvancedFragment : loginTypeSwitch.setOnCheckedChangeListener { _, checkedId -> presenter.onLoginModeSelected( when (checkedId) { - R.id.loginTypeApi -> Sdk.Mode.HEBE + R.id.loginTypeApi -> Sdk.Mode.API R.id.loginTypeScrapper -> Sdk.Mode.SCRAPPER else -> Sdk.Mode.HYBRID } @@ -283,7 +279,6 @@ class LoginAdvancedFragment : loginFormUsernameLayout.visibility = VISIBLE loginFormPassLayout.visibility = VISIBLE loginFormHostLayout.visibility = VISIBLE - loginFormDomainSuffixLayout.isVisible = true loginFormPinLayout.visibility = GONE loginFormSymbolLayout.visibility = VISIBLE loginFormTokenLayout.visibility = GONE @@ -295,7 +290,6 @@ class LoginAdvancedFragment : loginFormUsernameLayout.visibility = VISIBLE loginFormPassLayout.visibility = VISIBLE loginFormHostLayout.visibility = VISIBLE - loginFormDomainSuffixLayout.isVisible = true loginFormPinLayout.visibility = GONE loginFormSymbolLayout.visibility = VISIBLE loginFormTokenLayout.visibility = GONE @@ -307,7 +301,6 @@ class LoginAdvancedFragment : loginFormUsernameLayout.visibility = GONE loginFormPassLayout.visibility = GONE loginFormHostLayout.visibility = GONE - loginFormDomainSuffixLayout.isVisible = false loginFormPinLayout.visibility = VISIBLE loginFormSymbolLayout.visibility = VISIBLE loginFormTokenLayout.visibility = VISIBLE @@ -334,8 +327,8 @@ class LoginAdvancedFragment : (activity as? LoginActivity)?.navigateToSymbolFragment(loginData) } - override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) { - (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser) + override fun navigateToStudentSelect(studentsWithSemesters: List) { + (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters) } override fun onResume() { 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 009f26e17..1b42c6c52 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 @@ -1,13 +1,12 @@ package io.github.wulkanowy.ui.modules.login.advanced import io.github.wulkanowy.data.Resource +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.logResourceStatus import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.pojos.RegisterUser import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.resourceFlow import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginData import io.github.wulkanowy.ui.modules.login.LoginErrorHandler @@ -71,7 +70,7 @@ class LoginAdvancedPresenter @Inject constructor( fun updateUsernameLabel() { view?.apply { - setUsernameLabel(if ("vulcan" in formHostValue || "wulkanowy" in formHostValue) emailLabel else nicknameLabel) + setUsernameLabel(if ("vulcan" in formHostValue || "fakelog" in formHostValue) emailLabel else nicknameLabel) } } @@ -79,7 +78,7 @@ class LoginAdvancedPresenter @Inject constructor( view?.apply { clearPassError() clearUsernameError() - if (formHostValue.contains("wulkanowy")) { + if (formHostValue.contains("fakelog")) { setDefaultCredentials( "jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999" ) @@ -92,16 +91,14 @@ class LoginAdvancedPresenter @Inject constructor( fun onLoginModeSelected(type: Sdk.Mode) { view?.run { when (type) { - Sdk.Mode.HEBE -> { + Sdk.Mode.API -> { showOnlyMobileApiModeInputs() showMobileApiWarningMessage() } - Sdk.Mode.SCRAPPER -> { showOnlyScrapperModeInputs() showScraperWarningMessage() } - Sdk.Mode.HYBRID -> { showOnlyHybridModeInputs() showHybridWarningMessage() @@ -142,30 +139,23 @@ class LoginAdvancedPresenter @Inject constructor( showProgress(true) showContent(false) } - is Resource.Success -> { analytics.logEvent( "registration_form", - "success" to true, - "scrapperBaseUrl" to view?.formHostValue.orEmpty(), - "error" to "No error" - ) - val loginData = LoginData( - login = view?.formUsernameValue.orEmpty().trim(), - password = view?.formPassValue.orEmpty().trim(), - baseUrl = view?.formHostValue.orEmpty().trim(), - domainSuffix = view?.formDomainSuffix.orEmpty().trim(), - defaultSymbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(), - ) - when (it.data.symbols.size) { - 0 -> view?.navigateToSymbol(loginData) - else -> view?.navigateToStudentSelect( - loginData = loginData, - registerUser = it.data, - ) - } + "success" to true, + "students" to it.data.size, + "error" to "No error" + ) + val loginData = LoginData( + login = view?.formUsernameValue.orEmpty().trim(), + password = view?.formPassValue.orEmpty().trim(), + baseUrl = view?.formHostValue.orEmpty().trim() + ) + when (it.data.size) { + 0 -> view?.navigateToSymbol(loginData) + else -> view?.navigateToStudentSelect(it.data) + } } - is Resource.Error -> { analytics.logEvent( "registration_form", @@ -183,22 +173,20 @@ class LoginAdvancedPresenter @Inject constructor( }.launch("login") } - private suspend fun getStudentsAppropriatesToLoginType(): RegisterUser { + private suspend fun getStudentsAppropriatesToLoginType(): List { val email = view?.formUsernameValue.orEmpty() val password = view?.formPassValue.orEmpty() val endpoint = view?.formHostValue.orEmpty() - val domainSuffix = view?.formDomainSuffix.orEmpty() val pin = view?.formPinValue.orEmpty() val symbol = view?.formSymbolValue.orEmpty() val token = view?.formTokenValue.orEmpty() return when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) { - Sdk.Mode.HEBE -> studentRepository.getStudentsApi(pin, symbol, token) - Sdk.Mode.SCRAPPER -> studentRepository.getUserSubjectsFromScrapper( - email, password, endpoint, domainSuffix, symbol + Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token) + Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper( + email, password, endpoint, symbol ) - Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid( email, password, endpoint, symbol ) @@ -217,8 +205,8 @@ class LoginAdvancedPresenter @Inject constructor( var isCorrect = true - when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) { - Sdk.Mode.HEBE -> { + when (Sdk.Mode.valueOf(view?.formLoginType ?: "")) { + Sdk.Mode.API -> { if (pin.isEmpty()) { view?.setErrorPinRequired() isCorrect = false @@ -234,17 +222,17 @@ class LoginAdvancedPresenter @Inject constructor( isCorrect = false } } - Sdk.Mode.HYBRID, Sdk.Mode.SCRAPPER -> { if (login.isEmpty()) { view?.setErrorUsernameRequired() isCorrect = false } else { - if ("@" in login && "login" in host) { + if ("@" in login && "standard" !in host) { view?.setErrorLoginRequired() isCorrect = false } - if ("@" !in login && "email" in host) { + + if ("@" !in login && "standard" in host) { view?.setErrorEmailRequired() isCorrect = false } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt index afd33e3b6..f9b84f1ab 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.login.advanced -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.modules.login.LoginData @@ -12,8 +12,6 @@ interface LoginAdvancedView : BaseView { val formHostValue: String - val formDomainSuffix: String - val formHostSymbol: String val formLoginType: String @@ -74,7 +72,7 @@ interface LoginAdvancedView : BaseView { fun navigateToSymbol(loginData: LoginData) - fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) + fun navigateToStudentSelect(studentsWithSemesters: List) fun setErrorPinRequired() 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 1c4920696..463e192de 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 @@ -7,21 +7,20 @@ import android.view.View.GONE import android.view.View.VISIBLE import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged -import androidx.fragment.app.setFragmentResultListener import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.AdminMessage -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.FragmentLoginFormBinding import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog -import io.github.wulkanowy.ui.modules.dashboard.viewholders.AdminMessageViewHolder import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo -import io.github.wulkanowy.utils.* +import io.github.wulkanowy.utils.AppInfo +import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.openEmailClient +import io.github.wulkanowy.utils.openInternetBrowser +import io.github.wulkanowy.utils.setOnEditorDoneSignIn +import io.github.wulkanowy.utils.showSoftInput import javax.inject.Inject @AndroidEntryPoint @@ -51,9 +50,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme get() = hostValues.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())) .orEmpty() - override val formDomainSuffix: String - get() = binding.loginFormDomainSuffix.text.toString() - override val formHostSymbol: String get() = hostSymbols.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())) .orEmpty() @@ -74,13 +70,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme super.onViewCreated(view, savedInstanceState) binding = FragmentLoginFormBinding.bind(view) presenter.onAttachView(this) - initializeCaptchaResultObserver() - } - - private fun initializeCaptchaResultObserver() { - setFragmentResultListener(CaptchaDialog.CAPTCHA_SUCCESS) { _, _ -> - presenter.onRetryAfterCaptcha() - } } override fun initView() { @@ -94,7 +83,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() } loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } - loginFormDomainSuffix.doOnTextChanged { _, _, _, _ -> presenter.onDomainSuffixChanged() } loginFormSignIn.setOnClickListener { presenter.onSignInClick() } loginFormAdvancedButton.setOnClickListener { presenter.onAdvancedLoginClick() } loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() } @@ -161,14 +149,12 @@ class LoginFormFragment : BaseFragment(R.layout.fragme override fun setErrorPassRequired(focus: Boolean) { with(binding.loginFormPassLayout) { error = getString(R.string.error_field_required) - setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError)) } } override fun setErrorPassInvalid(focus: Boolean) { with(binding.loginFormPassLayout) { error = getString(R.string.login_invalid_password) - setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError)) } } @@ -176,7 +162,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme with(binding) { loginFormUsernameLayout.error = " " loginFormPassLayout.error = " " - loginFormPassLayout.setEndIconTintList(requireContext().getAttrColorStateList(R.attr.colorError)) loginFormHostLayout.error = " " loginFormErrorBox.text = message ?: getString(R.string.login_incorrect_password_default) loginFormErrorBox.isVisible = true @@ -189,12 +174,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme } } - override fun setDomainSuffixInvalid() { - with(binding.loginFormDomainSuffixLayout) { - error = getString(R.string.login_invalid_domain_suffix) - } - } - override fun clearUsernameError() { binding.loginFormUsernameLayout.error = null binding.loginFormErrorBox.isVisible = false @@ -202,9 +181,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme override fun clearPassError() { binding.loginFormPassLayout.error = null - binding.loginFormPassLayout.setEndIconTintList( - requireContext().getAttrColorStateList(R.attr.colorOnSurface) - ) binding.loginFormErrorBox.isVisible = false } @@ -213,10 +189,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme binding.loginFormErrorBox.isVisible = false } - override fun clearDomainSuffixError() { - binding.loginFormDomainSuffixLayout.error = null - } - override fun showSoftKeyboard() { activity?.showSoftInput() } @@ -233,34 +205,14 @@ class LoginFormFragment : BaseFragment(R.layout.fragme binding.loginFormContainer.visibility = if (show) VISIBLE else GONE } - override fun showAdminMessage(message: AdminMessage?) { - AdminMessageViewHolder( - binding = binding.loginFormMessage, - onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, - onAdminMessageClickListener = presenter::onAdminMessageSelected, - ).bind(message) - binding.loginFormMessage.root.isVisible = message != null - } - - override fun openInternetBrowser(url: String) { - requireContext().openInternetBrowser(url) - } - - override fun showDomainSuffixInput(show: Boolean) { - binding.loginFormDomainSuffixLayout.isVisible = show - } - - override fun showOtherOptionsButton(show: Boolean) { - binding.loginFormAdvancedButton.isVisible = show - } - @SuppressLint("SetTextI18n") override fun showVersion() { binding.loginFormVersion.text = "v${appInfo.versionName}" } override fun showContact(show: Boolean) { - binding.loginFormContact.isVisible = show + binding.loginFormContact.visibility = if (show) VISIBLE else GONE + binding.loginFormRecoverLink.visibility = if (show) GONE else VISIBLE } override fun openPrivacyPolicyPage() { @@ -274,8 +226,8 @@ class LoginFormFragment : BaseFragment(R.layout.fragme (activity as? LoginActivity)?.navigateToSymbolFragment(loginData) } - override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) { - (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser) + override fun navigateToStudentSelect(studentsWithSemesters: List) { + (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters) } override fun openAdvancedLogin() { @@ -301,10 +253,22 @@ class LoginFormFragment : BaseFragment(R.layout.fragme override fun onResume() { super.onResume() presenter.updateUsernameLabel() - presenter.updateCustomDomainSuffixVisibility() } - override fun openEmail(supportInfo: LoginSupportInfo) { - LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog") + override fun openEmail(lastError: String) { + context?.openEmailClient( + chooserTitle = requireContext().getString(R.string.login_email_intent_title), + email = "wulkanowyinc@gmail.com", + subject = requireContext().getString(R.string.login_email_subject), + body = requireContext().getString( + R.string.login_email_text, + "${appInfo.systemManufacturer} ${appInfo.systemModel}", + appInfo.systemVersion.toString(), + "${appInfo.versionName}-${appInfo.buildFlavor}", + "$formHostValue/$formHostSymbol", + preferencesRepository.installationId, + lastError + ) + ) } } 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 39bc3f02d..0acb0ea6d 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,26 +1,12 @@ package io.github.wulkanowy.ui.modules.login.form import androidx.core.net.toUri -import io.github.wulkanowy.data.db.entities.AdminMessage -import io.github.wulkanowy.data.enums.MessageType -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.onResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceLoading -import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.onResourceSuccess -import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.data.resourceFlow -import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase -import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginData import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.ifNullOrBlank import timber.log.Timber import java.net.URL @@ -29,10 +15,7 @@ import javax.inject.Inject class LoginFormPresenter @Inject constructor( studentRepository: StudentRepository, private val loginErrorHandler: LoginErrorHandler, - private val appInfo: AppInfo, - private val analytics: AnalyticsHelper, - private val getAppropriateAdminMessageUseCase: GetAppropriateAdminMessageUseCase, - private val preferencesRepository: PreferencesRepository, + private val analytics: AnalyticsHelper ) : BasePresenter(loginErrorHandler, studentRepository) { private var lastError: Throwable? = null @@ -42,7 +25,6 @@ class LoginFormPresenter @Inject constructor( view.run { initView() showContact(false) - showOtherOptionsButton(appInfo.isDebug) showVersion() loginErrorHandler.onBadCredentials = { @@ -51,31 +33,6 @@ class LoginFormPresenter @Inject constructor( Timber.i("Entered wrong username or password") } } - - reloadAdminMessage() - } - - private fun reloadAdminMessage() { - flatResourceFlow { - getAppropriateAdminMessageUseCase( - scrapperBaseUrl = view?.formHostValue.orEmpty(), - type = MessageType.LOGIN_MESSAGE, - ) - } - .logResourceStatus("load login admin message") - .onResourceData { view?.showAdminMessage(it) } - .onResourceError { view?.showAdminMessage(null) } - .launch() - } - - fun onAdminMessageSelected(url: String?) { - url?.let { view?.openInternetBrowser(it) } - } - - fun onAdminMessageDismissed(adminMessage: AdminMessage) { - preferencesRepository.dismissedAdminMessageIds += adminMessage.id - - view?.showAdminMessage(null) } fun onPrivacyLinkClick() { @@ -91,26 +48,12 @@ class LoginFormPresenter @Inject constructor( clearPassError() clearUsernameError() clearHostError() - if (formHostValue.contains("wulkanowy")) { + if (formHostValue.contains("fakelog")) { setCredentials("jan@fakelog.cf", "jan123") } else if (formUsernameValue == "jan@fakelog.cf" && formPassValue == "jan123") { setCredentials("", "") } - updateCustomDomainSuffixVisibility() updateUsernameLabel() - reloadAdminMessage() - } - } - - fun onDomainSuffixChanged() { - view?.apply { - clearDomainSuffixError() - } - } - - fun updateCustomDomainSuffixVisibility() { - view?.run { - showDomainSuffixInput("customSuffix" in formHostValue) } } @@ -141,40 +84,20 @@ class LoginFormPresenter @Inject constructor( } } - private fun getLoginData(): LoginData { + fun onSignInClick() { val email = view?.formUsernameValue.orEmpty().trim() val password = view?.formPassValue.orEmpty().trim() val host = view?.formHostValue.orEmpty().trim() - val domainSuffix = view?.formDomainSuffix.orEmpty().trim().takeIf { - "customSuffix" in host - }.orEmpty() val symbol = view?.formHostSymbol.orEmpty().trim() - return LoginData( - login = email, - password = password, - baseUrl = host, - domainSuffix = domainSuffix, - defaultSymbol = symbol - ) - } - - fun onRetryAfterCaptcha() { - onSignInClick() - } - - fun onSignInClick() { - val loginData = getLoginData() - - if (!validateCredentials(loginData)) return + if (!validateCredentials(email, password, host)) return resourceFlow { - studentRepository.getUserSubjectsFromScrapper( - email = loginData.login, - password = loginData.password, - scrapperBaseUrl = loginData.baseUrl, - domainSuffix = loginData.domainSuffix, - symbol = loginData.defaultSymbol, + studentRepository.getStudentsScrapper( + email = email, + password = password, + scrapperBaseUrl = host, + symbol = symbol ) } .logResourceStatus("login") @@ -186,14 +109,15 @@ class LoginFormPresenter @Inject constructor( } } .onResourceSuccess { - when (it.symbols.size) { - 0 -> view?.navigateToSymbol(loginData) - else -> view?.navigateToStudentSelect(loginData, it) + when (it.size) { + 0 -> view?.navigateToSymbol(LoginData(email, password, host)) + else -> view?.navigateToStudentSelect(it) } analytics.logEvent( "registration_form", "success" to true, - "scrapperBaseUrl" to loginData.baseUrl, + "students" to it.size, + "scrapperBaseUrl" to host, "error" to "No error" ) } @@ -205,15 +129,13 @@ class LoginFormPresenter @Inject constructor( } .onResourceError { loginErrorHandler.dispatch(it) - if (it is InvalidSymbolException) { - loginErrorHandler.showDefaultMessage(it) - } lastError = it view?.showContact(true) analytics.logEvent( "registration_form", "success" to false, - "scrapperBaseUrl" to loginData.baseUrl, + "students" to -1, + "scrapperBaseUrl" to host, "error" to it.message.ifNullOrBlank { "No message" } ) } @@ -225,43 +147,31 @@ class LoginFormPresenter @Inject constructor( } fun onEmailClick() { - view?.openEmail( - LoginSupportInfo( - loginData = getLoginData(), - lastErrorMessage = lastError?.message, - registerUser = null, - enteredSymbol = null, - ) - ) + view?.openEmail(lastError?.message.ifNullOrBlank { "none" }) } fun onRecoverClick() { view?.onRecoverClick() } - private fun validateCredentials(loginData: LoginData): Boolean { + private fun validateCredentials(login: String, password: String, host: String): Boolean { var isCorrect = true - if (loginData.login.isEmpty()) { + if (login.isEmpty()) { view?.setErrorUsernameRequired() isCorrect = false } else { - if ("@" in loginData.login && "login" in loginData.baseUrl) { + if ("@" in login && "login" in host) { view?.setErrorLoginRequired() isCorrect = false } - if ("@" !in loginData.login && "email" in loginData.baseUrl) { + if ("@" !in login && "email" in host) { view?.setErrorEmailRequired() isCorrect = false } - - val isEmailLogin = "@" in loginData.login - val isEmailWithLogin = "||" !in loginData.login - val isLoginNotRequired = "login" !in loginData.baseUrl - val isEmailNotRequired = "email" !in loginData.baseUrl - if (isEmailLogin && isEmailWithLogin && isLoginNotRequired && isEmailNotRequired) { - val emailHost = loginData.login.substringAfter("@") - val emailDomain = URL(loginData.baseUrl).host + if ("@" in login && "||" !in login && "login" !in host && "email" !in host) { + val emailHost = login.substringAfter("@") + val emailDomain = URL(host).host if (!emailHost.equals(emailDomain, true)) { view?.setErrorEmailInvalid(domain = emailDomain) isCorrect = false @@ -269,21 +179,16 @@ class LoginFormPresenter @Inject constructor( } } - if (loginData.password.isEmpty()) { + if (password.isEmpty()) { view?.setErrorPassRequired(focus = isCorrect) isCorrect = false } - if (loginData.password.length < 6 && loginData.password.isNotEmpty()) { + if (password.length < 6 && password.isNotEmpty()) { view?.setErrorPassInvalid(focus = isCorrect) isCorrect = false } - if (loginData.domainSuffix !in listOf("", "rc", "kurs")) { - view?.setDomainSuffixInvalid() - isCorrect = false - } - return isCorrect } } 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 6ea22d180..8003975db 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 @@ -1,10 +1,8 @@ package io.github.wulkanowy.ui.modules.login.form -import io.github.wulkanowy.data.db.entities.AdminMessage -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo interface LoginFormView : BaseView { @@ -16,8 +14,6 @@ interface LoginFormView : BaseView { val formHostValue: String - val formDomainSuffix: String - val formHostSymbol: String val nicknameLabel: String @@ -46,16 +42,12 @@ interface LoginFormView : BaseView { fun setErrorEmailInvalid(domain: String) - fun setDomainSuffixInvalid() - fun clearUsernameError() fun clearPassError() fun clearHostError() - fun clearDomainSuffixError() - fun showSoftKeyboard() fun hideSoftKeyboard() @@ -64,19 +56,11 @@ interface LoginFormView : BaseView { fun showContent(show: Boolean) - fun showAdminMessage(message: AdminMessage?) - - fun openInternetBrowser(url: String) - - fun showDomainSuffixInput(show: Boolean) - - fun showOtherOptionsButton(show: Boolean) - fun showVersion() fun navigateToSymbol(loginData: LoginData) - fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) + fun navigateToStudentSelect(studentsWithSemesters: List) fun openPrivacyPolicyPage() @@ -84,7 +68,7 @@ interface LoginFormView : BaseView { fun openFaqPage() - fun openEmail(supportInfo: LoginSupportInfo) + fun openEmail(lastError: String) fun openAdvancedLogin() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt index b9afba986..786bbfce8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt @@ -98,7 +98,7 @@ class LoginRecoverFragment : loginRecoverButton.setOnClickListener { presenter.onRecoverClick() } loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() } loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() } - loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressedDispatcher.onBackPressed() } + loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() } } with(bindingLocal.loginRecoverHost) { 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 18902e014..3d0493012 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 @@ -38,7 +38,7 @@ class LoginRecoverPresenter @Inject constructor( fun onHostSelected() { view?.run { - if ("wulkanowy" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf") + if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf") clearUsernameError() updateFields() } @@ -46,7 +46,7 @@ class LoginRecoverPresenter @Inject constructor( fun updateFields() { view?.run { - setUsernameHint(if ("email" in recoverHostValue) emailHintString else loginPeselEmailHintString) + setUsernameHint(if ("standard" in recoverHostValue) emailHintString else loginPeselEmailHintString) } } @@ -60,7 +60,7 @@ class LoginRecoverPresenter @Inject constructor( resourceFlow { recoverRepository.getReCaptchaSiteKey( host, - symbol.ifBlank { "default" }) + symbol.ifBlank { "Default" }) }.onEach { when (it) { is Resource.Loading -> view?.run { @@ -92,7 +92,7 @@ class LoginRecoverPresenter @Inject constructor( isCorrect = false } - if ("email" in host && "@" !in username) { + if ("standard" in host && "@" !in username) { view?.setUsernameError(view?.invalidEmailString.orEmpty()) isCorrect = false } @@ -103,7 +103,7 @@ class LoginRecoverPresenter @Inject constructor( fun onReCaptchaVerified(reCaptchaResponse: String) { val username = view?.recoverNameValue.orEmpty() val host = view?.recoverHostValue.orEmpty() - val symbol = view?.formHostSymbol.ifNullOrBlank { "default" } + val symbol = view?.formHostSymbol.ifNullOrBlank { "Default" } resourceFlow { recoverRepository.sendRecoverRequest( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt index ef8cf4ee9..c046c2ff5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt @@ -2,190 +2,65 @@ package io.github.wulkanowy.ui.modules.login.studentselect import android.annotation.SuppressLint import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.recyclerview.widget.DiffUtil.ItemCallback -import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.* +import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.databinding.ItemLoginStudentSelectBinding import javax.inject.Inject -@SuppressLint("SetTextI18n") class LoginStudentSelectAdapter @Inject constructor() : - ListAdapter(Differ) { + RecyclerView.Adapter() { - override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal + private val checkedList = mutableMapOf() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - return when (LoginStudentSelectItemType.entries[viewType]) { - LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER -> EmptySymbolsHeaderViewHolder( - ItemLoginStudentSelectEmptySymbolHeaderBinding.inflate(inflater, parent, false), - ) - - LoginStudentSelectItemType.SYMBOL_HEADER -> SymbolsHeaderViewHolder( - ItemLoginStudentSelectHeaderSymbolBinding.inflate(inflater, parent, false) - ) - - LoginStudentSelectItemType.SCHOOL_HEADER -> SchoolHeaderViewHolder( - ItemLoginStudentSelectHeaderSchoolBinding.inflate(inflater, parent, false) - ) - - LoginStudentSelectItemType.STUDENT -> StudentViewHolder( - ItemLoginStudentSelectStudentBinding.inflate(inflater, parent, false) - ) - - LoginStudentSelectItemType.HELP -> HelpViewHolder( - ItemLoginStudentSelectHelpBinding.inflate(inflater, parent, false) - ) + var items = emptyList>() + set(value) { + field = value + checkedList.clear() } - } - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is EmptySymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.EmptySymbolsHeader) - is SymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SymbolHeader) - is SchoolHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SchoolHeader) - is StudentViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Student) - is HelpViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Help) - } - } + var onClickListener: (StudentWithSemesters, alreadySaved: Boolean) -> Unit = { _, _ -> } - private class EmptySymbolsHeaderViewHolder( - private val binding: ItemLoginStudentSelectEmptySymbolHeaderBinding, - ) : RecyclerView.ViewHolder(binding.root) { + override fun getItemCount() = items.size - fun bind(item: LoginStudentSelectItem.EmptySymbolsHeader) { - with(binding) { - loginStudentSelectEmptySymbolChevron.rotation = if (item.isExpanded) 270f else 90f - root.setOnClickListener { item.onClick() } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( + ItemLoginStudentSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val (studentAndSemesters, alreadySaved) = items[position] + val student = studentAndSemesters.student + val semesters = studentAndSemesters.semesters + val diary = semesters.maxByOrNull { it.semesterId } + + with(holder.binding) { + loginItemName.text = "${student.studentName} ${diary?.diaryName.orEmpty()}" + loginItemSchool.text = student.schoolName + loginItemName.isEnabled = !alreadySaved + loginItemSchool.isEnabled = !alreadySaved + loginItemSignedIn.visibility = if (alreadySaved) View.VISIBLE else View.GONE + + with(loginItemCheck) { + isEnabled = !alreadySaved + keyListener = null + isChecked = checkedList[position] ?: false } - } - } - private class SymbolsHeaderViewHolder( - private val binding: ItemLoginStudentSelectHeaderSymbolBinding, - ) : RecyclerView.ViewHolder(binding.root) { - - fun bind(item: LoginStudentSelectItem.SymbolHeader) { - with(binding) { - loginStudentSelectHeaderSymbolValue.text = buildString { - append(root.context.getString(R.string.mobile_device_symbol)) - append(": ") - append(item.humanReadableName ?: item.symbol.symbol) - if (!item.humanReadableName.isNullOrBlank()) { - append(" (${item.symbol.symbol})") - } - } - loginStudentSelectHeaderSymbolUsername.text = item.symbol.userName - loginStudentSelectHeaderSymbolUsername.isVisible = item.symbol.userName.isNotBlank() - loginStudentSelectHeaderSymbolError.text = item.symbol.error?.message - loginStudentSelectHeaderSymbolError.isVisible = item.symbol.error != null - loginStudentSelectHeaderSymbolError.maxLines = when { - item.isErrorExpanded -> Int.MAX_VALUE - else -> 2 - } - - if (item.symbol.error != null) { - root.setOnClickListener { item.onClick(item.symbol) } - } else root.setOnClickListener(null) - } - } - } - - private class SchoolHeaderViewHolder( - private val binding: ItemLoginStudentSelectHeaderSchoolBinding, - ) : RecyclerView.ViewHolder(binding.root) { - - fun bind(item: LoginStudentSelectItem.SchoolHeader) { - with(binding) { - loginStudentSelectHeaderSchoolName.text = buildString { - append(item.unit.schoolName.trim()) - if (item.unit.schoolShortName.isNotBlank()) { - append(" (") - append(item.unit.schoolShortName) - append(")") - } - } - loginStudentSelectHeaderSchoolDetails.isVisible = item.unit.students.isEmpty() - loginStudentSelectHeaderSchoolError.text = item.unit.error?.message - loginStudentSelectHeaderSchoolError.isVisible = item.unit.error != null - loginStudentSelectHeaderSchoolError.maxLines = when { - item.isErrorExpanded -> Int.MAX_VALUE - else -> 2 - } - - if (item.unit.error != null) { - root.setOnClickListener { item.onClick(item.unit) } - } else root.setOnClickListener(null) - } - } - } - - private class StudentViewHolder( - private val binding: ItemLoginStudentSelectStudentBinding, - ) : RecyclerView.ViewHolder(binding.root) { - - fun bind(item: LoginStudentSelectItem.Student) { - val student = item.student - val semesters = student.semesters - val diary = semesters.maxByOrNull { it.semesterId } - - with(binding) { - loginItemName.text = "${student.studentName} ${student.studentSurname}" - loginItemName.isEnabled = item.isEnabled - loginItemSignedIn.text = if (!item.isEnabled) { - root.context.getString(R.string.login_signed_in) - } else diary?.diaryName + root.setOnClickListener { + onClickListener(studentAndSemesters, alreadySaved) with(loginItemCheck) { - keyListener = null - isEnabled = item.isEnabled - isChecked = item.isSelected || !item.isEnabled - } - - root.isEnabled = item.isEnabled - root.setOnClickListener { - item.onClick(item) + if (isEnabled) { + isChecked = !isChecked + checkedList[position] = isChecked + } } } } } - private class HelpViewHolder( - private val binding: ItemLoginStudentSelectHelpBinding, - ) : RecyclerView.ViewHolder(binding.root) { - - fun bind(item: LoginStudentSelectItem.Help) { - with(binding) { - loginStudentSelectHelpSymbol.isVisible = item.isSymbolButtonVisible - loginStudentSelectHelpSymbol.setOnClickListener { item.onEnterSymbolClick() } - loginStudentSelectHelpMail.setOnClickListener { item.onContactUsClick() } - loginStudentSelectHelpDiscord.setOnClickListener { item.onDiscordClick() } - } - } - } - - private object Differ : ItemCallback() { - - override fun areItemsTheSame( - oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem - ): Boolean = when { - oldItem is LoginStudentSelectItem.EmptySymbolsHeader && newItem is LoginStudentSelectItem.EmptySymbolsHeader -> true - oldItem is LoginStudentSelectItem.SymbolHeader && newItem is LoginStudentSelectItem.SymbolHeader -> { - oldItem.symbol == newItem.symbol - } - - oldItem is LoginStudentSelectItem.Student && newItem is LoginStudentSelectItem.Student -> { - oldItem.student == newItem.student - } - - else -> oldItem == newItem - } - - override fun areContentsTheSame( - oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem - ): Boolean = oldItem == newItem - } + class ItemViewHolder(val binding: ItemLoginStudentSelectBinding) : + RecyclerView.ViewHolder(binding.root) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt index 0fe36aa99..c42a4e9d1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt @@ -2,21 +2,21 @@ package io.github.wulkanowy.ui.modules.login.studentselect import android.os.Bundle import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE import androidx.core.os.bundleOf -import androidx.core.view.isVisible +import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo +import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.utils.AppInfo +import io.github.wulkanowy.utils.openEmailClient import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -36,83 +36,93 @@ class LoginStudentSelectFragment : @Inject lateinit var preferencesRepository: PreferencesRepository - private lateinit var symbolsNames: Array - private lateinit var symbolsValues: Array - - override val symbols: Map by lazy { - symbolsValues.zip(symbolsNames).toMap() - } - companion object { - private const val ARG_LOGIN = "LOGIN" - private const val ARG_STUDENTS = "STUDENTS" + const val ARG_STUDENTS = "STUDENTS" - fun newInstance(loginData: LoginData, registerUser: RegisterUser) = + fun newInstance(studentsWithSemesters: List) = LoginStudentSelectFragment().apply { - arguments = bundleOf( - ARG_LOGIN to loginData, - ARG_STUDENTS to registerUser, - ) + arguments = bundleOf(ARG_STUDENTS to studentsWithSemesters) } } + @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentLoginStudentSelectBinding.bind(view) - - symbolsNames = resources.getStringArray(R.array.symbols) - symbolsValues = resources.getStringArray(R.array.symbols_values) - presenter.onAttachView( view = this, - loginData = requireArguments().serializable(ARG_LOGIN), - registerUser = requireArguments().serializable(ARG_STUDENTS), + students = requireArguments().getSerializable(ARG_STUDENTS) as List, ) } override fun initView() { (requireActivity() as LoginActivity).showActionBar(true) + loginAdapter.onClickListener = presenter::onItemSelected + with(binding) { loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() } - loginStudentSelectRecycler.adapter = loginAdapter + loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() } + loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() } + + with(loginStudentSelectRecycler) { + layoutManager = LinearLayoutManager(context) + adapter = loginAdapter + } } } - override fun updateData(data: List) { - loginAdapter.submitList(data) + override fun updateData(data: List>) { + with(loginAdapter) { + items = data + notifyDataSetChanged() + } } - override fun navigateToSymbol(loginData: LoginData) { - (requireActivity() as LoginActivity).navigateToSymbolFragment(loginData) - } - - override fun navigateToNext() { - (requireActivity() as LoginActivity).navigateToNotifications() + override fun openMainView() { + startActivity(MainActivity.getStartIntent(requireContext())) + requireActivity().finish() } override fun showProgress(show: Boolean) { - binding.loginStudentSelectProgress.isVisible = show + binding.loginStudentSelectProgress.visibility = if (show) VISIBLE else GONE } override fun showContent(show: Boolean) { - binding.loginStudentSelectContent.isVisible = show + binding.loginStudentSelectContent.visibility = if (show) VISIBLE else GONE } override fun enableSignIn(enable: Boolean) { binding.loginStudentSelectSignIn.isEnabled = enable } - override fun openDiscordInvite() { - context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) - } - - override fun openEmail(supportInfo: LoginSupportInfo) { - LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog") + override fun showContact(show: Boolean) { + binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE } override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() } + + override fun openDiscordInvite() { + context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) + } + + override fun openEmail(lastError: String) { + context?.openEmailClient( + chooserTitle = requireContext().getString(R.string.login_email_intent_title), + email = "wulkanowyinc@gmail.com", + subject = requireContext().getString(R.string.login_email_subject), + body = requireContext().getString( + R.string.login_email_text, + "${appInfo.systemManufacturer} ${appInfo.systemModel}", + appInfo.systemVersion.toString(), + "${appInfo.versionName}-${appInfo.buildFlavor}", + "Select users to log in", + preferencesRepository.installationId, + lastError + ) + ) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt deleted file mode 100644 index 1edc8e7b4..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectItem.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.studentselect - -import io.github.wulkanowy.data.pojos.RegisterStudent -import io.github.wulkanowy.data.pojos.RegisterSymbol -import io.github.wulkanowy.data.pojos.RegisterUnit - -sealed class LoginStudentSelectItem(val type: LoginStudentSelectItemType) { - - data class EmptySymbolsHeader( - val isExpanded: Boolean, - val onClick: () -> Unit, - ) : LoginStudentSelectItem(LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER) - - data class SymbolHeader( - val symbol: RegisterSymbol, - val humanReadableName: String?, - val isErrorExpanded: Boolean, - val onClick: (RegisterSymbol) -> Unit, - ) : LoginStudentSelectItem(LoginStudentSelectItemType.SYMBOL_HEADER) - - data class SchoolHeader( - val unit: RegisterUnit, - val isErrorExpanded: Boolean, - val onClick: (RegisterUnit) -> Unit, - ) : LoginStudentSelectItem(LoginStudentSelectItemType.SCHOOL_HEADER) - - data class Student( - val symbol: RegisterSymbol, - val unit: RegisterUnit, - val student: RegisterStudent, - val isEnabled: Boolean, - val isSelected: Boolean, - val onClick: (Student) -> Unit, - ) : LoginStudentSelectItem(LoginStudentSelectItemType.STUDENT) - - data class Help( - val onEnterSymbolClick: () -> Unit, - val onContactUsClick: () -> Unit, - val onDiscordClick: () -> Unit, - val isSymbolButtonVisible: Boolean, - ) : LoginStudentSelectItem(LoginStudentSelectItemType.HELP) -} - -enum class LoginStudentSelectItemType { - EMPTY_SYMBOLS_HEADER, - SYMBOL_HEADER, - SCHOOL_HEADER, - STUDENT, - HELP, -} 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 c81d353d4..3455b3cf1 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 @@ -1,60 +1,36 @@ package io.github.wulkanowy.ui.modules.login.studentselect import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.dataOrNull +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.mappers.mapToStudentWithSemesters -import io.github.wulkanowy.data.pojos.RegisterStudent -import io.github.wulkanowy.data.pojos.RegisterSymbol -import io.github.wulkanowy.data.pojos.RegisterUnit -import io.github.wulkanowy.data.pojos.RegisterUser -import io.github.wulkanowy.data.repositories.SchoolsRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.resourceFlow -import io.github.wulkanowy.sdk.scrapper.exception.StudentGraduateException -import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.modules.login.LoginData import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.isCurrent +import io.github.wulkanowy.utils.ifNullOrBlank import kotlinx.coroutines.flow.onEach import timber.log.Timber import javax.inject.Inject class LoginStudentSelectPresenter @Inject constructor( studentRepository: StudentRepository, - private val schoolsRepository: SchoolsRepository, private val loginErrorHandler: LoginErrorHandler, private val syncManager: SyncManager, - private val analytics: AnalyticsHelper, - private val appInfo: AppInfo, + private val analytics: AnalyticsHelper ) : BasePresenter(loginErrorHandler, studentRepository) { private var lastError: Throwable? = null - private lateinit var registerUser: RegisterUser - private lateinit var loginData: LoginData + private val selectedStudents = mutableListOf() - private lateinit var students: List - private var isEmptySymbolsExpanded = false - private var expandedSymbolError: RegisterSymbol? = null - private var expandedSchoolError: RegisterUnit? = null - - private val selectedStudents = mutableListOf() - - fun onAttachView( - view: LoginStudentSelectView, - loginData: LoginData, - registerUser: RegisterUser, - ) { + fun onAttachView(view: LoginStudentSelectView, students: List) { super.onAttachView(view) with(view) { initView() + showContact(false) enableSignIn(false) loginErrorHandler.onStudentDuplicate = { showMessage(it) @@ -62,199 +38,50 @@ class LoginStudentSelectPresenter @Inject constructor( } } - this.loginData = loginData - this.registerUser = registerUser - loadData() + if (students.size == 1) registerStudents(students) + loadData(students) } - private fun loadData() { - resetSelectedState() - - resourceFlow { studentRepository.getSavedStudents(false) }.onEach { - students = it.dataOrNull.orEmpty() - when (it) { - is Resource.Loading -> Timber.d("Login student select students load started") - is Resource.Success -> { - getStudentsWithCurrentlyActiveSemesters() - selectedStudents.clear() - selectedStudents.addAll(getStudentsWithCurrentlyActiveSemesters()) - view?.enableSignIn(selectedStudents.isNotEmpty()) - refreshItems() - } - - is Resource.Error -> { - errorHandler.dispatch(it.error) - lastError = it.error - refreshItems() - } - } - }.launch() - } - - private fun getStudentsWithCurrentlyActiveSemesters(): List { - val students = registerUser.symbols.flatMap { symbol -> - symbol.schools.flatMap { unit -> - unit.students.map { - createStudentItem(it, symbol, unit, students) - } - } - } - return students - .filter { it.isEnabled } - .filter { student -> - student.student.semesters.any { semester -> - semester.isCurrent() - } - } - } - - private fun createItems(): List = buildList { - val notEmptySymbols = registerUser.symbols.filter { it.shouldShowOnTop() } - val emptySymbols = registerUser.symbols.filter { !it.shouldShowOnTop() } - - if (emptySymbols.isNotEmpty() && notEmptySymbols.isNotEmpty() && emptySymbols.any { it.symbol == loginData.userEnteredSymbol }) { - add(createEmptySymbolItem(emptySymbols.first { it.symbol == loginData.userEnteredSymbol })) - } - - addAll(createNotEmptySymbolItems(notEmptySymbols, students)) - addAll(createEmptySymbolItems(emptySymbols, notEmptySymbols.isNotEmpty())) - - val helpItem = LoginStudentSelectItem.Help( - onEnterSymbolClick = ::onEnterSymbol, - onContactUsClick = ::onEmailClick, - onDiscordClick = ::onDiscordClick, - isSymbolButtonVisible = "login" !in loginData.baseUrl, - ) - add(helpItem) - } - - private fun RegisterSymbol.shouldShowOnTop(): Boolean { - return schools.isNotEmpty() || error is StudentGraduateException - } - - private fun createNotEmptySymbolItems( - notEmptySymbols: List, - students: List, - ) = buildList { - notEmptySymbols.forEach { registerSymbol -> - val symbolHeader = LoginStudentSelectItem.SymbolHeader( - symbol = registerSymbol, - humanReadableName = view?.symbols?.get(registerSymbol.symbol), - isErrorExpanded = expandedSymbolError == registerSymbol, - onClick = ::onSymbolItemClick, - ) - add(symbolHeader) - - registerSymbol.schools.forEach { registerUnit -> - val schoolHeader = LoginStudentSelectItem.SchoolHeader( - unit = registerUnit, - isErrorExpanded = expandedSchoolError == registerUnit, - onClick = ::onUnitItemClick, - ) - add(schoolHeader) - - registerUnit.students.forEach { - add(createStudentItem(it, registerSymbol, registerUnit, students)) - } - } - } - } - - private fun createStudentItem( - student: RegisterStudent, - symbol: RegisterSymbol, - school: RegisterUnit, - students: List, - ) = LoginStudentSelectItem.Student( - symbol = symbol, - unit = school, - student = student, - onClick = ::onItemSelected, - isEnabled = students.none { - it.student.email == registerUser.login - && it.student.symbol == symbol.symbol - && it.student.studentId == student.studentId - && it.student.schoolSymbol == school.schoolId - && it.student.classId == student.classId - }, - isSelected = selectedStudents - .filter { it.symbol.symbol == symbol.symbol } - .filter { it.unit.schoolId == school.schoolId } - .filter { it.student.studentId == student.studentId } - .filter { it.student.classId == student.classId } - .size == 1, - ) - - private fun createEmptySymbolItems( - emptySymbols: List, - isNotEmptySymbolsExist: Boolean, - ) = buildList { - val filteredEmptySymbols = emptySymbols.filter { - it.error !is InvalidSymbolException - }.ifEmpty { emptySymbols.takeIf { !isNotEmptySymbolsExist }.orEmpty() } - - if (filteredEmptySymbols.isNotEmpty() && isNotEmptySymbolsExist) { - val emptyHeader = LoginStudentSelectItem.EmptySymbolsHeader( - isExpanded = isEmptySymbolsExpanded, - onClick = ::onEmptySymbolsToggle, - ) - add(emptyHeader) - if (isEmptySymbolsExpanded) { - filteredEmptySymbols.forEach { - add(createEmptySymbolItem(it)) - } - } - } - - if (filteredEmptySymbols.isNotEmpty() && !isNotEmptySymbolsExist) { - filteredEmptySymbols.forEach { - add(createEmptySymbolItem(it)) - } - } - } - - private fun createEmptySymbolItem(registerSymbol: RegisterSymbol) = - LoginStudentSelectItem.SymbolHeader( - symbol = registerSymbol, - humanReadableName = view?.symbols?.get(registerSymbol.symbol), - isErrorExpanded = expandedSymbolError == registerSymbol, - onClick = ::onSymbolItemClick, - ) - fun onSignIn() { registerStudents(selectedStudents) } - private fun onEmptySymbolsToggle() { - isEmptySymbolsExpanded = !isEmptySymbolsExpanded - - refreshItems() - } - - private fun onItemSelected(item: LoginStudentSelectItem.Student) { - if (!item.isEnabled) return + fun onItemSelected(studentWithSemester: StudentWithSemesters, alreadySaved: Boolean) { + if (alreadySaved) return selectedStudents - .removeAll { - it.student.studentId == item.student.studentId && - it.student.classId == item.student.classId && - it.unit.schoolId == item.unit.schoolId && - it.symbol.symbol == item.symbol.symbol - } - .let { if (!it) selectedStudents.add(item) } + .removeAll { it == studentWithSemester } + .let { if (!it) selectedStudents.add(studentWithSemester) } view?.enableSignIn(selectedStudents.isNotEmpty()) - refreshItems() } - private fun onSymbolItemClick(symbol: RegisterSymbol) { - expandedSymbolError = if (symbol != expandedSymbolError) symbol else null - refreshItems() + private fun compareStudents(a: Student, b: Student): Boolean { + return a.email == b.email + && a.symbol == b.symbol + && a.studentId == b.studentId + && a.schoolSymbol == b.schoolSymbol + && a.classId == b.classId } - private fun onUnitItemClick(unit: RegisterUnit) { - expandedSchoolError = if (unit != expandedSchoolError) unit else null - refreshItems() + private fun loadData(studentsWithSemesters: List) { + resetSelectedState() + + resourceFlow { studentRepository.getSavedStudents(false) }.onEach { + when (it) { + is Resource.Loading -> Timber.d("Login student select students load started") + is Resource.Success -> view?.updateData(studentsWithSemesters.map { studentWithSemesters -> + studentWithSemesters to it.data.any { item -> + compareStudents(studentWithSemesters.student, item.student) + } + }) + is Resource.Error -> { + errorHandler.dispatch(it.error) + lastError = it.error + view?.updateData(studentsWithSemesters.map { student -> student to false }) + } + } + }.launch() } private fun resetSelectedState() { @@ -262,25 +89,8 @@ class LoginStudentSelectPresenter @Inject constructor( view?.enableSignIn(false) } - private fun refreshItems() { - view?.updateData(createItems()) - } - - private fun registerStudents(students: List) { - val filteredStudents = students.filterIsInstance() - val studentsWithSemesters = filteredStudents.map { item -> - item.student.mapToStudentWithSemesters( - user = registerUser, - symbol = item.symbol, - scrapperDomainSuffix = loginData.domainSuffix, - unit = item.unit, - colors = appInfo.defaultColorsForAvatar, - ) - } - resourceFlow { - studentRepository.saveStudents(studentsWithSemesters) - schoolsRepository.logSchoolLogin(loginData, studentsWithSemesters) - } + private fun registerStudents(studentsWithSemesters: List) { + resourceFlow { studentRepository.saveStudents(studentsWithSemesters) } .logResourceStatus("registration") .onEach { when (it) { @@ -288,17 +98,16 @@ class LoginStudentSelectPresenter @Inject constructor( showProgress(true) showContent(false) } - is Resource.Success -> { syncManager.startOneTimeSyncWorker(quiet = true) - view?.navigateToNext() + view?.openMainView() logRegisterEvent(studentsWithSemesters) } - is Resource.Error -> { view?.apply { showProgress(false) showContent(true) + showContact(true) } lastError = it.error loginErrorHandler.dispatch(it.error) @@ -308,23 +117,12 @@ class LoginStudentSelectPresenter @Inject constructor( }.launch("register") } - private fun onEnterSymbol() { - view?.navigateToSymbol(loginData) - } - - private fun onDiscordClick() { + fun onDiscordClick() { view?.openDiscordInvite() } - private fun onEmailClick() { - view?.openEmail( - LoginSupportInfo( - loginData = loginData, - registerUser = registerUser, - lastErrorMessage = lastError?.message, - enteredSymbol = loginData.userEnteredSymbol, - ) - ) + fun onEmailClick() { + view?.openEmail(lastError?.message.ifNullOrBlank { "empty" }) } private fun logRegisterEvent( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt index b69700f17..f2acd76c5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt @@ -1,20 +1,15 @@ package io.github.wulkanowy.ui.modules.login.studentselect +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView -import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo interface LoginStudentSelectView : BaseView { - val symbols: Map - fun initView() - fun updateData(data: List) + fun updateData(data: List>) - fun navigateToSymbol(loginData: LoginData) - - fun navigateToNext() + fun openMainView() fun showProgress(show: Boolean) @@ -22,7 +17,9 @@ interface LoginStudentSelectView : BaseView { fun enableSignIn(enable: Boolean) + fun showContact(show: Boolean) + fun openDiscordInvite() - fun openEmail(supportInfo: LoginSupportInfo) + fun openEmail(lastError: String) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportDialog.kt deleted file mode 100644 index 4be2dbaad..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportDialog.kt +++ /dev/null @@ -1,149 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.support - -import android.os.Bundle -import android.util.Patterns -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.os.bundleOf -import androidx.core.widget.doOnTextChanged -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.PreferencesRepository -import io.github.wulkanowy.databinding.DialogLoginSupportBinding -import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException -import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.serializable -import javax.inject.Inject - -@AndroidEntryPoint -class LoginSupportDialog : BaseDialogFragment() { - - @Inject - lateinit var appInfo: AppInfo - - @Inject - lateinit var preferencesRepository: PreferencesRepository - - private lateinit var supportInfo: LoginSupportInfo - - companion object { - private const val ARGUMENT_KEY = "info" - - fun newInstance(info: LoginSupportInfo) = LoginSupportDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to info) - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_FRAME, R.style.WulkanowyTheme_NoActionBar) - supportInfo = requireArguments().serializable(ARGUMENT_KEY) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val binding = DialogLoginSupportBinding.inflate(inflater) - .apply { binding = this } - binding.dialogLoginSupportToolbar.setNavigationOnClickListener { dismiss() } - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - with(binding) { - dialogLoginSupportSchoolInput.doOnTextChanged { _, _, _, _ -> - with(dialogLoginSupportSchoolLayout) { - isErrorEnabled = false - error = null - } - } - dialogLoginSupportSubmit.setOnClickListener { onSubmitClick() } - } - } - - private fun onSubmitClick() { - when { - binding.dialogLoginSupportSchoolInput.text.isNullOrBlank() -> { - with(binding.dialogLoginSupportSchoolLayout) { - isErrorEnabled = true - error = getString(R.string.error_field_required) - } - } - - Patterns.EMAIL_ADDRESS.matcher( - binding.dialogLoginSupportSchoolInput.text.toString() - ).matches() -> { - with(binding.dialogLoginSupportSchoolLayout) { - isErrorEnabled = true - error = getString(R.string.login_support_school_invalid) - } - } - - else -> { - openEmailClientWithFilledTemplate() - dismiss() - } - } - } - - private fun openEmailClientWithFilledTemplate() { - with(binding) { - context?.openEmailClient( - chooserTitle = requireContext().getString(R.string.login_email_intent_title), - email = "wulkanowyinc@gmail.com", - subject = requireContext().getString(R.string.login_email_subject), - body = requireContext().getString( - R.string.login_email_text, - "${appInfo.systemManufacturer} ${appInfo.systemModel}", - appInfo.systemVersion.toString(), - "${appInfo.versionName}-${appInfo.buildFlavor}", - supportInfo.loginData.let { "${it.baseUrl}/${it.defaultSymbol}/${it.userEnteredSymbol}" }, - preferencesRepository.installationId, - getLastErrorFromStudentSelectScreen(), - dialogLoginSupportSchoolInput.text.takeIf { !it.isNullOrBlank() } - ?: return@with, - dialogLoginSupportAdditionalInput.text, - ) - ) - } - } - - private fun getLastErrorFromStudentSelectScreen(): String { - if (!supportInfo.lastErrorMessage.isNullOrBlank()) { - return supportInfo.lastErrorMessage!! - } - if (supportInfo.registerUser?.symbols.isNullOrEmpty()) { - return "" - } - - return "\n" + supportInfo.registerUser?.symbols?.filterNot { - (it.error is AccountPermissionException || it.error is InvalidSymbolException) && - it.symbol != supportInfo.enteredSymbol - }?.joinToString(";\n") { symbol -> - buildString { - append(" -") - append(symbol.symbol) - append("(${symbol.error?.message?.let { it.take(46) + "..." } ?: symbol.schools.size})") - if (symbol.schools.isNotEmpty()) { - append(": ") - } - append(symbol.schools.joinToString(", ") { unit -> - buildString { - append(unit.schoolShortName) - append("(${unit.error?.message?.let { it.take(46) + "..." } ?: unit.students.size})") - } - }) - } - } + "\nPozostałe: " + supportInfo.registerUser?.symbols?.filter { - it.error is AccountPermissionException || it.error is InvalidSymbolException - }?.joinToString(", ") { it.symbol } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportInfo.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportInfo.kt deleted file mode 100644 index 3f101dd63..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/support/LoginSupportInfo.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.support - -import io.github.wulkanowy.data.pojos.RegisterUser -import io.github.wulkanowy.ui.modules.login.LoginData -import java.io.Serializable - -data class LoginSupportInfo( - val loginData: LoginData, - val registerUser: RegisterUser?, - val lastErrorMessage: String?, - val enteredSymbol: String?, -) : Serializable diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt index 23ebffe9d..36c40d156 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt @@ -12,18 +12,16 @@ import androidx.core.text.parseAsHtml import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportDialog -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.hideSoftInput +import io.github.wulkanowy.utils.openEmailClient import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.showSoftInput import javax.inject.Inject @@ -48,8 +46,6 @@ class LoginSymbolFragment : } } - override val symbolValue: String? get() = binding.loginSymbolName.text?.toString() - override val symbolNameError: CharSequence? get() = binding.loginSymbolNameLayout.error @@ -58,7 +54,7 @@ class LoginSymbolFragment : binding = FragmentLoginSymbolBinding.bind(view) presenter.onAttachView( view = this, - loginData = requireArguments().serializable(SAVED_LOGIN_DATA), + loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData, ) } @@ -66,7 +62,7 @@ class LoginSymbolFragment : (requireActivity() as LoginActivity).showActionBar(true) with(binding) { - loginSymbolSignIn.setOnClickListener { presenter.attemptLogin() } + loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) } loginSymbolFaq.setOnClickListener { presenter.onFaqClick() } loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() } @@ -99,28 +95,10 @@ class LoginSymbolFragment : } } - override fun setErrorSymbolInvalid() { - with(binding.loginSymbolNameLayout) { - requestFocus() - error = getString(R.string.login_invalid_symbol) - } - } - - override fun setErrorSymbolDefinitelyInvalid() { - with(binding.loginSymbolNameLayout) { - requestFocus() - error = getString(R.string.login_invalid_symbol_definitely) - } - } - override fun setErrorSymbolRequire() { - setErrorSymbol(getString(R.string.error_field_required)) - } - - override fun setErrorSymbol(message: String) { - with(binding.loginSymbolNameLayout) { + binding.loginSymbolNameLayout.apply { requestFocus() - error = message + error = getString(R.string.error_field_required) } } @@ -151,8 +129,8 @@ class LoginSymbolFragment : binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE } - override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) { - (activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser) + override fun navigateToStudentSelect(studentsWithSemesters: List) { + (activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters) } override fun onSaveInstanceState(outState: Bundle) { @@ -176,7 +154,20 @@ class LoginSymbolFragment : ) } - override fun openSupportDialog(supportInfo: LoginSupportInfo) { - LoginSupportDialog.newInstance(supportInfo).show(childFragmentManager, "support_dialog") + override fun openEmail(host: String, lastError: String) { + context?.openEmailClient( + chooserTitle = requireContext().getString(R.string.login_email_intent_title), + email = "wulkanowyinc@gmail.com", + subject = requireContext().getString(R.string.login_email_subject), + body = requireContext().getString( + R.string.login_email_text, + "${appInfo.systemManufacturer} ${appInfo.systemModel}", + appInfo.systemVersion.toString(), + "${appInfo.versionName}-${appInfo.buildFlavor}", + "$host/${binding.loginSymbolName.text}", + preferencesRepository.installationId, + lastError + ) + ) } } 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 5c31f14d4..691cd4481 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,17 +1,12 @@ package io.github.wulkanowy.ui.modules.login.symbol import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.dataOrNull import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.pojos.RegisterUser import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.resourceFlow -import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol -import io.github.wulkanowy.sdk.scrapper.login.InvalidSymbolException import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginData import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.ifNullOrBlank import kotlinx.coroutines.flow.onEach @@ -28,14 +23,9 @@ class LoginSymbolPresenter @Inject constructor( lateinit var loginData: LoginData - private var registerUser: RegisterUser? = null - fun onAttachView(view: LoginSymbolView, loginData: LoginData) { super.onAttachView(view) this.loginData = loginData - loginErrorHandler.onBadCredentials = { - view.setErrorSymbol(it.orEmpty()) - } with(view) { initView() showContact(false) @@ -49,39 +39,29 @@ class LoginSymbolPresenter @Inject constructor( view?.apply { if (symbolNameError != null) clearSymbolError() } } - fun attemptLogin() { - if (view?.symbolValue.isNullOrBlank()) { + fun attemptLogin(symbol: String) { + if (symbol.isBlank()) { view?.setErrorSymbolRequire() return } - if (isFormDefinitelyInvalid()) { - view?.setErrorSymbolDefinitelyInvalid() - return - } - loginData = loginData.copy( - userEnteredSymbol = view?.symbolValue?.getNormalizedSymbol(), - ) resourceFlow { - studentRepository.getUserSubjectsFromScrapper( + studentRepository.getStudentsScrapper( email = loginData.login, password = loginData.password, scrapperBaseUrl = loginData.baseUrl, - domainSuffix = loginData.domainSuffix, - symbol = loginData.userEnteredSymbol.orEmpty(), + symbol = symbol, ) - }.onEach { user -> - registerUser = user.dataOrNull - when (user) { + }.onEach { + when (it) { is Resource.Loading -> view?.run { Timber.i("Login with symbol started") hideSoftKeyboard() showProgress(true) showContent(false) } - is Resource.Success -> { - when (user.data.symbols.size) { + when (it.data.size) { 0 -> { Timber.i("Login with symbol result: Empty student list") view?.run { @@ -89,29 +69,20 @@ class LoginSymbolPresenter @Inject constructor( showContact(true) } } - else -> { - val enteredSymbolDetails = user.data.symbols - .firstOrNull() - ?.takeIf { it.symbol == loginData.userEnteredSymbol } - - if (enteredSymbolDetails?.error is InvalidSymbolException) { - showInvalidSymbolError() - } else { - Timber.i("Login with symbol result: Success") - view?.navigateToStudentSelect(loginData, requireNotNull(user.data)) - } + Timber.i("Login with symbol result: Success") + view?.navigateToStudentSelect(requireNotNull(it.data)) } } analytics.logEvent( "registration_symbol", "success" to true, + "students" to it.data.size, "scrapperBaseUrl" to loginData.baseUrl, - "symbol" to view?.symbolValue, + "symbol" to symbol, "error" to "No error" ) } - is Resource.Error -> { Timber.i("Login with symbol result: An exception occurred") analytics.logEvent( @@ -119,15 +90,12 @@ class LoginSymbolPresenter @Inject constructor( "success" to false, "students" to -1, "scrapperBaseUrl" to loginData.baseUrl, - "symbol" to view?.symbolValue, - "error" to user.error.message.ifNullOrBlank { "No message" } + "symbol" to symbol, + "error" to it.error.message.ifNullOrBlank { "No message" } ) - loginErrorHandler.dispatch(user.error) - lastError = user.error + loginErrorHandler.dispatch(it.error) + lastError = it.error view?.showContact(true) - if (user.error is InvalidSymbolException) { - showInvalidSymbolError() - } } } }.onResourceNotLoading { @@ -138,32 +106,11 @@ class LoginSymbolPresenter @Inject constructor( }.launch("login") } - private fun isFormDefinitelyInvalid(): Boolean { - val definitelyInvalidSymbols = listOf("vulcan", "uonet", "wulkanowy", "standardowa") - val normalizedSymbol = view?.symbolValue.orEmpty().getNormalizedSymbol() - - return normalizedSymbol in definitelyInvalidSymbols - } - - private fun showInvalidSymbolError() { - view?.run { - setErrorSymbolInvalid() - showContact(true) - } - } - fun onFaqClick() { view?.openFaqPage() } fun onEmailClick() { - view?.openSupportDialog( - LoginSupportInfo( - loginData = loginData, - registerUser = registerUser, - lastErrorMessage = lastError?.message, - enteredSymbol = view?.symbolValue, - ) - ) + view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank { "empty" }) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt index ace12f780..527895b77 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt @@ -1,14 +1,10 @@ package io.github.wulkanowy.ui.modules.login.symbol -import io.github.wulkanowy.data.pojos.RegisterUser +import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView -import io.github.wulkanowy.ui.modules.login.LoginData -import io.github.wulkanowy.ui.modules.login.support.LoginSupportInfo interface LoginSymbolView : BaseView { - val symbolValue: String? - val symbolNameError: CharSequence? fun initView() @@ -17,14 +13,8 @@ interface LoginSymbolView : BaseView { fun setErrorSymbolIncorrect() - fun setErrorSymbolInvalid() - - fun setErrorSymbolDefinitelyInvalid() - fun setErrorSymbolRequire() - fun setErrorSymbol(message: String) - fun clearSymbolError() fun clearAndFocusSymbol() @@ -37,11 +27,11 @@ interface LoginSymbolView : BaseView { fun showContent(show: Boolean) - fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) + fun navigateToStudentSelect(studentsWithSemesters: List) fun showContact(show: Boolean) fun openFaqPage() - fun openSupportDialog(supportInfo: LoginSupportInfo) + fun openEmail(host: String, lastError: String) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt index a6c75c1d9..0a73fe15d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt @@ -18,7 +18,7 @@ import javax.inject.Inject @AndroidEntryPoint class LuckyNumberFragment : BaseFragment(R.layout.fragment_lucky_number), LuckyNumberView, - MainView.TitledView, MainView.MainChildView { + MainView.TitledView { @Inject lateinit var presenter: LuckyNumberPresenter @@ -86,14 +86,6 @@ class LuckyNumberFragment : (activity as? MainActivity)?.pushView(LuckyNumberHistoryFragment.newInstance()) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun popView() { - (activity as? MainActivity)?.popView() - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() 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 2039624b1..6f5c8e740 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 @@ -99,9 +99,4 @@ class LuckyNumberPresenter @Inject constructor( fun onDetailsClick() { view?.showErrorDetailsDialog(lastError) } - - fun onViewReselected() { - Timber.i("Luckynumber view is reselected") - view?.popView() - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt index 3d34ebc8f..0c05a1566 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt @@ -26,6 +26,4 @@ interface LuckyNumberView : BaseView { fun showContent(show: Boolean) fun openLuckyNumberHistory() - - fun popView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt index a78ce5dd2..53f06cacd 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt @@ -61,7 +61,7 @@ class LuckyNumberHistoryFragment : luckyNumberHistoryPreviousButton.setOnClickListener { presenter.onPreviousWeek() } luckyNumberHistoryNextButton.setOnClickListener { presenter.onNextWeek() } - luckyNumberHistoryNavContainer.elevation = requireContext().dpToPx(3f) + luckyNumberHistoryNavContainer.elevation = requireContext().dpToPx(8f) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt index a2d23e543..024beff85 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt @@ -1,12 +1,16 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget -import android.appwidget.AppWidgetManager.* +import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE +import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID +import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS import android.content.Intent +import android.os.Build import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity @@ -37,6 +41,7 @@ class LuckyNumberWidgetConfigureActivity : setContentView( ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root ) + intent.extras.let { presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID)) } @@ -51,6 +56,22 @@ class LuckyNumberWidgetConfigureActivity : configureAdapter.onClickListener = presenter::onItemSelect } + override fun showThemeDialog() { + var items = arrayOf( + getString(R.string.widget_timetable_theme_light), + getString(R.string.widget_timetable_theme_dark) + ) + if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += (getString(R.string.widget_timetable_theme_system)) + + dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher) + .setTitle(R.string.widget_timetable_theme_title) + .setOnDismissListener { presenter.onDismissThemeView() } + .setSingleChoiceItems(items, -1) { _, which -> + presenter.onThemeSelect(which) + } + .show() + } + override fun updateData(data: List, selectedStudentId: Long) { with(configureAdapter) { selectedId = selectedStudentId 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 7e53dad06..cac648da8 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 @@ -8,6 +8,7 @@ import io.github.wulkanowy.data.resourceFlow import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey +import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey import kotlinx.coroutines.flow.onEach import timber.log.Timber import javax.inject.Inject @@ -31,9 +32,20 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor( fun onItemSelect(student: Student) { selectedStudent = student + view?.showThemeDialog() + } + + fun onThemeSelect(index: Int) { + appWidgetId?.let { + sharedPref.putLong(getThemeWidgetKey(it), index.toLong()) + } registerStudent(selectedStudent) } + fun onDismissThemeView() { + view?.finishView() + } + private fun loadData() { resourceFlow { studentRepository.getSavedStudents(false) }.onEach { when (it) { @@ -44,7 +56,10 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor( } ?: -1 when { it.data.isEmpty() -> view?.openLoginView() - it.data.size == 1 -> onItemSelect(it.data.single().student) + it.data.size == 1 -> { + selectedStudent = it.data.single().student + view?.showThemeDialog() + } else -> view?.updateData(it.data, selectedStudentId) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt index df13b993d..b4556f7ef 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt @@ -7,6 +7,8 @@ interface LuckyNumberWidgetConfigureView : BaseView { fun initView() + fun showThemeDialog() + fun updateData(data: List, selectedStudentId: Long) fun updateLuckyNumberWidget(widgetId: Int) 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 1ab079a3a..e03e3e90e 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 @@ -2,17 +2,22 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget import android.app.PendingIntent import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT +import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH import android.appwidget.AppWidgetProvider import android.content.Context import android.content.res.Configuration import android.os.Bundle -import android.util.TypedValue.COMPLEX_UNIT_SP -import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE import android.widget.RemoteViews import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.dataOrThrow +import io.github.wulkanowy.data.Resource +import io.github.wulkanowy.data.dataOrNull import io.github.wulkanowy.data.db.SharedPrefProvider +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.data.repositories.LuckyNumberRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.toFirstResult @@ -36,12 +41,16 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() { lateinit var sharedPref: SharedPrefProvider companion object { - private const val LUCKY_NUMBER_WIDGET_MAX_SIZE = 196 - private const val LUCKY_NUMBER_PENDING_INTENT_ID = 300 - private const val LUCKY_NUMBER_HISTORY_PENDING_INTENT_ID = 301 + const val LUCKY_NUMBER_PENDING_INTENT_ID = 200 fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId" + + fun getThemeWidgetKey(appWidgetId: Int) = "lucky_number_widget_theme_$appWidgetId" + + fun getHeightWidgetKey(appWidgetId: Int) = "lucky_number_widget_height_$appWidgetId" + + fun getWidthWidgetKey(appWidgetId: Int) = "lucky_number_widget_width_$appWidgetId" } override fun onUpdate( @@ -50,85 +59,107 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() { appWidgetIds: IntArray? ) { super.onUpdate(context, appWidgetManager, appWidgetIds) + appWidgetIds?.forEach { appWidgetId -> + val luckyNumber = + getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) + val appIntent = PendingIntent.getActivity( + context, + LUCKY_NUMBER_PENDING_INTENT_ID, + SplashActivity.getStartIntent(context, Destination.LuckyNumber), + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE + ) - val appIntent = PendingIntent.getActivity( - context, - LUCKY_NUMBER_PENDING_INTENT_ID, - SplashActivity.getStartIntent(context, Destination.LuckyNumber), - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE - ) + if (luckyNumber is Resource.Error) { + Timber.e("Error loading lucky number for widget", luckyNumber.error) + } - val historyIntent = PendingIntent.getActivity( - context, - LUCKY_NUMBER_HISTORY_PENDING_INTENT_ID, - SplashActivity.getStartIntent(context, Destination.LuckyNumberHistory), - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE - ) + val remoteView = + RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context)) + .apply { + setTextViewText( + R.id.luckyNumberWidgetNumber, + luckyNumber.dataOrNull?.luckyNumber?.toString() ?: "#" + ) + setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent) + } - appWidgetIds?.forEach { widgetId -> - val studentId = sharedPref.getLong(getStudentWidgetKey(widgetId), 0) - val luckyNumber = getLuckyNumber(studentId, widgetId)?.luckyNumber?.toString() - val remoteView = RemoteViews(context.packageName, R.layout.widget_luckynumber) - .apply { - setTextViewText(R.id.luckyNumberWidgetValue, luckyNumber ?: "-") - setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent) - setOnClickPendingIntent(R.id.luckyNumberWidgetHistoryButton, historyIntent) - } - - resizeWidget(context, appWidgetManager.getAppWidgetOptions(widgetId), remoteView) - appWidgetManager.updateAppWidget(widgetId, remoteView) - } - } - - override fun onAppWidgetOptionsChanged( - context: Context?, - appWidgetManager: AppWidgetManager?, - appWidgetId: Int, - newOptions: Bundle? - ) { - super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions) - - if (context == null || newOptions == null || appWidgetManager == null) { - return - } - - val remoteView = RemoteViews(context.packageName, R.layout.widget_luckynumber) - resizeWidget(context, newOptions, remoteView) - appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteView) - } - - private fun resizeWidget(context: Context, options: Bundle, remoteViews: RemoteViews) { - val (width, height) = options.getWidgetSize(context) - val size = minOf(width, height, LUCKY_NUMBER_WIDGET_MAX_SIZE).toFloat() - resizeWidgetContents(size, remoteViews) - Timber.v("LuckyNumberWidget resized: ${width}x${height} ($size)") - } - - private fun resizeWidgetContents(size: Float, remoteViews: RemoteViews) { - var historyButtonVisibility = View.VISIBLE - var luckyNumberTextSize = 72f - - if (size < 150) { - luckyNumberTextSize = 44f - historyButtonVisibility = View.GONE - } - if (size < 75) { - luckyNumberTextSize = 26f - } - - remoteViews.apply { - setTextViewTextSize(R.id.luckyNumberWidgetValue, COMPLEX_UNIT_SP, luckyNumberTextSize) - setViewVisibility(R.id.luckyNumberWidgetHistoryButton, historyButtonVisibility) + setStyles(remoteView, appWidgetId) + appWidgetManager.updateAppWidget(appWidgetId, remoteView) } } override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { super.onDeleted(context, appWidgetIds) appWidgetIds?.forEach { appWidgetId -> - sharedPref.delete(getStudentWidgetKey(appWidgetId)) + with(sharedPref) { + delete(getHeightWidgetKey(appWidgetId)) + delete(getStudentWidgetKey(appWidgetId)) + delete(getThemeWidgetKey(appWidgetId)) + delete(getWidthWidgetKey(appWidgetId)) + } } } + override fun onAppWidgetOptionsChanged( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetId: Int, + newOptions: Bundle? + ) { + super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions) + + val remoteView = RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context)) + + setStyles(remoteView, appWidgetId, newOptions) + appWidgetManager.updateAppWidget(appWidgetId, remoteView) + } + + private fun setStyles(views: RemoteViews, appWidgetId: Int, options: Bundle? = null) { + val width = options?.getInt(OPTION_APPWIDGET_MIN_WIDTH) ?: sharedPref.getLong( + getWidthWidgetKey(appWidgetId), 74 + ).toInt() + val height = options?.getInt(OPTION_APPWIDGET_MAX_HEIGHT) ?: sharedPref.getLong( + getHeightWidgetKey(appWidgetId), 74 + ).toInt() + + with(sharedPref) { + putLong(getWidthWidgetKey(appWidgetId), width.toLong()) + putLong(getHeightWidgetKey(appWidgetId), height.toLong()) + } + + val rows = getCellsForSize(height) + val cols = getCellsForSize(width) + + Timber.d("New lucky number widget measurement: %dx%d", width, height) + Timber.d("Widget size: $cols x $rows") + + when { + 1 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = false) + 1 == cols && 1 < rows -> views.setVisibility(imageTop = true, imageLeft = false) + 1 < cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true) + 1 == cols && 1 == rows -> views.setVisibility(imageTop = true, imageLeft = false) + 2 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true) + else -> views.setVisibility(imageTop = false, imageLeft = false, title = true) + } + } + + private fun RemoteViews.setVisibility( + imageTop: Boolean, + imageLeft: Boolean, + title: Boolean = false + ) { + setViewVisibility(R.id.luckyNumberWidgetImageTop, if (imageTop) VISIBLE else GONE) + setViewVisibility(R.id.luckyNumberWidgetImageLeft, if (imageLeft) VISIBLE else GONE) + setViewVisibility(R.id.luckyNumberWidgetTitle, if (title) VISIBLE else GONE) + setViewVisibility(R.id.luckyNumberWidgetNumber, VISIBLE) + } + + private fun getCellsForSize(size: Int): Int { + var n = 2 + while (74 * n - 30 < size) ++n + return n - 1 + } + private fun getLuckyNumber(studentId: Long, appWidgetId: Int) = runBlocking { try { val students = studentRepository.getSavedStudents() @@ -140,34 +171,32 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } } - else -> null } if (currentStudent != null) { luckyNumberRepository.getLuckyNumber(currentStudent, forceRefresh = false) .toFirstResult() - .dataOrThrow - } else null + } else { + Resource.Success(null) + } } catch (e: Exception) { - Timber.e(e, "An error has occurred in lucky number provider") - null + if (e.cause !is NoCurrentStudentException) { + Timber.e(e, "An error has occurred in lucky number provider") + } + Resource.Error(e) } } - private fun Bundle.getWidgetSize(context: Context): Pair { - val minWidth = getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) - val maxWidth = getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) - val minHeight = getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) - val maxHeight = getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT) + private fun getCorrectLayoutId(appWidgetId: Int, context: Context): Int { + val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0) + val isSystemDarkMode = + context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES - val orientation = context.resources.configuration.orientation - val isPortrait = orientation == Configuration.ORIENTATION_PORTRAIT - - return if (isPortrait) { - minWidth to maxHeight + return if (savedTheme == 1L || (savedTheme == 2L && isSystemDarkMode)) { + R.layout.widget_luckynumber_dark } else { - maxWidth to minHeight + R.layout.widget_luckynumber } } } 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 62c16257e..5cd6fa103 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 @@ -2,21 +2,14 @@ package io.github.wulkanowy.ui.modules.main import android.content.Context import android.content.Intent -import android.os.Build +import android.os.Build.VERSION_CODES.P import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.ViewGroup.MarginLayoutParams -import androidx.activity.OnBackPressedCallback -import androidx.activity.addCallback import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible -import androidx.core.view.updateLayoutParams import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment -import androidx.lifecycle.lifecycleScope import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -28,32 +21,15 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityMainBinding +import io.github.wulkanowy.databinding.DialogAdsConsentBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.Destination import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog -import io.github.wulkanowy.ui.modules.auth.AuthDialog -import io.github.wulkanowy.ui.modules.captcha.CaptchaDialog -import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem -import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.InAppReviewHelper -import io.github.wulkanowy.utils.InAppUpdateHelper -import io.github.wulkanowy.utils.createNameInitialsDrawable -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.nickOrName -import io.github.wulkanowy.utils.safelyPopFragments -import io.github.wulkanowy.utils.setOnViewChangeListener -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch +import io.github.wulkanowy.utils.* import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import timber.log.Timber import javax.inject.Inject -import kotlin.time.Duration.Companion.seconds @AndroidEntryPoint class MainActivity : BaseActivity(), MainView, @@ -66,7 +42,7 @@ class MainActivity : BaseActivity(), MainVie lateinit var analytics: AnalyticsHelper @Inject - lateinit var inAppUpdateHelper: InAppUpdateHelper + lateinit var updateHelper: UpdateHelper @Inject lateinit var inAppReviewHelper: InAppReviewHelper @@ -74,8 +50,6 @@ class MainActivity : BaseActivity(), MainVie @Inject lateinit var appInfo: AppInfo - private var onBackCallback: OnBackPressedCallback? = null - private var accountMenu: MenuItem? = null private val overlayProvider by lazy { ElevationOverlayProvider(this) } @@ -83,8 +57,6 @@ class MainActivity : BaseActivity(), MainVie private val navController = FragNavController(supportFragmentManager, R.id.main_fragment_container) - private val captchaVerificationEvent = MutableSharedFlow() - companion object { private const val EXTRA_START_DESTINATION = "start_destination_json" @@ -113,31 +85,28 @@ class MainActivity : BaseActivity(), MainVie super.onCreate(savedInstanceState) setContentView(ActivityMainBinding.inflate(layoutInflater).apply { binding = this }.root) setSupportActionBar(binding.mainToolbar) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - WindowCompat.setDecorFitsSystemWindows(window, false) - binding.mainAppBar.isLifted = true - } - initializeFragmentContainer() - this.savedInstanceState = savedInstanceState messageContainer = binding.mainMessageContainer - messageAnchor = binding.mainMessageContainer - inAppUpdateHelper.messageContainer = binding.mainFragmentContainer - onBackCallback = onBackPressedDispatcher.addCallback(this, enabled = false) { - presenter.onBackPressed() - } + updateHelper.messageContainer = binding.mainFragmentContainer val destination = intent.getStringExtra(EXTRA_START_DESTINATION) ?.takeIf { savedInstanceState == null } presenter.onAttachView(this, destination) - inAppUpdateHelper.checkAndInstallUpdates() + updateHelper.checkAndInstallUpdates(this) } override fun onResume() { super.onResume() - inAppUpdateHelper.onResume() + updateHelper.onResume(this) + } + + //https://developer.android.com/guide/playcore/in-app-updates#status_callback + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + updateHelper.onActivityResult(requestCode, resultCode) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -148,21 +117,13 @@ class MainActivity : BaseActivity(), MainVie return true } - override fun initView( - startMenuIndex: Int, - rootAppMenuItems: List, - rootUpdatedDestinations: List - ) { + override fun initView(startMenuIndex: Int, rootDestinations: List) { initializeToolbar() - initializeBottomNavigation(startMenuIndex, rootAppMenuItems) - initializeNavController(startMenuIndex, rootUpdatedDestinations) - initializeCaptchaVerificationEvent() + initializeBottomNavigation(startMenuIndex) + initializeNavController(startMenuIndex, rootDestinations) } - private fun initializeNavController( - startMenuIndex: Int, - rootUpdatedDestinations: List - ) { + private fun initializeNavController(startMenuIndex: Int, rootDestinations: List) { with(navController) { setOnViewChangeListener { destinationView -> presenter.onViewChange(destinationView) @@ -172,7 +133,7 @@ class MainActivity : BaseActivity(), MainVie ) } fragmentHideStrategy = HIDE - rootFragments = rootUpdatedDestinations.map { it.destinationFragment } + rootFragments = rootDestinations.map { it.destinationFragment } initialize(startMenuIndex, savedInstanceState) } @@ -188,16 +149,17 @@ class MainActivity : BaseActivity(), MainVie } } - private fun initializeBottomNavigation( - startMenuIndex: Int, - rootAppMenuItems: List - ) { + private fun initializeBottomNavigation(startMenuIndex: Int) { with(binding.mainBottomNav) { with(menu) { - rootAppMenuItems.forEachIndexed { index, item -> - add(Menu.NONE, index, Menu.NONE, item.title) - .setIcon(item.icon) - } + add(Menu.NONE, 0, Menu.NONE, R.string.dashboard_title) + .setIcon(R.drawable.ic_main_dashboard) + add(Menu.NONE, 1, Menu.NONE, R.string.grade_title) + .setIcon(R.drawable.ic_main_grade) + add(Menu.NONE, 2, Menu.NONE, R.string.attendance_title) + .setIcon(R.drawable.ic_main_attendance) + add(Menu.NONE, 3, Menu.NONE, R.string.timetable_title) + .setIcon(R.drawable.ic_main_timetable) add(Menu.NONE, 4, Menu.NONE, R.string.more_title) .setIcon(R.drawable.ic_main_more) } @@ -211,17 +173,6 @@ class MainActivity : BaseActivity(), MainVie } } - private fun initializeFragmentContainer() { - ViewCompat.setOnApplyWindowInsetsListener(binding.mainFragmentContainer) { view, insets -> - val bottomInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars()) - - view.updateLayoutParams { - bottomMargin = if (binding.mainBottomNav.isVisible) 0 else bottomInsets.bottom - } - WindowInsetsCompat.CONSUMED - } - } - override fun onPreferenceStartFragment( caller: PreferenceFragmentCompat, pref: Preference @@ -266,9 +217,20 @@ class MainActivity : BaseActivity(), MainVie showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters)) } + override fun showActionBarElevation(show: Boolean) { + ViewCompat.setElevation(binding.mainToolbar, if (show) dpToPx(4f) else 0f) + } + override fun showBottomNavigation(show: Boolean) { binding.mainBottomNav.isVisible = show - binding.mainFragmentContainer.requestApplyInsets() + + if (appInfo.systemVersion >= P) { + window.navigationBarColor = if (show) { + getThemeAttrColor(android.R.attr.navigationBarColor) + } else { + getThemeAttrColor(R.attr.colorSurface) + } + } } override fun openMoreDestination(destination: Destination) { @@ -304,7 +266,6 @@ class MainActivity : BaseActivity(), MainVie analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.pushFragment(fragment) - onBackCallback?.isEnabled = !isRootView } override fun popView(depth: Int) { @@ -312,7 +273,10 @@ class MainActivity : BaseActivity(), MainVie analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.safelyPopFragments(depth) - onBackCallback?.isEnabled = !isRootView + } + + override fun onBackPressed() { + presenter.onBackPressed { super.onBackPressed() } } override fun showStudentAvatar(student: Student) { @@ -336,25 +300,38 @@ class MainActivity : BaseActivity(), MainVie .show() } - @OptIn(FlowPreview::class) - private fun initializeCaptchaVerificationEvent() { - captchaVerificationEvent - .debounce(1.seconds) - .onEach { url -> - Timber.d("Showing captcha dialog for: $url") - showDialogFragment(CaptchaDialog.newInstance(url)) - } - .launchIn(lifecycleScope) - } + override fun showPrivacyPolicyDialog() { + val dialogAdsConsentBinding = DialogAdsConsentBinding.inflate(layoutInflater) - override fun onCaptchaVerificationRequired(url: String?) { - lifecycleScope.launch { - captchaVerificationEvent.emit(url) + val dialog = MaterialAlertDialogBuilder(this) + .setTitle(R.string.pref_ads_consent_title) + .setMessage(R.string.pref_ads_consent_description) + .setView(dialogAdsConsentBinding.root) + .show() + + dialogAdsConsentBinding.adsConsentOver.setOnCheckedChangeListener { _, isChecked -> + dialogAdsConsentBinding.adsConsentPersonalised.isEnabled = isChecked } + + dialogAdsConsentBinding.adsConsentPersonalised.setOnClickListener { + presenter.onPrivacyAgree(true) + dialog.dismiss() + } + + dialogAdsConsentBinding.adsConsentNonPersonalised.setOnClickListener { + presenter.onPrivacyAgree(false) + dialog.dismiss() + } + + dialogAdsConsentBinding.adsConsentPrivacy.setOnClickListener { presenter.onPrivacySelected() } + dialogAdsConsentBinding.adsConsentCancel.setOnClickListener { dialog.cancel() } } - override fun showAuthDialog() { - showDialogFragment(AuthDialog.newInstance()) + override fun openPrivacyPolicy() { + openInternetBrowser( + "https://wulkanowy.github.io/polityka-prywatnosci.html", + ::showMessage + ) } override fun onSaveInstanceState(outState: Bundle) { 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 a544381ce..9c32d8583 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 @@ -14,11 +14,15 @@ import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.Destination import io.github.wulkanowy.ui.modules.account.AccountView import io.github.wulkanowy.ui.modules.account.accountdetails.AccountDetailsView +import io.github.wulkanowy.ui.modules.grade.GradeView +import io.github.wulkanowy.ui.modules.message.MessageView +import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersView import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView import io.github.wulkanowy.utils.AdsHelper import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.AppInfo import kotlinx.coroutines.launch +import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import timber.log.Timber import java.time.Duration @@ -38,20 +42,20 @@ class MainPresenter @Inject constructor( private var studentsWitSemesters: List? = null - private val rootAppMenuItems = preferencesRepository.appMenuItemOrder - .sortedBy { it.order } - .take(4) - - private val rootDestinationTypeList = rootAppMenuItems.map { it.destinationType } - .plus(Destination.Type.MORE) + private val rootDestinationTypeList = listOf( + Destination.Type.DASHBOARD, + Destination.Type.GRADE, + Destination.Type.ATTENDANCE, + Destination.Type.TIMETABLE, + Destination.Type.MORE + ) private val Destination?.startMenuIndex get() = when { - this == null -> 0 + this == null -> preferencesRepository.startMenuIndex destinationType in rootDestinationTypeList -> { rootDestinationTypeList.indexOf(destinationType) } - else -> 4 } @@ -65,7 +69,7 @@ class MainPresenter @Inject constructor( if (it == initDestination?.destinationType) initDestination else it.defaultDestination } - view.initView(startMenuIndex, rootAppMenuItems, destinations) + view.initView(startMenuIndex, destinations) if (initDestination != null && startMenuIndex == 4) { view.openMoreDestination(initDestination) } @@ -73,7 +77,6 @@ class MainPresenter @Inject constructor( syncManager.startPeriodicSyncWorker() checkAppSupport() - updateCurrentStudentAuthStatus() analytics.logEvent("app_open", "destination" to initDestination.toString()) Timber.i("Main view was initialized with $initDestination") @@ -98,6 +101,7 @@ class MainPresenter @Inject constructor( fun onViewChange(destinationView: BaseView) { view?.apply { showBottomNavigation(shouldShowBottomNavigation(destinationView)) + showActionBarElevation(shouldShowActionBarElevation(destinationView)) currentViewTitle?.let { setViewTitle(it) } currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) } currentStackSize?.let { @@ -107,11 +111,17 @@ class MainPresenter @Inject constructor( } } + private fun shouldShowActionBarElevation(destination: BaseView) = when (destination) { + is GradeView, + is MessageView, + is SchoolAndTeachersView -> false + else -> true + } + private fun shouldShowBottomNavigation(destination: BaseView) = when (destination) { is AccountView, is StudentInfoView, is AccountDetailsView -> false - else -> true } @@ -129,9 +139,12 @@ class MainPresenter @Inject constructor( return true } - fun onBackPressed() { + fun onBackPressed(default: () -> Unit) { Timber.i("Back pressed in main view") - view?.popView() + view?.run { + if (isRootView) default() + else popView() + } } fun onTabSelected(index: Int, wasSelected: Boolean): Boolean { @@ -150,8 +163,20 @@ class MainPresenter @Inject constructor( } fun onEnableAdsSelected() { - preferencesRepository.isAdsEnabled = true + view?.showPrivacyPolicyDialog() + } + + fun onPrivacyAgree(isPersonalizedAds: Boolean) { + preferencesRepository.isAgreeToProcessData = true + preferencesRepository.isPersonalizedAdsEnabled = isPersonalizedAds + adsHelper.initialize() + + preferencesRepository.isAdsEnabled = true + } + + fun onPrivacySelected() { + view?.openPrivacyPolicy() } private fun checkInAppReview() { @@ -179,8 +204,8 @@ class MainPresenter @Inject constructor( .getOrElse { return@launch } if (Instant.now().minus(Duration.ofDays(28)).isAfter(student.registrationDate)) { - preferencesRepository.isAppSupportShown = true view?.showAppSupport() + preferencesRepository.isAppSupportShown = true } } } @@ -192,11 +217,4 @@ class MainPresenter @Inject constructor( view?.showStudentAvatar(currentStudent) } - - private fun updateCurrentStudentAuthStatus() { - presenterScope.launch { - runCatching { studentRepository.updateCurrentStudentAuthStatus() } - .onFailure { errorHandler.dispatch(it) } - } - } } 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 70a94fc81..3d018e3d6 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 @@ -4,7 +4,6 @@ import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.modules.Destination -import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem interface MainView : BaseView { @@ -16,11 +15,7 @@ interface MainView : BaseView { val currentStackSize: Int? - fun initView( - startMenuIndex: Int, - rootAppMenuItems: List, - rootUpdatedDestinations: List - ) + fun initView(startMenuIndex: Int, rootDestinations: List) fun switchMenuView(position: Int) @@ -28,6 +23,8 @@ interface MainView : BaseView { fun showAccountPicker(studentWithSemesters: List) + fun showActionBarElevation(show: Boolean) + fun showBottomNavigation(show: Boolean) fun notifyMenuViewReselected() @@ -46,6 +43,10 @@ interface MainView : BaseView { fun showAppSupport() + fun showPrivacyPolicyDialog() + + fun openPrivacyPolicy() + fun openMoreDestination(destination: Destination) interface MainChildView { 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 02bc13a16..4607793c9 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 @@ -11,13 +11,10 @@ import androidx.core.view.updateMargins import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -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.data.enums.MessageFolder.* import io.github.wulkanowy.databinding.FragmentMessageBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment @@ -27,7 +24,7 @@ import javax.inject.Inject @AndroidEntryPoint class MessageFragment : BaseFragment(R.layout.fragment_message), - MessageView, MainView.TitledView, MainView.MainChildView { + MessageView, MainView.TitledView { @Inject lateinit var presenter: MessagePresenter @@ -51,7 +48,6 @@ class MessageFragment : BaseFragment(R.layout.fragment_m override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentMessageBinding.bind(view) - messageContainer = binding.messageViewPager presenter.onAttachView(this) } @@ -98,10 +94,6 @@ class MessageFragment : BaseFragment(R.layout.fragment_m binding.messageProgress.visibility = if (show) VISIBLE else INVISIBLE } - override fun showMessage(messageId: Int) { - showMessage(getString(messageId)) - } - override fun showNewMessage(show: Boolean) { binding.openSendMessageButton.run { if (show) show() else hide() @@ -131,12 +123,8 @@ class MessageFragment : BaseFragment(R.layout.fragment_m presenter.onChildViewShowNewMessage(show) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onFragmentReselected() - } - - override fun onFragmentChanged() { - if (::presenter.isInitialized) presenter.onFragmentChanged() + fun onFragmentChanged() { + presenter.onFragmentChanged() } override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) { @@ -151,19 +139,10 @@ class MessageFragment : BaseFragment(R.layout.fragment_m } } - override fun notifyChildParentReselected(index: Int) { - (pagerAdapter.getFragmentInstance(index) as? MessageTabFragment) - ?.onParentReselected() - } - override fun openSendMessage() { context?.let { it.startActivity(SendMessageActivity.getStartIntent(it)) } } - override fun popView() { - (activity as? MainActivity)?.popView() - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() 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 37a2d422a..68bdc4b7c 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,7 +1,5 @@ package io.github.wulkanowy.ui.modules.message -import io.github.wulkanowy.R -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 @@ -11,8 +9,7 @@ import javax.inject.Inject class MessagePresenter @Inject constructor( errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val preferencesRepository: PreferencesRepository, + studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { override fun onAttachView(view: MessageView) { @@ -22,14 +19,6 @@ class MessagePresenter @Inject constructor( Timber.i("Message view was initialized") loadData() } - - showIncognitoModeReminderMessage() - } - - private fun showIncognitoModeReminderMessage() { - if (preferencesRepository.isIncognitoMode) { - view?.showMessage(R.string.message_incognito_mode_on) - } } fun onPageSelected(index: Int) { @@ -50,14 +39,6 @@ class MessagePresenter @Inject constructor( view?.notifyChildrenFinishActionMode() } - fun onFragmentReselected() { - Timber.i("Message view is reselected") - view?.run { - popView() - notifyChildParentReselected(currentPageIndex) - } - } - fun onChildViewLoaded() { view?.apply { showContent(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt index 7fdc6e181..e0cc5098c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.message -import androidx.annotation.StringRes import io.github.wulkanowy.ui.base.BaseView interface MessageView : BaseView { @@ -13,8 +12,6 @@ interface MessageView : BaseView { fun showProgress(show: Boolean) - fun showMessage(@StringRes messageId: Int) - fun showNewMessage(show: Boolean) fun showTabLayout(show: Boolean) @@ -23,9 +20,5 @@ interface MessageView : BaseView { fun notifyChildrenFinishActionMode() - fun notifyChildParentReselected(index: Int) - fun openSendMessage() - - fun popView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt index 11d3c6c12..222412ef1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/mailboxchooser/MailboxChooserDialog.kt @@ -1,16 +1,15 @@ package io.github.wulkanowy.ui.modules.message.mailboxchooser -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.core.os.bundleOf import androidx.fragment.app.setFragmentResult -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.Mailbox import io.github.wulkanowy.databinding.DialogMailboxChooserBinding import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.parcelableArray import javax.inject.Inject @AndroidEntryPoint @@ -37,22 +36,24 @@ class MailboxChooserDialog : BaseDialogFragment(), } } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView( - DialogMailboxChooserBinding.inflate(layoutInflater).apply { binding = this }.root - ) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogMailboxChooserBinding.inflate(inflater).apply { binding = this }.root + @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) presenter.onAttachView( view = this, requireMailbox = requireArguments().getBoolean(REQUIRED_KEY, false), - mailboxes = requireArguments().parcelableArray(MAILBOX_KEY).orEmpty().toList(), + mailboxes = requireArguments().getParcelableArray(MAILBOX_KEY).orEmpty() + .toList() as List, ) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt index b83f7e232..d3c6b95c7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt @@ -50,15 +50,12 @@ class MessagePreviewAdapter @Inject constructor() : ViewType.MESSAGE.id -> MessageViewHolder( ItemMessagePreviewBinding.inflate(inflater, parent, false) ) - ViewType.DIVIDER.id -> DividerViewHolder( ItemMessageDividerBinding.inflate(inflater, parent, false) ) - ViewType.ATTACHMENT.id -> AttachmentViewHolder( ItemMessageAttachmentBinding.inflate(inflater, parent, false) ) - else -> throw IllegalStateException() } } @@ -69,7 +66,6 @@ class MessagePreviewAdapter @Inject constructor() : holder, requireNotNull(messageWithAttachment).message ) - is AttachmentViewHolder -> bindAttachment( holder, requireNotNull(messageWithAttachment).attachments[position - 2] @@ -86,11 +82,9 @@ class MessagePreviewAdapter @Inject constructor() : recipientCount > 1 -> { context.getString(R.string.message_read_by, message.readBy, recipientCount) } - message.readBy == 1 || (isReceived && !message.unread) -> { context.getString(R.string.message_read, context.getString(R.string.all_yes)) } - else -> context.getString(R.string.message_read, context.getString(R.string.all_no)) } 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 8e7c72765..2a5523f4d 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 @@ -12,9 +12,7 @@ import android.view.View.VISIBLE import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient -import androidx.annotation.StringRes import androidx.core.content.getSystemService -import androidx.core.os.bundleOf import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -25,7 +23,6 @@ import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity -import io.github.wulkanowy.utils.serializable import io.github.wulkanowy.utils.shareText import javax.inject.Inject @@ -44,33 +41,18 @@ class MessagePreviewFragment : private var menuForwardButton: MenuItem? = null - private var menuRestoreButton: MenuItem? = null - private var menuDeleteButton: MenuItem? = null - private var menuDeleteForeverButton: MenuItem? = null - private var menuShareButton: MenuItem? = null private var menuPrintButton: MenuItem? = null - private var menuMuteButton: MenuItem? = null - override val titleStringId: Int get() = R.string.message_title override val deleteMessageSuccessString: String get() = getString(R.string.message_delete_success) - override val muteMessageSuccessString: String - get() = getString(R.string.message_mute_success) - - override val unmuteMessageSuccessString: String - get() = getString(R.string.message_unmute_success) - - override val restoreMessageSuccessString: String - get() = getString(R.string.message_restore_success) - override val messageNoSubjectString: String get() = getString(R.string.message_no_subject) @@ -82,14 +64,15 @@ class MessagePreviewFragment : get() = getString(R.string.message_not_exists) companion object { - private const val MESSAGE_ARG_KEY = "message" + const val MESSAGE_ID_KEY = "message_id" - fun newInstance(message: Message) = MessagePreviewFragment().apply { - arguments = bundleOf(MESSAGE_ARG_KEY to message) + fun newInstance(message: Message): MessagePreviewFragment { + return MessagePreviewFragment().apply { + arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) } + } } } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -100,8 +83,8 @@ class MessagePreviewFragment : binding = FragmentMessagePreviewBinding.bind(view) messageContainer = binding.messagePreviewContainer presenter.onAttachView( - view = this, - message = requireArguments().serializable(MESSAGE_ARG_KEY), + this, + (savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message ) } @@ -118,12 +101,9 @@ class MessagePreviewFragment : inflater.inflate(R.menu.action_menu_message_preview, menu) menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply) menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward) - menuRestoreButton = menu.findItem(R.id.messagePreviewMenuRestore) menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete) - menuDeleteForeverButton = menu.findItem(R.id.messagePreviewMenuDeleteForever) menuShareButton = menu.findItem(R.id.messagePreviewMenuShare) menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint) - menuMuteButton = menu.findItem(R.id.messagePreviewMenuMute) presenter.onCreateOptionsMenu() menu.findItem(R.id.mainMenuAccount).isVisible = false @@ -133,12 +113,9 @@ class MessagePreviewFragment : return when (item.itemId) { R.id.messagePreviewMenuReply -> presenter.onReply() R.id.messagePreviewMenuForward -> presenter.onForward() - R.id.messagePreviewMenuRestore -> presenter.onMessageRestore() R.id.messagePreviewMenuDelete -> presenter.onMessageDelete() - R.id.messagePreviewMenuDeleteForever -> presenter.onMessageDelete() R.id.messagePreviewMenuShare -> presenter.onShare() R.id.messagePreviewMenuPrint -> presenter.onPrint() - R.id.messagePreviewMenuMute -> presenter.onMute() else -> false } } @@ -150,11 +127,6 @@ class MessagePreviewFragment : } } - override fun updateMuteToggleButton(isMuted: Boolean) { - menuMuteButton?.setTitle(if (isMuted) R.string.message_unmute else R.string.message_mute) - - } - override fun showProgress(show: Boolean) { binding.messagePreviewProgress.visibility = if (show) VISIBLE else GONE } @@ -163,15 +135,20 @@ class MessagePreviewFragment : binding.messagePreviewRecycler.visibility = if (show) VISIBLE else GONE } - override fun showOptions(show: Boolean, isReplayable: Boolean, isRestorable: Boolean) { - menuReplyButton?.isVisible = show && isReplayable + override fun showOptions(show: Boolean, isReplayable: Boolean) { + menuReplyButton?.isVisible = isReplayable menuForwardButton?.isVisible = show - menuRestoreButton?.isVisible = show && isRestorable - menuDeleteButton?.isVisible = show && !isRestorable - menuDeleteForeverButton?.isVisible = show && isRestorable + menuDeleteButton?.isVisible = show menuShareButton?.isVisible = show menuPrintButton?.isVisible = show - menuMuteButton?.isVisible = show && isReplayable + } + + override fun setDeletedOptionsLabels() { + menuDeleteButton?.setTitle(R.string.message_delete_forever) + } + + override fun setNotDeletedOptionsLabels() { + menuDeleteButton?.setTitle(R.string.message_move_to_trash) } override fun showErrorView(show: Boolean) { @@ -186,10 +163,6 @@ class MessagePreviewFragment : binding.messagePreviewErrorRetry.setOnClickListener { callback() } } - override fun showMessage(@StringRes messageId: Int) { - showMessage(getString(messageId)) - } - override fun openMessageReply(message: Message?) { context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message, true)) } } @@ -233,6 +206,11 @@ class MessagePreviewFragment : (activity as MainActivity).popView() } + override fun onSaveInstanceState(outState: Bundle) { + outState.putSerializable(MESSAGE_ID_KEY, presenter.message) + super.onSaveInstanceState(outState) + } + override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() 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 3b3b2b420..fd75f6f3a 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 @@ -2,48 +2,41 @@ package io.github.wulkanowy.ui.modules.message.preview import android.annotation.SuppressLint import androidx.core.text.parseAsHtml -import io.github.wulkanowy.R +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment +import io.github.wulkanowy.data.db.entities.MessageAttachment import io.github.wulkanowy.data.enums.MessageFolder -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.onResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.onResourceSuccess import io.github.wulkanowy.data.repositories.MessageRepository -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.AnalyticsHelper import io.github.wulkanowy.utils.toFormattedString -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -import kotlin.time.Duration.Companion.seconds class MessagePreviewPresenter @Inject constructor( errorHandler: ErrorHandler, studentRepository: StudentRepository, private val messageRepository: MessageRepository, - private val preferencesRepository: PreferencesRepository, private val analytics: AnalyticsHelper ) : BasePresenter(errorHandler, studentRepository) { - private var messageWithAttachments: MessageWithAttachment? = null + var message: Message? = null + + var attachments: List? = null private lateinit var lastError: Throwable private var retryCallback: () -> Unit = {} - fun onAttachView(view: MessagePreviewView, message: Message) { + fun onAttachView(view: MessagePreviewView, message: Message?) { super.onAttachView(view) view.initView() errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(message) + this.message = message + loadData(requireNotNull(message)) } private fun onMessageLoadRetry(message: Message) { @@ -61,33 +54,26 @@ class MessagePreviewPresenter @Inject constructor( private fun loadData(messageToLoad: Message) { flatResourceFlow { val student = studentRepository.getCurrentStudent() - messageRepository.getMessage( - student = student, - message = messageToLoad, - markAsRead = !preferencesRepository.isIncognitoMode, - ) + messageRepository.getMessage(student, messageToLoad, true) } .logResourceStatus("message ${messageToLoad.messageId} preview") .onResourceData { if (it != null) { - messageWithAttachments = it + message = it.message + attachments = it.attachments view?.apply { setMessageWithAttachment(it) showContent(true) initOptions() - updateMuteToggleButton(isMuted = it.mutedMessageSender != null) - if (preferencesRepository.isIncognitoMode && it.message.unread) { - showMessage(R.string.message_incognito_description) - } } } else { - delay(1.seconds) view?.run { showMessage(messageNotExists) popView() } } - }.onResourceSuccess { + } + .onResourceSuccess { if (it != null) { analytics.logEvent( "load_item", @@ -95,28 +81,31 @@ class MessagePreviewPresenter @Inject constructor( "length" to it.message.content.length ) } - }.onResourceNotLoading { view?.showProgress(false) }.onResourceError { + } + .onResourceNotLoading { view?.showProgress(false) } + .onResourceError { retryCallback = { onMessageLoadRetry(messageToLoad) } errorHandler.dispatch(it) - }.launch() + } + .launch() } fun onReply(): Boolean { - return if (messageWithAttachments?.message != null) { - view?.openMessageReply(messageWithAttachments?.message) + return if (message != null) { + view?.openMessageReply(message) true } else false } fun onForward(): Boolean { - return if (messageWithAttachments?.message != null) { - view?.openMessageForward(messageWithAttachments?.message) + return if (message != null) { + view?.openMessageForward(message) true } else false } fun onShare(): Boolean { - val message = messageWithAttachments?.message ?: return false + val message = message ?: return false val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() } val text = buildString { @@ -129,15 +118,13 @@ class MessagePreviewPresenter @Inject constructor( appendLine(message.content.parseAsHtml()) - if (!messageWithAttachments?.attachments.isNullOrEmpty()) { + if (!attachments.isNullOrEmpty()) { appendLine() appendLine("Załączniki:") - append( - messageWithAttachments?.attachments.orEmpty() - .joinToString(separator = "\n") { attachment -> - "${attachment.filename}: ${attachment.url}" - }) + append(attachments.orEmpty().joinToString(separator = "\n") { attachment -> + "${attachment.filename}: ${attachment.url}" + }) } } @@ -150,7 +137,7 @@ class MessagePreviewPresenter @Inject constructor( @SuppressLint("NewApi") fun onPrint(): Boolean { - val message = messageWithAttachments?.message ?: return false + val message = message ?: return false val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() } val dateString = message.date.toFormattedString("yyyy-MM-dd HH:mm:ss") @@ -161,7 +148,8 @@ class MessagePreviewPresenter @Inject constructor( append("

Od

${message.sender}
") append("

DO

${message.recipients}
") } - val messageContent = "

${message.content}

".replace(Regex("[\\n\\r]{2,}"), "

") + val messageContent = "

${message.content}

" + .replace(Regex("[\\n\\r]{2,}"), "

") .replace(Regex("[\\n\\r]"), "
") val jobName = buildString { @@ -172,7 +160,9 @@ class MessagePreviewPresenter @Inject constructor( } view?.apply { - val html = printHTML.replace("%SUBJECT%", subject).replace("%CONTENT%", messageContent) + val html = printHTML + .replace("%SUBJECT%", subject) + .replace("%CONTENT%", messageContent) .replace("%INFO%", infoContent) printDocument(html, jobName) } @@ -180,69 +170,34 @@ class MessagePreviewPresenter @Inject constructor( return true } - private fun restoreMessage() { - val message = messageWithAttachments?.message ?: return + private fun deleteMessage() { + message ?: return view?.run { showContent(false) showProgress(true) - showOptions( - show = false, - isReplayable = false, - isRestorable = false, - ) + showOptions(show = false, isReplayable = false) showErrorView(false) } - Timber.i("Restore message ${message.messageGlobalKey}") + + Timber.i("Delete message ${message?.messageGlobalKey}") + presenterScope.launch { runCatching { val student = studentRepository.getCurrentStudent(decryptPass = true) val mailbox = messageRepository.getMailboxByStudent(student) - messageRepository.restoreMessages(student, mailbox, listOfNotNull(message)) + messageRepository.deleteMessage(student, mailbox!!, message!!) } .onFailure { - retryCallback = { onMessageRestore() } + retryCallback = { onMessageDelete() } errorHandler.dispatch(it) } .onSuccess { view?.run { - showMessage(restoreMessageSuccessString) + showMessage(deleteMessageSuccessString) popView() } } - view?.showProgress(false) - } - } - - private fun deleteMessage() { - messageWithAttachments?.message ?: return - - view?.run { - showContent(false) - showProgress(true) - showOptions( - show = false, - isReplayable = false, - isRestorable = false, - ) - showErrorView(false) - } - - Timber.i("Delete message ${messageWithAttachments?.message?.messageGlobalKey}") - - presenterScope.launch { - runCatching { - val student = studentRepository.getCurrentStudent(decryptPass = true) - messageRepository.deleteMessage(student, messageWithAttachments?.message!!) - }.onFailure { - retryCallback = { onMessageDelete() } - errorHandler.dispatch(it) - }.onSuccess { - view?.run { - showMessage(deleteMessageSuccessString) - popView() - } - } view?.showProgress(false) } @@ -258,11 +213,6 @@ class MessagePreviewPresenter @Inject constructor( } } - fun onMessageRestore(): Boolean { - restoreMessage() - return true - } - fun onMessageDelete(): Boolean { deleteMessage() return true @@ -271,39 +221,20 @@ class MessagePreviewPresenter @Inject constructor( private fun initOptions() { view?.apply { showOptions( - show = messageWithAttachments?.message != null, - isReplayable = messageWithAttachments?.message?.folderId == MessageFolder.RECEIVED.id, - isRestorable = messageWithAttachments?.message?.folderId == MessageFolder.TRASHED.id, + show = message != null, + isReplayable = message?.folderId != MessageFolder.SENT.id, ) + message?.let { + when (it.folderId == MessageFolder.TRASHED.id) { + true -> setDeletedOptionsLabels() + false -> setNotDeletedOptionsLabels() + } + } + } } fun onCreateOptionsMenu() { initOptions() } - - fun onMute(): Boolean { - val message = messageWithAttachments?.message ?: return false - val isMuted = messageWithAttachments?.mutedMessageSender != null - - presenterScope.launch { - runCatching { - when (isMuted) { - true -> { - messageRepository.unmuteMessage(message.correspondents) - view?.run { showMessage(unmuteMessageSuccessString) } - } - - false -> { - messageRepository.muteMessage(message.correspondents) - view?.run { showMessage(muteMessageSuccessString) } - } - } - }.onFailure { - errorHandler.dispatch(it) - } - } - view?.updateMuteToggleButton(isMuted) - return true - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt index ee0b6ce0a..c5a947939 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.message.preview -import androidx.annotation.StringRes import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.MessageWithAttachment import io.github.wulkanowy.ui.base.BaseView @@ -9,12 +8,6 @@ interface MessagePreviewView : BaseView { val deleteMessageSuccessString: String - val muteMessageSuccessString: String - - val unmuteMessageSuccessString: String - - val restoreMessageSuccessString: String - val messageNoSubjectString: String val printHTML: String @@ -25,8 +18,6 @@ interface MessagePreviewView : BaseView { fun setMessageWithAttachment(item: MessageWithAttachment) - fun updateMuteToggleButton(isMuted: Boolean) - fun showProgress(show: Boolean) fun showContent(show: Boolean) @@ -37,7 +28,11 @@ interface MessagePreviewView : BaseView { fun setErrorRetryCallback(callback: () -> Unit) - fun showOptions(show: Boolean, isReplayable: Boolean, isRestorable: Boolean) + fun showOptions(show: Boolean, isReplayable: Boolean) + + fun setDeletedOptionsLabels() + + fun setNotDeletedOptionsLabels() fun openMessageReply(message: Message?) @@ -48,6 +43,4 @@ interface MessagePreviewView : BaseView { fun popView() fun printDocument(html: String, jobName: String) - - fun showMessage(@StringRes messageId: Int) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt index 0ba82f1a0..b5f687bd4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt @@ -1,10 +1,10 @@ package io.github.wulkanowy.ui.modules.message.send import android.annotation.SuppressLint +import android.app.AlertDialog import android.content.Context import android.content.Intent import android.graphics.Rect -import android.os.Build import android.os.Bundle import android.text.Spanned import android.view.Menu @@ -12,14 +12,11 @@ import android.view.MenuItem import android.view.TouchDelegate import android.view.View.GONE import android.view.View.VISIBLE -import android.view.ViewGroup import android.widget.Toast import android.widget.Toast.LENGTH_LONG import androidx.core.text.parseAsHtml import androidx.core.text.toHtml -import androidx.core.view.* import androidx.core.widget.doOnTextChanged -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Mailbox @@ -27,11 +24,10 @@ import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.databinding.ActivitySendMessageBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog -import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.MAILBOX_KEY +import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog.Companion.LISTENER_KEY import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.nullableSerializable import io.github.wulkanowy.utils.showSoftInput import javax.inject.Inject @@ -102,13 +98,6 @@ class SendMessageActivity : BaseActivity= Build.VERSION_CODES.R) { - WindowCompat.setDecorFitsSystemWindows(window, false) - binding.sendAppBar.isLifted = true - } - initializeMessageContainer() - messageContainer = binding.sendMessageContainer formRecipientsData = binding.sendMessageTo.addedChipItems as List @@ -119,12 +108,12 @@ class SendMessageActivity : BaseActivity - presenter.onMailboxSelected(bundle.nullableSerializable(MAILBOX_KEY)) + presenter.onMailboxSelected(bundle.getSerializable(MAILBOX_KEY) as? Mailbox) } } @@ -140,22 +129,6 @@ class SendMessageActivity : BaseActivity - val navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars()) - val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) - - view.updateLayoutParams { - bottomMargin = if (imeInsets.bottom > navigationBarInsets.bottom) { - imeInsets.bottom - } else { - navigationBarInsets.bottom - } - } - WindowInsetsCompat.CONSUMED - } - } - private fun onMessageSubjectChange(text: CharSequence?) { formSubjectValue = text.toString() presenter.onMessageContentChange() @@ -278,7 +251,7 @@ class SendMessageActivity : BaseActivity presenter.restoreMessageParts() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessagePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessagePresenter.kt index 6155baea3..5ab8f8fc9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessagePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessagePresenter.kt @@ -55,7 +55,7 @@ class SendMessagePresenter @Inject constructor( view.showMessageBackupDialog() } reason?.let { - setSubject("Usprawiedliwienie") + setSubject("Usprawiedliwenie") setContent(it) } message?.let { @@ -203,7 +203,7 @@ class SendMessagePresenter @Inject constructor( subject = subject, content = content, recipients = recipients, - mailbox = mailbox, + mailboxId = mailbox.globalKey, ) }.logResourceStatus("sending message").onEach { when (it) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt index fadc77e6d..6df6153c5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.message.tab -import android.annotation.SuppressLint import android.content.res.ColorStateList import android.graphics.Typeface import android.view.LayoutInflater @@ -18,7 +17,8 @@ import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.toFormattedString import javax.inject.Inject -class MessageTabAdapter @Inject constructor() : RecyclerView.Adapter() { +class MessageTabAdapter @Inject constructor() : + RecyclerView.Adapter() { lateinit var onItemClickListener: (MessageTabDataItem.MessageItem, position: Int) -> Unit @@ -51,11 +51,10 @@ class MessageTabAdapter @Inject constructor() : RecyclerView.Adapter HeaderViewHolder( ItemMessageChipsBinding.inflate(inflater, parent, false) ) - MessageItemViewType.MESSAGE -> ItemViewHolder( ItemMessageBinding.inflate(inflater, parent, false) ) @@ -69,23 +68,21 @@ class MessageTabAdapter @Inject constructor() : RecyclerView.Adapter messageItemUnreadIndicator.setImageResource(R.drawable.ic_notifications_off) - else -> messageItemUnreadIndicator.setImageResource(R.drawable.ic_circle_notification) - } + messageItemUnreadIndicator.isVisible = message.unread root.setOnClickListener { holder.bindingAdapterPosition.let { @@ -170,7 +162,8 @@ class MessageTabAdapter @Inject constructor() : RecyclerView.Adapter, private val new: List + private val old: List, + private val new: List ) : DiffUtil.Callback() { override fun getOldListSize(): Int = old.size diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt index ef640e040..c0bd4170e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt @@ -6,7 +6,6 @@ sealed class MessageTabDataItem(val viewType: MessageItemViewType) { data class MessageItem( val message: Message, - val isMuted: Boolean, val isSelected: Boolean, val isActionMode: Boolean ) : MessageTabDataItem(MessageItemViewType.MESSAGE) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt index 12f9d3234..5d608ad3b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt @@ -5,14 +5,10 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE +import android.view.View.* import android.widget.CompoundButton -import androidx.annotation.StringRes import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView -import androidx.core.os.bundleOf import androidx.core.view.updatePadding import androidx.fragment.app.setFragmentResultListener import androidx.recyclerview.widget.LinearLayoutManager @@ -31,7 +27,6 @@ import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.nullableSerializable import javax.inject.Inject @AndroidEntryPoint @@ -48,8 +43,12 @@ class MessageTabFragment : BaseFragment(R.layout.frag const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id" - fun newInstance(folder: MessageFolder) = MessageTabFragment().apply { - arguments = bundleOf(MESSAGE_TAB_FOLDER_ID to folder.name) + fun newInstance(folder: MessageFolder): MessageTabFragment { + return MessageTabFragment().apply { + arguments = Bundle().apply { + putString(MESSAGE_TAB_FOLDER_ID, folder.name) + } + } } } @@ -66,12 +65,10 @@ class MessageTabFragment : BaseFragment(R.layout.frag } override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { - val isTrashFolder = presenter.folder == MessageFolder.TRASHED - - menu.findItem(R.id.messageTabContextMenuDelete).setVisible(!isTrashFolder) - menu.findItem(R.id.messageTabContextMenuDeleteForever).setVisible(isTrashFolder) - menu.findItem(R.id.messageTabContextMenuRestore).setVisible(isTrashFolder) - + if (presenter.folder == MessageFolder.TRASHED) { + val menuItem = menu.findItem(R.id.messageTabContextMenuDelete) + menuItem.setTitle(R.string.message_delete_forever) + } return presenter.onPrepareActionMode() } @@ -83,15 +80,12 @@ class MessageTabFragment : BaseFragment(R.layout.frag override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean { when (menu.itemId) { R.id.messageTabContextMenuDelete -> presenter.onActionModeSelectDelete() - R.id.messageTabContextMenuRestore -> presenter.onActionModeSelectRestore() - R.id.messageTabContextMenuDeleteForever -> presenter.onActionModeSelectDelete() R.id.messageTabContextMenuSelectAll -> presenter.onActionModeSelectCheckAll() } return true } } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -136,25 +130,18 @@ class MessageTabFragment : BaseFragment(R.layout.frag setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle -> presenter.onMailboxSelected( - mailbox = bundle.nullableSerializable(MailboxChooserDialog.MAILBOX_KEY), + mailbox = bundle.getSerializable(MailboxChooserDialog.MAILBOX_KEY) as? Mailbox, ) } } - @Deprecated("Deprecated in Java") - @Suppress("DEPRECATION") override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) inflater.inflate(R.menu.action_menu_message_tab, menu) - initializeSearchView(menu) - } - - private fun initializeSearchView(menu: Menu) { - val searchView = (menu.findItem(R.id.action_search).actionView as SearchView).apply { - queryHint = getString(R.string.all_search_hint) - maxWidth = Int.MAX_VALUE - } + val searchView = menu.findItem(R.id.action_search).actionView as SearchView + searchView.queryHint = getString(R.string.all_search_hint) + searchView.maxWidth = Int.MAX_VALUE searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String) = false override fun onQueryTextChange(query: String): Boolean { @@ -220,8 +207,8 @@ class MessageTabFragment : BaseFragment(R.layout.frag binding.messageTabSwipe.isRefreshing = show } - override fun showMessage(@StringRes messageId: Int) { - showMessage(getString(messageId)) + override fun showMessagesDeleted() { + showMessage(getString(R.string.message_messages_deleted)) } override fun notifyParentShowNewMessage(show: Boolean) { @@ -248,10 +235,6 @@ class MessageTabFragment : BaseFragment(R.layout.frag presenter.onParentFinishActionMode() } - fun onParentReselected() { - presenter.onParentReselected() - } - private fun onChipChecked(chip: CompoundButton, isChecked: Boolean) { when (chip.id) { R.id.chip_unread -> presenter.onUnreadFilterSelected(isChecked) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt index cda0b32bd..ea142db2b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt @@ -1,10 +1,8 @@ package io.github.wulkanowy.ui.modules.message.tab -import io.github.wulkanowy.R import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Mailbox import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor import io.github.wulkanowy.data.enums.MessageFolder import io.github.wulkanowy.data.repositories.MessageRepository import io.github.wulkanowy.data.repositories.StudentRepository @@ -28,7 +26,7 @@ class MessageTabPresenter @Inject constructor( errorHandler: ErrorHandler, studentRepository: StudentRepository, private val messageRepository: MessageRepository, - private val analytics: AnalyticsHelper, + private val analytics: AnalyticsHelper ) : BasePresenter(errorHandler, studentRepository) { lateinit var folder: MessageFolder @@ -40,7 +38,7 @@ class MessageTabPresenter @Inject constructor( private var mailboxes: List = emptyList() private var selectedMailbox: Mailbox? = null - private var messages = emptyList() + private var messages = emptyList() private val searchChannel = Channel() @@ -85,14 +83,6 @@ class MessageTabPresenter @Inject constructor( view?.showActionMode(false) } - fun onParentReselected() { - view?.run { - if (!isViewEmpty) { - resetListPosition() - } - } - } - fun onDestroyActionMode() { isActionMode = false messagesToDelete.clear() @@ -121,27 +111,8 @@ class MessageTabPresenter @Inject constructor( return true } - fun onActionModeSelectRestore() { - Timber.i("Restore ${messagesToDelete.size} messages") - val messageList = messagesToDelete.toList() - - presenterScope.launch { - view?.run { - showProgress(true) - showContent(false) - showActionMode(false) - } - runCatching { - val student = studentRepository.getCurrentStudent(true) - messageRepository.restoreMessages(student, selectedMailbox, messageList) - } - .onFailure(errorHandler::dispatch) - .onSuccess { view?.showMessage(R.string.message_messages_restored) } - } - } - fun onActionModeSelectDelete() { - Timber.i("Delete ${messagesToDelete.size} messages") + Timber.i("Delete ${messagesToDelete.size} messages)") val messageList = messagesToDelete.toList() presenterScope.launch { @@ -153,15 +124,15 @@ class MessageTabPresenter @Inject constructor( runCatching { val student = studentRepository.getCurrentStudent(true) - messageRepository.deleteMessages(student, messageList) + messageRepository.deleteMessages(student, selectedMailbox, messageList) } .onFailure(errorHandler::dispatch) - .onSuccess { view?.showMessage(R.string.message_messages_deleted) } + .onSuccess { view?.showMessagesDeleted() } } } fun onActionModeSelectCheckAll() { - val messagesToSelect = getFilteredData().map { it.message } + val messagesToSelect = getFilteredData() val isAllSelected = messagesToDelete.containsAll(messagesToSelect) if (isAllSelected) { @@ -208,7 +179,7 @@ class MessageTabPresenter @Inject constructor( view?.showActionMode(false) } - val filteredData = getFilteredData().map { it.message } + val filteredData = getFilteredData() view?.run { updateActionModeTitle(messagesToDelete.size) @@ -340,31 +311,25 @@ class MessageTabPresenter @Inject constructor( } } - private fun getFilteredData(): List { + private fun getFilteredData(): List { if (lastSearchQuery.trim().isEmpty()) { - val sortedMessages = messages.sortedByDescending { it.message.date } + val sortedMessages = messages.sortedByDescending { it.date } return when { - (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { - it.message.unread == onlyUnread && it.message.hasAttachments == onlyWithAttachments - } - - (onlyUnread == true) -> sortedMessages.filter { it.message.unread == onlyUnread } - onlyWithAttachments -> sortedMessages.filter { it.message.hasAttachments == onlyWithAttachments } + (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { it.unread == onlyUnread && it.hasAttachments == onlyWithAttachments } + (onlyUnread == true) -> sortedMessages.filter { it.unread == onlyUnread } + onlyWithAttachments -> sortedMessages.filter { it.hasAttachments == onlyWithAttachments } else -> sortedMessages } } else { val sortedMessages = messages - .map { it to calculateMatchRatio(it.message, lastSearchQuery) } - .sortedWith(compareBy> { -it.second }.thenByDescending { it.first.message.date }) + .map { it to calculateMatchRatio(it, lastSearchQuery) } + .sortedWith(compareBy> { -it.second }.thenByDescending { it.first.date }) .filter { it.second > 6000 } .map { it.first } return when { - (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { - it.message.unread == onlyUnread && it.message.hasAttachments == onlyWithAttachments - } - - (onlyUnread == true) -> sortedMessages.filter { it.message.unread == onlyUnread } - onlyWithAttachments -> sortedMessages.filter { it.message.hasAttachments == onlyWithAttachments } + (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { it.unread == onlyUnread && it.hasAttachments == onlyWithAttachments } + (onlyUnread == true) -> sortedMessages.filter { it.unread == onlyUnread } + onlyWithAttachments -> sortedMessages.filter { it.hasAttachments == onlyWithAttachments } else -> sortedMessages } } @@ -393,9 +358,8 @@ class MessageTabPresenter @Inject constructor( addAll(data.map { message -> MessageTabDataItem.MessageItem( - message = message.message, - isMuted = message.mutedMessageSender != null, - isSelected = messagesToDelete.any { it.messageGlobalKey == message.message.messageGlobalKey }, + message = message, + isSelected = messagesToDelete.any { it.messageGlobalKey == message.messageGlobalKey }, isActionMode = isActionMode ) }) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt index 247af4342..6ece6621b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.message.tab -import androidx.annotation.StringRes import io.github.wulkanowy.data.db.entities.Mailbox import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.ui.base.BaseView @@ -27,7 +26,7 @@ interface MessageTabView : BaseView { fun showEmpty(show: Boolean) - fun showMessage(@StringRes messageId: Int) + fun showMessagesDeleted() fun showErrorView(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt index 1afe773cf..f8e367c57 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt @@ -22,7 +22,7 @@ import javax.inject.Inject @AndroidEntryPoint class MobileDeviceFragment : BaseFragment(R.layout.fragment_mobile_device), MobileDeviceView, - MainView.TitledView, MainView.MainChildView { + MainView.TitledView { @Inject lateinit var presenter: MobileDevicePresenter @@ -135,14 +135,6 @@ class MobileDeviceFragment : (activity as? MainActivity)?.showDialogFragment(MobileDeviceTokenDialog.newInstance()) } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onFragmentReselected() - } - - override fun resetView() { - binding.mobileDevicesRecycler.smoothScrollToPosition(0) - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt index 56785dbf4..36a720e53 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt @@ -129,10 +129,4 @@ class MobileDevicePresenter @Inject constructor( .onResourceError(errorHandler::dispatch) .launch("unregister") } - - fun onFragmentReselected() { - if (view?.isViewEmpty == false) { - view?.resetView() - } - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt index 973cb1234..b94646a7b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt @@ -32,6 +32,4 @@ interface MobileDeviceView : BaseView { fun setErrorDetails(message: String) fun showTokenDialog() - - fun resetView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt index 2cc2a2aa7..eb420a6ae 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt @@ -1,17 +1,17 @@ package io.github.wulkanowy.ui.modules.mobiledevice.token -import android.app.Dialog import android.content.ClipData import android.content.ClipboardManager import android.graphics.BitmapFactory import android.os.Bundle import android.util.Base64 +import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import android.view.ViewGroup import android.widget.Toast import androidx.core.content.getSystemService -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.pojos.MobileDeviceToken @@ -31,14 +31,17 @@ class MobileDeviceTokenDialog : BaseDialogFragment(), fun newInstance() = MobileDeviceTokenDialog() } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView( - DialogMobileDeviceBinding.inflate(layoutInflater).apply { binding = this }.root - ) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogMobileDeviceBinding.inflate(inflater).apply { binding = this }.root + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter.onAttachView(this) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt index 697eab330..70587b0cf 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.more +import android.graphics.drawable.Drawable import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView @@ -8,9 +9,9 @@ import javax.inject.Inject class MoreAdapter @Inject constructor() : RecyclerView.Adapter() { - var items = emptyList() + var items = emptyList>() - var onClickListener: (moreItem: MoreItem) -> Unit = {} + var onClickListener: (name: String) -> Unit = {} override fun getItemCount() = items.size @@ -19,14 +20,13 @@ class MoreAdapter @Inject constructor() : RecyclerView.Adapter(R.layout.fragment_more), override val titleStringId: Int get() = R.string.more_title + override val messagesRes: Pair? + get() = context?.run { getString(R.string.message_title) to getCompatDrawable(R.drawable.ic_more_messages) } + + override val homeworkRes: Pair? + get() = context?.run { getString(R.string.homework_title) to getCompatDrawable(R.drawable.ic_more_homework) } + + override val noteRes: Pair? + get() = context?.run { getString(R.string.note_title) to getCompatDrawable(R.drawable.ic_more_note) } + + override val conferencesRes: Pair? + get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) } + + override val schoolAnnouncementRes: Pair? + get() = context?.run { getString(R.string.school_announcement_title) to getCompatDrawable(R.drawable.ic_all_about) } + + override val schoolAndTeachersRes: Pair? + get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) } + + override val mobileDevicesRes: Pair? + get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) } + + override val settingsRes: Pair? + get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) } + + override val examRes: Pair? + get() = context?.run { getString(R.string.exam_title) to getCompatDrawable(R.drawable.ic_main_exam) } + + override val luckyNumberRes: Pair? + get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentMoreBinding.bind(view) @@ -54,19 +94,55 @@ class MoreFragment : BaseFragment(R.layout.fragment_more), ?.onFragmentChanged() } - override fun updateData(data: List) { + override fun updateData(data: List>) { with(moreAdapter) { items = data notifyDataSetChanged() } } - override fun popView(depth: Int) { - (activity as? MainActivity)?.popView(depth) + override fun openMessagesView() { + (activity as? MainActivity)?.pushView(MessageFragment.newInstance()) } - override fun openView(destination: Destination) { - (activity as? MainActivity)?.pushView(destination.destinationFragment) + override fun openHomeworkView() { + (activity as? MainActivity)?.pushView(HomeworkFragment.newInstance()) + } + + override fun openNoteView() { + (activity as? MainActivity)?.pushView(NoteFragment.newInstance()) + } + + override fun openSchoolAnnouncementView() { + (activity as? MainActivity)?.pushView(SchoolAnnouncementFragment.newInstance()) + } + + override fun openConferencesView() { + (activity as? MainActivity)?.pushView(ConferenceFragment.newInstance()) + } + + override fun openSchoolAndTeachersView() { + (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance()) + } + + override fun openMobileDevicesView() { + (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance()) + } + + override fun openSettingsView() { + (activity as? MainActivity)?.pushView(SettingsFragment.newInstance()) + } + + override fun openExamView() { + (activity as? MainActivity)?.pushView(ExamFragment.newInstance()) + } + + override fun openLuckyNumberView() { + (activity as? MainActivity)?.pushView(LuckyNumberFragment.newInstance()) + } + + override fun popView(depth: Int) { + (activity as? MainActivity)?.popView(depth) } override fun onDestroyView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt deleted file mode 100644 index d544f041c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreItem.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.ui.modules.more - -import io.github.wulkanowy.ui.modules.Destination - -data class MoreItem( - - val icon: Int, - - val title: Int, - - val destination: Destination -) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt index 0ebaf4c7b..92551d6e9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt @@ -1,24 +1,16 @@ package io.github.wulkanowy.ui.modules.more -import io.github.wulkanowy.R -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.ui.modules.Destination import timber.log.Timber import javax.inject.Inject class MorePresenter @Inject constructor( errorHandler: ErrorHandler, - studentRepository: StudentRepository, - preferencesRepository: PreferencesRepository + studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { - private val moreAppMenuItem = preferencesRepository.appMenuItemOrder - .sortedBy { it.order } - .drop(4) - override fun onAttachView(view: MoreView) { super.onAttachView(view) view.initView() @@ -26,10 +18,22 @@ class MorePresenter @Inject constructor( loadData() } - fun onItemSelected(moreItem: MoreItem) { - Timber.i("Select more item \"${moreItem.destination.destinationType}\"") - - view?.openView(moreItem.destination) + fun onItemSelected(title: String) { + Timber.i("Select more item \"${title}\"") + view?.run { + when (title) { + messagesRes?.first -> openMessagesView() + examRes?.first -> openExamView() + homeworkRes?.first -> openHomeworkView() + noteRes?.first -> openNoteView() + conferencesRes?.first -> openConferencesView() + schoolAnnouncementRes?.first -> openSchoolAnnouncementView() + schoolAndTeachersRes?.first -> openSchoolAndTeachersView() + mobileDevicesRes?.first -> openMobileDevicesView() + settingsRes?.first -> openSettingsView() + luckyNumberRes?.first -> openLuckyNumberView() + } + } } fun onViewReselected() { @@ -39,21 +43,19 @@ class MorePresenter @Inject constructor( private fun loadData() { Timber.i("Load items for more view") - val moreItems = moreAppMenuItem.map { - MoreItem( - icon = it.icon, - title = it.title, - destination = it.destinationType.defaultDestination - ) + view?.run { + updateData(listOfNotNull( + messagesRes, + examRes, + homeworkRes, + noteRes, + luckyNumberRes, + conferencesRes, + schoolAnnouncementRes, + schoolAndTeachersRes, + mobileDevicesRes, + settingsRes + )) } - .plus( - MoreItem( - icon = R.drawable.ic_more_settings, - title = R.string.settings_title, - destination = Destination.Settings - ) - ) - - view?.updateData(moreItems) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt index fbca97edc..cb895de28 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt @@ -1,15 +1,53 @@ package io.github.wulkanowy.ui.modules.more +import android.graphics.drawable.Drawable import io.github.wulkanowy.ui.base.BaseView -import io.github.wulkanowy.ui.modules.Destination interface MoreView : BaseView { + val messagesRes: Pair? + + val homeworkRes: Pair? + + val noteRes: Pair? + + val conferencesRes: Pair? + + val schoolAnnouncementRes: Pair? + + val schoolAndTeachersRes: Pair? + + val mobileDevicesRes: Pair? + + val settingsRes: Pair? + + val examRes: Pair? + + val luckyNumberRes: Pair? + fun initView() - fun updateData(data: List) + fun updateData(data: List>) + + fun openSettingsView() fun popView(depth: Int) - fun openView(destination: Destination) + fun openMessagesView() + + fun openHomeworkView() + + fun openNoteView() + + fun openSchoolAnnouncementView() + + fun openConferencesView() + + fun openSchoolAndTeachersView() + + fun openMobileDevicesView() + + fun openExamView() + + fun openLuckyNumberView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt index 0592e9243..5811456b6 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt @@ -1,24 +1,23 @@ package io.github.wulkanowy.ui.modules.note import android.annotation.SuppressLint -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.core.content.ContextCompat -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.databinding.DialogNoteBinding import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory -import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.serializable +import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.toFormattedString -@AndroidEntryPoint -class NoteDialog : BaseDialogFragment() { +class NoteDialog : DialogFragment() { + + private var binding: DialogNoteBinding by lifecycleAwareVariable() private lateinit var note: Note @@ -26,21 +25,24 @@ class NoteDialog : BaseDialogFragment() { private const val ARGUMENT_KEY = "Item" - fun newInstance(note: Note) = NoteDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to note) + fun newInstance(exam: Note) = NoteDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - note = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + note = getSerializable(ARGUMENT_KEY) as Note + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogNoteBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogNoteBinding.inflate(inflater).apply { binding = this }.root @SuppressLint("SetTextI18n") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt index cb54b3840..dd6223448 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt @@ -18,7 +18,7 @@ import javax.inject.Inject @AndroidEntryPoint class NoteFragment : BaseFragment(R.layout.fragment_note), NoteView, - MainView.TitledView, MainView.MainChildView { + MainView.TitledView { @Inject lateinit var presenter: NotePresenter @@ -112,14 +112,6 @@ class NoteFragment : BaseFragment(R.layout.fragment_note), binding.noteSwipe.isRefreshing = show } - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onFragmentReselected() - } - - override fun resetView() { - binding.noteRecycler.smoothScrollToPosition(0) - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt index 62ad347fa..440565e11 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt @@ -121,10 +121,4 @@ class NotePresenter @Inject constructor( } .launch("update_note") } - - fun onFragmentReselected() { - if (view?.isViewEmpty == false) { - view?.resetView() - } - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt index b813b3159..9fc0be94c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt @@ -30,6 +30,4 @@ interface NoteView : BaseView { fun showRefresh(show: Boolean) fun showNoteDialog(note: Note) - - fun resetView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt deleted file mode 100644 index 0763d4fa8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/notifications/NotificationsFragment.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.ui.modules.notifications - -import android.os.Bundle -import android.view.View -import androidx.activity.result.contract.ActivityResultContracts.RequestPermission -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentNotificationsBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.utils.openNotificationSettings - -@AndroidEntryPoint -class NotificationsFragment : - BaseFragment(R.layout.fragment_notifications) { - - private val permission = "android.permission.POST_NOTIFICATIONS" - - private val requestPermissionLauncher = registerForActivityResult(RequestPermission()) { - if (it) { - navigateToFinish() - } else showSettingsDialog() - } - - companion object { - fun newInstance() = NotificationsFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentNotificationsBinding.bind(view) - initView() - } - - private fun initView() { - with(binding) { - notificationsSkip.setOnClickListener { navigateToFinish() } - notificationsEnable.setOnClickListener { requestPermission() } - } - } - - private fun showSettingsDialog() { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.notifications_header_title) - .setMessage(R.string.notifications_header_description) - .setNegativeButton(R.string.notifications_skip) { dialog, _ -> - dialog.dismiss() - navigateToFinish() - } - .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ -> - requireActivity().openNotificationSettings() - } - .show() - } - - private fun requestPermission() { - requestPermissionLauncher.launch(permission) - } - - private fun navigateToFinish() { - (requireActivity() as LoginActivity).navigateToFinish() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt index fef06328d..e2af05c92 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt @@ -58,10 +58,7 @@ class TeacherPresenter @Inject constructor( .logResourceStatus("load teachers data") .onResourceData { view?.run { - updateData(it - .filter { item -> item.name.isNotBlank() } - .sortedBy { it.name } - ) + updateData(it.filter { item -> item.name.isNotBlank() }) showContent(it.isNotEmpty()) showEmpty(it.isEmpty()) showErrorView(false) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt index 731488a9c..62f6251ec 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementAdapter.kt @@ -2,11 +2,10 @@ package io.github.wulkanowy.ui.modules.schoolannouncement import android.view.LayoutInflater import android.view.ViewGroup -import androidx.core.view.isVisible +import androidx.core.text.parseAsHtml import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.data.db.entities.SchoolAnnouncement import io.github.wulkanowy.databinding.ItemSchoolAnnouncementBinding -import io.github.wulkanowy.utils.parseUonetHtml import io.github.wulkanowy.utils.toFormattedString import javax.inject.Inject @@ -29,11 +28,7 @@ class SchoolAnnouncementAdapter @Inject constructor() : with(holder.binding) { schoolAnnouncementItemDate.text = item.date.toFormattedString() schoolAnnouncementItemType.text = item.subject - schoolAnnouncementItemContent.text = item.content.parseUonetHtml() - with(schoolAnnouncementItemAuthor) { - text = item.author - isVisible = !item.author.isNullOrBlank() - } + schoolAnnouncementItemContent.text = item.content.parseAsHtml() root.setOnClickListener { onItemClickListener(item) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt index c1c584414..7dcd51cea 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolannouncement/SchoolAnnouncementDialog.kt @@ -1,20 +1,19 @@ package io.github.wulkanowy.ui.modules.schoolannouncement -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import android.view.ViewGroup +import androidx.core.text.parseAsHtml +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.SchoolAnnouncement import io.github.wulkanowy.databinding.DialogSchoolAnnouncementBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.parseUonetHtml -import io.github.wulkanowy.utils.serializable +import io.github.wulkanowy.utils.lifecycleAwareVariable import io.github.wulkanowy.utils.toFormattedString -@AndroidEntryPoint -class SchoolAnnouncementDialog : BaseDialogFragment() { +class SchoolAnnouncementDialog : DialogFragment() { + + private var binding: DialogSchoolAnnouncementBinding by lifecycleAwareVariable() private lateinit var announcement: SchoolAnnouncement @@ -22,24 +21,24 @@ class SchoolAnnouncementDialog : BaseDialogFragment)?.showMessage(text) } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun showChangePasswordSnackbar(redirectUrl: String) { @@ -70,10 +62,6 @@ class AdvancedFragment : PreferenceFragmentCompat(), ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() - } - override fun onResume() { super.onResume() preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt index 4bc24594a..d38f841fe 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt @@ -18,8 +18,7 @@ class AdvancedPresenter @Inject constructor( Timber.i("Settings advanced view was initialized") } - fun onSharedPreferenceChanged(key: String?) { - key ?: return + fun onSharedPreferenceChanged(key: String) { Timber.i("Change settings $key") analytics.logEvent("setting_changed", "name" to key) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt index 3d0c8052b..1f6d5143b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt @@ -38,7 +38,7 @@ class AppearanceFragment : PreferenceFragmentCompat(), setPreferencesFromResource(R.xml.scheme_preferences_appearance, rootKey) } - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { presenter.onSharedPreferenceChanged(key) } @@ -62,16 +62,8 @@ class AppearanceFragment : PreferenceFragmentCompat(), (activity as? BaseActivity<*, *>)?.showMessage(text) } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun showChangePasswordSnackbar(redirectUrl: String) { @@ -86,10 +78,6 @@ class AppearanceFragment : PreferenceFragmentCompat(), ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() - } - override fun onResume() { super.onResume() preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt index d3410ea84..14592a6cc 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt @@ -22,8 +22,7 @@ class AppearancePresenter @Inject constructor( Timber.i("Settings appearance view was initialized") } - fun onSharedPreferenceChanged(key: String?) { - key ?: return + fun onSharedPreferenceChanged(key: String) { Timber.i("Change settings $key") preferencesRepository.apply { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/AppMenuItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/AppMenuItem.kt deleted file mode 100644 index f522913ac..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/AppMenuItem.kt +++ /dev/null @@ -1,206 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import io.github.wulkanowy.R -import io.github.wulkanowy.ui.modules.Destination -import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient - -@Serializable -sealed class AppMenuItem { - - companion object { - val defaultAppMenuItemList = setOf( - DashboardAppMenuItem(), - GradeAppMenuItem(), - TimetableAppMenuItem(), - AttendanceAppMenuItem(), - ExamsAppMenuItem(), - HomeworkAppMenuItem(), - NoteAppMenuItem(), - LuckyNumberAppMenuItem(), - SchoolAnnouncementsAppMenuItem(), - SchoolAndTeachersAppMenuItem(), - MobileDevicesAppMenuItem(), - ConferenceAppMenuItem(), - MessageAppMenuItem() - ).sortedBy { it.order } - } - - // https://youtrack.jetbrains.com/issue/KT-38958 - abstract var order: Int - - abstract val icon: Int - - abstract val title: Int - - abstract val destinationType: Destination.Type - - @Serializable - data class DashboardAppMenuItem(override var order: Int = 0) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_main_dashboard - - @Transient - override val title = R.string.dashboard_title - - @Transient - override val destinationType = Destination.Type.DASHBOARD - } - - @Serializable - data class GradeAppMenuItem(override var order: Int = 1) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_main_grade - - @Transient - override val title = R.string.grade_title - - @Transient - override val destinationType = Destination.Type.GRADE - } - - @Serializable - data class AttendanceAppMenuItem(override var order: Int = 2) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_main_attendance - - @Transient - override val title = R.string.attendance_title - - @Transient - override val destinationType = Destination.Type.ATTENDANCE - } - - @Serializable - data class TimetableAppMenuItem(override var order: Int = 3) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_main_timetable - - @Transient - override val title = R.string.timetable_title - - @Transient - override val destinationType = Destination.Type.TIMETABLE - } - - @Serializable - data class MessageAppMenuItem(override var order: Int = 4) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_messages - - @Transient - override val title = R.string.message_title - - @Transient - override val destinationType = Destination.Type.MESSAGE - } - - @Serializable - data class ExamsAppMenuItem(override var order: Int = 5) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_main_exam - - @Transient - override val title = R.string.exam_title - - @Transient - override val destinationType = Destination.Type.EXAM - } - - @Serializable - data class HomeworkAppMenuItem(override var order: Int = 6) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_homework - - @Transient - override val title = R.string.homework_title - - @Transient - override val destinationType = Destination.Type.HOMEWORK - } - - @Serializable - data class NoteAppMenuItem(override var order: Int = 7) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_note - - @Transient - override val title = R.string.note_title - - @Transient - override val destinationType = Destination.Type.NOTE - } - - @Serializable - data class LuckyNumberAppMenuItem(override var order: Int = 8) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_lucky_number - - @Transient - override val title = R.string.lucky_number_title - - @Transient - override val destinationType = Destination.Type.LUCKY_NUMBER - } - - @Serializable - data class ConferenceAppMenuItem(override var order: Int = 9) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_conferences - - @Transient - override val title = R.string.conferences_title - - @Transient - override val destinationType = Destination.Type.CONFERENCE - } - - @Serializable - data class SchoolAnnouncementsAppMenuItem(override var order: Int = 10) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_all_about - - @Transient - override val title = R.string.school_announcement_title - - @Transient - override val destinationType = Destination.Type.SCHOOL_ANNOUNCEMENT - } - - @Serializable - data class SchoolAndTeachersAppMenuItem(override var order: Int = 11) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_schoolandteachers - - @Transient - override val title = R.string.schoolandteachers_title - - @Transient - override val destinationType = Destination.Type.SCHOOL_AND_TEACHERS - } - - @Serializable - data class MobileDevicesAppMenuItem(override var order: Int = 12) : AppMenuItem() { - - @Transient - override val icon = R.drawable.ic_more_mobile_devices - - @Transient - override val title = R.string.mobile_devices_title - - @Transient - override val destinationType = Destination.Type.MOBILE_DEVICE - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuItemMoveCallback.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuItemMoveCallback.kt deleted file mode 100644 index 49196fad2..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuItemMoveCallback.kt +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.RecyclerView -import java.util.* - -class MenuItemMoveCallback( - private val menuOrderAdapter: MenuOrderAdapter, - private var onUserInteractionEndListener: (List) -> Unit = {} -) : ItemTouchHelper.Callback() { - - override fun isLongPressDragEnabled() = true - - override fun isItemViewSwipeEnabled() = false - - override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - //Not implemented - } - - override fun getMovementFlags( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder - ) = makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) - - override fun onMove( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder - ): Boolean { - val list = menuOrderAdapter.items.toMutableList() - - Collections.swap(list, viewHolder.bindingAdapterPosition, target.bindingAdapterPosition) - - menuOrderAdapter.submitList(list) - return true - } - - override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { - super.clearView(recyclerView, viewHolder) - - onUserInteractionEndListener(menuOrderAdapter.items.toList()) - } -} - diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt deleted file mode 100644 index 6bdd2fe0c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderAdapter.kt +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.databinding.ItemMenuOrderBinding -import javax.inject.Inject - -class MenuOrderAdapter @Inject constructor() : - RecyclerView.Adapter() { - - val items = mutableListOf() - - fun submitList(newItems: List) { - val diffResult = DiffUtil.calculateDiff(DiffCallback(newItems, items.toMutableList())) - - with(items) { - clear() - addAll(newItems) - } - - diffResult.dispatchUpdatesTo(this) - } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( - ItemMenuOrderBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val item = items[position].appMenuItem - - with(holder.binding) { - menuOrderItemTitle.setText(item.title) - menuOrderItemIcon.setImageResource(item.icon) - } - } - - class ViewHolder(val binding: ItemMenuOrderBinding) : RecyclerView.ViewHolder(binding.root) - - private class DiffCallback( - private val oldList: List, - private val newList: List - ) : DiffUtil.Callback() { - - override fun getNewListSize() = newList.size - - override fun getOldListSize() = oldList.size - - override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = - oldList[oldItemPosition] == newList[newItemPosition] - - override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = - oldList[oldItemPosition].appMenuItem.destinationType == newList[newItemPosition].appMenuItem.destinationType - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt deleted file mode 100644 index 21a7f5e80..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderDividerItemDecoration.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Rect -import android.graphics.drawable.ShapeDrawable -import android.view.View -import androidx.core.graphics.drawable.DrawableCompat -import androidx.core.view.forEach -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.utils.getThemeAttrColor - -class MenuOrderDividerItemDecoration(private val context: Context) : - DividerItemDecoration(context, VERTICAL) { - - private val dividerDrawable = ShapeDrawable() - .apply { - DrawableCompat.setTint(this, context.getThemeAttrColor(R.attr.colorDivider)) - } - - override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { - canvas.save() - val dividerLeft = parent.paddingLeft - val dividerRight = parent.width - parent.paddingRight - - parent.forEach { - if (parent.getChildAdapterPosition(it) == 3) { - val params = it.layoutParams as RecyclerView.LayoutParams - val dividerTop = it.bottom + params.bottomMargin - val dividerBottom = dividerTop + dividerDrawable.intrinsicHeight - - dividerDrawable.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom + 30) - dividerDrawable.draw(canvas) - } - } - - canvas.restore() - } - - override fun getItemOffsets( - outRect: Rect, view: View, parent: RecyclerView, - state: RecyclerView.State - ) { - if (parent.getChildAdapterPosition(view) == 3) { - outRect.bottom = dividerDrawable.intrinsicHeight + 30 - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt deleted file mode 100644 index e08fc5dd3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderFragment.kt +++ /dev/null @@ -1,101 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import androidx.activity.addCallback -import androidx.core.view.MenuProvider -import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.SimpleItemAnimator -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentMenuOrderBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import javax.inject.Inject - - -@AndroidEntryPoint -class MenuOrderFragment : BaseFragment(R.layout.fragment_menu_order), - MenuOrderView, MainView.TitledView { - - @Inject - lateinit var presenter: MenuOrderPresenter - - @Inject - lateinit var menuOrderAdapter: MenuOrderAdapter - - override val titleStringId = R.string.menu_order_title - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMenuOrderBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - val itemTouchHelper = ItemTouchHelper( - MenuItemMoveCallback(menuOrderAdapter, presenter::onDragAndDropEnd) - ) - - itemTouchHelper.attachToRecyclerView(binding.menuOrderRecycler) - - with(binding.menuOrderRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = menuOrderAdapter - addItemDecoration(MenuOrderDividerItemDecoration(context)) - addItemDecoration(DividerItemDecoration(context)) - (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false - } - - requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { - presenter.onBackSelected() - } - - initializeToolbar() - } - - private fun initializeToolbar() { - requireActivity().addMenuProvider(object : MenuProvider { - override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { - } - - override fun onMenuItemSelected(menuItem: MenuItem): Boolean { - if (menuItem.itemId == android.R.id.home) { - presenter.onBackSelected() - return true - } - return false - } - - }, viewLifecycleOwner) - } - - override fun updateData(data: List) { - menuOrderAdapter.submitList(data) - } - - override fun restartApp() { - startActivity(MainActivity.getStartIntent(requireContext())) - requireActivity().finishAffinity() - } - - override fun popView() { - (activity as? MainActivity?)?.popView() - } - - override fun showRestartConfirmationDialog() { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.menu_order_confirm_title) - .setMessage(R.string.menu_order_confirm_content) - .setPositiveButton(R.string.menu_order_confirm_restart) { _, _ -> presenter.onConfirmRestart() } - .setNegativeButton(R.string.all_cancel) { _, _ -> presenter.onCancelRestart() } - .show() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt deleted file mode 100644 index b82bc1bd2..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderItem.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -data class MenuOrderItem( - val appMenuItem: AppMenuItem, - val order: Int -) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt deleted file mode 100644 index 1c90cc5e6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderPresenter.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -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 timber.log.Timber -import javax.inject.Inject - -class MenuOrderPresenter @Inject constructor( - studentRepository: StudentRepository, - errorHandler: ErrorHandler, - private val preferencesRepository: PreferencesRepository -) : BasePresenter(errorHandler, studentRepository) { - - private var updatedMenuOrderItems = emptyList() - - override fun onAttachView(view: MenuOrderView) { - super.onAttachView(view) - view.initView() - Timber.i("Menu order view was initialized") - loadData() - } - - private fun loadData() { - val savedMenuItemList = (preferencesRepository.appMenuItemOrder) - .sortedBy { it.order } - .map { MenuOrderItem(it, it.order) } - - view?.updateData(savedMenuItemList) - } - - fun onDragAndDropEnd(list: List) { - val updatedList = list.mapIndexed { index, menuOrderItem -> - menuOrderItem.copy(order = index) - } - - updatedMenuOrderItems = updatedList - view?.updateData(updatedList) - } - - fun onBackSelected() { - if (updatedMenuOrderItems.isNotEmpty()) { - view?.showRestartConfirmationDialog() - } else { - view?.popView() - } - } - - fun onConfirmRestart() { - updatedMenuOrderItems.forEach { - it.appMenuItem.apply { - order = it.order - } - } - - preferencesRepository.appMenuItemOrder = updatedMenuOrderItems.map { it.appMenuItem } - view?.restartApp() - } - - fun onCancelRestart() { - view?.popView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt deleted file mode 100644 index 264e68ccb..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/menuorder/MenuOrderView.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance.menuorder - -import io.github.wulkanowy.ui.base.BaseView - -interface MenuOrderView : BaseView { - - fun initView() - - fun updateData(data: List) - - fun restartApp() - - fun showRestartConfirmationDialog() - - fun popView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt index 0bf9ddadd..364ad2137 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt @@ -1,20 +1,22 @@ package io.github.wulkanowy.ui.modules.settings.notifications +import android.annotation.SuppressLint import android.content.Intent import android.content.SharedPreferences -import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build import android.os.Bundle +import android.provider.Settings import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AlertDialog import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.thelittlefireman.appkillermanager.AppKillerManager import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException import dagger.hilt.android.AndroidEntryPoint @@ -24,7 +26,7 @@ import io.github.wulkanowy.ui.base.ErrorDialog import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.openNotificationSettings +import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint @@ -40,14 +42,7 @@ class NotificationsFragment : PreferenceFragmentCompat(), override val titleStringId get() = R.string.pref_settings_notifications_title - private val notificationsPermission = "android.permission.POST_NOTIFICATIONS" - override val isNotificationPermissionGranted: Boolean - get() = ContextCompat.checkSelfPermission( - requireContext(), notificationsPermission - ) == PackageManager.PERMISSION_GRANTED - - override val isNotificationPiggybackPermissionGranted: Boolean get() { val packageNameList = NotificationManagerCompat.getEnabledListenerPackages(requireContext()) @@ -56,13 +51,6 @@ class NotificationsFragment : PreferenceFragmentCompat(), return appPackageName in packageNameList } - private val requestPermissionLauncher = - registerForActivityResult(ActivityResultContracts.RequestPermission()) { - if (it) { - presenter.onNotificationsPermissionResult() - } else openNotificationsPermissionDialog() - } - private val notificationSettingsPiggybackContract = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { presenter.onNotificationPiggybackPermissionResult() @@ -113,7 +101,7 @@ class NotificationsFragment : PreferenceFragmentCompat(), setPreferencesFromResource(R.xml.scheme_preferences_notifications, rootKey) } - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { presenter.onSharedPreferenceChanged(key) } @@ -132,16 +120,8 @@ class NotificationsFragment : PreferenceFragmentCompat(), (activity as? BaseActivity<*, *>)?.showMessage(text) } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun showChangePasswordSnackbar(redirectUrl: String) { @@ -156,12 +136,8 @@ class NotificationsFragment : PreferenceFragmentCompat(), ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() - } - override fun showFixSyncDialog() { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(R.string.pref_notify_fix_sync_issues) .setMessage(R.string.pref_notify_fix_sync_issues_message) .setNegativeButton(android.R.string.cancel) { _, _ -> } @@ -180,30 +156,26 @@ class NotificationsFragment : PreferenceFragmentCompat(), .show() } + @SuppressLint("InlinedApi") override fun openSystemSettings() { - requireActivity().openNotificationSettings() - } - - override fun requestNotificationPermissions() { - requestPermissionLauncher.launch(notificationsPermission) - } - - override fun openNotificationsPermissionDialog() { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.notifications_header_title) - .setMessage(R.string.notifications_header_description) - .setPositiveButton(R.string.pref_notification_go_to_settings) { _, _ -> - requireActivity().openNotificationSettings() + val intent = if (appInfo.systemVersion >= Build.VERSION_CODES.O) { + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra("android.provider.extra.APP_PACKAGE", requireActivity().packageName) } - .setNegativeButton(android.R.string.cancel) { _, _ -> - setNotificationPreferencesChecked(false) + } else { + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", requireActivity().packageName, null) } - .setOnDismissListener { setNotificationPreferencesChecked(false) } - .show() + } + try { + requireActivity().startActivity(intent) + } catch (e: Exception) { + Timber.e(e) + } } - override fun openNotificationPiggyBackPermissionDialog() { - MaterialAlertDialogBuilder(requireContext()) + override fun openNotificationPermissionDialog() { + AlertDialog.Builder(requireContext()) .setTitle(getString(R.string.pref_notification_piggyback_popup_title)) .setMessage(getString(R.string.pref_notification_piggyback_popup_description)) .setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ -> @@ -217,7 +189,7 @@ class NotificationsFragment : PreferenceFragmentCompat(), } override fun openNotificationExactAlarmSettings() { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(getString(R.string.pref_notification_exact_alarm_popup_title)) .setMessage(getString(R.string.pref_notification_exact_alarm_popup_descriptions)) .setPositiveButton(getString(R.string.pref_notification_go_to_settings)) { _, _ -> @@ -230,11 +202,6 @@ class NotificationsFragment : PreferenceFragmentCompat(), .show() } - override fun setNotificationPreferencesChecked(isChecked: Boolean) { - findPreference(getString(R.string.pref_key_notifications_enable))?.isChecked = - isChecked - } - override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) { findPreference(getString(R.string.pref_key_notifications_piggyback))?.isChecked = isChecked diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt index b2938cf65..4cbdac945 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt @@ -26,20 +26,18 @@ class NotificationsPresenter @Inject constructor( with(view) { enableNotification( - notificationKey = preferencesRepository.notificationsEnableKey, - enable = preferencesRepository.isServiceEnabled + preferencesRepository.notificationsEnableKey, + preferencesRepository.isServiceEnabled ) initView(appInfo.isDebug) } - checkNotificationsPermissionState() checkNotificationPiggybackState() Timber.i("Settings notifications view was initialized") } - fun onSharedPreferenceChanged(key: String?) { - key ?: return + fun onSharedPreferenceChanged(key: String) { Timber.i("Change settings $key") preferencesRepository.apply { @@ -51,17 +49,12 @@ class NotificationsPresenter @Inject constructor( view?.openNotificationExactAlarmSettings() } } - notificationsEnableKey -> { - if (isNotificationsEnable && view?.isNotificationPermissionGranted == false) { - view?.requestNotificationPermissions() - } - } isDebugNotificationEnableKey -> { chuckerCollector.showNotification = isDebugNotificationEnable } isNotificationPiggybackEnabledKey -> { - if (isNotificationPiggybackEnabled && view?.isNotificationPiggybackPermissionGranted == false) { - view?.openNotificationPiggyBackPermissionDialog() + if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) { + view?.openNotificationPermissionDialog() } } } @@ -77,15 +70,9 @@ class NotificationsPresenter @Inject constructor( view?.openSystemSettings() } - fun onNotificationsPermissionResult() { - view?.run { - setNotificationPreferencesChecked(isNotificationPermissionGranted) - } - } - fun onNotificationPiggybackPermissionResult() { view?.run { - setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted) + setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted) } } @@ -93,18 +80,10 @@ class NotificationsPresenter @Inject constructor( view?.setUpcomingLessonsNotificationPreferenceChecked(timetableNotificationHelper.canScheduleExactAlarms()) } - private fun checkNotificationsPermissionState() { - if (preferencesRepository.isNotificationsEnable) { - view?.run { - setNotificationPreferencesChecked(isNotificationPermissionGranted) - } - } - } - private fun checkNotificationPiggybackState() { if (preferencesRepository.isNotificationPiggybackEnabled) { view?.run { - setNotificationPiggybackPreferenceChecked(isNotificationPiggybackPermissionGranted) + setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt index a391681cb..2bf8e31f4 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt @@ -6,8 +6,6 @@ interface NotificationsView : BaseView { val isNotificationPermissionGranted: Boolean - val isNotificationPiggybackPermissionGranted: Boolean - fun initView(showDebugNotificationSwitch: Boolean) fun showFixSyncDialog() @@ -16,16 +14,10 @@ interface NotificationsView : BaseView { fun enableNotification(notificationKey: String, enable: Boolean) - fun requestNotificationPermissions() - - fun openNotificationsPermissionDialog() - - fun openNotificationPiggyBackPermissionDialog() + fun openNotificationPermissionDialog() fun openNotificationExactAlarmSettings() - fun setNotificationPreferencesChecked(isChecked: Boolean) - fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) fun setUpcomingLessonsNotificationPreferenceChecked(isChecked: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt index d57144832..8477e3222 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt @@ -5,7 +5,6 @@ import android.os.Bundle import android.view.View import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.ui.base.BaseActivity @@ -51,7 +50,7 @@ class SyncFragment : PreferenceFragmentCompat(), setPreferencesFromResource(R.xml.scheme_preferences_sync, rootKey) } - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { presenter.onSharedPreferenceChanged(key) } @@ -76,23 +75,11 @@ class SyncFragment : PreferenceFragmentCompat(), } override fun showMessage(text: String) { - Snackbar.make(requireView(), text, Snackbar.LENGTH_LONG) - .apply { - anchorView = requireActivity().findViewById(R.id.main_bottom_nav) - show() - } + (activity as? BaseActivity<*, *>)?.showMessage(text) } - override fun showExpiredCredentialsDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredCredentialsDialog() - } - - override fun onCaptchaVerificationRequired(url: String?) { - (activity as? BaseActivity<*, *>)?.onCaptchaVerificationRequired(url) - } - - override fun showDecryptionFailedDialog() { - (activity as? BaseActivity<*, *>)?.showDecryptionFailedDialog() + override fun showExpiredDialog() { + (activity as? BaseActivity<*, *>)?.showExpiredDialog() } override fun showChangePasswordSnackbar(redirectUrl: String) { @@ -107,10 +94,6 @@ class SyncFragment : PreferenceFragmentCompat(), ErrorDialog.newInstance(error).show(childFragmentManager, "error_details") } - override fun showAuthDialog() { - (activity as? BaseActivity<*, *>)?.showAuthDialog() - } - override fun onResume() { super.onResume() preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt index 594e097af..1ecb4a6ef 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt @@ -31,8 +31,7 @@ class SyncPresenter @Inject constructor( setSyncDateInView() } - fun onSharedPreferenceChanged(key: String?) { - key ?: return + fun onSharedPreferenceChanged(key: String) { Timber.i("Change settings $key") preferencesRepository.apply { @@ -53,12 +52,10 @@ class SyncPresenter @Inject constructor( Timber.i("Setting sync now started") analytics.logEvent("sync_now", "status" to "started") } - WorkInfo.State.SUCCEEDED -> { showMessage(syncSuccessString) analytics.logEvent("sync_now", "status" to "success") } - WorkInfo.State.FAILED -> { showError( syncFailedString, @@ -69,7 +66,6 @@ class SyncPresenter @Inject constructor( ) analytics.logEvent("sync_now", "status" to "failed") } - else -> Timber.d("Sync now state: ${workInfo?.state}") } if (workInfo?.state?.isFinished == true) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt index 598046a2d..361a59440 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/studentinfo/StudentInfoFragment.kt @@ -8,7 +8,6 @@ import android.view.MenuInflater import android.view.View import android.widget.Toast import androidx.core.content.getSystemService -import androidx.core.os.bundleOf import androidx.core.view.get import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager @@ -25,8 +24,6 @@ import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.capitalise import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.nullableSerializable -import io.github.wulkanowy.utils.serializable import javax.inject.Inject @AndroidEntryPoint @@ -41,9 +38,7 @@ class StudentInfoFragment : lateinit var studentInfoAdapter: StudentInfoAdapter override val titleStringId: Int - get() = when ( - requireArguments().nullableSerializable(INFO_TYPE_ARGUMENT_KEY) - ) { + get() = when (requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as? StudentInfoView.Type) { StudentInfoView.Type.PERSONAL -> R.string.account_personal_data StudentInfoView.Type.CONTACT -> R.string.account_contact StudentInfoView.Type.ADDRESS -> R.string.account_address @@ -63,14 +58,13 @@ class StudentInfoFragment : fun newInstance(type: StudentInfoView.Type, studentWithSemesters: StudentWithSemesters) = StudentInfoFragment().apply { - arguments = bundleOf( - INFO_TYPE_ARGUMENT_KEY to type, - STUDENT_ARGUMENT_KEY to studentWithSemesters - ) + arguments = Bundle().apply { + putSerializable(INFO_TYPE_ARGUMENT_KEY, type) + putSerializable(STUDENT_ARGUMENT_KEY, studentWithSemesters) + } } } - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -80,9 +74,9 @@ class StudentInfoFragment : super.onViewCreated(view, savedInstanceState) binding = FragmentStudentInfoBinding.bind(view) presenter.onAttachView( - view = this, - type = requireArguments().serializable(INFO_TYPE_ARGUMENT_KEY), - studentWithSemesters = requireArguments().serializable(STUDENT_ARGUMENT_KEY), + this, + requireArguments().getSerializable(INFO_TYPE_ARGUMENT_KEY) as StudentInfoView.Type, + requireArguments().getSerializable(STUDENT_ARGUMENT_KEY) as StudentWithSemesters ) } @@ -159,6 +153,7 @@ class StudentInfoFragment : ) } + @OptIn(ExperimentalStdlibApi::class) override fun showFamilyTypeData(studentInfo: StudentInfo) { val items = buildList { add(studentInfo.firstGuardian?.let { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt index a4221a2a2..2f0d697fc 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt @@ -12,9 +12,7 @@ import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.databinding.ItemTimetableBinding -import io.github.wulkanowy.databinding.ItemTimetableEmptyBinding import io.github.wulkanowy.databinding.ItemTimetableSmallBinding -import io.github.wulkanowy.utils.getPlural import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.toFormattedString import javax.inject.Inject @@ -27,18 +25,13 @@ class TimetableAdapter @Inject constructor() : override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) - return when (TimetableItemType.entries[viewType]) { + return when (TimetableItemType.values()[viewType]) { TimetableItemType.SMALL -> SmallViewHolder( ItemTimetableSmallBinding.inflate(inflater, parent, false) ) - TimetableItemType.NORMAL -> NormalViewHolder( ItemTimetableBinding.inflate(inflater, parent, false) ) - - TimetableItemType.EMPTY -> EmptyViewHolder( - ItemTimetableEmptyBinding.inflate(inflater, parent, false) - ) } } @@ -47,12 +40,12 @@ class TimetableAdapter @Inject constructor() : position: Int, payloads: MutableList ) { - if (payloads.isNotEmpty() && holder is NormalViewHolder) { - updateTimeLeft( - binding = holder.binding, - timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft, - ) - } else super.onBindViewHolder(holder, position, payloads) + if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, payloads) + + if (holder is NormalViewHolder) updateTimeLeft( + binding = holder.binding, + timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft, + ) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { @@ -61,16 +54,10 @@ class TimetableAdapter @Inject constructor() : binding = holder.binding, item = getItem(position) as TimetableItem.Small, ) - is NormalViewHolder -> bindNormalView( binding = holder.binding, item = getItem(position) as TimetableItem.Normal, ) - - is EmptyViewHolder -> bindEmptyView( - binding = holder.binding, - item = getItem(position) as TimetableItem.Empty, - ) } } @@ -79,7 +66,6 @@ class TimetableAdapter @Inject constructor() : with(binding) { timetableSmallItemNumber.text = lesson.number.toString() - timetableSmallItemNumber.isVisible = item.isLessonNumberVisible timetableSmallItemSubject.text = lesson.subject timetableSmallItemTimeStart.text = lesson.start.toFormattedString("HH:mm") timetableSmallItemRoom.text = lesson.room @@ -98,7 +84,6 @@ class TimetableAdapter @Inject constructor() : with(binding) { timetableItemNumber.text = lesson.number.toString() - timetableItemNumber.isVisible = item.isLessonNumberVisible timetableItemSubject.text = lesson.subject timetableItemGroup.text = lesson.group timetableItemRoom.text = lesson.room @@ -115,19 +100,6 @@ class TimetableAdapter @Inject constructor() : } } - private fun bindEmptyView(binding: ItemTimetableEmptyBinding, item: TimetableItem.Empty) { - with(binding) { - timetableEmptyItemNumber.text = when (item.numFrom) { - item.numTo -> item.numFrom.toString() - else -> "${item.numFrom}-${item.numTo}" - } - timetableEmptyItemSubject.text = timetableEmptyItemSubject.context.getPlural( - R.plurals.timetable_no_lesson, - item.numTo - item.numFrom + 1 - ) - } - } - private fun updateTimeLeft(binding: ItemTimetableBinding, timeLeft: TimeLeft?) { with(binding) { when { @@ -165,7 +137,6 @@ class TimetableAdapter @Inject constructor() : timetableItemTimeLeft.visibility = VISIBLE timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished) } - else -> { timetableItemTimeUntil.visibility = GONE timetableItemTimeLeft.visibility = GONE @@ -189,7 +160,7 @@ class TimetableAdapter @Inject constructor() : timetableSmallItemDescription.setTextColor( root.context.getThemeAttrColor( - if (lesson.canceled) R.attr.colorTimetableCanceled + if (lesson.canceled) R.attr.colorPrimary else R.attr.colorTimetableChange ) ) @@ -214,14 +185,13 @@ class TimetableAdapter @Inject constructor() : timetableItemDescription.setTextColor( root.context.getThemeAttrColor( - if (lesson.canceled) R.attr.colorTimetableCanceled + if (lesson.canceled) R.attr.colorPrimary else R.attr.colorTimetableChange ) ) } else { timetableItemDescription.visibility = GONE - timetableItemRoom.isVisible = - lesson.room.isNotBlank() || lesson.roomOld.isNotBlank() + timetableItemRoom.isVisible = lesson.room.isNotBlank() || lesson.roomOld.isNotBlank() timetableItemGroup.isVisible = item.showGroupsInPlan && lesson.group.isNotBlank() timetableItemTeacher.visibility = VISIBLE } @@ -258,8 +228,8 @@ class TimetableAdapter @Inject constructor() : } private fun updateNumberAndSubjectCanceledColor(numberView: TextView, subjectView: TextView) { - numberView.setTextColor(numberView.context.getThemeAttrColor(R.attr.colorTimetableCanceled)) - subjectView.setTextColor(subjectView.context.getThemeAttrColor(R.attr.colorTimetableCanceled)) + numberView.setTextColor(numberView.context.getThemeAttrColor(R.attr.colorPrimary)) + subjectView.setTextColor(subjectView.context.getThemeAttrColor(R.attr.colorPrimary)) } private fun updateNumberColor(numberView: TextView, lesson: Timetable) { @@ -304,9 +274,6 @@ class TimetableAdapter @Inject constructor() : private class SmallViewHolder(val binding: ItemTimetableSmallBinding) : RecyclerView.ViewHolder(binding.root) - private class EmptyViewHolder(val binding: ItemTimetableEmptyBinding) : - RecyclerView.ViewHolder(binding.root) - companion object { private val differ = object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: TimetableItem, newItem: TimetableItem): Boolean = @@ -314,11 +281,9 @@ class TimetableAdapter @Inject constructor() : oldItem is TimetableItem.Small && newItem is TimetableItem.Small -> { oldItem.lesson.start == newItem.lesson.start } - oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal -> { oldItem.lesson.start == newItem.lesson.start } - else -> oldItem == newItem } @@ -327,7 +292,7 @@ class TimetableAdapter @Inject constructor() : override fun getChangePayload(oldItem: TimetableItem, newItem: TimetableItem): Any? { return if (oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal) { - if (oldItem.lesson == newItem.lesson && oldItem.showGroupsInPlan == newItem.showGroupsInPlan && oldItem.timeLeft != newItem.timeLeft) { + if (oldItem.lesson == newItem.lesson && oldItem.timeLeft != newItem.timeLeft) { "time_left" } else super.getChangePayload(oldItem, newItem) } else super.getChangePayload(oldItem, newItem) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt index e8a853479..c9243b12e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt @@ -1,24 +1,26 @@ package io.github.wulkanowy.ui.modules.timetable import android.annotation.SuppressLint -import android.app.Dialog import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG import android.os.Bundle +import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.View.VISIBLE -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.databinding.DialogTimetableBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.* +import io.github.wulkanowy.utils.capitalise +import io.github.wulkanowy.utils.getThemeAttrColor +import io.github.wulkanowy.utils.lifecycleAwareVariable +import io.github.wulkanowy.utils.toFormattedString import java.time.Instant -@AndroidEntryPoint -class TimetableDialog : BaseDialogFragment() { +class TimetableDialog : DialogFragment() { + + private var binding: DialogTimetableBinding by lifecycleAwareVariable() private lateinit var lesson: Timetable @@ -26,21 +28,24 @@ class TimetableDialog : BaseDialogFragment() { private const val ARGUMENT_KEY = "Item" - fun newInstance(lesson: Timetable) = TimetableDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to lesson) + fun newInstance(exam: Timetable) = TimetableDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - lesson = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + lesson = getSerializable(ARGUMENT_KEY) as Timetable + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView(DialogTimetableBinding.inflate(layoutInflater).apply { binding = this }.root) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogTimetableBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -81,12 +86,12 @@ class TimetableDialog : BaseDialogFragment() { if (canceled) { timetableDialogChangesTitle.setTextColor( requireContext().getThemeAttrColor( - R.attr.colorTimetableCanceled + R.attr.colorPrimary ) ) timetableDialogChangesValue.setTextColor( requireContext().getThemeAttrColor( - R.attr.colorTimetableCanceled + R.attr.colorPrimary ) ) } else { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt index 0e6459110..fdd4aface 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt @@ -7,9 +7,7 @@ import android.view.MenuItem import android.view.View import android.view.View.GONE import android.view.View.VISIBLE -import androidx.core.os.bundleOf import androidx.core.text.parseAsHtml -import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -41,7 +39,9 @@ class TimetableFragment : BaseFragment(R.layout.fragme private const val ARGUMENT_DATE_KEY = "ARGUMENT_DATE" fun newInstance(date: LocalDate? = null) = TimetableFragment().apply { - arguments = date?.let { bundleOf(ARGUMENT_DATE_KEY to it.toEpochDay()) } + arguments = Bundle().apply { + date?.let { putLong(ARGUMENT_DATE_KEY, it.toEpochDay()) } + } } } @@ -51,7 +51,6 @@ class TimetableFragment : BaseFragment(R.layout.fragme override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize - @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) @@ -88,7 +87,7 @@ class TimetableFragment : BaseFragment(R.layout.fragme timetableNavDate.setOnClickListener { presenter.onPickDate() } timetableNextButton.setOnClickListener { presenter.onNextDay() } - timetableNavContainer.elevation = requireContext().dpToPx(3f) + timetableNavContainer.elevation = requireContext().dpToPx(8f) } } @@ -161,10 +160,6 @@ class TimetableFragment : BaseFragment(R.layout.fragme binding.timetableRecycler.visibility = if (show) VISIBLE else GONE } - override fun showNavigation(show: Boolean) { - binding.timetableNavContainer.isVisible = true - } - override fun showPreButton(show: Boolean) { binding.timetablePreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE } @@ -198,9 +193,7 @@ class TimetableFragment : BaseFragment(R.layout.fragme override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - presenter.currentDate?.toEpochDay()?.let { - outState.putLong(SAVED_DATE_KEY, it) - } + outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) } override fun onDestroyView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt index 402b03dd9..92716ace8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableItem.kt @@ -7,22 +7,15 @@ sealed class TimetableItem(val type: TimetableItemType) { data class Small( val lesson: Timetable, - val isLessonNumberVisible: Boolean, val onClick: (Timetable) -> Unit, ) : TimetableItem(TimetableItemType.SMALL) data class Normal( val lesson: Timetable, val showGroupsInPlan: Boolean, - val isLessonNumberVisible: Boolean, val timeLeft: TimeLeft?, val onClick: (Timetable) -> Unit, ) : TimetableItem(TimetableItemType.NORMAL) - - data class Empty( - val numFrom: Int, - val numTo: Int - ) : TimetableItem(TimetableItemType.EMPTY) } data class TimeLeft( @@ -34,5 +27,4 @@ data class TimeLeft( enum class TimetableItemType { SMALL, NORMAL, - EMPTY } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt index 8ef0772b8..d06874082 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt @@ -1,46 +1,23 @@ package io.github.wulkanowy.ui.modules.timetable -import android.os.Handler -import android.os.Looper -import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.* import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS -import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS import io.github.wulkanowy.data.enums.TimetableMode -import io.github.wulkanowy.data.flatResourceFlow -import io.github.wulkanowy.data.logResourceStatus -import io.github.wulkanowy.data.onResourceData -import io.github.wulkanowy.data.onResourceError -import io.github.wulkanowy.data.onResourceIntermediate -import io.github.wulkanowy.data.onResourceNotLoading -import io.github.wulkanowy.data.onResourceSuccess 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.domain.timetable.IsStudentHasLessonsOnWeekendUseCase -import io.github.wulkanowy.domain.timetable.IsWeekendHasLessonsUseCase 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.capitalise -import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday -import io.github.wulkanowy.utils.isHolidays -import io.github.wulkanowy.utils.isJustFinished -import io.github.wulkanowy.utils.isShowTimeUntil -import io.github.wulkanowy.utils.left -import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.nextSchoolDay -import io.github.wulkanowy.utils.previousSchoolDay -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.utils.until +import io.github.wulkanowy.utils.* +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.onEach import timber.log.Timber import java.time.Instant import java.time.LocalDate -import java.time.LocalDate.now -import java.time.LocalDate.of -import java.time.LocalDate.ofEpochDay -import java.util.Timer +import java.time.LocalDate.* +import java.util.* import javax.inject.Inject import kotlin.concurrent.timer @@ -48,18 +25,14 @@ class TimetablePresenter @Inject constructor( errorHandler: ErrorHandler, studentRepository: StudentRepository, private val timetableRepository: TimetableRepository, - private val isStudentHasLessonsOnWeekendUseCase: IsStudentHasLessonsOnWeekendUseCase, - private val isWeekendHasLessonsUseCase: IsWeekendHasLessonsUseCase, private val semesterRepository: SemesterRepository, private val prefRepository: PreferencesRepository, private val analytics: AnalyticsHelper, ) : BasePresenter(errorHandler, studentRepository) { - private var initialDate: LocalDate? = null - private var isWeekendHasLessons: Boolean = false - private var isEduOne: Boolean = false + private var baseDate: LocalDate = now().nextOrSameSchoolDay - var currentDate: LocalDate? = null + lateinit var currentDate: LocalDate private set private lateinit var lastError: Throwable @@ -71,30 +44,23 @@ class TimetablePresenter @Inject constructor( view.initView() Timber.i("Timetable was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - currentDate = date?.let(::ofEpochDay) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) loadData() + if (currentDate.isHolidays) setBaseDateOnHolidays() } fun onPreviousDay() { - val date = if (isWeekendHasLessons) { - currentDate?.minusDays(1) - } else currentDate?.previousSchoolDay - - reloadView(date ?: return) + reloadView(currentDate.previousSchoolDay) loadData() } fun onNextDay() { - val date = if (isWeekendHasLessons) { - currentDate?.plusDays(1) - } else currentDate?.nextSchoolDay - - reloadView(date ?: return) + reloadView(currentDate.nextSchoolDay) loadData() } fun onPickDate() { - view?.showDatePickerDialog(currentDate ?: return) + view?.showDatePickerDialog(currentDate) } fun onDateSet(year: Int, month: Int, day: Int) { @@ -123,8 +89,10 @@ class TimetablePresenter @Inject constructor( Timber.i("Timetable view is reselected") view?.let { view -> if (view.currentStackSize == 1) { - if (currentDate != initialDate) { - reloadView(initialDate ?: return) + baseDate = now().nextOrSameSchoolDay + + if (currentDate != baseDate) { + reloadView(baseDate) loadData() } else if (!view.isViewEmpty) { view.resetView() @@ -145,26 +113,34 @@ class TimetablePresenter @Inject constructor( return true } + private fun setBaseDateOnHolidays() { + flow { + val student = studentRepository.getCurrentStudent() + emit(semesterRepository.getCurrentSemester(student)) + }.catch { + Timber.i("Loading semester result: An exception occurred") + }.onEach { + baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) + currentDate = baseDate + reloadNavigation() + }.launch("holidays") + } + private fun loadData(forceRefresh: Boolean = false) { flatResourceFlow { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - - isEduOne = student.isEduOne == true - checkInitialAndCurrentDate(semester) timetableRepository.getTimetable( student = student, semester = semester, - start = currentDate ?: now(), - end = currentDate ?: now(), + start = currentDate, + end = currentDate, forceRefresh = forceRefresh, timetableType = TimetableRepository.TimetableType.NORMAL ) } .logResourceStatus("load timetable data") .onResourceData { - isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessonsUseCase(it.lessons) - view?.run { enableSwipe(true) showProgress(false) @@ -172,8 +148,7 @@ class TimetablePresenter @Inject constructor( showContent(it.lessons.isNotEmpty()) showEmpty(it.lessons.isEmpty()) updateData(it.lessons) - setDayHeaderMessage(it.headers.find { header -> header.date == currentDate }?.content) - reloadNavigation() + setDayHeaderMessage(it.headers.singleOrNull { header -> header.date == currentDate }?.content) } } .onResourceIntermediate { view?.showRefresh(true) } @@ -195,37 +170,14 @@ class TimetablePresenter @Inject constructor( .launch() } - private suspend fun checkInitialAndCurrentDate(semester: Semester) { - if (initialDate == null) { - isWeekendHasLessons = isStudentHasLessonsOnWeekendUseCase(semester) - initialDate = getInitialDate(semester) - } - - if (currentDate == null) { - currentDate = initialDate - } - } - - private fun getInitialDate(semester: Semester): LocalDate { - val now = now() - - return when { - now.isHolidays -> now.getLastSchoolDayIfHoliday(semester.schoolYear) - isWeekendHasLessons -> now - else -> now.nextOrSameSchoolDay - } - } - private fun updateData(lessons: List) { tickTimer?.cancel() - if (currentDate != now()) { + if (!prefRepository.showTimetableTimers) { view?.updateData(createItems(lessons)) } else { tickTimer = timer(period = 2_000) { - Handler(Looper.getMainLooper()).post { - view?.updateData(createItems(lessons)) - } + view?.updateData(createItems(lessons)) } } } @@ -236,43 +188,20 @@ class TimetablePresenter @Inject constructor( if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) { it.isStudentPlan } else true - } - .sortedWith(compareBy({ item -> item.start }, { item -> !item.isStudentPlan })) + }.sortedWith( + compareBy({ item -> item.number }, { item -> !item.isStudentPlan }) + ) - var prevNum = when (prefRepository.showTimetableGaps) { - BETWEEN_AND_BEFORE_LESSONS -> 0 - else -> null - } - return buildList { - filteredItems.forEachIndexed { i, it -> - if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) { - val emptyLesson = TimetableItem.Empty( - numFrom = prevNum!! + 1, - numTo = it.number - 1 - ) - add(emptyLesson) - } - - if (it.isStudentPlan) { - val normalLesson = TimetableItem.Normal( - lesson = it, - showGroupsInPlan = prefRepository.showGroupsInPlan, - timeLeft = filteredItems.getTimeLeftForLesson(it, i), - onClick = ::onTimetableItemSelected, - isLessonNumberVisible = !isEduOne - ) - add(normalLesson) - } else { - val smallLesson = TimetableItem.Small( - lesson = it, - onClick = ::onTimetableItemSelected, - isLessonNumberVisible = !isEduOne - ) - add(smallLesson) - } - - prevNum = it.number - } + return filteredItems.mapIndexed { i, it -> + if (it.isStudentPlan) TimetableItem.Normal( + lesson = it, + showGroupsInPlan = prefRepository.showGroupsInPlan, + timeLeft = filteredItems.getTimeLeftForLesson(it, i), + onClick = ::onTimetableItemSelected + ) else TimetableItem.Small( + lesson = it, + onClick = ::onTimetableItemSelected + ) } } @@ -313,7 +242,7 @@ class TimetablePresenter @Inject constructor( private fun reloadView(date: LocalDate) { currentDate = date - Timber.i("Reload timetable view with the date ${currentDate?.toFormattedString()}") + Timber.i("Reload timetable view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) enableSwipe(false) @@ -326,13 +255,10 @@ class TimetablePresenter @Inject constructor( } private fun reloadNavigation() { - val currentDate = currentDate ?: return - view?.apply { showPreButton(!currentDate.minusDays(1).isHolidays) showNextButton(!currentDate.plusDays(1).isHolidays) updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise()) - showNavigation(true) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt index 40190d51f..8cfb26204 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt @@ -36,8 +36,6 @@ interface TimetableView : BaseView { fun showContent(show: Boolean) - fun showNavigation(show: Boolean) - fun showPreButton(show: Boolean) fun showNextButton(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt index faa833c20..043fa1f7d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt @@ -2,8 +2,8 @@ package io.github.wulkanowy.ui.modules.timetable.additional import android.os.Bundle import android.view.View +import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.TimetableAdditional @@ -13,7 +13,11 @@ import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.timetable.additional.add.AdditionalLessonAddDialog import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.* +import io.github.wulkanowy.utils.dpToPx +import io.github.wulkanowy.utils.firstSchoolDayInSchoolYear +import io.github.wulkanowy.utils.getThemeAttrColor +import io.github.wulkanowy.utils.lastSchoolDayInSchoolYear +import io.github.wulkanowy.utils.openMaterialDatePicker import java.time.LocalDate import javax.inject.Inject @@ -69,7 +73,7 @@ class AdditionalLessonsFragment : openAddAdditionalLessonButton.setOnClickListener { presenter.onAdditionalLessonAddButtonClicked() } - additionalLessonsNavContainer.elevation = requireContext().dpToPx(3f) + additionalLessonsNavContainer.elevation = requireContext().dpToPx(8f) } } @@ -150,7 +154,7 @@ class AdditionalLessonsFragment : } override fun showDeleteLessonDialog(timetableAdditional: TimetableAdditional) { - MaterialAlertDialogBuilder(requireContext()) + AlertDialog.Builder(requireContext()) .setTitle(getString(R.string.additional_lessons_delete_title)) .setItems( arrayOf( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/add/AdditionalLessonAddDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/add/AdditionalLessonAddDialog.kt index 134719979..f82d64830 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/add/AdditionalLessonAddDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/add/AdditionalLessonAddDialog.kt @@ -1,10 +1,10 @@ package io.github.wulkanowy.ui.modules.timetable.additional.add -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup import androidx.core.widget.doOnTextChanged -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import dagger.hilt.android.AndroidEntryPoint @@ -29,15 +29,17 @@ class AdditionalLessonAddDialog : BaseDialogFragment fun newInstance() = AdditionalLessonAddDialog() } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView( - DialogAdditionalAddBinding.inflate(layoutInflater).apply { binding = this }.root - ) - .create() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, 0) } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogAdditionalAddBinding.inflate(inflater).apply { binding = this }.root + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter.onAttachView(this) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt index d937d4dd0..7d32278f0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt @@ -1,18 +1,17 @@ package io.github.wulkanowy.ui.modules.timetable.completed -import android.app.Dialog import android.os.Bundle +import android.view.LayoutInflater import android.view.View -import androidx.core.os.bundleOf -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.databinding.DialogLessonCompletedBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.utils.serializable +import io.github.wulkanowy.utils.lifecycleAwareVariable -@AndroidEntryPoint -class CompletedLessonDialog : BaseDialogFragment() { +class CompletedLessonDialog : DialogFragment() { + + private var binding: DialogLessonCompletedBinding by lifecycleAwareVariable() private lateinit var completedLesson: CompletedLesson @@ -20,23 +19,24 @@ class CompletedLessonDialog : BaseDialogFragment() private const val ARGUMENT_KEY = "Item" - fun newInstance(lesson: CompletedLesson) = CompletedLessonDialog().apply { - arguments = bundleOf(ARGUMENT_KEY to lesson) + fun newInstance(exam: CompletedLesson) = CompletedLessonDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - completedLesson = requireArguments().serializable(ARGUMENT_KEY) + setStyle(STYLE_NO_TITLE, 0) + arguments?.run { + completedLesson = getSerializable(ARGUMENT_KEY) as CompletedLesson + } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext(), theme) - .setView( - DialogLessonCompletedBinding.inflate(layoutInflater).apply { binding = this }.root - ) - .create() - } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ) = DialogLessonCompletedBinding.inflate(inflater).apply { binding = this }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt index 77a7bbd5a..34a69e6ab 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt @@ -2,7 +2,9 @@ package io.github.wulkanowy.ui.modules.timetable.completed import android.os.Bundle import android.view.View -import android.view.View.* +import android.view.View.GONE +import android.view.View.INVISIBLE +import android.view.View.VISIBLE import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -12,7 +14,12 @@ import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.* +import io.github.wulkanowy.utils.dpToPx +import io.github.wulkanowy.utils.firstSchoolDayInSchoolYear +import io.github.wulkanowy.utils.getCompatDrawable +import io.github.wulkanowy.utils.getThemeAttrColor +import io.github.wulkanowy.utils.lastSchoolDayInSchoolYear +import io.github.wulkanowy.utils.openMaterialDatePicker import java.time.LocalDate import javax.inject.Inject @@ -66,7 +73,7 @@ class CompletedLessonsFragment : completedLessonsNavDate.setOnClickListener { presenter.onPickDate() } completedLessonsNextButton.setOnClickListener { presenter.onNextDay() } - completedLessonsNavContainer.elevation = requireContext().dpToPx(3f) + completedLessonsNavContainer.elevation = requireContext().dpToPx(8f) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt index 672dbe720..6ef6cfc98 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt @@ -2,11 +2,14 @@ package io.github.wulkanowy.ui.modules.timetablewidget import android.appwidget.AppWidgetManager.* import android.content.Intent +import android.os.Build import android.os.Bundle import android.widget.Toast import android.widget.Toast.LENGTH_LONG +import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity @@ -31,6 +34,8 @@ class TimetableWidgetConfigureActivity : @Inject lateinit var appInfo: AppInfo + private var dialog: AlertDialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResult(RESULT_CANCELED) @@ -56,6 +61,23 @@ class TimetableWidgetConfigureActivity : configureAdapter.onClickListener = presenter::onItemSelect } + override fun showThemeDialog() { + var items = arrayOf( + getString(R.string.widget_timetable_theme_light), + getString(R.string.widget_timetable_theme_dark) + ) + + if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += getString(R.string.widget_timetable_theme_system) + + dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher) + .setTitle(R.string.widget_timetable_theme_title) + .setOnDismissListener { presenter.onDismissThemeView() } + .setSingleChoiceItems(items, -1) { _, which -> + presenter.onThemeSelect(which) + } + .show() + } + override fun updateData(data: List, selectedStudentId: Long) { with(configureAdapter) { selectedId = selectedStudentId @@ -88,4 +110,9 @@ class TimetableWidgetConfigureActivity : override fun openLoginView() { startActivity(LoginActivity.getStartIntent(this)) } + + override fun onDestroy() { + super.onDestroy() + dialog?.dismiss() + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt index 87e89336c..dc2a7c6c7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt @@ -8,6 +8,7 @@ import io.github.wulkanowy.data.resourceFlow import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey +import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey import kotlinx.coroutines.flow.onEach import timber.log.Timber import javax.inject.Inject @@ -38,9 +39,22 @@ class TimetableWidgetConfigurePresenter @Inject constructor( fun onItemSelect(student: Student) { selectedStudent = student + + if (isFromProvider) registerStudent(selectedStudent) + else view?.showThemeDialog() + } + + fun onThemeSelect(index: Int) { + appWidgetId?.let { + sharedPref.putLong(getThemeWidgetKey(it), index.toLong()) + } registerStudent(selectedStudent) } + fun onDismissThemeView() { + view?.finishView() + } + private fun loadData() { resourceFlow { studentRepository.getSavedStudents(false) }.onEach { when (it) { @@ -51,7 +65,10 @@ class TimetableWidgetConfigurePresenter @Inject constructor( } ?: -1 when { it.data.isEmpty() -> view?.openLoginView() - it.data.size == 1 && !isFromProvider -> onItemSelect(it.data.single().student) + it.data.size == 1 && !isFromProvider -> { + selectedStudent = it.data.single().student + view?.showThemeDialog() + } else -> view?.updateData(it.data, selectedStudentId) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt index 7740b9bbe..accdc28dc 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt @@ -11,6 +11,8 @@ interface TimetableWidgetConfigureView : BaseView { fun updateTimetableWidget(widgetId: Int) + fun showThemeDialog() + fun setSuccessResult(widgetId: Int) fun finishView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetFactory.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetFactory.kt index 218c25834..664086bca 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetFactory.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetFactory.kt @@ -1,62 +1,63 @@ package io.github.wulkanowy.ui.modules.timetablewidget +import android.annotation.SuppressLint import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID import android.content.Context import android.content.Intent -import android.content.res.Configuration import android.graphics.Paint.ANTI_ALIAS_FLAG import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG import android.view.View.GONE import android.view.View.VISIBLE +import android.widget.AdapterView.INVALID_POSITION import android.widget.RemoteViews import android.widget.RemoteViewsService import io.github.wulkanowy.R -import io.github.wulkanowy.data.dataOrThrow +import io.github.wulkanowy.data.dataOrNull import io.github.wulkanowy.data.db.SharedPrefProvider -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.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS -import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS +import io.github.wulkanowy.data.enums.TimetableMode 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.data.toFirstResult +import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getCurrentThemeWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getTodayLastLessonEndDateTimeWidgetKey import io.github.wulkanowy.utils.getCompatColor -import io.github.wulkanowy.utils.getErrorString -import io.github.wulkanowy.utils.getPlural import io.github.wulkanowy.utils.toFormattedString import kotlinx.coroutines.runBlocking import timber.log.Timber -import java.time.Instant import java.time.LocalDate class TimetableWidgetFactory( private val timetableRepository: TimetableRepository, private val studentRepository: StudentRepository, private val semesterRepository: SemesterRepository, - private val sharedPref: SharedPrefProvider, private val prefRepository: PreferencesRepository, + private val sharedPref: SharedPrefProvider, private val context: Context, private val intent: Intent? ) : RemoteViewsService.RemoteViewsFactory { - private var items = emptyList() - private var timetableCanceledColor: Int? = null + private var lessons = emptyList() + + private var savedCurrentTheme: Long? = null + + private var primaryColor: Int? = null + private var textColor: Int? = null + private var timetableChangeColor: Int? = null override fun getLoadingView() = null override fun hasStableIds() = true - override fun getCount() = items.size + override fun getCount() = lessons.size - override fun getViewTypeCount() = 3 + override fun getViewTypeCount() = 2 override fun getItemId(position: Int) = position.toLong() @@ -65,260 +66,199 @@ class TimetableWidgetFactory( override fun onDestroy() {} override fun onDataSetChanged() { - val appWidgetId = intent?.extras?.getInt(EXTRA_APPWIDGET_ID) ?: return - val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0)) - val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0) + intent?.extras?.getInt(EXTRA_APPWIDGET_ID)?.let { appWidgetId -> + val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0)) + val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0) - items = emptyList() + updateTheme(appWidgetId) + lessons = getLessons(date, studentId) + val todayLastLessonEndTimestamp = lessons.maxOfOrNull { it.end } + if (date == LocalDate.now() && todayLastLessonEndTimestamp != null) { + sharedPref.putLong( + key = getTodayLastLessonEndDateTimeWidgetKey(appWidgetId), + value = todayLastLessonEndTimestamp.epochSecond, + sync = true + ) + } + } + } + + private fun updateTheme(appWidgetId: Int) { + savedCurrentTheme = sharedPref.getLong(getCurrentThemeWidgetKey(appWidgetId), 0) + + if (savedCurrentTheme == 0L) { + primaryColor = R.color.colorPrimary + textColor = android.R.color.black + timetableChangeColor = R.color.timetable_change_dark + } else { + primaryColor = R.color.colorPrimaryLight + textColor = android.R.color.white + timetableChangeColor = R.color.timetable_change_light + } + } + + private fun getItemLayout(lesson: Timetable): Int { + return when { + prefRepository.showWholeClassPlan == TimetableMode.SMALL_OTHER_GROUP && !lesson.isStudentPlan -> { + if (savedCurrentTheme == 0L) R.layout.item_widget_timetable_small + else R.layout.item_widget_timetable_small_dark + } + savedCurrentTheme == 1L -> R.layout.item_widget_timetable_dark + else -> R.layout.item_widget_timetable + } + } + + private fun getLessons(date: LocalDate, studentId: Long) = try { runBlocking { - runCatching { - val student = getStudent(studentId) ?: return@runBlocking - val semester = semesterRepository.getCurrentSemester(student) - val lessons = getLessons(student, semester, date) - val lastSync = timetableRepository.getLastRefreshTimestamp(semester, date, date) + if (!studentRepository.isStudentSaved()) return@runBlocking emptyList() - createItems(lessons, lastSync, !(student.isEduOne ?: false)) - } - .onFailure { - items = listOf(TimetableWidgetItem.Error(it)) - Timber.e(it, "An error has occurred in timetable widget factory") - } - .onSuccess { - items = it - if (date == LocalDate.now()) { - updateTodayLastLessonEnd(appWidgetId) - } + val students = studentRepository.getSavedStudents() + val student = students.singleOrNull { it.student.id == studentId }?.student + ?: return@runBlocking emptyList() + + val semester = semesterRepository.getCurrentSemester(student) + timetableRepository.getTimetable(student, semester, date, date, false) + .toFirstResult().dataOrNull?.lessons.orEmpty() + .sortedWith(compareBy({ it.number }, { !it.isStudentPlan })) + .filter { + if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) { + it.isStudentPlan + } else true } } + } catch (e: Exception) { + Timber.e(e, "An error has occurred in timetable widget factory") + emptyList() } - private suspend fun getStudent(studentId: Long): Student? { - val students = studentRepository.getSavedStudents() - return students.singleOrNull { it.student.id == studentId }?.student - } - - private suspend fun getLessons( - student: Student, semester: Semester, date: LocalDate - ): List { - val timetable = timetableRepository.getTimetable(student, semester, date, date, false) - val lessons = timetable.toFirstResult().dataOrThrow.lessons - return lessons.sortedBy { it.start } - } - - private fun createItems( - lessons: List, - lastSync: Instant?, - isEduOne: Boolean - ): List { - var prevNum = when (prefRepository.showTimetableGaps) { - BETWEEN_AND_BEFORE_LESSONS -> 0 - else -> null - } - - return buildList { - lessons.forEach { - if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) { - val emptyItem = TimetableWidgetItem.Empty( - numFrom = prevNum!! + 1, - numTo = it.number - 1 - ) - add(emptyItem) - } - add(TimetableWidgetItem.Normal(it, isEduOne)) - prevNum = it.number - } - add(TimetableWidgetItem.Synchronized(lastSync ?: Instant.MIN)) - } - } - - private fun updateTodayLastLessonEnd(appWidgetId: Int) { - val todayLastLessonEnd = items.filterIsInstance() - .maxOfOrNull { it.lesson.end } ?: return - val key = getTodayLastLessonEndDateTimeWidgetKey(appWidgetId) - sharedPref.putLong(key, todayLastLessonEnd.epochSecond, true) - } - + @SuppressLint("DefaultLocale") override fun getViewAt(position: Int): RemoteViews? { - return when (val item = items.getOrNull(position) ?: return null) { - is TimetableWidgetItem.Normal -> getNormalItemRemoteView(item) - is TimetableWidgetItem.Empty -> getEmptyItemRemoteView(item) - is TimetableWidgetItem.Synchronized -> getSynchronizedItemRemoteView(item) - is TimetableWidgetItem.Error -> getErrorItemRemoteView(item) - } - } + if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null - private fun getNormalItemRemoteView(item: TimetableWidgetItem.Normal): RemoteViews { - val lesson = item.lesson - - val lessonStartTime = lesson.start.toFormattedString(TIME_FORMAT_STYLE) - val lessonEndTime = lesson.end.toFormattedString(TIME_FORMAT_STYLE) - val lessonNumberVisibility = if (item.isLessonNumberVisible) VISIBLE else GONE - - val remoteViews = RemoteViews(context.packageName, R.layout.item_widget_timetable).apply { - setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString()) - setViewVisibility(R.id.timetableWidgetItemNumber, lessonNumberVisibility) - setTextViewText(R.id.timetableWidgetItemTimeStart, lessonStartTime) - setTextViewText(R.id.timetableWidgetItemTimeFinish, lessonEndTime) + val lesson = lessons[position] + return RemoteViews(context.packageName, getItemLayout(lesson)).apply { setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject) + setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString()) + setTextViewText( + R.id.timetableWidgetItemTimeStart, + lesson.start.toFormattedString("HH:mm") + ) + setTextViewText( + R.id.timetableWidgetItemTimeFinish, + lesson.end.toFormattedString("HH:mm") + ) + + updateDescription(this, lesson) + + if (lesson.canceled) { + updateStylesCanceled(this) + } else { + updateStylesNotCanceled(this, lesson) + } - setTextViewText(R.id.timetableWidgetItemTeacher, lesson.teacher) - setTextViewText(R.id.timetableWidgetItemDescription, lesson.info) setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent()) } - updateTheme() - clearLessonStyles(remoteViews) - if (lesson.room.isBlank()) { - remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE) - } else { - remoteViews.setTextViewText(R.id.timetableWidgetItemRoom, lesson.room) - } - when { - lesson.canceled -> applyCancelledLessonStyles(remoteViews) - lesson.changes or lesson.info.isNotBlank() -> applyChangedLessonStyles( - remoteViews = remoteViews, - lesson = lesson, - ) - } - return remoteViews } - private fun getEmptyItemRemoteView(item: TimetableWidgetItem.Empty): RemoteViews { - return RemoteViews( - context.packageName, - R.layout.item_widget_timetable_empty - ).apply { - setTextViewText( - R.id.timetableWidgetEmptyItemNumber, - when (item.numFrom) { - item.numTo -> item.numFrom.toString() - else -> "${item.numFrom}-${item.numTo}" - } - ) - setTextViewText( - R.id.timetableWidgetEmptyItemText, - context.getPlural( - R.plurals.timetable_no_lesson, - item.numTo - item.numFrom + 1 - ) - ) - setOnClickFillInIntent(R.id.timetableWidgetEmptyItemContainer, Intent()) - } - } - - private fun getSynchronizedItemRemoteView(item: TimetableWidgetItem.Synchronized): RemoteViews { - return RemoteViews( - context.packageName, - R.layout.item_widget_timetable_footer - ).apply { - setTextViewText( - R.id.timetableWidgetSynchronizationTime, - getSynchronizationInfoText(item.timestamp) - ) - } - } - - private fun getErrorItemRemoteView(item: TimetableWidgetItem.Error): RemoteViews { - return RemoteViews( - context.packageName, - R.layout.item_widget_timetable_error - ).apply { - setTextViewText( - R.id.timetable_widget_item_error_message, - context.resources.getErrorString(item.error) - ) - } - } - - private fun updateTheme() { - when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { - Configuration.UI_MODE_NIGHT_YES -> { - textColor = android.R.color.white - timetableChangeColor = R.color.timetable_change_dark - timetableCanceledColor = R.color.timetable_canceled_dark - } - - else -> { - textColor = android.R.color.black - timetableChangeColor = R.color.timetable_change_light - timetableCanceledColor = R.color.timetable_canceled_light + private fun updateDescription(remoteViews: RemoteViews, lesson: Timetable) { + with(remoteViews) { + if (lesson.info.isNotBlank() && !lesson.changes) { + setTextViewText(R.id.timetableWidgetItemDescription, lesson.info) + setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE) + setViewVisibility(R.id.timetableWidgetItemRoom, GONE) + setViewVisibility(R.id.timetableWidgetItemTeacher, GONE) + } else { + setViewVisibility(R.id.timetableWidgetItemDescription, GONE) + setViewVisibility(R.id.timetableWidgetItemRoom, VISIBLE) + setViewVisibility(R.id.timetableWidgetItemTeacher, VISIBLE) } } } - private fun clearLessonStyles(remoteViews: RemoteViews) { - val defaultTextColor = context.getCompatColor(textColor ?: 0) + private fun updateStylesCanceled(remoteViews: RemoteViews) { + with(remoteViews) { + setInt( + R.id.timetableWidgetItemSubject, "setPaintFlags", + STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG + ) + setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(primaryColor!!)) + setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(primaryColor!!)) + setTextColor( + R.id.timetableWidgetItemDescription, + context.getCompatColor(primaryColor!!) + ) + } + } - remoteViews.apply { + private fun updateStylesNotCanceled(remoteViews: RemoteViews, lesson: Timetable) { + with(remoteViews) { setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG) - setViewVisibility(R.id.timetableWidgetItemRoom, VISIBLE) - setViewVisibility(R.id.timetableWidgetItemTeacher, VISIBLE) - setViewVisibility(R.id.timetableWidgetItemIcon, GONE) - setViewVisibility(R.id.timetableWidgetItemDescription, GONE) - setTextColor(R.id.timetableWidgetItemNumber, defaultTextColor) - setTextColor(R.id.timetableWidgetItemSubject, defaultTextColor) - setTextColor(R.id.timetableWidgetItemRoom, defaultTextColor) - setTextColor(R.id.timetableWidgetItemTeacher, defaultTextColor) - setTextColor(R.id.timetableWidgetItemDescription, defaultTextColor) - } - } - - private fun applyCancelledLessonStyles(remoteViews: RemoteViews) { - val cancelledThemeColor = context.getCompatColor(timetableCanceledColor ?: 0) - val strikeThroughPaintFlags = STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG - - remoteViews.apply { - setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", strikeThroughPaintFlags) - setTextColor(R.id.timetableWidgetItemNumber, cancelledThemeColor) - setTextColor(R.id.timetableWidgetItemSubject, cancelledThemeColor) - setTextColor(R.id.timetableWidgetItemDescription, cancelledThemeColor) - setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE) - setViewVisibility(R.id.timetableWidgetItemRoom, GONE) - setViewVisibility(R.id.timetableWidgetItemTeacher, GONE) - } - } - - private fun applyChangedLessonStyles(remoteViews: RemoteViews, lesson: Timetable) { - val changesTextColor = context.getCompatColor(timetableChangeColor ?: 0) - - remoteViews.apply { - setTextColor(R.id.timetableWidgetItemNumber, changesTextColor) - setTextColor(R.id.timetableWidgetItemDescription, changesTextColor) - setViewVisibility(R.id.timetableWidgetItemIcon, VISIBLE) - setImageViewResource(R.id.timetableWidgetItemIcon, R.drawable.ic_timetable_widget_swap) - } - - if (lesson.subject != lesson.subjectOld) { - remoteViews.setTextColor(R.id.timetableWidgetItemSubject, changesTextColor) - } - - if (lesson.room != lesson.roomOld) { - remoteViews.setTextColor(R.id.timetableWidgetItemRoom, changesTextColor) - } - - if (lesson.teacher != lesson.teacherOld) { - remoteViews.setTextColor(R.id.timetableWidgetItemTeacher, changesTextColor) - } - - if (lesson.info.isNotBlank() && !lesson.changes) { - remoteViews.setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE) - remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE) - remoteViews.setViewVisibility(R.id.timetableWidgetItemTeacher, GONE) - } - } - - private fun getSynchronizationInfoText(synchronizationInstant: Instant) = - synchronizationInstant.run { - val synchronizationTime = toFormattedString(TIME_FORMAT_STYLE) - val synchronizationDate = toFormattedString() - context.getString( - R.string.widget_timetable_last_synchronization, - synchronizationDate, - synchronizationTime, + setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(textColor!!)) + setTextColor( + R.id.timetableWidgetItemDescription, + context.getCompatColor(timetableChangeColor!!) ) - } - private companion object { - private const val TIME_FORMAT_STYLE = "HH:mm" + updateNotCanceledLessonNumberColor(this, lesson) + updateNotCanceledSubjectColor(this, lesson) + + val teacherChange = lesson.teacherOld.isNotBlank() + updateNotCanceledRoom(this, lesson, teacherChange) + updateNotCanceledTeacher(this, lesson, teacherChange) + } + } + + private fun updateNotCanceledLessonNumberColor(remoteViews: RemoteViews, lesson: Timetable) { + remoteViews.setTextColor( + R.id.timetableWidgetItemNumber, context.getCompatColor( + if (lesson.changes || (lesson.info.isNotBlank() && !lesson.canceled)) timetableChangeColor!! + else textColor!! + ) + ) + } + + private fun updateNotCanceledSubjectColor(remoteViews: RemoteViews, lesson: Timetable) { + remoteViews.setTextColor( + R.id.timetableWidgetItemSubject, context.getCompatColor( + if (lesson.subjectOld.isNotBlank() && lesson.subject != lesson.subjectOld) timetableChangeColor!! + else textColor!! + ) + ) + } + + private fun updateNotCanceledRoom( + remoteViews: RemoteViews, + lesson: Timetable, + teacherChange: Boolean + ) { + with(remoteViews) { + if (lesson.room.isNotBlank()) { + setTextViewText( + R.id.timetableWidgetItemRoom, + if (teacherChange) lesson.room + else "${context.getString(R.string.timetable_room)} ${lesson.room}" + ) + + setTextColor( + R.id.timetableWidgetItemRoom, context.getCompatColor( + if (lesson.roomOld.isNotBlank() && lesson.room != lesson.roomOld) timetableChangeColor!! + else textColor!! + ) + ) + } else setTextViewText(R.id.timetableWidgetItemRoom, "") + } + } + + private fun updateNotCanceledTeacher( + remoteViews: RemoteViews, + lesson: Timetable, + teacherChange: Boolean + ) { + remoteViews.setTextViewText( + R.id.timetableWidgetItemTeacher, + if (teacherChange) lesson.teacher + else "" + ) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetItem.kt deleted file mode 100644 index d4c2cfc00..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetItem.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -import io.github.wulkanowy.data.db.entities.Timetable -import java.time.Instant - -sealed class TimetableWidgetItem(val type: TimetableWidgetItemType) { - - data class Normal( - val lesson: Timetable, - val isLessonNumberVisible: Boolean, - ) : TimetableWidgetItem(TimetableWidgetItemType.NORMAL) - - data class Empty( - val numFrom: Int, - val numTo: Int - ) : TimetableWidgetItem(TimetableWidgetItemType.EMPTY) - - data class Synchronized( - val timestamp: Instant, - ) : TimetableWidgetItem(TimetableWidgetItemType.SYNCHRONIZED) - - data class Error( - val error: Throwable - ) : TimetableWidgetItem(TimetableWidgetItemType.ERROR) -} - -enum class TimetableWidgetItemType { - NORMAL, - EMPTY, - SYNCHRONIZED, - ERROR, -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt index cc48539a5..3ba2ae946 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt @@ -8,11 +8,10 @@ import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK +import android.content.res.Configuration import android.graphics.Bitmap +import android.graphics.Canvas import android.widget.RemoteViews -import androidx.appcompat.content.res.AppCompatResources -import androidx.core.graphics.drawable.DrawableCompat -import androidx.core.graphics.drawable.toBitmap import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.SharedPrefProvider @@ -71,177 +70,175 @@ class TimetableWidgetProvider : BroadcastReceiver() { "timetable_widget_today_last_lesson_end_date_time_$appWidgetId" fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId" + + fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId" + + fun getCurrentThemeWidgetKey(appWidgetId: Int) = + "timetable_widget_current_theme_$appWidgetId" } @OptIn(DelicateCoroutinesApi::class) override fun onReceive(context: Context, intent: Intent) { GlobalScope.launch { when (intent.action) { - ACTION_APPWIDGET_UPDATE -> onWidgetUpdate(context, intent) - ACTION_APPWIDGET_DELETED -> onWidgetDeleted(intent) + ACTION_APPWIDGET_UPDATE -> onUpdate(context, intent) + ACTION_APPWIDGET_DELETED -> onDelete(intent) } } } - private suspend fun onWidgetUpdate(context: Context, intent: Intent) { - val pressedButton = intent.getPressedButton() + private suspend fun onUpdate(context: Context, intent: Intent) { + if (intent.getStringExtra(EXTRA_BUTTON_TYPE) == null) { + val isFromConfigure = intent.getBooleanExtra(EXTRA_FROM_CONFIGURE, false) + val appWidgetIds = intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS) ?: return - if (pressedButton == null) { - val updatedWidgetIds = intent.getWidgetIds() ?: return - updatedWidgetIds.forEach { updateWidgetLayout(context, it) } + appWidgetIds.forEach { appWidgetId -> + val student = + getStudent(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) + val savedDataEpochDay = sharedPref.getLong(getDateWidgetKey(appWidgetId), 0) + + val dateToLoad = if (isFromConfigure && savedDataEpochDay != 0L) { + LocalDate.ofEpochDay(savedDataEpochDay) + } else { + getWidgetDefaultDateToLoad(appWidgetId) + } + + updateWidget(context, appWidgetId, dateToLoad, student) + } } else { - val widgetId = intent.getToggledWidgetId() ?: return - reportChangedDay(pressedButton) - updateSavedWidgetDate(widgetId, pressedButton) - updateWidgetLayout(context, widgetId) + val buttonType = intent.getStringExtra(EXTRA_BUTTON_TYPE) + val toggledWidgetId = intent.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0) + val student = getStudent( + sharedPref.getLong(getStudentWidgetKey(toggledWidgetId), 0), + toggledWidgetId + ) + val savedDate = + LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(toggledWidgetId), 0)) + val date = when (buttonType) { + BUTTON_RESET -> getWidgetDefaultDateToLoad(toggledWidgetId) + BUTTON_NEXT -> savedDate.nextSchoolDay + BUTTON_PREV -> savedDate.previousSchoolDay + else -> getWidgetDefaultDateToLoad(toggledWidgetId) + } + if (!buttonType.isNullOrBlank()) { + analytics.logEvent( + "changed_timetable_widget_day", + "button" to buttonType + ) + } + updateWidget(context, toggledWidgetId, date, student) } } - private fun Intent.getPressedButton(): String? { - return getStringExtra(EXTRA_BUTTON_TYPE) - } + private fun onDelete(intent: Intent) { + val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0) - private fun Intent.getWidgetIds(): IntArray? { - return getIntArrayExtra(EXTRA_APPWIDGET_IDS) - } - - private fun Intent.getToggledWidgetId(): Int? { - val toggledWidgetId = getIntExtra(EXTRA_TOGGLED_WIDGET_ID, INVALID_APPWIDGET_ID) - return toggledWidgetId.takeIf { it != INVALID_APPWIDGET_ID } - } - - private fun reportChangedDay(buttonType: String) { - if (buttonType.isNotBlank()) { - analytics.logEvent("changed_timetable_widget_day", "button" to buttonType) + if (appWidgetId != 0) { + with(sharedPref) { + delete(getStudentWidgetKey(appWidgetId)) + delete(getDateWidgetKey(appWidgetId)) + delete(getThemeWidgetKey(appWidgetId)) + delete(getCurrentThemeWidgetKey(appWidgetId)) + } } } - private fun updateSavedWidgetDate(widgetId: Int, buttonType: String) { - val savedDate = getSavedWidgetDate(widgetId) - val newDate = savedDate?.let { getNewDate(it, widgetId, buttonType) } - ?: getWidgetDefaultDateToLoad(widgetId) - setWidgetDate(widgetId, newDate) - } - - private fun getSavedWidgetDate(widgetId: Int): LocalDate? { - val epochDay = sharedPref.getLong(getDateWidgetKey(widgetId), 0) - return if (epochDay == 0L) null else LocalDate.ofEpochDay(epochDay) - } - - private fun getNewDate( - currentDate: LocalDate, - widgetId: Int, - selectedButton: String - ): LocalDate { - return when (selectedButton) { - BUTTON_NEXT -> currentDate.nextSchoolDay - BUTTON_PREV -> currentDate.previousSchoolDay - else -> getWidgetDefaultDateToLoad(widgetId) - } - } - - private fun setWidgetDate(widgetId: Int, dateToSet: LocalDate) { - val widgetDateKey = getDateWidgetKey(widgetId) - sharedPref.putLong(widgetDateKey, dateToSet.toEpochDay(), true) - } - - private fun getWidgetDefaultDateToLoad(widgetId: Int): LocalDate { - val lastLessonEndDateTime = getLastLessonDateTime(widgetId) - - val todayDate = LocalDate.now() - val isLastLessonToday = lastLessonEndDateTime.toLocalDate() == todayDate - val isEndOfLessons = LocalDateTime.now() > lastLessonEndDateTime - - return if (isLastLessonToday && isEndOfLessons) { - todayDate.nextSchoolDay - } else { - todayDate.nextOrSameSchoolDay - } - } - - private fun getLastLessonDateTime(widgetId: Int): LocalDateTime { - val lastLessonTimestamp = sharedPref - .getLong(getTodayLastLessonEndDateTimeWidgetKey(widgetId), 0) - return LocalDateTime.ofEpochSecond(lastLessonTimestamp, 0, ZoneOffset.UTC) - } - - private suspend fun updateWidgetLayout( - context: Context, widgetId: Int + private fun updateWidget( + context: Context, + appWidgetId: Int, + date: LocalDate, + student: Student? ) { - val widgetRemoteViews = RemoteViews(context.packageName, R.layout.widget_timetable) + val savedConfigureTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0) + val isSystemDarkMode = + context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + var currentTheme = 0L + var layoutId = R.layout.widget_timetable - // Apply the click action intent - val appIntent = createPendingAppIntent(context) - widgetRemoteViews.setPendingIntentTemplate(R.id.timetableWidgetList, appIntent) + if (savedConfigureTheme == 1L || (savedConfigureTheme == 2L && isSystemDarkMode)) { + currentTheme = 1L + layoutId = R.layout.widget_timetable_dark + } - // Display saved date - val date = getSavedWidgetDate(widgetId) ?: getWidgetDefaultDateToLoad(widgetId) - val formattedDate = date.toFormattedString("EEE, dd.MM").capitalise() - widgetRemoteViews.setTextViewText(R.id.timetableWidgetDate, formattedDate) - - // Apply intents to the date switcher buttons - val nextNavIntent = createNavButtonIntent(context, widgetId, widgetId, BUTTON_NEXT) - val prevNavIntent = createNavButtonIntent(context, -widgetId, widgetId, BUTTON_PREV) + val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT) + val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV) val resetNavIntent = - createNavButtonIntent(context, Int.MAX_VALUE - widgetId, widgetId, BUTTON_RESET) - widgetRemoteViews.run { + createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET) + val adapterIntent = Intent(context, TimetableWidgetService::class.java) + .apply { + putExtra(EXTRA_APPWIDGET_ID, appWidgetId) + //make Intent unique + action = appWidgetId.toString() + } + val accountIntent = PendingIntent.getActivity( + context, + -Int.MAX_VALUE + appWidgetId, + Intent(context, TimetableWidgetConfigureActivity::class.java).apply { + addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK) + putExtra(EXTRA_APPWIDGET_ID, appWidgetId) + putExtra(EXTRA_FROM_PROVIDER, true) + }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE + + ) + val appIntent = PendingIntent.getActivity( + context, + TIMETABLE_PENDING_INTENT_ID, + SplashActivity.getStartIntent(context, Destination.Timetable()), + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE + ) + + val remoteView = RemoteViews(context.packageName, layoutId).apply { + setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) + setTextViewText( + R.id.timetableWidgetDate, + date.toFormattedString("EEEE, dd.MM").capitalise() + ) + setTextViewText( + R.id.timetableWidgetName, + student?.nickOrName ?: context.getString(R.string.all_no_data) + ) + + student?.let { + setImageViewBitmap(R.id.timetableWidgetAccount, context.createAvatarBitmap(it)) + } + + setRemoteAdapter(R.id.timetableWidgetList, adapterIntent) setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent) setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent) setOnClickPendingIntent(R.id.timetableWidgetDate, resetNavIntent) + setOnClickPendingIntent(R.id.timetableWidgetName, resetNavIntent) + setOnClickPendingIntent(R.id.timetableWidgetAccount, accountIntent) + setPendingIntentTemplate(R.id.timetableWidgetList, appIntent) } - // Setup the lesson list adapter - val lessonListAdapterIntent = createLessonListAdapterIntent(context, widgetId) - // --- Ensure the selected date is stored in the shared preferences, - // --- on which the TimetableWidgetFactory relies - setWidgetDate(widgetId, date) - // --- - widgetRemoteViews.apply { - setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) - setRemoteAdapter(R.id.timetableWidgetList, lessonListAdapterIntent) + with(sharedPref) { + putLong(getCurrentThemeWidgetKey(appWidgetId), currentTheme) + putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true) } - // Setup profile picture - getWidgetStudent(widgetId)?.let { student -> - setupAccountView(context, student, widgetRemoteViews, widgetId) - } - - // Apply updates with(appWidgetManager) { - partiallyUpdateAppWidget(widgetId, widgetRemoteViews) - notifyAppWidgetViewDataChanged(widgetId, R.id.timetableWidgetList) + updateAppWidget(appWidgetId, remoteView) + notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList) + Timber.d("TimetableWidgetProvider updated") } - - Timber.d("TimetableWidgetProvider updated") } - private fun createPendingAppIntent(context: Context) = PendingIntent.getActivity( - context, TIMETABLE_PENDING_INTENT_ID, - SplashActivity.getStartIntent(context, Destination.Timetable()), - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE - ) - - private fun createNavButtonIntent( - context: Context, code: Int, appWidgetId: Int, buttonType: String + private fun createNavIntent( + context: Context, + code: Int, + appWidgetId: Int, + buttonType: String ) = PendingIntent.getBroadcast( - context, code, Intent(context, TimetableWidgetProvider::class.java).apply { + context, + code, + Intent(context, TimetableWidgetProvider::class.java).apply { action = ACTION_APPWIDGET_UPDATE putExtra(EXTRA_BUTTON_TYPE, buttonType) putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId) - }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE + }, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE ) - private fun createLessonListAdapterIntent(context: Context, widgetId: Int) = - Intent(context, TimetableWidgetService::class.java).apply { - putExtra(EXTRA_APPWIDGET_ID, widgetId) - action = widgetId.toString() //make Intent unique - } - - private suspend fun getWidgetStudent(widgetId: Int): Student? { - val studentId = sharedPref.getLong(getStudentWidgetKey(widgetId), 0) - return getStudent(studentId, widgetId) - } - private suspend fun getStudent(studentId: Long, appWidgetId: Int) = try { val students = studentRepository.getSavedStudents(false) val student = students.singleOrNull { it.student.id == studentId }?.student @@ -252,7 +249,6 @@ class TimetableWidgetProvider : BroadcastReceiver() { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } } - else -> null } } catch (e: Exception) { @@ -262,64 +258,45 @@ class TimetableWidgetProvider : BroadcastReceiver() { null } - private fun setupAccountView( - context: Context, student: Student, remoteViews: RemoteViews, widgetId: Int - ) { - val accountInitials = getAccountInitials(student.nickOrName) - val accountPickerPendingIntent = createAccountPickerPendingIntent(context, widgetId) - - getAvatarBackgroundBitmap(context, student.avatarColor)?.let { - remoteViews.setImageViewBitmap(R.id.timetableWidgetAccountBackground, it) + private fun Context.createAvatarBitmap(student: Student): Bitmap { + val avatarColor = if (student.avatarColor == -2937041L) { + getCompatColor(R.color.colorPrimaryLight).toLong() + } else { + student.avatarColor } + val avatarDrawable = createNameInitialsDrawable(student.nickOrName, avatarColor, 0.5f) - remoteViews.apply { - setTextViewText(R.id.timetableWidgetAccountInitials, accountInitials) - setOnClickPendingIntent(R.id.timetableWidgetAccount, accountPickerPendingIntent) - } - } - - private fun getAccountInitials(name: String): String { - val firstLetters = name.split(" ").mapNotNull { it.firstOrNull() } - return firstLetters.joinToString(separator = "").uppercase() - } - - private fun createAccountPickerPendingIntent(context: Context, widgetId: Int) = - PendingIntent.getActivity( - context, - -Int.MAX_VALUE + widgetId, - Intent(context, TimetableWidgetConfigureActivity::class.java).apply { - addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK) - putExtra(EXTRA_APPWIDGET_ID, widgetId) - putExtra(EXTRA_FROM_PROVIDER, true) - }, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE - ) - - private fun getAvatarBackgroundBitmap(context: Context, avatarColor: Long): Bitmap? { - val avatarDrawableResource = R.drawable.background_timetable_widget_avatar - return AppCompatResources.getDrawable(context, avatarDrawableResource)?.let { drawable -> - val screenDensity = context.resources.displayMetrics.density - val avatarSize = (48 * screenDensity).toInt() - DrawableCompat.wrap(drawable).run { - DrawableCompat.setTint(this, avatarColor.toInt()) - toBitmap(avatarSize, avatarSize) + val avatarBitmap = + if (avatarDrawable.intrinsicWidth <= 0 || avatarDrawable.intrinsicHeight <= 0) { + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + } else { + Bitmap.createBitmap( + avatarDrawable.intrinsicWidth, + avatarDrawable.intrinsicHeight, + Bitmap.Config.ARGB_8888 + ) } - } + + val canvas = Canvas(avatarBitmap) + avatarDrawable.setBounds(0, 0, canvas.width, canvas.height) + avatarDrawable.draw(canvas) + return avatarBitmap } - private fun onWidgetDeleted(intent: Intent) { - val deletedWidgetId = intent.getWidgetId() - deleteWidgetPreferences(deletedWidgetId) - } + private fun getWidgetDefaultDateToLoad(appWidgetId: Int): LocalDate { + val lastLessonEndTimestamp = + sharedPref.getLong(getTodayLastLessonEndDateTimeWidgetKey(appWidgetId), 0) + val lastLessonEndDateTime = + LocalDateTime.ofEpochSecond(lastLessonEndTimestamp, 0, ZoneOffset.UTC) - private fun Intent.getWidgetId(): Int { - return getIntExtra(EXTRA_APPWIDGET_ID, INVALID_APPWIDGET_ID) - } + val todayDate = LocalDate.now() + val isLastLessonEndDateNow = lastLessonEndDateTime.toLocalDate() == todayDate + val isLastLessonEndDateAfterNowTime = LocalDateTime.now() > lastLessonEndDateTime - private fun deleteWidgetPreferences(widgetId: Int) { - with(sharedPref) { - delete(getStudentWidgetKey(widgetId)) - delete(getDateWidgetKey(widgetId)) + return if (isLastLessonEndDateNow && isLastLessonEndDateAfterNowTime) { + todayDate.nextSchoolDay + } else { + todayDate.nextOrSameSchoolDay } } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt index e16db53c6..962e5b208 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt @@ -25,8 +25,7 @@ open class AppInfo @Inject constructor() { open val systemModel: String get() = Build.MODEL - open val messagesBaseUrl: String = BuildConfig.MESSAGES_BASE_URL - open val schoolsBaseUrl: String = BuildConfig.SCHOOLS_BASE_URL + open val messagesBaseUrl = BuildConfig.MESSAGES_BASE_URL @Suppress("DEPRECATION") open val systemLanguage: String diff --git a/app/src/main/java/io/github/wulkanowy/utils/BaseRemoteConfigHelper.kt b/app/src/main/java/io/github/wulkanowy/utils/BaseRemoteConfigHelper.kt deleted file mode 100644 index 002612a87..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/BaseRemoteConfigHelper.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.utils - -abstract class BaseRemoteConfigHelper { - - open fun initialize() = Unit - - open val userAgentTemplate: String - get() = RemoteConfigDefaults.USER_AGENT_TEMPLATE.value as String -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt deleted file mode 100644 index b1742b4fa..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/BundleExtension.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.utils - -import android.content.Intent -import android.os.Build -import android.os.Bundle -import android.os.Parcelable -import androidx.core.os.BundleCompat -import java.io.Serializable - -// Even though API was introduced in 33, we use 34 as 33 is bugged in some scenarios. - -inline fun Bundle.serializable(key: String): T = when { - Build.VERSION.SDK_INT >= 34 -> getSerializable(key, T::class.java)!! - else -> @Suppress("DEPRECATION") getSerializable(key) as T -} - -inline fun Bundle.nullableSerializable(key: String): T? = when { - Build.VERSION.SDK_INT >= 34 -> getSerializable(key, T::class.java) - else -> @Suppress("DEPRECATION") getSerializable(key) as T? -} - -@Suppress("UNCHECKED_CAST") -inline fun Bundle.parcelableArray(key: String): Array? = - BundleCompat.getParcelableArray(this, key, T::class.java) as Array? - -inline fun Intent.serializable(key: String): T = when { - Build.VERSION.SDK_INT >= 34 -> getSerializableExtra(key, T::class.java)!! - else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T -} - -inline fun Intent.nullableSerializable(key: String): T? = when { - Build.VERSION.SDK_INT >= 34 -> getSerializableExtra(key, T::class.java) - else -> @Suppress("DEPRECATION") getSerializableExtra(key) as T? -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt index 77f3eb64a..cc4c5aaa4 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt @@ -6,6 +6,7 @@ import android.content.res.ColorStateList import android.graphics.* import android.text.TextPaint import android.util.DisplayMetrics.DENSITY_DEFAULT +import android.widget.ImageView import androidx.annotation.* import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils @@ -13,6 +14,7 @@ import androidx.core.graphics.applyCanvas import androidx.core.graphics.drawable.RoundedBitmapDrawable import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import androidx.core.graphics.drawable.toBitmap +import androidx.core.widget.ImageViewCompat @ColorInt @@ -87,6 +89,6 @@ fun Context.createNameInitialsDrawable( .apply { isCircular = true } } -fun Context.getAttrColorStateList(@AttrRes color: Int): ColorStateList { - return ColorStateList.valueOf(getThemeAttrColor(color)) +fun ImageView.setTint(@ColorInt color: Int) { + ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(color)) } diff --git a/app/src/main/java/io/github/wulkanowy/utils/ExceptionExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ExceptionExtension.kt index d541c0a7e..a4c2537ac 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/ExceptionExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/ExceptionExtension.kt @@ -3,13 +3,10 @@ package io.github.wulkanowy.utils import android.content.res.Resources import io.github.wulkanowy.R import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException -import io.github.wulkanowy.sdk.scrapper.exception.AccountInactiveException -import io.github.wulkanowy.sdk.scrapper.exception.CloudflareVerificationException import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException import io.github.wulkanowy.sdk.scrapper.exception.VulcanException -import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException import okhttp3.internal.http2.StreamResetException @@ -35,11 +32,8 @@ fun Resources.getErrorString(error: Throwable): String = when (error) { is ServiceUnavailableException -> R.string.error_service_unavailable is FeatureDisabledException -> R.string.error_feature_disabled is FeatureNotAvailableException -> R.string.error_feature_not_available - is BadCredentialsException -> R.string.error_password_invalid - is AccountInactiveException -> R.string.error_account_inactive is VulcanException -> R.string.error_unknown_uonet is ScrapperException -> R.string.error_unknown_app - is CloudflareVerificationException -> R.string.error_cloudflare_captcha is SSLHandshakeException -> when { error.isCausedByCertificateNotValidNow() -> R.string.error_invalid_device_datetime else -> R.string.error_timeout diff --git a/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt index 62b85af4d..1ef03f2e6 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/IntentUtils.kt @@ -1,15 +1,11 @@ package io.github.wulkanowy.utils -import android.app.Activity import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri -import android.os.Build import android.provider.CalendarContract -import android.provider.Settings import io.github.wulkanowy.BuildConfig -import timber.log.Timber import java.time.LocalDateTime import java.time.ZoneId @@ -90,23 +86,6 @@ fun Context.openDialer(phone: String) { } } -fun Activity.openNotificationSettings() { - val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { - putExtra("android.provider.extra.APP_PACKAGE", packageName) - } - } else { - Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { - data = Uri.fromParts("package", packageName, null) - } - } - try { - startActivity(intent) - } catch (e: Exception) { - Timber.e(e) - } -} - fun Context.shareText(text: String, subject: String?) { val sendIntent: Intent = Intent().apply { action = Intent.ACTION_SEND diff --git a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt b/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt index 76ce66dc5..032e2d28a 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt @@ -3,7 +3,6 @@ package io.github.wulkanowy.utils import android.os.Handler import android.os.Looper import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner @@ -30,18 +29,18 @@ class LifecycleAwareVariable : ReadWriteProperty, DefaultL } } -class LifecycleAwareVariableComponent : ReadWriteProperty, +class LifecycleAwareVariableActivity : ReadWriteProperty, DefaultLifecycleObserver { private var _value: T? = null - override fun setValue(thisRef: LifecycleOwner, property: KProperty<*>, value: T) { + override fun setValue(thisRef: AppCompatActivity, property: KProperty<*>, value: T) { thisRef.lifecycle.removeObserver(this) _value = value thisRef.lifecycle.addObserver(this) } - override fun getValue(thisRef: LifecycleOwner, property: KProperty<*>) = _value + override fun getValue(thisRef: AppCompatActivity, property: KProperty<*>) = _value ?: throw IllegalStateException("Trying to call an lifecycle-aware value outside of the view lifecycle, or the value has not been initialized") override fun onDestroy(owner: LifecycleOwner) { @@ -54,8 +53,4 @@ class LifecycleAwareVariableComponent : ReadWriteProperty Fragment.lifecycleAwareVariable() = LifecycleAwareVariable() -@Suppress("unused") -fun DialogFragment.lifecycleAwareVariable() = LifecycleAwareVariableComponent() - -@Suppress("unused") -fun AppCompatActivity.lifecycleAwareVariable() = LifecycleAwareVariableComponent() +fun lifecycleAwareVariable() = LifecycleAwareVariableActivity() diff --git a/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt index 00ed2c110..1e9f49a66 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt @@ -7,7 +7,7 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager -import fr.bipi.treessence.common.filters.Filter +import fr.bipi.tressence.common.filters.Filter import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException import timber.log.Timber diff --git a/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt index e43654b8b..93e67be01 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt @@ -23,7 +23,7 @@ fun getRefreshKey(name: String, semester: Semester): String { } fun getRefreshKey(name: String, student: Student): String { - return "${name}_${student.studentId}" + return "${name}_${student.userLoginId}" } fun getRefreshKey(name: String, mailbox: Mailbox?, folder: MessageFolder): String { @@ -49,9 +49,4 @@ class AutoRefreshHelper @Inject constructor( fun updateLastRefreshTimestamp(key: String) { sharedPref.putLong(key, Instant.now().toEpochMilli()) } - - fun getLastRefreshTimestamp(key: String): Instant { - val refreshTimestampMilli = sharedPref.getLong(key, 0) - return Instant.ofEpochMilli(refreshTimestampMilli) - } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/RemoteConfigDefaults.kt b/app/src/main/java/io/github/wulkanowy/utils/RemoteConfigDefaults.kt deleted file mode 100644 index 6e8f7ae65..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/RemoteConfigDefaults.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.wulkanowy.utils - -enum class RemoteConfigDefaults(val value: Any) { - USER_AGENT_TEMPLATE(""), - ; - - val key get() = name.lowercase() -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt new file mode 100644 index 000000000..63a30db8c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt @@ -0,0 +1,31 @@ +package io.github.wulkanowy.utils + +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.sdk.Sdk +import timber.log.Timber + +fun Sdk.init(student: Student): Sdk { + email = student.email + password = student.password + symbol = student.symbol + schoolSymbol = student.schoolSymbol + studentId = student.studentId + classId = student.classId + + if (Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { + scrapperBaseUrl = student.scrapperBaseUrl + loginType = Sdk.ScrapperLoginType.valueOf(student.loginType) + } + loginId = student.userLoginId + + mode = Sdk.Mode.valueOf(student.loginMode) + mobileBaseUrl = student.mobileBaseUrl + certKey = student.certificateKey + privateKey = student.privateKey + + emptyCookieJarInterceptor = true + + Timber.d("Sdk in ${student.loginMode} mode reinitialized") + + return this +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt index 6cfc4fa11..380d6bf6e 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt @@ -1,27 +1,16 @@ package io.github.wulkanowy.utils import io.github.wulkanowy.data.db.entities.Semester -import java.time.LocalDate import java.time.LocalDate.now -import java.time.Month -fun Semester.isCurrent(now: LocalDate = now()): Boolean { - val shiftedStart = if (start.month == Month.SEPTEMBER) { - start.minusDays(3) - } else start - - val shiftedEnd = if (end.month == Month.AUGUST || end.month == Month.SEPTEMBER) { - end.minusDays(3) - } else end - - return now in shiftedStart..shiftedEnd -} +inline val Semester.isCurrent: Boolean + get() = now() in start..end fun List.getCurrentOrLast(): Semester { - if (isEmpty()) throw IllegalStateException("Empty semester list") + if (isEmpty()) throw RuntimeException("Empty semester list") // when there is only one current semester - singleOrNull { it.isCurrent() }?.let { return it } + singleOrNull { it.isCurrent }?.let { return it } // when there is more than one current semester - find one with higher id singleOrNull { semester -> semester.semesterId == maxByOrNull { it.semesterId }?.semesterId }?.let { return it } diff --git a/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt index 8043e3659..bddd7df4c 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt @@ -1,15 +1,7 @@ package io.github.wulkanowy.utils -import androidx.core.text.parseAsHtml -import org.apache.commons.text.StringEscapeUtils - inline fun String?.ifNullOrBlank(defaultValue: () -> String) = if (isNullOrBlank()) defaultValue() else this fun String.capitalise() = - replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } - -fun String.parseUonetHtml() = this - .let(StringEscapeUtils::unescapeHtml4) - .replace("\n", "
") - .parseAsHtml() + replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/utils/StudentExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/StudentExtension.kt index 132a3085e..fdd0610a0 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/StudentExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/StudentExtension.kt @@ -2,4 +2,4 @@ package io.github.wulkanowy.utils import io.github.wulkanowy.data.db.entities.Student -inline val Student.nickOrName get() = nick.ifBlank { studentName } +inline val Student.nickOrName get() = if (nick.isBlank()) studentName else nick diff --git a/app/src/main/java/io/github/wulkanowy/utils/WebkitCookieManagerProxy.kt b/app/src/main/java/io/github/wulkanowy/utils/WebkitCookieManagerProxy.kt deleted file mode 100644 index 4d2dde788..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/WebkitCookieManagerProxy.kt +++ /dev/null @@ -1,74 +0,0 @@ -package io.github.wulkanowy.utils - -import android.util.AndroidRuntimeException -import java.net.CookiePolicy -import java.net.CookieStore -import java.net.HttpCookie -import java.net.URI -import javax.inject.Inject -import javax.inject.Singleton -import android.webkit.CookieManager as WebkitCookieManager -import java.net.CookieManager as JavaCookieManager - -@Singleton -class WebkitCookieManagerProxy @Inject constructor() : - JavaCookieManager(null, CookiePolicy.ACCEPT_ALL) { - - val webkitCookieManager: WebkitCookieManager? = getCookieManager() - - /** - * @see [https://stackoverflow.com/a/70354583/6695449] - */ - private fun getCookieManager(): WebkitCookieManager? { - return try { - WebkitCookieManager.getInstance() - } catch (e: AndroidRuntimeException) { - null - } - } - - override fun put(uri: URI?, responseHeaders: Map>?) { - if (uri == null || responseHeaders == null) return - val url = uri.toString() - for (headerKey in responseHeaders.keys) { - if (headerKey == null || !( - headerKey.equals("Set-Cookie2", ignoreCase = true) || - headerKey.equals("Set-Cookie", ignoreCase = true) - ) - ) continue - - // process each of the headers - for (headerValue in responseHeaders[headerKey].orEmpty()) { - webkitCookieManager?.setCookie(url, headerValue) - } - } - } - - override operator fun get( - uri: URI?, - requestHeaders: Map?>? - ): Map> { - require(!(uri == null || requestHeaders == null)) { "Argument is null" } - val res = mutableMapOf>() - val cookie = webkitCookieManager?.getCookie(uri.toString()) - if (cookie != null) res["Cookie"] = listOf(cookie) - return res - } - - override fun getCookieStore(): CookieStore { - val cookies = super.getCookieStore() - return object : CookieStore { - override fun add(uri: URI?, cookie: HttpCookie?) = cookies.add(uri, cookie) - override fun get(uri: URI?): List = cookies.get(uri) - override fun getCookies(): List = cookies.cookies - override fun getURIs(): List = cookies.urIs - override fun remove(uri: URI?, cookie: HttpCookie?): Boolean = - cookies.remove(uri, cookie) - - override fun removeAll(): Boolean { - webkitCookieManager?.removeAllCookies(null) ?: return false - return true - } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt b/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt index db16a2563..c994ebab6 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt @@ -16,7 +16,6 @@ import android.util.Base64.DEFAULT import android.util.Base64.decode import android.util.Base64.encode import android.util.Base64.encodeToString -import dagger.hilt.android.qualifiers.ApplicationContext import timber.log.Timber import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream @@ -34,124 +33,108 @@ import javax.crypto.CipherInputStream import javax.crypto.CipherOutputStream import javax.crypto.spec.OAEPParameterSpec import javax.crypto.spec.PSource.PSpecified -import javax.inject.Inject -import javax.inject.Singleton import javax.security.auth.x500.X500Principal -@Singleton -class Scrambler @Inject constructor( - @ApplicationContext private val context: Context, -) { - private val keyCharset = Charset.forName("UTF-8") +private const val KEYSTORE_NAME = "AndroidKeyStore" - private val isKeyPairExists: Boolean - get() = keyStore.getKey(KEY_ALIAS, null) != null +private const val KEY_ALIAS = "wulkanowy_password" - private val keyStore: KeyStore - get() = KeyStore.getInstance(KEYSTORE_NAME).apply { load(null) } +private val KEY_CHARSET = Charset.forName("UTF-8") - private val cipher: Cipher - get() { - return if (SDK_INT >= M) Cipher.getInstance( - "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", - "AndroidKeyStoreBCWorkaround" - ) - else Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL") - } +private val isKeyPairExists: Boolean + get() = keyStore.getKey(KEY_ALIAS, null) != null - fun encrypt(plainText: String): String { - if (plainText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") +private val keyStore: KeyStore + get() = KeyStore.getInstance(KEYSTORE_NAME).apply { load(null) } - return try { - if (!isKeyPairExists) generateKeyPair() +private val cipher: Cipher + get() { + return if (SDK_INT >= M) Cipher.getInstance( + "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", + "AndroidKeyStoreBCWorkaround" + ) + else Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL") + } - cipher.let { - if (SDK_INT >= M) { - OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> - it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey, spec) - } - } else it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey) +fun encrypt(plainText: String, context: Context): String { + if (plainText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") - ByteArrayOutputStream().let { output -> - CipherOutputStream(output, it).apply { - write(plainText.toByteArray(keyCharset)) - close() - } - encodeToString(output.toByteArray(), DEFAULT) + return try { + if (!isKeyPairExists) generateKeyPair(context) + + cipher.let { + if (SDK_INT >= M) { + OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> + it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey, spec) } - } - } catch (exception: Exception) { - Timber.e(exception, "An error occurred while encrypting text") - String(encode(plainText.toByteArray(keyCharset), DEFAULT), keyCharset) - } - } + } else it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey) - fun decrypt(cipherText: String): String { - if (cipherText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") - - return try { - if (!isKeyPairExists) throw ScramblerException("KeyPair doesn't exist") - - cipher.let { - if (SDK_INT >= M) { - OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> - it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null), spec) - } - } else it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null)) - - CipherInputStream( - ByteArrayInputStream(decode(cipherText, DEFAULT)), - it - ).let { input -> - val values = ArrayList() - var nextByte: Int - while (run { nextByte = input.read(); nextByte } != -1) { - values.add(nextByte.toByte()) - } - val bytes = ByteArray(values.size) - for (i in bytes.indices) { - bytes[i] = values[i] - } - String(bytes, 0, bytes.size, keyCharset) + ByteArrayOutputStream().let { output -> + CipherOutputStream(output, it).apply { + write(plainText.toByteArray(KEY_CHARSET)) + close() } - } - } catch (e: Exception) { - throw ScramblerException("An error occurred while decrypting text", e) - } - } - - private fun generateKeyPair() { - (if (SDK_INT >= M) { - KeyGenParameterSpec.Builder(KEY_ALIAS, PURPOSE_DECRYPT or PURPOSE_ENCRYPT) - .setDigests(DIGEST_SHA256, DIGEST_SHA512) - .setEncryptionPaddings(ENCRYPTION_PADDING_RSA_OAEP) - .setCertificateSerialNumber(BigInteger.TEN) - .setCertificateSubject(X500Principal("CN=Wulkanowy")) - .build() - } else { - KeyPairGeneratorSpec.Builder(context) - .setAlias(KEY_ALIAS) - .setSubject(X500Principal("CN=Wulkanowy")) - .setSerialNumber(BigInteger.TEN) - .setStartDate(Calendar.getInstance().time) - .setEndDate(Calendar.getInstance().apply { add(YEAR, 99) }.time) - .build() - }).let { - KeyPairGenerator.getInstance("RSA", KEYSTORE_NAME).apply { - initialize(it) - genKeyPair() + encodeToString(output.toByteArray(), DEFAULT) } } - Timber.i("A new KeyPair has been generated") - } - - fun clearKeyPair() { - keyStore.deleteEntry(KEY_ALIAS) - Timber.i("KeyPair has been cleared") - } - - private companion object { - private const val KEYSTORE_NAME = "AndroidKeyStore" - private const val KEY_ALIAS = "wulkanowy_password" + } catch (exception: Exception) { + Timber.e(exception, "An error occurred while encrypting text") + String(encode(plainText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET) } } + +fun decrypt(cipherText: String): String { + if (cipherText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") + + return try { + if (!isKeyPairExists) throw ScramblerException("KeyPair doesn't exist") + + cipher.let { + if (SDK_INT >= M) { + OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> + it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null), spec) + } + } else it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null)) + + CipherInputStream(ByteArrayInputStream(decode(cipherText, DEFAULT)), it).let { input -> + val values = ArrayList() + var nextByte: Int + while (run { nextByte = input.read(); nextByte } != -1) { + values.add(nextByte.toByte()) + } + val bytes = ByteArray(values.size) + for (i in bytes.indices) { + bytes[i] = values[i] + } + String(bytes, 0, bytes.size, KEY_CHARSET) + } + } + } catch (e: Exception) { + throw ScramblerException("An error occurred while decrypting text", e) + } +} + +private fun generateKeyPair(context: Context) { + (if (SDK_INT >= M) { + KeyGenParameterSpec.Builder(KEY_ALIAS, PURPOSE_DECRYPT or PURPOSE_ENCRYPT) + .setDigests(DIGEST_SHA256, DIGEST_SHA512) + .setEncryptionPaddings(ENCRYPTION_PADDING_RSA_OAEP) + .setCertificateSerialNumber(BigInteger.TEN) + .setCertificateSubject(X500Principal("CN=Wulkanowy")) + .build() + } else { + KeyPairGeneratorSpec.Builder(context) + .setAlias(KEY_ALIAS) + .setSubject(X500Principal("CN=Wulkanowy")) + .setSerialNumber(BigInteger.TEN) + .setStartDate(Calendar.getInstance().time) + .setEndDate(Calendar.getInstance().apply { add(YEAR, 99) }.time) + .build() + }).let { + KeyPairGenerator.getInstance("RSA", KEYSTORE_NAME).apply { + initialize(it) + genKeyPair() + } + } + Timber.i("A new KeyPair has been generated") +} diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index a966a31f6..7b2fda861 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,5 +1,9 @@ -Wersja 2.5.6 +Wersja 1.8.1 -— naprawiliśmy logowanie (pusta lista z wyborem uczniów), które zepsuło się po zmianach po stronie VULCANa +- naprawiliśmy liczenie średniej ucznia w ocenach klasy dla wykresu "Wszystkie" +- zmieniliśmy kolejność przycisków akcji w podglądzie wiadomości +- ulepszyliśmy oznaczenie nieodczytanych wiadomości +- naprawiliśmy pokazywanie informacji o odczytanej wiadomości w wysłanych +- dodaliśmy opcję ręcznego wybierania skrzynki pocztowej Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases diff --git a/app/src/main/res/drawable-night/background_header_note.xml b/app/src/main/res/drawable-night/background_header_note.xml new file mode 100644 index 000000000..6b594e7c6 --- /dev/null +++ b/app/src/main/res/drawable-night/background_header_note.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/background_grade_details_rounded.xml b/app/src/main/res/drawable/background_grade_details_rounded.xml deleted file mode 100644 index e24088a0c..000000000 --- a/app/src/main/res/drawable/background_grade_details_rounded.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/background_grade_details_weight_rounded.xml b/app/src/main/res/drawable/background_grade_details_weight_rounded.xml deleted file mode 100644 index 4b2109128..000000000 --- a/app/src/main/res/drawable/background_grade_details_weight_rounded.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/background_header_note.xml b/app/src/main/res/drawable/background_header_note.xml index 8cf84a1cd..c21e55c6b 100644 --- a/app/src/main/res/drawable/background_header_note.xml +++ b/app/src/main/res/drawable/background_header_note.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/background_luckynumber_widget_button.xml b/app/src/main/res/drawable/background_luckynumber_widget.xml similarity index 65% rename from app/src/main/res/drawable/background_luckynumber_widget_button.xml rename to app/src/main/res/drawable/background_luckynumber_widget.xml index 66b1685f6..367c55275 100644 --- a/app/src/main/res/drawable/background_luckynumber_widget_button.xml +++ b/app/src/main/res/drawable/background_luckynumber_widget.xml @@ -1,6 +1,6 @@ - - + + diff --git a/app/src/main/res/drawable/background_luckynumber_widget_dark.xml b/app/src/main/res/drawable/background_luckynumber_widget_dark.xml new file mode 100644 index 000000000..cb094b57e --- /dev/null +++ b/app/src/main/res/drawable/background_luckynumber_widget_dark.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/background_material_alert_dialog.xml b/app/src/main/res/drawable/background_material_alert_dialog.xml deleted file mode 100644 index 5ab8a3506..000000000 --- a/app/src/main/res/drawable/background_material_alert_dialog.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/background_timetable_widget_avatar.xml b/app/src/main/res/drawable/background_timetable_widget_avatar.xml deleted file mode 100644 index 48298d675..000000000 --- a/app/src/main/res/drawable/background_timetable_widget_avatar.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_circle_notification.xml b/app/src/main/res/drawable/background_widget_header_timetable.xml similarity index 57% rename from app/src/main/res/drawable/ic_circle_notification.xml rename to app/src/main/res/drawable/background_widget_header_timetable.xml index 6059212cb..98eec700d 100644 --- a/app/src/main/res/drawable/ic_circle_notification.xml +++ b/app/src/main/res/drawable/background_widget_header_timetable.xml @@ -1,10 +1,7 @@ - - + - - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_widget_header_timetable_dark.xml b/app/src/main/res/drawable/background_widget_header_timetable_dark.xml new file mode 100644 index 000000000..616a91279 --- /dev/null +++ b/app/src/main/res/drawable/background_widget_header_timetable_dark.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_widget_item_timetable.xml b/app/src/main/res/drawable/background_widget_item_timetable.xml index 510c70c0c..08854fba2 100644 --- a/app/src/main/res/drawable/background_widget_item_timetable.xml +++ b/app/src/main/res/drawable/background_widget_item_timetable.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_grade_small_rounded.xml b/app/src/main/res/drawable/background_widget_item_timetable_dark.xml similarity index 51% rename from app/src/main/res/drawable/background_grade_small_rounded.xml rename to app/src/main/res/drawable/background_widget_item_timetable_dark.xml index dd50417f7..e432a648c 100644 --- a/app/src/main/res/drawable/background_grade_small_rounded.xml +++ b/app/src/main/res/drawable/background_widget_item_timetable_dark.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_widget_timetable.xml b/app/src/main/res/drawable/background_widget_timetable.xml index b589ad29d..2267587d9 100644 --- a/app/src/main/res/drawable/background_widget_timetable.xml +++ b/app/src/main/res/drawable/background_widget_timetable.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_grade_rounded.xml b/app/src/main/res/drawable/background_widget_timetable_dark.xml similarity index 74% rename from app/src/main/res/drawable/background_grade_rounded.xml rename to app/src/main/res/drawable/background_widget_timetable_dark.xml index 52c10c2f4..6fe7d0ab2 100644 --- a/app/src/main/res/drawable/background_grade_rounded.xml +++ b/app/src/main/res/drawable/background_widget_timetable_dark.xml @@ -1,5 +1,5 @@ - + - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_auth_success.xml b/app/src/main/res/drawable/ic_auth_success.xml deleted file mode 100644 index 015553c02..000000000 --- a/app/src/main/res/drawable/ic_auth_success.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_chevron_left.xml b/app/src/main/res/drawable/ic_chevron_left.xml index 4250fae47..ee3ff4be8 100644 --- a/app/src/main/res/drawable/ic_chevron_left.xml +++ b/app/src/main/res/drawable/ic_chevron_left.xml @@ -1,10 +1,5 @@ - - + + diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml index de5037cf0..a6d734973 100644 --- a/app/src/main/res/drawable/ic_chevron_right.xml +++ b/app/src/main/res/drawable/ic_chevron_right.xml @@ -1,10 +1,5 @@ - - + + diff --git a/app/src/main/res/drawable/ic_close.xml b/app/src/main/res/drawable/ic_close.xml deleted file mode 100644 index 1d6c00461..000000000 --- a/app/src/main/res/drawable/ic_close.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_history.xml b/app/src/main/res/drawable/ic_history.xml deleted file mode 100644 index f20e2094b..000000000 --- a/app/src/main/res/drawable/ic_history.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml b/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml deleted file mode 100644 index b1b01a0b6..000000000 --- a/app/src/main/res/drawable/ic_launcher_foreground_dev_mono.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground_mono.xml b/app/src/main/res/drawable/ic_launcher_foreground_mono.xml deleted file mode 100644 index e2e747316..000000000 --- a/app/src/main/res/drawable/ic_launcher_foreground_mono.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_login.xml b/app/src/main/res/drawable/ic_login.xml deleted file mode 100644 index 57aef3dca..000000000 --- a/app/src/main/res/drawable/ic_login.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_delete_forever.xml b/app/src/main/res/drawable/ic_menu_message_delete_forever.xml deleted file mode 100644 index a7b5ac53b..000000000 --- a/app/src/main/res/drawable/ic_menu_message_delete_forever.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_restore.xml b/app/src/main/res/drawable/ic_menu_message_restore.xml deleted file mode 100644 index 5c8544f28..000000000 --- a/app/src/main/res/drawable/ic_menu_message_restore.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_order_drag.xml b/app/src/main/res/drawable/ic_menu_order_drag.xml deleted file mode 100644 index 623c67d2e..000000000 --- a/app/src/main/res/drawable/ic_menu_order_drag.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_notifications_off.xml b/app/src/main/res/drawable/ic_notifications_off.xml deleted file mode 100644 index 094ed75fa..000000000 --- a/app/src/main/res/drawable/ic_notifications_off.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_scale_balance.xml b/app/src/main/res/drawable/ic_scale_balance.xml deleted file mode 100644 index c65467a6c..000000000 --- a/app/src/main/res/drawable/ic_scale_balance.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_timetable_widget_swap.xml b/app/src/main/res/drawable/ic_timetable_widget_swap.xml deleted file mode 100644 index 09c50b4f1..000000000 --- a/app/src/main/res/drawable/ic_timetable_widget_swap.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_widget_chevron.png b/app/src/main/res/drawable/ic_widget_chevron.png new file mode 100644 index 000000000..34345521a Binary files /dev/null and b/app/src/main/res/drawable/ic_widget_chevron.png differ diff --git a/app/src/main/res/drawable/ic_widget_chevron.xml b/app/src/main/res/drawable/ic_widget_chevron.xml deleted file mode 100644 index 871aca9bf..000000000 --- a/app/src/main/res/drawable/ic_widget_chevron.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/img_luckynumber_widget_preview.png b/app/src/main/res/drawable/img_luckynumber_widget_preview.png index 267018550..539b0a598 100644 Binary files a/app/src/main/res/drawable/img_luckynumber_widget_preview.png and b/app/src/main/res/drawable/img_luckynumber_widget_preview.png differ diff --git a/app/src/main/res/drawable/img_timetable_widget_preview.png b/app/src/main/res/drawable/img_timetable_widget_preview.png old mode 100644 new mode 100755 index 5c1752cb5..849430187 Binary files a/app/src/main/res/drawable/img_timetable_widget_preview.png and b/app/src/main/res/drawable/img_timetable_widget_preview.png differ diff --git a/app/src/main/res/drawable/shape_badge.xml b/app/src/main/res/drawable/shape_badge.xml deleted file mode 100644 index 3153f592d..000000000 --- a/app/src/main/res/drawable/shape_badge.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout-v31/widget_timetable_preview.xml b/app/src/main/res/layout-v31/widget_timetable_preview.xml deleted file mode 100644 index 2c47836cc..000000000 --- a/app/src/main/res/layout-v31/widget_timetable_preview.xml +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a9284234e..11844e244 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,31 +1,24 @@ - - - - + app:contentInsetStartWithNavigation="0dp" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/main_toolbar" /> - - - - + android:elevation="4dp" + app:layout_constraintBottom_toTopOf="@id/sendMessageScroll" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/sendMessageToolbar"> + android:layout_height="match_parent"> + app:layout_constraintTop_toBottomOf="@id/sendMessageToolbar" /> diff --git a/app/src/main/res/layout/dialog_account_edit.xml b/app/src/main/res/layout/dialog_account_edit.xml index ec5f93a68..9f617e440 100644 --- a/app/src/main/res/layout/dialog_account_edit.xml +++ b/app/src/main/res/layout/dialog_account_edit.xml @@ -1,14 +1,19 @@ - + + android:layout_height="match_parent" + android:fillViewport="true" + android:minWidth="300dp" + android:paddingStart="8dp" + android:paddingEnd="8dp"> - + android:minWidth="300dp" + android:orientation="vertical"> + android:textSize="21sp" + android:textStyle="bold" /> - + android:text="@string/additional_lessons_repeat" /> @@ -76,9 +78,9 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginHorizontal="16dp" android:layout_marginTop="16dp" android:hint="@string/additional_lessons_end" - app:layout_constraintTop_toBottomOf="@id/additionalLessonDialogStart" app:startIconDrawable="@drawable/ic_all_clock"> @@ -96,54 +98,59 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginHorizontal="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="16dp" - android:hint="@string/all_subject" - app:layout_constraintTop_toBottomOf="@id/additionalLessonDialogEnd"> + android:hint="@string/all_subject"> - + - - + + + + + diff --git a/app/src/main/res/layout/dialog_ads_consent.xml b/app/src/main/res/layout/dialog_ads_consent.xml new file mode 100644 index 000000000..816074783 --- /dev/null +++ b/app/src/main/res/layout/dialog_ads_consent.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_attendance.xml b/app/src/main/res/layout/dialog_attendance.xml index b9c63539c..08ed9d4a3 100644 --- a/app/src/main/res/layout/dialog_attendance.xml +++ b/app/src/main/res/layout/dialog_attendance.xml @@ -5,21 +5,28 @@ android:layout_height="match_parent"> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_captcha.xml b/app/src/main/res/layout/dialog_captcha.xml deleted file mode 100644 index 019d89327..000000000 --- a/app/src/main/res/layout/dialog_captcha.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_conference.xml b/app/src/main/res/layout/dialog_conference.xml index 3d33fd568..d08edf4f7 100644 --- a/app/src/main/res/layout/dialog_conference.xml +++ b/app/src/main/res/layout/dialog_conference.xml @@ -6,20 +6,28 @@ android:layout_height="match_parent"> + + + android:layout_height="match_parent" + tools:context=".ui.modules.exam.ExamDialog"> + + + app:layout_constraintStart_toStartOf="parent" /> + android:layout_height="wrap_content"> + android:hint="@string/attendance_excuse_dialog_reason" /> diff --git a/app/src/main/res/layout/dialog_grade.xml b/app/src/main/res/layout/dialog_grade.xml index 8606a5ce5..94facb232 100644 --- a/app/src/main/res/layout/dialog_grade.xml +++ b/app/src/main/res/layout/dialog_grade.xml @@ -32,57 +32,43 @@ android:id="@+id/gradeDialogValue" android:layout_width="match_parent" android:layout_height="86dp" + android:layout_marginStart="0dp" android:layout_marginEnd="16dp" - android:background="@drawable/background_grade_details_rounded" - android:backgroundTint="@color/grade_material_default" + android:background="@color/grade_material_default" android:gravity="center" android:textColor="@android:color/white" android:textSize="30sp" tools:text="6" /> - - - - - - + android:background="@color/grade_black" + android:gravity="center" + android:maxLines="2" + android:minHeight="32dp" + android:textColor="@android:color/white" + android:textIsSelectable="true" + android:textSize="14sp" + tools:text="Waga: 1.00" /> + android:textIsSelectable="true" + android:textSize="21sp" + android:textStyle="bold" /> + android:layout_marginTop="8dp" + android:textIsSelectable="true" + android:textSize="16sp" /> + android:textColor="?android:textColorSecondary" + android:textSize="12sp" /> + android:textIsSelectable="true" + android:textSize="16sp" /> + android:textColor="?android:textColorSecondary" + android:textSize="12sp" /> + android:textIsSelectable="true" + android:textSize="16sp" /> + android:textColor="?android:textColorSecondary" + android:textSize="12sp" /> + android:textIsSelectable="true" + android:textSize="16sp" /> + android:textColor="?android:textColorSecondary" + android:textSize="12sp" /> + android:textIsSelectable="true" + android:textSize="16sp" /> + + diff --git a/app/src/main/res/layout/dialog_homework.xml b/app/src/main/res/layout/dialog_homework.xml index 10b719077..341cec544 100644 --- a/app/src/main/res/layout/dialog_homework.xml +++ b/app/src/main/res/layout/dialog_homework.xml @@ -1,58 +1,71 @@ - + android:layout_height="match_parent" + android:minWidth="300dp" + android:orientation="vertical"> + android:background="@drawable/ic_all_divider" /> - + android:gravity="end" + android:minHeight="52dp" + android:orientation="horizontal"> - - + + + + + diff --git a/app/src/main/res/layout/dialog_homework_add.xml b/app/src/main/res/layout/dialog_homework_add.xml index dc7ae32d5..524f0db0d 100644 --- a/app/src/main/res/layout/dialog_homework_add.xml +++ b/app/src/main/res/layout/dialog_homework_add.xml @@ -2,35 +2,37 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:fillViewport="true" + android:minWidth="300dp" + android:paddingStart="8dp" + android:paddingEnd="8dp"> - + android:minWidth="300dp" + android:orientation="vertical"> + android:textSize="21sp" + android:textStyle="bold" /> + android:hint="@string/all_subject"> + android:hint="@string/all_teacher"> + android:hint="@string/all_content"> - + - - + + + + + diff --git a/app/src/main/res/layout/dialog_lesson_completed.xml b/app/src/main/res/layout/dialog_lesson_completed.xml index fc32a252a..500cdb6f3 100644 --- a/app/src/main/res/layout/dialog_lesson_completed.xml +++ b/app/src/main/res/layout/dialog_lesson_completed.xml @@ -1,5 +1,4 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_mobile_device.xml b/app/src/main/res/layout/dialog_mobile_device.xml index c526ed74c..043afb2ad 100644 --- a/app/src/main/res/layout/dialog_mobile_device.xml +++ b/app/src/main/res/layout/dialog_mobile_device.xml @@ -7,10 +7,18 @@ tools:context=".ui.modules.mobiledevice.token.MobileDeviceTokenDialog"> + + + app:layout_constraintTop_toTopOf="parent" /> - + tools:visibility="visible" + app:constraint_referenced_ids="mobileDeviceQr,mobileDeviceDialogTokenTitle,mobileDeviceDialogTokenValue,mobileDeviceDialogSymbolTitle,mobileDeviceDialogSymbolValue,mobileDeviceDialogPinTitle,mobileDeviceDialogPinValue,mobileDeviceDialogClose" /> + app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/dialog_note.xml b/app/src/main/res/layout/dialog_note.xml index 3b88ea5f8..57a4ad820 100644 --- a/app/src/main/res/layout/dialog_note.xml +++ b/app/src/main/res/layout/dialog_note.xml @@ -1,25 +1,32 @@ - + + - + + + + + app:layout_constraintTop_toBottomOf="@id/timetableDialogLessonValue" /> + app:layout_constraintTop_toBottomOf="@id/timetableDialogTeacherValue" /> + app:layout_constraintTop_toBottomOf="@id/timetableDialogRoomValue" /> @@ -105,7 +106,7 @@ + tools:ignore="UnusedAttribute"> + android:layout_height="match_parent"> + android:paddingBottom="6dp" /> - - - @@ -70,25 +54,18 @@ android:gravity="center" android:padding="8dp" android:text="@string/error_unknown" - android:textSize="20sp" - app:layout_constraintBottom_toTopOf="@id/dashboard_error_buttons" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/dashboard_error_image" /> + android:textSize="20sp" /> + android:orientation="horizontal"> - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_exam.xml b/app/src/main/res/layout/fragment_exam.xml index 8dba5361b..0c62aab5f 100644 --- a/app/src/main/res/layout/fragment_exam.xml +++ b/app/src/main/res/layout/fragment_exam.xml @@ -91,7 +91,7 @@ diff --git a/app/src/main/res/layout/fragment_login_advanced.xml b/app/src/main/res/layout/fragment_login_advanced.xml index 37551decb..c7acaa70b 100644 --- a/app/src/main/res/layout/fragment_login_advanced.xml +++ b/app/src/main/res/layout/fragment_login_advanced.xml @@ -97,7 +97,7 @@ @@ -185,34 +185,9 @@ tools:ignore="Deprecated,LabelFor" /> - - - - - + app:layout_constraintTop_toBottomOf="@+id/loginFormHostLayout"> - - + app:layout_constraintTop_toBottomOf="@+id/loginFormUsernameLayout" + app:passwordToggleEnabled="true"> - - - - - + app:layout_constraintTop_toBottomOf="@+id/loginFormHostLayout" /> + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + tools:itemCount="6" + tools:listitem="@layout/item_login_student_select" /> - - diff --git a/app/src/main/res/layout/fragment_login_symbol.xml b/app/src/main/res/layout/fragment_login_symbol.xml index 37f4c731a..f1c9be4a0 100644 --- a/app/src/main/res/layout/fragment_login_symbol.xml +++ b/app/src/main/res/layout/fragment_login_symbol.xml @@ -66,7 +66,7 @@ + app:layout_constraintTop_toBottomOf="@+id/loginSymbolHelper"> - - - - diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml index b3dac0dd1..5269d95e8 100644 --- a/app/src/main/res/layout/fragment_message.xml +++ b/app/src/main/res/layout/fragment_message.xml @@ -29,7 +29,6 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_notifications_center.xml b/app/src/main/res/layout/fragment_notifications_center.xml index ba2f0ff49..f59ce33c9 100644 --- a/app/src/main/res/layout/fragment_notifications_center.xml +++ b/app/src/main/res/layout/fragment_notifications_center.xml @@ -89,7 +89,7 @@ + tools:ignore="UnusedAttribute"> + android:layout_height="match_parent" + android:layout_marginBottom="50dp"> @@ -173,4 +173,4 @@ app:srcCompat="@drawable/ic_chevron_right" app:tint="?colorPrimary" /> - + diff --git a/app/src/main/res/layout/fragment_timetable_completed.xml b/app/src/main/res/layout/fragment_timetable_completed.xml index 8d647ff61..e089275d9 100644 --- a/app/src/main/res/layout/fragment_timetable_completed.xml +++ b/app/src/main/res/layout/fragment_timetable_completed.xml @@ -93,7 +93,7 @@ @@ -58,12 +55,8 @@ android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginTop="5dp" - android:ellipsize="end" - android:maxLines="1" android:textColor="?android:textColorSecondary" android:textSize="12sp" - app:layout_constrainedWidth="true" - app:layout_constraintEnd_toStartOf="@id/gradeHeaderNumber" app:layout_constraintStart_toEndOf="@+id/gradeHeaderAverage" app:layout_constraintTop_toBottomOf="@+id/gradeHeaderSubject" tools:text="Points: 123/200 (61,5%)" /> @@ -74,13 +67,8 @@ android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginTop="5dp" - android:layout_marginEnd="8dp" - android:ellipsize="end" - android:maxLines="1" android:textColor="?android:textColorSecondary" android:textSize="12sp" - app:layout_constrainedWidth="true" - app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/gradeHeaderPointsSum" app:layout_constraintTop_toBottomOf="@id/gradeHeaderSubject" tools:text="12 grades" /> @@ -97,9 +85,6 @@ android:paddingRight="5dp" android:textColor="?colorOnPrimary" android:textSize="14sp" - app:autoSizeMaxTextSize="16dp" - app:autoSizeMinTextSize="10dp" - app:autoSizeTextType="uniform" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" diff --git a/app/src/main/res/layout/item_dashboard_account.xml b/app/src/main/res/layout/item_dashboard_account.xml index 7ae0c84d2..139157c8b 100644 --- a/app/src/main/res/layout/item_dashboard_account.xml +++ b/app/src/main/res/layout/item_dashboard_account.xml @@ -5,7 +5,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="12dp" - android:layout_marginVertical="6dp"> + android:layout_marginVertical="6dp" + app:cardElevation="4dp"> + tools:text="Szkoła Wulkanowego " /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_admin_message.xml b/app/src/main/res/layout/item_dashboard_admin_message.xml index 407e12921..67836561b 100644 --- a/app/src/main/res/layout/item_dashboard_admin_message.xml +++ b/app/src/main/res/layout/item_dashboard_admin_message.xml @@ -5,7 +5,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="12dp" - android:layout_marginVertical="6dp"> + android:layout_marginVertical="6dp" + app:cardElevation="4dp"> - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_announcements.xml b/app/src/main/res/layout/item_dashboard_announcements.xml index b9ddb7575..19f720884 100644 --- a/app/src/main/res/layout/item_dashboard_announcements.xml +++ b/app/src/main/res/layout/item_dashboard_announcements.xml @@ -8,7 +8,8 @@ android:layout_marginVertical="6dp" android:clickable="true" android:focusable="true" - android:foreground="?selectableItemBackground"> + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_conferences.xml b/app/src/main/res/layout/item_dashboard_conferences.xml index b02b8e18f..02d3edfc8 100644 --- a/app/src/main/res/layout/item_dashboard_conferences.xml +++ b/app/src/main/res/layout/item_dashboard_conferences.xml @@ -8,7 +8,8 @@ android:layout_marginVertical="6dp" android:clickable="true" android:focusable="true" - android:foreground="?selectableItemBackground"> + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_exams.xml b/app/src/main/res/layout/item_dashboard_exams.xml index 84302403c..9cc98d790 100644 --- a/app/src/main/res/layout/item_dashboard_exams.xml +++ b/app/src/main/res/layout/item_dashboard_exams.xml @@ -8,7 +8,8 @@ android:layout_marginVertical="6dp" android:clickable="true" android:focusable="true" - android:foreground="?selectableItemBackground"> + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_grades.xml b/app/src/main/res/layout/item_dashboard_grades.xml index 345d8a5e4..5cc9ce308 100644 --- a/app/src/main/res/layout/item_dashboard_grades.xml +++ b/app/src/main/res/layout/item_dashboard_grades.xml @@ -6,7 +6,8 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="12dp" android:layout_marginVertical="6dp" - android:foreground="?selectableItemBackground"> + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_homework.xml b/app/src/main/res/layout/item_dashboard_homework.xml index b36afc570..975d66efd 100644 --- a/app/src/main/res/layout/item_dashboard_homework.xml +++ b/app/src/main/res/layout/item_dashboard_homework.xml @@ -8,7 +8,8 @@ android:layout_marginVertical="6dp" android:clickable="true" android:focusable="true" - android:foreground="?selectableItemBackground"> + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_dashboard_horizontal_group.xml b/app/src/main/res/layout/item_dashboard_horizontal_group.xml index 1c9246a19..0c59d1ebf 100644 --- a/app/src/main/res/layout/item_dashboard_horizontal_group.xml +++ b/app/src/main/res/layout/item_dashboard_horizontal_group.xml @@ -13,6 +13,7 @@ android:layout_width="0dp" android:layout_height="44dp" android:layout_marginVertical="4dp" + app:cardElevation="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/dashboard_horizontal_group_item_message_container" app:layout_constraintHorizontal_chainStyle="spread_inside" @@ -80,6 +81,7 @@ android:layout_height="44dp" android:layout_marginVertical="4dp" android:layout_marginEnd="8dp" + app:cardElevation="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/dashboard_horizontal_group_item_attendance_container" app:layout_constraintStart_toEndOf="@id/dashboard_horizontal_group_item_lucky_container" @@ -152,6 +154,7 @@ android:layout_width="0dp" android:layout_height="44dp" android:layout_marginVertical="4dp" + app:cardElevation="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/dashboard_horizontal_group_item_message_container" @@ -218,6 +221,7 @@ android:layout_height="44dp" android:layout_marginVertical="4dp" android:visibility="gone" + app:cardElevation="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/dashboard_horizontal_group_item_message_container" diff --git a/app/src/main/res/layout/item_dashboard_lessons.xml b/app/src/main/res/layout/item_dashboard_lessons.xml index a40f17f22..9156c1a2f 100644 --- a/app/src/main/res/layout/item_dashboard_lessons.xml +++ b/app/src/main/res/layout/item_dashboard_lessons.xml @@ -5,7 +5,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="12dp" - android:layout_marginVertical="6dp"> + android:layout_marginVertical="6dp" + android:clickable="true" + android:focusable="true" + android:foreground="?selectableItemBackground" + app:cardElevation="4dp"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_grade_details.xml b/app/src/main/res/layout/item_grade_details.xml index 6849e929f..2f3bd2de5 100644 --- a/app/src/main/res/layout/item_grade_details.xml +++ b/app/src/main/res/layout/item_grade_details.xml @@ -20,12 +20,11 @@ android:id="@+id/gradeItemValue" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/background_grade_rounded" - android:backgroundTint="@color/grade_material_default" + android:background="@color/grade_material_default" android:gravity="center" android:maxLength="5" android:minWidth="45dp" - android:minHeight="45dp" + android:minHeight="40dp" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="@+id/gradeDetailsContainer" diff --git a/app/src/main/res/layout/item_grade_statistics_header.xml b/app/src/main/res/layout/item_grade_statistics_header.xml index cc35f6066..92f522ba4 100644 --- a/app/src/main/res/layout/item_grade_statistics_header.xml +++ b/app/src/main/res/layout/item_grade_statistics_header.xml @@ -1,10 +1,8 @@ + android:layout_height="wrap_content"> - + android:paddingEnd="16dp"> -