diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..f760aa01 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,141 @@ +name: Test and deploy + +on: + push: + branches: [ develop ] + tags: [ '*' ] + pull_request: + branches: [ develop ] + + workflow_dispatch: + +jobs: + build: + name: Pre-build + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: fkirc/skip-duplicate-actions@master + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - name: Build + run: ./gradlew --build-cache compileFdroidDebugUnitTestKotlin preFdroidDebugAndroidTestBuild dexBuilderFdroidDebugAndroidTest packageFdroidDebug packageFdroidDebugAndroidTest + - name: Prepare build cache + run: tar -cf prebuild.tar .build-cache .gradle app/build + - uses: actions/upload-artifact@v2 + with: + name: prebuild.tar + path: prebuild.tar + + unit-tests: + name: Unit tests + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [ build ] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar + - name: Unit tests + run: | + ./gradlew --build-cache -Pcoverage testFdroidDebugUnitTest --stacktrace + ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace + - uses: codecov/codecov-action@v1 + with: + flags: unit + + instrumentation-tests: + name: Instrumentation tests + runs-on: macOS-latest + timeout-minutes: 15 + needs: [ build ] + strategy: + fail-fast: true + matrix: + api-level: [21, 29] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar + - name: Instrumentation tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86 + script: | + ./gradlew --build-cache -Pcoverage connectedFdroidDebugAndroidTest --stacktrace + ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace + - uses: codecov/codecov-action@v1 + with: + flags: instrumented,api-${{ matrix.api-level }} + + deploy-google-play: + name: Deploy to google play + runs-on: ubuntu-latest + timeout-minutes: 10 + environment: google-play + needs: [ build, unit-tests, instrumentation-tests ] + if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar + - name: Decrypt keys + env: + ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }} + SERVICES_ENCRYPT_KEY: ${{ secrets.SERVICES_ENCRYPT_KEY }} + run: | + gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg + gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/key.p12.gpg + gpg --yes --batch --passphrase=$ENCRYPT_KEY ./app/upload-key.jks.gpg + - name: Upload apk to google play + env: + PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }} + PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }} + PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }} + run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace; diff --git a/.gitignore b/.gitignore index 5daeb6b9..5d3321e3 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ out/ # Gradle files .gradle/ build/ +.build-cache # Local configuration file (sdk path, etc) local.properties diff --git a/.travis.yml b/.travis.yml index 238fefdf..04db3a61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.23.1 + - 0.24.0 android: licenses: diff --git a/README.en.md b/README.en.md index 4c5e53da..accc3608 100644 --- a/README.en.md +++ b/README.en.md @@ -1,7 +1,8 @@ [Polska wersja README](README.md) # Wulkanowy -[![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy) + +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Test%20and%20deploy/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/) @@ -50,7 +51,8 @@ You can also download a [development version](https://wulkanowy.github.io/#downl * [Wulkanowy SDK](https://github.com/wulkanowy/sdk) -* [Dagger 2](https://github.com/google/dagger) +* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) +* [Hilt](https://dagger.dev/hilt/) * [Room](https://developer.android.com/topic/libraries/architecture/room) * [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) diff --git a/README.md b/README.md index 9e29cdb6..ca3b5590 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ [English version of README](README.en.md) # Wulkanowy -[![Travis](https://img.shields.io/travis/com/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://travis-ci.com/wulkanowy/wulkanowy) + +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/wulkanowy/wulkanowy/Test%20and%20deploy/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/) @@ -50,8 +51,9 @@ Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#downloa ## Zbudowana za pomocą -* [Wulkanowy SDK](https://github.com/wulkanowy/SDK) -* [Dagger 2](https://github.com/google/dagger) +* [Wulkanowy SDK](https://github.com/wulkanowy/sdk) +* [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) +* [Hilt](https://dagger.dev/hilt/) * [Room](https://developer.android.com/topic/libraries/architecture/room) * [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) diff --git a/app/build.gradle b/app/build.gradle index 89b5346a..291dfaff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 30 - versionCode 77 - versionName "0.23.1" + versionCode 78 + versionName "0.24.0" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -131,18 +131,14 @@ play { ext { work_manager = "2.4.0" - room = "2.2.5" + room = "2.2.6" chucker = "3.4.0" - mockk = "1.10.3-jdk8" + mockk = "1.10.5" moshi = "1.11.0" } -configurations.all { - resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3" -} - dependencies { - implementation "io.github.wulkanowy:sdk:0.23.1" + implementation "io.github.wulkanowy:sdk:0.24.0" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' @@ -161,7 +157,7 @@ dependencies { implementation "androidx.recyclerview:recyclerview:1.1.0" implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation "androidx.constraintlayout:constraintlayout:2.0.1" + implementation "androidx.constraintlayout:constraintlayout:2.0.4" implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" implementation "com.google.android.material:material:1.2.1" implementation "com.github.wulkanowy:material-chips-input:2.1.1" @@ -169,7 +165,7 @@ dependencies { implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" implementation "androidx.work:work-runtime-ktx:$work_manager" - implementation "androidx.work:work-gcm:$work_manager" + playImplementation "androidx.work:work-gcm:$work_manager" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" @@ -194,19 +190,20 @@ dependencies { implementation "fr.bipi.treessence:treessence:0.3.2" implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation 'com.wdullaer:materialdatetimepicker:4.2.3' - implementation "io.coil-kt:coil:1.1.0" + implementation "io.coil-kt:coil:1.1.1" implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' - playImplementation 'com.google.firebase:firebase-analytics:18.0.0' - playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2' - playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" - playImplementation 'com.google.firebase:firebase-messaging:21.0.0' - playImplementation 'com.google.firebase:firebase-crashlytics:17.3.0' + playImplementation platform('com.google.firebase:firebase-bom:26.3.0') + playImplementation 'com.google.firebase:firebase-analytics-ktx' + playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx' + playImplementation "com.google.firebase:firebase-inappmessaging-ktx" + playImplementation 'com.google.firebase:firebase-messaging:' + playImplementation 'com.google.firebase:firebase-crashlytics:' playImplementation 'com.google.android.play:core-ktx:1.8.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - hmsImplementation 'com.huawei.hms:hianalytics:5.0.5.301' + hmsImplementation 'com.huawei.hms:hianalytics:5.1.0.301' hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.2.301' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" diff --git a/app/jacoco.gradle b/app/jacoco.gradle index a5cf84e6..94469fbc 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -7,6 +7,7 @@ jacoco { tasks.withType(Test) { jacoco.includeNoLocationClasses = true + jacoco.excludes = ['jdk.internal.*'] } task jacocoTestReport(type: JacocoReport) { diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json new file mode 100644 index 00000000..309f4ac0 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/30.json @@ -0,0 +1,1954 @@ +{ + "formatVersion": 1, + "database": { + "version": 30, + "identityHash": "891980e378373d0a17bd341f9b07cc74", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scrapperBaseUrl", + "columnName": "scrapper_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mobileBaseUrl", + "columnName": "mobile_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "login_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginMode", + "columnName": "login_mode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificateKey", + "columnName": "certificate_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "privateKey", + "columnName": "private_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isParent", + "columnName": "is_parent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userLoginId", + "columnName": "user_login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userName", + "columnName": "user_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolShortName", + "columnName": "school_short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "className", + "columnName": "class_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "current", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolYear", + "columnName": "school_year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isStudentPlan", + "columnName": "student_plan", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeId", + "columnName": "time_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excusable", + "columnName": "excusable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excuseStatus", + "columnName": "excuse_status", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPredictedGradeNotified", + "columnName": "is_predicted_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isFinalGradeNotified", + "columnName": "is_final_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "predictedGradeLastChange", + "columnName": "predicted_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "finalGradeLastChange", + "columnName": "final_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predicted_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "final_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "proposedPoints", + "columnName": "proposed_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalPoints", + "columnName": "final_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pointsSum", + "columnName": "points_sum", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "average", + "columnName": "average", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradePartialStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classAverage", + "columnName": "class_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAverage", + "columnName": "student_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classAmounts", + "columnName": "class_amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAmounts", + "columnName": "student_amounts", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesPointsStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "others", + "columnName": "others", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "student", + "columnName": "student", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradeSemesterStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "amounts", + "columnName": "amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentGrade", + "columnName": "student_grade", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hasAttachments", + "columnName": "has_attachments", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MessageAttachments", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", + "fields": [ + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "oneDriveId", + "columnName": "one_drive_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filename", + "columnName": "filename", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "real_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categoryType", + "columnName": "category_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPointsShow", + "columnName": "is_points_show", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isDone", + "columnName": "is_done", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MobileDevices", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceId", + "columnName": "device_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Teachers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "School", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contact", + "columnName": "contact", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "headmaster", + "columnName": "headmaster", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pedagogue", + "columnName": "pedagogue", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Conferences", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "agenda", + "columnName": "agenda", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presentOnConference", + "columnName": "present_on_conference", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conferenceId", + "columnName": "conference_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "TimetableAdditional", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '891980e378373d0a17bd341f9b07cc74')" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt index 611161e5..aca28732 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.data.db.migrations +import android.content.Context import androidx.preference.PreferenceManager import androidx.room.Room import androidx.room.testing.MigrationTestHelper @@ -22,10 +23,11 @@ abstract class AbstractMigrationTest { ) fun getMigratedRoomDatabase(): AppDatabase { + val context = ApplicationProvider.getApplicationContext() val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java, dbName) .addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager - .getDefaultSharedPreferences(ApplicationProvider.getApplicationContext()))) + .getDefaultSharedPreferences(context))) ) .build() // close the database and release any stream resources when the test finishes diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt deleted file mode 100644 index 04d13be4..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.data.repositories - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import java.time.LocalDate.now -import java.time.LocalDateTime - -fun getStudent(): Student { - return Student( - email = "test", - password = "test123", - schoolSymbol = "23", - scrapperBaseUrl = "fakelog.cf", - loginType = "AUTO", - isCurrent = true, - userName = "", - studentName = "", - schoolShortName = "", - schoolName = "", - studentId = 0, - classId = 1, - symbol = "", - registrationDate = LocalDateTime.now(), - className = "", - loginMode = "API", - certificateKey = "", - privateKey = "", - mobileBaseUrl = "", - userLoginId = 0, - isParent = false - ) -} - -fun getSemester() = Semester( - semesterId = 1, - studentId = 1, - classId = 1, - diaryId = 2, - diaryName = "", - end = now(), - schoolYear = 2019, - semesterName = 1, - start = now(), - unitId = 1 -) diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt deleted file mode 100644 index fa128986..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt +++ /dev/null @@ -1,83 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDate.now -import java.time.LocalDate.of -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class AttendanceLocalTest { - - private lateinit var attendanceLocal: AttendanceLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build() - attendanceLocal = AttendanceLocal(testDb.attendanceDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - getAttendanceEntity( - of(2018, 9, 10), - SentExcuseStatus.ACCEPTED - ), - getAttendanceEntity( - of(2018, 9, 14), - SentExcuseStatus.WAITING - ), - getAttendanceEntity( - of(2018, 9, 17), - SentExcuseStatus.ACCEPTED - ) - ) - runBlocking { attendanceLocal.saveAttendance(list) } - - val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1) - val attendance = runBlocking { attendanceLocal.getAttendance(semester, of(2018, 9, 10), of(2018, 9, 14)).first() } - assertEquals(2, attendance.size) - assertEquals(attendance[0].date, of(2018, 9, 10)) - assertEquals(attendance[1].date, of(2018, 9, 14)) - } - - private fun getAttendanceEntity( - date: LocalDate, - excuseStatus: SentExcuseStatus - ) = Attendance( - studentId = 1, - diaryId = 2, - timeId = 3, - date = date, - number = 0, - subject = "", - name = "", - presence = false, - absence = false, - exemption = false, - lateness = false, - excused = false, - deleted = false, - excusable = false, - excuseStatus = excuseStatus.name - ) -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt deleted file mode 100644 index ca7d0b1b..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDate.now -import java.time.LocalDate.of -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class CompletedLessonsLocalTest { - - private lateinit var completedLessonsLocal: CompletedLessonsLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room - .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - completedLessonsLocal = CompletedLessonsLocal(testDb.completedLessonsDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - getCompletedLesson(of(2018, 9, 10), 1), - getCompletedLesson(of(2018, 9, 14), 2), - getCompletedLesson(of(2018, 9, 17), 3) - ) - runBlocking { completedLessonsLocal.saveCompletedLessons(list) } - - val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1) - val completed = runBlocking { completedLessonsLocal.getCompletedLessons(semester, of(2018, 9, 10), of(2018, 9, 14)).first() } - assertEquals(2, completed.size) - assertEquals(completed[0].date, of(2018, 9, 10)) - assertEquals(completed[1].date, of(2018, 9, 14)) - } - - private fun getCompletedLesson(date: LocalDate, number: Int): CompletedLesson { - return CompletedLesson(1, 2, date, number, "", "", "", "", "", "", "") - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt deleted file mode 100644 index 14b29c9f..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.data.repositories.exam - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate.now -import java.time.LocalDate.of -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class ExamLocalTest { - - private lateinit var examLocal: ExamLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java).build() - examLocal = ExamLocal(testDb.examsDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - Exam(1, 2, of(2018, 9, 10), now(), "", "", "", "", "", ""), - Exam(1, 2, of(2018, 9, 14), now(), "", "", "", "", "", ""), - Exam(1, 2, of(2018, 9, 17), now(), "", "", "", "", "", "") - ) - runBlocking { examLocal.saveExams(list) } - - val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1) - val exams = runBlocking { examLocal.getExams(semester, of(2018, 9, 10), of(2018, 9, 14)).first() } - assertEquals(2, exams.size) - assertEquals(exams[0].date, of(2018, 9, 10)) - assertEquals(exams[1].date, of(2018, 9, 14)) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt deleted file mode 100644 index 946ebf8e..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDate.now -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class GradeLocalTest { - - private lateinit var gradeLocal: GradeLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room - .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - createGradeLocal(5, 3.0, LocalDate.of(2018, 9, 10), "", 1), - createGradeLocal(4, 4.0, LocalDate.of(2019, 2, 27), "", 2), - createGradeLocal(3, 5.0, LocalDate.of(2019, 2, 28), "", 2) - ) - runBlocking { gradeLocal.saveGrades(list) } - - val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1) - - val grades = runBlocking { gradeLocal.getGradesDetails(semester).first() } - - assertEquals(2, grades.size) - assertEquals(grades[0].date, LocalDate.of(2019, 2, 27)) - assertEquals(grades[1].date, LocalDate.of(2019, 2, 28)) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt deleted file mode 100644 index 5cf9c219..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt +++ /dev/null @@ -1,221 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import android.os.Build.VERSION_CODES.P -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider.getApplicationContext -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SdkSuppress -import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.mockk.MockKAnnotations -import io.mockk.coEvery -import io.mockk.every -import io.mockk.impl.annotations.MockK -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate.of -import java.time.LocalDateTime -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -@SdkSuppress(minSdkVersion = P) -@RunWith(AndroidJUnit4::class) -class GradeRepositoryTest { - - @MockK - private lateinit var semesterMock: Semester - - private lateinit var studentMock: Student - - @MockK - private lateinit var gradeRemote: GradeRemote - - private lateinit var gradeLocal: GradeLocal - - private lateinit var testDb: AppDatabase - - @Before - fun initApi() { - MockKAnnotations.init(this) - testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() - gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao) - studentMock = getStudentMock() - - every { semesterMock.studentId } returns 1 - every { semesterMock.diaryId } returns 1 - every { semesterMock.schoolYear } returns 2019 - every { semesterMock.semesterId } returns 1 - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun markOlderThanRegisterDateAsRead() { - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf( - createGradeLocal(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"), - createGradeLocal(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"), - createGradeLocal(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"), - createGradeLocal(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza") - ) to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date } - } - - assertFalse { grades[0].isRead } - assertFalse { grades[1].isRead } - assertTrue { grades[2].isRead } - assertTrue { grades[3].isRead } - } - - @Test - fun mitigateOldGradesNotifications() { - val list = listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Jedna ocena"), - createGradeLocal(4, 4.0, of(2019, 2, 26), "Druga"), - createGradeLocal(3, 5.0, of(2019, 2, 27), "Trzecia") - ) - runBlocking { gradeLocal.saveGrades(list) } - - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf( - createGradeLocal(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), - createGradeLocal(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), - createGradeLocal(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), - createGradeLocal(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa") - ) to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date } - } - - assertFalse { grades[0].isRead } - assertFalse { grades[1].isRead } - assertTrue { grades[2].isRead } - assertTrue { grades[3].isRead } - } - - @Test - fun subtractLocaleDuplicateGrades() { - val list = listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) - runBlocking { gradeLocal.saveGrades(list) } - - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!! - } - - assertEquals(2, grades.first.size) - } - - @Test - fun subtractRemoteDuplicateGrades() { - val list = listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) - runBlocking { gradeLocal.saveGrades(list) } - - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!! - } - - assertEquals(3, grades.first.size) - } - - @Test - fun emptyLocal() { - runBlocking { gradeLocal.saveGrades(listOf()) } - - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!! - } - - assertEquals(3, grades.first.size) - } - - @Test - fun emptyRemote() { - val list = listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) - runBlocking { gradeLocal.saveGrades(list) } - - coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (emptyList() to emptyList()) - - val grades = runBlocking { - GradeRepository(gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true) - .filter { it.status == Status.SUCCESS }.first().data!! - } - - assertEquals(0, grades.first.size) - } - - private fun getStudentMock() = Student( - scrapperBaseUrl = "http://fakelog.cf", - email = "jan@fakelog.cf", - certificateKey = "", - classId = 0, - className = "", - isCurrent = false, - isParent = false, - loginMode = Sdk.Mode.SCRAPPER.name, - loginType = "STANDARD", - mobileBaseUrl = "", - password = "", - privateKey = "", - registrationDate = LocalDateTime.of(2019, 2, 27, 12, 0), - schoolName = "", - schoolShortName = "test", - schoolSymbol = "", - studentId = 0, - studentName = "", - symbol = "", - userLoginId = 0, - userName = "" - ) -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt deleted file mode 100644 index 629c2432..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import java.time.LocalDate -import io.github.wulkanowy.sdk.pojo.Grade as GradeRemote -import io.github.wulkanowy.data.db.entities.Grade as GradeLocal - -fun createGradeLocal(value: Int, weight: Double, date: LocalDate, desc: String, semesterId: Int = 1): GradeLocal { - return GradeLocal( - semesterId = semesterId, - studentId = 1, - modifier = .0, - teacher = "", - subject = "", - date = date, - color = "", - comment = "", - description = desc, - entry = "", - gradeSymbol = "", - value = value.toDouble(), - weight = "", - weightValue = weight - ) -} - -fun createGradeApi(value: Int, weight: Double, date: LocalDate, desc: String): GradeRemote { - return GradeRemote( - subject = "", - color = "", - comment = "", - date = date, - description = desc, - entry = "", - modifier = .0, - symbol = "", - teacher = "", - value = value.toDouble(), - weight = weight.toString(), - weightValue = weight - ) -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt deleted file mode 100644 index db083432..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt +++ /dev/null @@ -1,110 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.GradePartialStatistics -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate.now -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class GradeStatisticsLocalTest { - - private lateinit var gradeStatisticsLocal: GradeStatisticsLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradePartialStatisticsDao, testDb.gradePointsStatisticsDao, testDb.gradeSemesterStatisticsDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndRead_subject() { - val list = listOf( - getGradeStatistics("Matematyka", 2, 1), - getGradeStatistics("Fizyka", 1, 2) - ) - runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) } - - val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() } - assertEquals(1, stats.size) - assertEquals(stats[0].subject, "Matematyka") - } - - @Test - fun saveAndRead_all() { - val list = listOf( - getGradeStatistics("Matematyka", 2, 1), - getGradeStatistics("Chemia", 2, 1), - getGradeStatistics("Fizyka", 1, 2) - ) - runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) } - - val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() } - assertEquals(2, stats.size) - assertEquals(stats[0].subject, "Matematyka") - assertEquals(stats[1].subject, "Chemia") - } - - @Test - fun saveAndRead_points() { - val list = listOf( - getGradePointsStatistics("Matematyka", 2, 1), - getGradePointsStatistics("Chemia", 2, 1), - getGradePointsStatistics("Fizyka", 1, 2) - ) - runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(list) } - - val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } - with(stats[0]) { - assertEquals(subject, "Matematyka") - assertEquals(others, 5.0) - assertEquals(student, 5.0) - } - } - - @Test - fun saveAndRead_subjectEmpty() { - runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) } - - val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } - assertEquals(emptyList(), stats) - } - - @Test - fun saveAndRead_allEmpty() { - runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) } - - val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } - assertEquals(emptyList(), stats) - } - - private fun getSemester(): Semester { - return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1) - } - - private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradePartialStatistics { - return GradePartialStatistics(studentId, semesterId, subject, "", "", listOf(5), listOf(5)) - } - - private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics { - return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt deleted file mode 100644 index ca38b1fe..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDateTime.now -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class LuckyNumberLocalTest { - - private lateinit var luckyNumberLocal: LuckyNumberLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room - .inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - luckyNumberLocal = LuckyNumberLocal(testDb.luckyNumberDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val number = LuckyNumber(1, LocalDate.of(2019, 1, 20), 14) - runBlocking { luckyNumberLocal.saveLuckyNumber(number) } - - val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", "", 1, false, now()) - val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() } - - assertEquals(1, luckyNumber?.studentId) - assertEquals(LocalDate.of(2019, 1, 20), luckyNumber?.date) - assertEquals(14, luckyNumber?.luckyNumber) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt deleted file mode 100644 index 6bd1959b..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -package io.github.wulkanowy.data.repositories.recipient - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDateTime -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class RecipientLocalTest { - - private lateinit var recipientLocal: RecipientLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - recipientLocal = RecipientLocal(testDb.recipientDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - Recipient(1, "2rPracownik", "Kowalski Jan", "Kowalski Jan [KJ] - Pracownik (Fake123456)", 3, 4, 2, "hash"), - Recipient(1, "3rPracownik", "Kowalska Karolina", "Kowalska Karolina [KK] - Pracownik (Fake123456)", 4, 4, 2, "hash"), - Recipient(1, "4rPracownik", "Krupa Stanisław", "Krupa Stanisław [KS] - Uczeń (Fake123456)", 5, 4, 1, "hash") - ) - runBlocking { recipientLocal.saveRecipients(list) } - - val student = Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", "", 1, true, LocalDateTime.now()) - val recipients = runBlocking { - recipientLocal.getRecipients( - student = student, - role = 2, - unit = ReportingUnit(1, 4, "", 0, "", emptyList()) - ) - } - - assertEquals(2, recipients.size) - assertEquals(1, recipients[0].studentId) - assertEquals("3rPracownik", recipients[1].realId) - assertEquals("Kowalski Jan", recipients[0].name) - assertEquals("Kowalska Karolina [KK] - Pracownik (Fake123456)", recipients[1].realName) - assertEquals(3, recipients[0].loginId) - assertEquals(4, recipients[1].unitId) - assertEquals(2, recipients[0].role) - assertEquals("hash", recipients[1].hash) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt deleted file mode 100644 index d68f15a8..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import android.content.Context -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.TestDispatchersProvider -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.repositories.getStudent -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class StudentLocalTest { - - private lateinit var studentLocal: StudentLocal - - private lateinit var testDb: AppDatabase - - private val student = getStudent() - - @Before - fun createDb() { - val context = ApplicationProvider.getApplicationContext() - testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java) - .build() - studentLocal = StudentLocal(testDb.studentDao, TestDispatchersProvider(), context) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - runBlocking { studentLocal.saveStudents(listOf(student)) } - - val student = runBlocking { studentLocal.getCurrentStudent(true) } - assertEquals("23", student?.schoolSymbol) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt deleted file mode 100644 index dddf6464..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import java.time.LocalDateTime -import java.time.LocalDateTime.now -import io.github.wulkanowy.data.db.entities.Timetable as TimetableLocal -import io.github.wulkanowy.sdk.pojo.Timetable as TimetableRemote - -fun createTimetableLocal(start: LocalDateTime, number: Int, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableLocal { - return TimetableLocal( - studentId = 1, - diaryId = 2, - number = number, - start = start, - end = now(), - date = start.toLocalDate(), - subject = subject, - subjectOld = "", - group = "", - room = room, - roomOld = "", - teacher = teacher, - teacherOld = "", - info = "", - isStudentPlan = true, - changes = changes, - canceled = false - ) -} - -fun createTimetableRemote(start: LocalDateTime, number: Int = 1, room: String = "", subject: String = "", teacher: String = "", changes: Boolean = false): TimetableRemote { - return TimetableRemote( - number = number, - start = start, - end = start.plusMinutes(45), - date = start.toLocalDate(), - subject = subject, - group = "", - room = room, - teacher = teacher, - info = "", - changes = changes, - canceled = false, - roomOld = "", - subjectOld = "", - teacherOld = "", - studentPlan = true - ) -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt deleted file mode 100644 index e793212e..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDateTime.of -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class TimetableLocalTest { - - private lateinit var timetableDb: TimetableLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - timetableDb = TimetableLocal(testDb.timetableDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - val list = listOf( - createTimetableLocal(of(2018, 9, 10, 0, 0, 0), 1), - createTimetableLocal(of(2018, 9, 14, 0, 0, 0), 1), - createTimetableLocal(of(2018, 9, 17, 0, 0, 0), 1) - ) - runBlocking { timetableDb.saveTimetable(list) } - - val semester = Semester(1, 2, "", 1, 1, 2019, LocalDate.now(), LocalDate.now(), 1, 1) - val exams = runBlocking { - timetableDb.getTimetable( - semester = semester, - startDate = LocalDate.of(2018, 9, 10), - endDate = LocalDate.of(2018, 9, 14) - ).first() - } - - assertEquals(2, exams.size) - assertEquals(exams[0].date, LocalDate.of(2018, 9, 10)) - assertEquals(exams[1].date, LocalDate.of(2018, 9, 14)) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt deleted file mode 100644 index 1bd3c467..00000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import android.os.Build.VERSION_CODES.P -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider.getApplicationContext -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SdkSuppress -import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.repositories.getSemester -import io.github.wulkanowy.data.repositories.getStudent -import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper -import io.mockk.MockKAnnotations -import io.mockk.coEvery -import io.mockk.impl.annotations.MockK -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.time.LocalDate -import java.time.LocalDateTime.of -import kotlin.test.assertEquals - -@SdkSuppress(minSdkVersion = P) -@RunWith(AndroidJUnit4::class) -class TimetableRepositoryTest { - - @MockK(relaxed = true) - private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper - - @MockK - private lateinit var timetableRemote: TimetableRemote - - private lateinit var timetableLocal: TimetableLocal - - private lateinit var testDb: AppDatabase - - private val student = getStudent() - - private val semester = getSemester() - - @Before - fun initApi() { - MockKAnnotations.init(this) - testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() - timetableLocal = TimetableLocal(testDb.timetableDao) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun copyRoomToCompletedFromPrevious() { - runBlocking { - timetableLocal.saveTimetable(listOf( - createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "123", "Przyroda"), - createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "321", "Religia"), - createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "213", "W-F"), - createTimetableLocal(of(2019, 3, 5, 10, 30), 3, "213", "W-F", "Jan Kowalski") - )) - } - - coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf( - createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"), - createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "", "Religia"), - createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "", "W-F"), - createTimetableLocal(of(2019, 3, 5, 10, 30), 4, "", "W-F") - ) - - val lessons = runBlocking { - TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable( - student = student, - semester = semester, - start = LocalDate.of(2019, 3, 5), - end = LocalDate.of(2019, 3, 5), - forceRefresh = true - ).filter { it.status == Status.SUCCESS }.first().data.orEmpty() - } - - assertEquals(4, lessons.size) - assertEquals("123", lessons[0].room) - assertEquals("321", lessons[1].room) - assertEquals("213", lessons[2].room) - } - - @Test - fun copyTeacherToCompletedFromPrevious() { - val list = listOf( - createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false), - createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Paweł Poniedziałkowski", false), - createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Wtorkowska", true), - createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true), - - createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "Joanna Wtorkowska", false), - createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "Joanna Wtorkowska", false), - createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "Joanna Środowska", true), - createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "Joanna Środowska", true), - - createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "", false), - createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "", false), - createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "", true), - createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "", true) - ) - runBlocking { timetableLocal.saveTimetable(list) } - - coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf( - createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false), - createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true), - createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false), - createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true), - - createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false), - createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true), - createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false), - createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true), - - createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false), - createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true), - createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false), - createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true) - ) - - val lessons = runBlocking { - TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable( - student = student, - semester = semester, - start = LocalDate.of(2019, 12, 23), - end = LocalDate.of(2019, 12, 25), - forceRefresh = true - ).filter { it.status == Status.SUCCESS }.first().data.orEmpty() - } - - assertEquals(12, lessons.size) - - assertEquals("Paweł Poniedziałkowski", lessons[0].teacher) - assertEquals("Jakub Wtorkowski", lessons[1].teacher) - assertEquals("Joanna Poniedziałkowska", lessons[2].teacher) - assertEquals("Joanna Wtorkowska", lessons[3].teacher) - - assertEquals("Joanna Wtorkowska", lessons[4].teacher) - assertEquals("", lessons[5].teacher) - assertEquals("", lessons[6].teacher) - assertEquals("", lessons[7].teacher) - - assertEquals("Paweł Środowski", lessons[8].teacher) - assertEquals("Paweł Czwartkowski", lessons[9].teacher) - assertEquals("Paweł Środowski", lessons[10].teacher) - assertEquals("Paweł Czwartkowski", lessons[11].teacher) - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a8d2b49e..eaef4369 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,17 @@ + + + + + + + + + + + - + android:value="${install_channel}" /> diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt index 57d14725..f1c61e82 100644 --- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt +++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt @@ -11,8 +11,10 @@ import androidx.work.Configuration import com.yariksoffice.lingver.Lingver import dagger.hilt.android.HiltAndroidApp import fr.bipi.tressence.file.FileLoggerTree +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.ui.base.ThemeManager import io.github.wulkanowy.utils.ActivityLifecycleLogger +import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.CrashLogExceptionTree import io.github.wulkanowy.utils.CrashLogTree @@ -32,6 +34,12 @@ class WulkanowyApp : Application(), Configuration.Provider { @Inject lateinit var appInfo: AppInfo + @Inject + lateinit var preferencesRepository: PreferencesRepository + + @Inject + lateinit var analyticsHelper: AnalyticsHelper + override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) MultiDex.install(this) @@ -43,6 +51,7 @@ class WulkanowyApp : Application(), Configuration.Provider { themeManager.applyDefaultTheme() initLogging() + logCurrentLanguage() } private fun initLogging() { @@ -62,6 +71,16 @@ class WulkanowyApp : Application(), Configuration.Provider { registerActivityLifecycleCallbacks(ActivityLifecycleLogger()) } + private fun logCurrentLanguage() { + val newLang = if (preferencesRepository.appLanguage == "system") { + appInfo.systemLanguage + } else { + preferencesRepository.appLanguage + } + + analyticsHelper.logEvent("language", "startup" to newLang) + } + override fun getWorkManagerConfiguration() = Configuration.Builder() .setWorkerFactory(workerFactory) .setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO) diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index e8a3fa48..324cb89f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -15,7 +15,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.SharedPrefProvider -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.sdk.Sdk import timber.log.Timber import javax.inject.Singleton @@ -33,11 +33,11 @@ internal class RepositoryModule { setSimpleHttpLogger { Timber.d(it) } // for debug only - addInterceptor(ChuckerInterceptor( - context = context, - collector = chuckerCollector, - alwaysReadResponseBody = true - ), true) + addInterceptor(ChuckerInterceptor.Builder(context) + .collector(chuckerCollector) + .alwaysReadResponseBody(true) + .build(), network = true + ) } } @@ -162,4 +162,8 @@ internal class RepositoryModule { @Singleton @Provides fun provideConferenceDao(database: AppDatabase) = database.conferenceDao + + @Singleton + @Provides + fun provideTimetableAdditionalDao(database: AppDatabase) = database.timetableAdditionalDao } 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 57160a2b..6b2301fc 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 @@ -30,6 +30,7 @@ import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.dao.StudentDao 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.entities.Attendance import io.github.wulkanowy.data.db.entities.AttendanceSummary @@ -55,6 +56,7 @@ import io.github.wulkanowy.data.db.entities.Student 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.migrations.Migration10 import io.github.wulkanowy.data.db.migrations.Migration11 import io.github.wulkanowy.data.db.migrations.Migration12 @@ -77,6 +79,7 @@ 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.Migration4 import io.github.wulkanowy.data.db.migrations.Migration5 import io.github.wulkanowy.data.db.migrations.Migration6 @@ -112,6 +115,7 @@ import javax.inject.Singleton Teacher::class, School::class, Conference::class, + TimetableAdditional::class, ], version = AppDatabase.VERSION_SCHEMA, exportSchema = true @@ -120,7 +124,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 29 + const val VERSION_SCHEMA = 30 fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array { return arrayOf( @@ -151,7 +155,8 @@ abstract class AppDatabase : RoomDatabase() { Migration26(), Migration27(), Migration28(), - Migration29() + Migration29(), + Migration30(), ) } @@ -212,4 +217,6 @@ abstract class AppDatabase : RoomDatabase() { abstract val schoolDao: SchoolDao abstract val conferenceDao: ConferenceDao + + abstract val timetableAdditionalDao: TimetableAdditionalDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt index 4a4aaf74..9301d5fa 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt @@ -6,7 +6,9 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) { +class SharedPrefProvider @Inject constructor( + private val sharedPref: SharedPreferences +) { companion object { const val APP_VERSION_CODE_KEY = "app_version_code" diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt index 8c03609d..097ad7c8 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt @@ -12,5 +12,5 @@ import javax.inject.Singleton interface CompletedLessonsDao : BaseDao { @Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") - fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow> + fun loadAll(studentId: Int, diaryId: Int, from: LocalDate, end: LocalDate): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt index 8baba2c3..081e859a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt @@ -8,6 +8,6 @@ import kotlinx.coroutines.flow.Flow @Dao interface MobileDeviceDao : BaseDao { - @Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC") - fun loadAll(studentId: Int): Flow> + @Query("SELECT * FROM MobileDevices WHERE student_id = :userLoginId ORDER BY date DESC") + fun loadAll(userLoginId: Int): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt index 419efde0..943f3f0c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt @@ -9,6 +9,6 @@ import javax.inject.Singleton @Dao interface RecipientDao : BaseDao { - @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId") - suspend fun load(studentId: Int, role: Int, unitId: Int): List + @Query("SELECT * FROM Recipients WHERE student_id = :userLoginId AND unit_id = :unitId AND role = :role") + suspend fun loadAll(userLoginId: Int, unitId: Int, role: Int): List } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt new file mode 100644 index 00000000..335e003e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt @@ -0,0 +1,16 @@ +package io.github.wulkanowy.data.db.dao + +import androidx.room.Dao +import androidx.room.Query +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import kotlinx.coroutines.flow.Flow +import java.time.LocalDate +import javax.inject.Singleton + +@Dao +@Singleton +interface TimetableAdditionalDao : BaseDao { + + @Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") + fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow> +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt index 9d8f1162..83d82c0b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt @@ -10,7 +10,7 @@ import java.time.LocalDateTime data class MobileDevice( @ColumnInfo(name = "student_id") - val studentId: Int, + val userLoginId: Int, @ColumnInfo(name = "device_id") val deviceId: Int, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt index 3021da72..b1f1f353 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt @@ -9,7 +9,7 @@ import java.io.Serializable data class Recipient( @ColumnInfo(name = "student_id") - val studentId: Int, + val userLoginId: Int, @ColumnInfo(name = "real_id") val realId: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt index 601d8aac..0570a2ff 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt @@ -12,7 +12,7 @@ data class ReportingUnit( val studentId: Int, @ColumnInfo(name = "real_id") - val realId: Int, + val unitId: Int, @ColumnInfo(name = "short") val shortName: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt new file mode 100644 index 00000000..c1f1365f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt @@ -0,0 +1,30 @@ +package io.github.wulkanowy.data.db.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.io.Serializable +import java.time.LocalDate +import java.time.LocalDateTime + +@Entity(tableName = "TimetableAdditional") +data class TimetableAdditional( + + @ColumnInfo(name = "student_id") + val studentId: Int, + + @ColumnInfo(name = "diary_id") + val diaryId: Int, + + val start: LocalDateTime, + + val end: LocalDateTime, + + val date: LocalDate, + + val subject: String, +) : Serializable { + + @PrimaryKey(autoGenerate = true) + var id: Long = 0 +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt new file mode 100644 index 00000000..b33914fe --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt @@ -0,0 +1,21 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration30 : Migration(29, 30) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" + CREATE TABLE TimetableAdditional ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + student_id INTEGER NOT NULL, + diary_id INTEGER NOT NULL, + start INTEGER NOT NULL, + `end` INTEGER NOT NULL, + date INTEGER NOT NULL, + subject TEXT NOT NULL + ) + """) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt similarity index 63% rename from app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt rename to app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt index 06f5a1e0..899ba908 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt +++ b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.message +package io.github.wulkanowy.data.enums enum class MessageFolder(val id: Int = 1) { RECEIVED(1), diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt similarity index 60% rename from app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt rename to app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt index 50d6b8ed..99878152 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt +++ b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.attendance +package io.github.wulkanowy.data.enums enum class SentExcuseStatus(val id: Int = 0) { WAITING, diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt new file mode 100644 index 00000000..46e67fda --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt @@ -0,0 +1,43 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Attendance +import io.github.wulkanowy.data.db.entities.AttendanceSummary +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance +import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary + +fun List.mapToEntities(semester: Semester) = map { + Attendance( + studentId = semester.studentId, + diaryId = semester.diaryId, + date = it.date, + timeId = it.timeId, + number = it.number, + subject = it.subject, + name = it.name, + presence = it.presence, + absence = it.absence, + exemption = it.exemption, + lateness = it.lateness, + excused = it.excused, + deleted = it.deleted, + excusable = it.excusable, + excuseStatus = it.excuseStatus?.name + ) +} + +fun List.mapToEntities(semester: Semester, subjectId: Int) = map { + AttendanceSummary( + studentId = semester.studentId, + diaryId = semester.diaryId, + subjectId = subjectId, + month = it.month, + presence = it.presence, + absence = it.absence, + absenceExcused = it.absenceExcused, + absenceForSchoolReasons = it.absenceForSchoolReasons, + lateness = it.lateness, + latenessExcused = it.latenessExcused, + exemption = it.exemption + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt new file mode 100644 index 00000000..c42126eb --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt @@ -0,0 +1,21 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.CompletedLesson +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.CompletedLesson as SdkCompletedLesson + +fun List.mapToEntities(semester: Semester) = map { + CompletedLesson( + studentId = semester.studentId, + diaryId = semester.diaryId, + date = it.date, + number = it.number, + subject = it.subject, + topic = it.topic, + teacher = it.teacher, + teacherSymbol = it.teacherSymbol, + substitution = it.substitution, + absence = it.absence, + resources = it.resources + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt new file mode 100644 index 00000000..52dc9b30 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt @@ -0,0 +1,18 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.Conference as SdkConference + +fun List.mapToEntities(semester: Semester) = map { + Conference( + studentId = semester.studentId, + diaryId = semester.diaryId, + agenda = it.agenda, + conferenceId = it.id, + date = it.date, + presentOnConference = it.presentOnConference, + subject = it.subject, + title = it.title + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt new file mode 100644 index 00000000..bdb5efbb --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt @@ -0,0 +1,20 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Exam +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.Exam as SdkExam + +fun List.mapToEntities(semester: Semester) = map { + Exam( + studentId = semester.studentId, + diaryId = semester.diaryId, + date = it.date, + entryDate = it.entryDate, + subject = it.subject, + group = it.group, + type = it.type, + description = it.description, + teacher = it.teacher, + teacherSymbol = it.teacherSymbol + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt new file mode 100644 index 00000000..178de682 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt @@ -0,0 +1,42 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Grade +import io.github.wulkanowy.data.db.entities.GradeSummary +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.GradeSummary as SdkGradeSummary +import io.github.wulkanowy.sdk.pojo.Grade as SdkGrade + +fun List.mapToEntities(semester: Semester) = map { + Grade( + studentId = semester.studentId, + semesterId = semester.semesterId, + subject = it.subject, + entry = it.entry, + value = it.value, + modifier = it.modifier, + comment = it.comment, + color = it.color, + gradeSymbol = it.symbol, + description = it.description, + weight = it.weight, + weightValue = it.weightValue, + date = it.date, + teacher = it.teacher + ) +} + +@JvmName("mapGradeSummaryToEntities") +fun List.mapToEntities(semester: Semester) = map { + GradeSummary( + semesterId = semester.semesterId, + studentId = semester.studentId, + position = 0, + subject = it.name, + predictedGrade = it.predicted, + finalGrade = it.final, + pointsSum = it.pointsSum, + proposedPoints = it.proposedPoints, + finalPoints = it.finalPoints, + average = it.average + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt new file mode 100644 index 00000000..fbd40433 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt @@ -0,0 +1,80 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.GradePartialStatistics +import io.github.wulkanowy.data.db.entities.GradePointsStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.pojos.GradeStatisticsItem +import io.github.wulkanowy.ui.modules.grade.statistics.ViewType +import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject +import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester +import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics + +@JvmName("mapToEntitiesSubject") +fun List.mapToEntities(semester: Semester) = map { + GradePartialStatistics( + semesterId = semester.semesterId, + studentId = semester.studentId, + subject = it.subject, + classAverage = it.classAverage, + studentAverage = it.studentAverage, + classAmounts = it.classItems + .sortedBy { item -> item.grade } + .map { item -> item.amount }, + studentAmounts = it.studentItems.map { item -> item.amount } + ) +} + +@JvmName("mapToEntitiesSemester") +fun List.mapToEntities(semester: Semester) = map { + GradeSemesterStatistics( + semesterId = semester.semesterId, + studentId = semester.studentId, + subject = it.subject, + amounts = it.items + .sortedBy { item -> item.grade } + .map { item -> item.amount }, + studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0 + ) +} + +@JvmName("mapToEntitiesPoints") +fun List.mapToEntities(semester: Semester) = map { + GradePointsStatistics( + semesterId = semester.semesterId, + studentId = semester.studentId, + subject = it.subject, + others = it.others, + student = it.student + ) +} + +fun List.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map { + GradeStatisticsItem( + type = ViewType.PARTIAL, + average = it.classAverage, + partial = it, + points = null, + semester = null + ) +} + +fun List.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map { + GradeStatisticsItem( + type = ViewType.SEMESTER, + partial = null, + points = null, + average = "", + semester = it + ) +} + +fun List.mapPointsToStatisticsItems() = map { + GradeStatisticsItem( + type = ViewType.POINTS, + partial = null, + semester = null, + average = "", + points = it + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt new file mode 100644 index 00000000..880a26d6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt @@ -0,0 +1,21 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.sdk.pojo.Homework as SdkHomework +import io.github.wulkanowy.data.db.entities.Homework +import io.github.wulkanowy.data.db.entities.Semester + +fun List.mapToEntities(semester: Semester) = map { + Homework( + semesterId = semester.semesterId, + studentId = semester.studentId, + date = it.date, + entryDate = it.entryDate, + subject = it.subject, + content = it.content, + teacher = it.teacher, + teacherSymbol = it.teacherSymbol, + attachments = it.attachments.map { attachment -> + attachment.url to attachment.name + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt new file mode 100644 index 00000000..78ebe1d6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/LuckyNumberMapper.kt @@ -0,0 +1,12 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.data.db.entities.Student +import java.time.LocalDate +import io.github.wulkanowy.sdk.pojo.LuckyNumber as SdkLuckyNumber + +fun SdkLuckyNumber.mapToEntity(student: Student) = LuckyNumber( + studentId = student.studentId, + date = LocalDate.now(), + luckyNumber = number +) diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt new file mode 100644 index 00000000..2c815b30 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt @@ -0,0 +1,53 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Message +import io.github.wulkanowy.data.db.entities.MessageAttachment +import io.github.wulkanowy.data.db.entities.Recipient +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient +import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment +import java.time.LocalDateTime +import io.github.wulkanowy.sdk.pojo.Message as SdkMessage + +fun List.mapToEntities(student: Student) = map { + Message( + studentId = student.id.toInt(), + realId = it.id ?: 0, + messageId = it.messageId ?: 0, + sender = it.sender?.name.orEmpty(), + senderId = it.sender?.loginId ?: 0, + recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów", + subject = it.subject.trim(), + date = it.date ?: LocalDateTime.now(), + folderId = it.folderId, + unread = it.unread ?: false, + removed = it.removed, + hasAttachments = it.hasAttachments + ).apply { + content = it.content.orEmpty() + unreadBy = it.unreadBy ?: 0 + readBy = it.readBy ?: 0 + } +} + +fun List.mapToEntities() = map { + MessageAttachment( + realId = it.id, + messageId = it.messageId, + oneDriveId = it.oneDriveId, + url = it.url, + filename = it.filename + ) +} + +fun List.mapFromEntities() = map { + SdkRecipient( + id = it.realId, + name = it.realName, + loginId = it.loginId, + reportingUnitId = it.unitId, + role = it.role, + hash = it.hash, + shortName = it.name + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt new file mode 100644 index 00000000..f0c375bf --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MobileDeviceMapper.kt @@ -0,0 +1,23 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.MobileDevice +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.pojos.MobileDeviceToken +import io.github.wulkanowy.sdk.pojo.Token as SdkToken +import io.github.wulkanowy.sdk.pojo.Device as SdkDevice + +fun List.mapToEntities(semester: Semester) = map { + MobileDevice( + userLoginId = semester.studentId, + date = it.createDate, + deviceId = it.id, + name = it.name + ) +} + +fun SdkToken.mapToMobileDeviceToken() = MobileDeviceToken( + token = token, + symbol = symbol, + pin = pin, + qr = qrCodeImage +) diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt new file mode 100644 index 00000000..70941799 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/NoteMapper.kt @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Note +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.Note as SdkNote + +fun List.mapToEntities(semester: Semester) = map { + Note( + studentId = semester.studentId, + date = it.date, + teacher = it.teacher, + teacherSymbol = it.teacherSymbol, + category = it.category, + categoryType = it.categoryType.id, + isPointsShow = it.showPoints, + points = it.points, + content = it.content + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt new file mode 100644 index 00000000..9996f680 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt @@ -0,0 +1,17 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Recipient +import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient + +fun List.mapToEntities(userLoginId: Int) = map { + Recipient( + userLoginId = userLoginId, + realId = it.id, + realName = it.name, + name = it.shortName, + hash = it.hash, + loginId = it.loginId, + role = it.role, + unitId = it.reportingUnitId ?: 0 + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt new file mode 100644 index 00000000..71ea7099 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt @@ -0,0 +1,16 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.ReportingUnit +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit + +fun List.mapToEntities(student: Student) = map { + ReportingUnit( + studentId = student.studentId, + unitId = it.id, + roles = it.roles, + senderId = it.senderId, + senderName = it.senderName, + shortName = it.short + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt new file mode 100644 index 00000000..dc3a5a9e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/SchoolInfoMapper.kt @@ -0,0 +1,15 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.School +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.sdk.pojo.School as SdkSchool + +fun SdkSchool.mapToEntity(semester: Semester) = School( + studentId = semester.studentId, + classId = semester.classId, + name = name, + address = address, + contact = contact, + headmaster = headmaster, + pedagogue = pedagogue +) diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt new file mode 100644 index 00000000..4dc95aaa --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/SubjectMapper.kt @@ -0,0 +1,14 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Subject +import io.github.wulkanowy.sdk.pojo.Subject as SdkSubject + +fun List.mapToEntities(semester: Semester) = map { + Subject( + studentId = semester.studentId, + diaryId = semester.diaryId, + name = it.name, + realId = it.id + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt new file mode 100644 index 00000000..49cb7c29 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TeacherMapper.kt @@ -0,0 +1,15 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Teacher +import io.github.wulkanowy.sdk.pojo.Teacher as SdkTeacher + +fun List.mapToEntities(semester: Semester) = map { + Teacher( + studentId = semester.studentId, + name = it.name, + subject = it.subject, + shortName = it.short, + classId = semester.classId + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt new file mode 100644 index 00000000..ffd2ae34 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/TimetableMapper.kt @@ -0,0 +1,41 @@ +package io.github.wulkanowy.data.mappers + +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Timetable +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import io.github.wulkanowy.sdk.pojo.Timetable as SdkTimetable +import io.github.wulkanowy.sdk.pojo.TimetableAdditional as SdkTimetableAdditional + +fun List.mapToEntities(semester: Semester) = map { + Timetable( + studentId = semester.studentId, + diaryId = semester.diaryId, + number = it.number, + start = it.start, + end = it.end, + date = it.date, + subject = it.subject, + subjectOld = it.subjectOld, + group = it.group, + room = it.room, + roomOld = it.roomOld, + teacher = it.teacher, + teacherOld = it.teacherOld, + info = it.info, + isStudentPlan = it.studentPlan, + changes = it.changes, + canceled = it.canceled + ) +} + +@JvmName("mapToEntitiesTimetableAdditional") +fun List.mapToEntities(semester: Semester) = map { + TimetableAdditional( + studentId = semester.studentId, + diaryId = semester.diaryId, + subject = it.subject, + date = it.date, + start = it.start, + end = it.end + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt similarity index 93% rename from app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt index ff538969..aea8632a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AppCreatorRepository.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.appcreator +package io.github.wulkanowy.data.repositories import android.content.res.AssetManager import com.squareup.moshi.Moshi diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt new file mode 100644 index 00000000..9a6528f3 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt @@ -0,0 +1,57 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.AttendanceDao +import io.github.wulkanowy.data.db.entities.Attendance +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.sdk.pojo.Absent +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.uniqueSubtract +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class AttendanceRepository @Inject constructor( + private val attendanceDb: AttendanceDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "attendance" + + fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, + query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getAttendance(start.monday, end.sunday, semester.semesterId) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + attendanceDb.deleteAll(old uniqueSubtract new) + attendanceDb.insertAll(new uniqueSubtract old) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) + }, + filterResult = { it.filter { item -> item.date in start..end } } + ) + + suspend fun excuseForAbsence(student: Student, semester: Semester, absenceList: List, reason: String? = null) { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance -> + Absent( + date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)), + timeId = attendance.timeId + ) + }, reason) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt new file mode 100644 index 00000000..4edb507b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt @@ -0,0 +1,39 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class AttendanceSummaryRepository @Inject constructor( + private val attendanceDb: AttendanceSummaryDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "attendance_summary" + + fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, + query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getAttendanceSummary(subjectId) + .mapToEntities(semester, subjectId) + }, + saveFetchResult = { old, new -> + attendanceDb.deleteAll(old uniqueSubtract new) + attendanceDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt new file mode 100644 index 00000000..59aabdd5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt @@ -0,0 +1,43 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.CompletedLessonsDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.uniqueSubtract +import java.time.LocalDate +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CompletedLessonsRepository @Inject constructor( + private val completedLessonsDb: CompletedLessonsDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "completed" + + fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, + query = { completedLessonsDb.loadAll(semester.studentId, semester.diaryId, start.monday, end.sunday) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getCompletedLessons(start.monday, end.sunday) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + completedLessonsDb.deleteAll(old uniqueSubtract new) + completedLessonsDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) + }, + filterResult = { it.filter { item -> item.date in start..end } } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt new file mode 100644 index 00000000..befcf9e6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt @@ -0,0 +1,39 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.ConferenceDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ConferenceRepository @Inject constructor( + private val conferenceDb: ConferenceDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "conference" + + fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, + query = { conferenceDb.loadAll(semester.diaryId, student.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getConferences() + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + conferenceDb.deleteAll(old uniqueSubtract new) + conferenceDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt new file mode 100644 index 00000000..bd6e7d2d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt @@ -0,0 +1,43 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.ExamDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.endExamsDay +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.startExamsDay +import io.github.wulkanowy.utils.uniqueSubtract +import java.time.LocalDate +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ExamRepository @Inject constructor( + private val examDb: ExamDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "exam" + + fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, + query = { examDb.loadAll(semester.diaryId, semester.studentId, start.startExamsDay, start.endExamsDay) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getExams(start.startExamsDay, start.endExamsDay, semester.semesterId) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + examDb.deleteAll(old uniqueSubtract new) + examDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) + }, + filterResult = { it.filter { item -> item.date in start..end } } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt similarity index 54% rename from app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt index 8cbbfdfb..bab290f3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt @@ -1,9 +1,16 @@ -package io.github.wulkanowy.data.repositories.grade +package io.github.wulkanowy.data.repositories +import io.github.wulkanowy.data.db.dao.GradeDao +import io.github.wulkanowy.data.db.dao.GradeSummaryDao import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow @@ -15,24 +22,40 @@ import javax.inject.Singleton @Singleton class GradeRepository @Inject constructor( - private val local: GradeLocal, - private val remote: GradeRemote + private val gradeDb: GradeDao, + private val gradeSummaryDb: GradeSummaryDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, ) { + private val cacheKey = "grade" + fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh }, - query = { local.getGradesDetails(semester).combine(local.getGradesSummary(semester)) { details, summaries -> details to summaries } }, - fetch = { remote.getGrades(student, semester) }, - saveFetchResult = { old, new -> - refreshGradeDetails(student, old.first, new.first, notify) - refreshGradeSummaries(old.second, new.second, notify) + shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, + query = { + gradeDb.loadAll(semester.semesterId, semester.studentId).combine(gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)) { details, summaries -> + details to summaries + } + }, + fetch = { + val (details, summary) = sdk.init(student) + .switchDiary(semester.diaryId, semester.schoolYear) + .getGrades(semester.semesterId) + + details.mapToEntities(semester) to summary.mapToEntities(semester) + }, + saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) -> + refreshGradeDetails(student, oldDetails, newDetails, notify) + refreshGradeSummaries(oldSummary, newSummary, notify) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) } ) private suspend fun refreshGradeDetails(student: Student, oldGrades: List, newDetails: List, notify: Boolean) { val notifyBreakDate = oldGrades.maxByOrNull { it.date }?.date ?: student.registrationDate.toLocalDate() - local.deleteGrades(oldGrades uniqueSubtract newDetails) - local.saveGrades((newDetails uniqueSubtract oldGrades).onEach { + gradeDb.deleteAll(oldGrades uniqueSubtract newDetails) + gradeDb.insertAll((newDetails uniqueSubtract oldGrades).onEach { if (it.date >= notifyBreakDate) it.apply { isRead = false if (notify) isNotified = false @@ -41,8 +64,8 @@ class GradeRepository @Inject constructor( } private suspend fun refreshGradeSummaries(oldSummaries: List, newSummary: List, notify: Boolean) { - local.deleteGradesSummary(oldSummaries uniqueSubtract newSummary) - local.saveGradesSummary((newSummary uniqueSubtract oldSummaries).onEach { summary -> + gradeSummaryDb.deleteAll(oldSummaries uniqueSubtract newSummary) + gradeSummaryDb.insertAll((newSummary uniqueSubtract oldSummaries).onEach { summary -> val oldSummary = oldSummaries.find { oldSummary -> oldSummary.subject == summary.subject } summary.isPredictedGradeNotified = when { summary.predictedGrade.isEmpty() -> true @@ -69,30 +92,30 @@ class GradeRepository @Inject constructor( } fun getUnreadGrades(semester: Semester): Flow> { - return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isRead } } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isRead } } } fun getNotNotifiedGrades(semester: Semester): Flow> { - return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isNotified } } } fun getNotNotifiedPredictedGrades(semester: Semester): Flow> { - return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } } } fun getNotNotifiedFinalGrades(semester: Semester): Flow> { - return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } } } suspend fun updateGrade(grade: Grade) { - return local.updateGrades(listOf(grade)) + return gradeDb.updateAll(listOf(grade)) } suspend fun updateGrades(grades: List) { - return local.updateGrades(grades) + return gradeDb.updateAll(grades) } suspend fun updateGradesSummary(gradesSummary: List) { - return local.updateGradesSummary(gradesSummary) + return gradeSummaryDb.updateAll(gradesSummary) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt similarity index 55% rename from app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt index ca0f6ffb..ab65fb14 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt @@ -1,12 +1,20 @@ -package io.github.wulkanowy.data.repositories.gradestatistics +package io.github.wulkanowy.data.repositories +import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao +import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao +import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao import io.github.wulkanowy.data.db.entities.GradePartialStatistics -import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.ui.modules.grade.statistics.ViewType +import io.github.wulkanowy.data.mappers.mapPartialToStatisticItems +import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems +import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import java.util.Locale @@ -15,17 +23,29 @@ import javax.inject.Singleton @Singleton class GradeStatisticsRepository @Inject constructor( - private val local: GradeStatisticsLocal, - private val remote: GradeStatisticsRemote + private val gradePartialStatisticsDb: GradePartialStatisticsDao, + private val gradePointsStatisticsDb: GradePointsStatisticsDao, + private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, ) { + private val partialCacheKey = "grade_stats_partial" + private val semesterCacheKey = "grade_stats_semester" + private val pointsCacheKey = "grade_stats_points" + fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getGradePartialStatistics(semester) }, - fetch = { remote.getGradePartialStatistics(student, semester) }, + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(partialCacheKey, semester)) }, + query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getGradesPartialStatistics(semester.semesterId) + .mapToEntities(semester) + }, saveFetchResult = { old, new -> - local.deleteGradePartialStatistics(old uniqueSubtract new) - local.saveGradePartialStatistics(new uniqueSubtract old) + gradePartialStatisticsDb.deleteAll(old uniqueSubtract new) + gradePartialStatisticsDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(partialCacheKey, semester)) }, mapResult = { items -> when (subjectName) { @@ -51,12 +71,17 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getGradeSemesterStatistics(semester) }, - fetch = { remote.getGradeSemesterStatistics(student, semester) }, + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(semesterCacheKey, semester)) }, + query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getGradesSemesterStatistics(semester.semesterId) + .mapToEntities(semester) + }, saveFetchResult = { old, new -> - local.deleteGradeSemesterStatistics(old uniqueSubtract new) - local.saveGradeSemesterStatistics(new uniqueSubtract old) + gradeSemesterStatisticsDb.deleteAll(old uniqueSubtract new) + gradeSemesterStatisticsDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(semesterCacheKey, semester)) }, mapResult = { items -> val itemsWithAverage = items.map { item -> @@ -87,12 +112,17 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getGradePointsStatistics(semester) }, - fetch = { remote.getGradePointsStatistics(student, semester) }, + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(pointsCacheKey, semester)) }, + query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getGradesPointsStatistics(semester.semesterId) + .mapToEntities(semester) + }, saveFetchResult = { old, new -> - local.deleteGradePointsStatistics(old uniqueSubtract new) - local.saveGradePointsStatistics(new uniqueSubtract old) + gradePointsStatisticsDb.deleteAll(old uniqueSubtract new) + gradePointsStatisticsDb.insertAll(new uniqueSubtract old) + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(pointsCacheKey, semester)) }, mapResult = { items -> when (subjectName) { @@ -111,34 +141,4 @@ class GradeStatisticsRepository @Inject constructor( } return result } - - private fun List.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map { - GradeStatisticsItem( - type = ViewType.PARTIAL, - average = it.classAverage, - partial = it, - points = null, - semester = null - ) - } - - private fun List.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map { - GradeStatisticsItem( - type = ViewType.SEMESTER, - partial = null, - points = null, - average = "", - semester = it - ) - } - - private fun List.mapPointsToStatisticsItems() = map { - GradeStatisticsItem( - type = ViewType.POINTS, - partial = null, - semester = null, - average = "", - points = it - ) - } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt new file mode 100644 index 00000000..7625dbbc --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt @@ -0,0 +1,50 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.HomeworkDao +import io.github.wulkanowy.data.db.entities.Homework +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.uniqueSubtract +import java.time.LocalDate +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class HomeworkRepository @Inject constructor( + private val homeworkDb: HomeworkDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "homework" + + fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, + query = { homeworkDb.loadAll(semester.semesterId, semester.studentId, start.monday, end.sunday) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getHomework(start.monday, end.sunday) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + homeworkDb.deleteAll(old uniqueSubtract new) + homeworkDb.insertAll(new uniqueSubtract old) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) + } + ) + + suspend fun toggleDone(homework: Homework) { + homeworkDb.updateAll(listOf(homework.apply { + isDone = !isDone + })) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt similarity index 96% rename from app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt index 85168fee..6d509b02 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LoggerRepository.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.logger +package io.github.wulkanowy.data.repositories import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt new file mode 100644 index 00000000..801292b4 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt @@ -0,0 +1,41 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.LuckyNumberDao +import io.github.wulkanowy.data.db.entities.LuckyNumber +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntity +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import java.time.LocalDate.now +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class LuckyNumberRepository @Inject constructor( + private val luckyNumberDb: LuckyNumberDao, + private val sdk: Sdk +) { + + fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + shouldFetch = { it == null || forceRefresh }, + query = { luckyNumberDb.load(student.studentId, now()) }, + fetch = { sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student) }, + saveFetchResult = { old, new -> + if (new != old) { + old?.let { luckyNumberDb.deleteAll(listOfNotNull(it)) } + luckyNumberDb.insertAll(listOfNotNull((new?.apply { + if (notify) isNotified = false + }))) + } + } + ) + + suspend fun getNotNotifiedLuckyNumber(student: Student) = luckyNumberDb.load(student.studentId, now()).map { + if (it?.isNotified == false) it else null + }.first() + + suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) = luckyNumberDb.updateAll(listOfNotNull(luckyNumber)) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt new file mode 100644 index 00000000..ea7b2b0e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt @@ -0,0 +1,102 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.MessageAttachmentDao +import io.github.wulkanowy.data.db.dao.MessagesDao +import io.github.wulkanowy.data.db.entities.Message +import io.github.wulkanowy.data.db.entities.Recipient +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.enums.MessageFolder +import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED +import io.github.wulkanowy.data.mappers.mapFromEntities +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.sdk.pojo.Folder +import io.github.wulkanowy.sdk.pojo.SentMessage +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import timber.log.Timber +import java.time.LocalDateTime.now +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class MessageRepository @Inject constructor( + private val messagesDb: MessagesDao, + private val messageAttachmentDao: MessageAttachmentDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "message" + + @Suppress("UNUSED_PARAMETER") + fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student, folder)) }, + query = { messagesDb.loadAll(student.id.toInt(), folder.id) }, + fetch = { sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).mapToEntities(student) }, + saveFetchResult = { old, new -> + messagesDb.deleteAll(old uniqueSubtract new) + messagesDb.insertAll((new uniqueSubtract old).onEach { + it.isNotified = !notify + }) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder)) + } + ) + + fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource( + shouldFetch = { + checkNotNull(it, { "This message no longer exist!" }) + Timber.d("Message content in db empty: ${it.message.content.isEmpty()}") + it.message.unread || it.message.content.isEmpty() + }, + query = { messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) }, + fetch = { + sdk.init(student).getMessageDetails(it!!.message.messageId, message.folderId, markAsRead, message.realId).let { details -> + details.content to details.attachments.mapToEntities() + } + }, + saveFetchResult = { old, (downloadedMessage, attachments) -> + checkNotNull(old, { "Fetched message no longer exist!" }) + messagesDb.updateAll(listOf(old.message.copy(unread = !markAsRead).apply { + id = old.message.id + content = content.ifBlank { downloadedMessage } + })) + messageAttachmentDao.insertAttachments(attachments) + Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read") + } + ) + + fun getNotNotifiedMessages(student: Student): Flow> { + return messagesDb.loadAll(student.id.toInt(), RECEIVED.id).map { it.filter { message -> !message.isNotified && message.unread } } + } + + suspend fun updateMessages(messages: List) { + return messagesDb.updateAll(messages) + } + + suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage { + return sdk.init(student).sendMessage( + subject = subject, + content = content, + recipients = recipients.mapFromEntities() + ) + } + + suspend fun deleteMessage(student: Student, message: Message) { + val isDeleted = sdk.init(student).deleteMessages(listOf(message.messageId), message.folderId) + + if (message.folderId != MessageFolder.TRASHED.id) { + if (isDeleted) messagesDb.updateAll(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply { + id = message.id + content = message.content + })) + } else messagesDb.deleteAll(listOf(message)) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt new file mode 100644 index 00000000..7e83ef7d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt @@ -0,0 +1,56 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.MobileDeviceDao +import io.github.wulkanowy.data.db.entities.MobileDevice +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken +import io.github.wulkanowy.data.pojos.MobileDeviceToken +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class MobileDeviceRepository @Inject constructor( + private val mobileDb: MobileDeviceDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "devices" + + fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student)) }, + query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getRegisteredDevices() + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + mobileDb.deleteAll(old uniqueSubtract new) + mobileDb.insertAll(new uniqueSubtract old) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student)) + } + ) + + suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .unregisterDevice(device.deviceId) + + mobileDb.deleteAll(listOf(device)) + } + + suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken { + return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getToken() + .mapToMobileDeviceToken() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt new file mode 100644 index 00000000..85789f09 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt @@ -0,0 +1,60 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.NoteDao +import io.github.wulkanowy.data.db.entities.Note +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class NoteRepository @Inject constructor( + private val noteDb: NoteDao, + private val sdk: Sdk, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "note" + + fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, + query = { noteDb.loadAll(student.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getNotes(semester.semesterId) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + noteDb.deleteAll(old uniqueSubtract new) + noteDb.insertAll((new uniqueSubtract old).onEach { + if (it.date >= student.registrationDate.toLocalDate()) it.apply { + isRead = false + if (notify) isNotified = false + } + }) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester)) + } + ) + + fun getNotNotifiedNotes(student: Student): Flow> { + return noteDb.loadAll(student.studentId).map { it.filter { note -> !note.isNotified } } + } + + suspend fun updateNote(note: Note) { + noteDb.updateAll(listOf(note)) + } + + suspend fun updateNotes(notes: List) { + noteDb.updateAll(notes) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt similarity index 98% rename from app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt index da31751a..8cb815cc 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt @@ -1,4 +1,4 @@ -package io.github.wulkanowy.data.repositories.preferences +package io.github.wulkanowy.data.repositories import android.content.Context import android.content.SharedPreferences diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt new file mode 100644 index 00000000..24ab5f0c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt @@ -0,0 +1,40 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.RecipientDao +import io.github.wulkanowy.data.db.entities.Message +import io.github.wulkanowy.data.db.entities.Recipient +import io.github.wulkanowy.data.db.entities.ReportingUnit +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RecipientRepository @Inject constructor( + private val recipientDb: RecipientDao, + private val sdk: Sdk +) { + + suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) { + val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.senderId) + val old = recipientDb.loadAll(unit.senderId, unit.unitId, role) + + recipientDb.deleteAll(old uniqueSubtract new) + recipientDb.insertAll(new uniqueSubtract old) + } + + suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List { + return recipientDb.loadAll(unit.senderId, unit.unitId, role).ifEmpty { + refreshRecipients(student, unit, role) + + recipientDb.loadAll(unit.senderId, unit.unitId, role) + } + } + + suspend fun getMessageRecipients(student: Student, message: Message): List { + return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.userLoginId) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt similarity index 79% rename from app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt index 11eac71e..5e106355 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecoverRepository.kt @@ -1,11 +1,11 @@ -package io.github.wulkanowy.data.repositories.recover +package io.github.wulkanowy.data.repositories import io.github.wulkanowy.sdk.Sdk import javax.inject.Inject import javax.inject.Singleton @Singleton -class RecoverRemote @Inject constructor(private val sdk: Sdk) { +class RecoverRepository @Inject constructor(private val sdk: Sdk) { suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair { return sdk.getPasswordResetCaptchaCode(host, symbol) @@ -15,4 +15,3 @@ class RecoverRemote @Inject constructor(private val sdk: Sdk) { return sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse) } } - diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt new file mode 100644 index 00000000..792e66b5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt @@ -0,0 +1,42 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.ReportingUnitDao +import io.github.wulkanowy.data.db.entities.ReportingUnit +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ReportingUnitRepository @Inject constructor( + private val reportingUnitDb: ReportingUnitDao, + private val sdk: Sdk +) { + + suspend fun refreshReportingUnits(student: Student) { + val new = sdk.init(student).getReportingUnits().mapToEntities(student) + val old = reportingUnitDb.load(student.studentId) + + reportingUnitDb.deleteAll(old.uniqueSubtract(new)) + reportingUnitDb.insertAll(new.uniqueSubtract(old)) + } + + suspend fun getReportingUnits(student: Student): List { + return reportingUnitDb.load(student.studentId).ifEmpty { + refreshReportingUnits(student) + + reportingUnitDb.load(student.studentId) + } + } + + suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? { + return reportingUnitDb.loadOne(student.studentId, unitId) ?: run { + refreshReportingUnits(student) + + return reportingUnitDb.loadOne(student.studentId, unitId) + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt new file mode 100644 index 00000000..36d5c974 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt @@ -0,0 +1,31 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.SchoolDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntity +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SchoolRepository @Inject constructor( + private val schoolDb: SchoolDao, + private val sdk: Sdk +) { + + fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it == null || forceRefresh }, + query = { schoolDb.load(semester.studentId, semester.classId) }, + fetch = { sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).getSchool().mapToEntity(semester) }, + saveFetchResult = { old, new -> + if (new != old && old != null) { + schoolDb.deleteAll(listOf(old)) + schoolDb.insertAll(listOf(new)) + } + schoolDb.insertAll(listOf(new)) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt similarity index 73% rename from app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt rename to app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt index 2748f1df..8942391c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SemesterRepository.kt @@ -1,10 +1,13 @@ -package io.github.wulkanowy.data.repositories.semester +package io.github.wulkanowy.data.repositories +import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.DispatchersProvider import io.github.wulkanowy.utils.getCurrentOrLast +import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.isCurrent import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.withContext @@ -14,17 +17,17 @@ import javax.inject.Singleton @Singleton class SemesterRepository @Inject constructor( - private val remote: SemesterRemote, - private val local: SemesterLocal, + private val semesterDb: SemesterDao, + private val sdk: Sdk, private val dispatchers: DispatchersProvider ) { suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false) = withContext(dispatchers.backgroundThread) { - val semesters = local.getSemesters(student) + val semesters = semesterDb.loadAll(student.studentId, student.classId) if (isShouldFetch(student, semesters, forceRefresh, refreshOnNoCurrent)) { refreshSemesters(student) - local.getSemesters(student) + semesterDb.loadAll(student.studentId, student.classId) } else semesters } @@ -41,12 +44,12 @@ class SemesterRepository @Inject constructor( } private suspend fun refreshSemesters(student: Student) { - val new = remote.getSemesters(student) + val new = sdk.init(student).getSemesters().mapToEntities(student.studentId) if (new.isEmpty()) return Timber.i("Empty semester list!") - val old = local.getSemesters(student) - local.deleteSemesters(old.uniqueSubtract(new)) - local.saveSemesters(new.uniqueSubtract(old)) + val old = semesterDb.loadAll(student.studentId, student.classId) + semesterDb.deleteAll(old.uniqueSubtract(new)) + semesterDb.insertSemesters(new.uniqueSubtract(old)) } suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = withContext(dispatchers.backgroundThread) { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt new file mode 100644 index 00000000..5b80035b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt @@ -0,0 +1,85 @@ +package io.github.wulkanowy.data.repositories + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import io.github.wulkanowy.data.db.dao.SemesterDao +import io.github.wulkanowy.data.db.dao.StudentDao +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.data.exceptions.NoCurrentStudentException +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.DispatchersProvider +import io.github.wulkanowy.utils.security.decrypt +import io.github.wulkanowy.utils.security.encrypt +import kotlinx.coroutines.withContext +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class StudentRepository @Inject constructor( + @ApplicationContext private val context: Context, + private val dispatchers: DispatchersProvider, + private val studentDb: StudentDao, + private val semesterDb: SemesterDao, + private val sdk: Sdk +) { + + suspend fun isStudentSaved(): Boolean = getSavedStudents(false).isNotEmpty() + + suspend fun isCurrentStudentSet(): Boolean = studentDb.loadCurrent()?.isCurrent ?: false + + suspend fun getStudentsApi(pin: String, symbol: String, token: String): List { + return sdk.getStudentsFromMobileApi(token, pin, symbol, "").mapToEntities() + } + + suspend fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): List { + return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).mapToEntities(password) + } + + suspend fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): List { + return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).mapToEntities(password) + } + + suspend fun getSavedStudents(decryptPass: Boolean = true) = withContext(dispatchers.backgroundThread) { + studentDb.loadStudentsWithSemesters().map { + it.apply { + if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) student.password = decrypt(student.password) + } + } + } + + suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) { + studentDb.loadById(id)?.apply { + if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) + } + } ?: throw NoCurrentStudentException() + + suspend fun getCurrentStudent(decryptPass: Boolean = true) = withContext(dispatchers.backgroundThread) { + studentDb.loadCurrent()?.apply { + if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) + } + } ?: throw NoCurrentStudentException() + + suspend fun saveStudents(studentsWithSemesters: List): List { + semesterDb.insertSemesters(studentsWithSemesters.flatMap { it.semesters }) + + return withContext(dispatchers.backgroundThread) { + studentDb.insertAll(studentsWithSemesters.map { it.student }.map { + if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context)) + else it + }) + } + } + + suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) { + with(studentDb) { + resetCurrent() + updateCurrent(studentWithSemesters.student.id) + } + } + + suspend fun logoutStudent(student: Student) { + studentDb.delete(student) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt new file mode 100644 index 00000000..ef07a1d4 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt @@ -0,0 +1,32 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.SubjectDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SubjectRepository @Inject constructor( + private val subjectDao: SubjectDao, + private val sdk: Sdk +) { + + fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh }, + query = { subjectDao.loadAll(semester.diaryId, semester.studentId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getSubjects().mapToEntities(semester) + }, + saveFetchResult = { old, new -> + subjectDao.deleteAll(old uniqueSubtract new) + subjectDao.insertAll(new uniqueSubtract old) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt new file mode 100644 index 00000000..25da718c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt @@ -0,0 +1,33 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.TeacherDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class TeacherRepository @Inject constructor( + private val teacherDb: TeacherDao, + private val sdk: Sdk +) { + + fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh }, + query = { teacherDb.loadAll(semester.studentId, semester.classId) }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getTeachers(semester.semesterId) + .mapToEntities(semester) + }, + saveFetchResult = { old, new -> + teacherDb.deleteAll(old uniqueSubtract new) + teacherDb.insertAll(new uniqueSubtract old) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt new file mode 100644 index 00000000..fa1898f5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt @@ -0,0 +1,84 @@ +package io.github.wulkanowy.data.repositories + +import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao +import io.github.wulkanowy.data.db.dao.TimetableDao +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.data.db.entities.Timetable +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import io.github.wulkanowy.data.mappers.mapToEntities +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper +import io.github.wulkanowy.utils.AutoRefreshHelper +import io.github.wulkanowy.utils.getRefreshKey +import io.github.wulkanowy.utils.init +import io.github.wulkanowy.utils.monday +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.sunday +import io.github.wulkanowy.utils.uniqueSubtract +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import java.time.LocalDate +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class TimetableRepository @Inject constructor( + private val timetableDb: TimetableDao, + private val timetableAdditionalDb: TimetableAdditionalDao, + private val sdk: Sdk, + private val schedulerHelper: TimetableNotificationSchedulerHelper, + private val refreshHelper: AutoRefreshHelper, +) { + + private val cacheKey = "timetable" + + fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean, refreshAdditional: Boolean = false) = networkBoundResource( + shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, + query = { + timetableDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) + .map { schedulerHelper.scheduleNotifications(it, student); it } + .combine(timetableAdditionalDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)) { timetable, additional -> + timetable to additional + } + }, + fetch = { + sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getTimetable(start.monday, end.sunday) + .let { (normal, additional) -> normal.mapToEntities(semester) to additional.mapToEntities(semester) } + + }, + saveFetchResult = { (oldTimetable, oldAdditional), (newTimetable, newAdditional) -> + refreshTimetable(student, oldTimetable, newTimetable) + refreshAdditional(oldAdditional, newAdditional) + + refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) + }, + filterResult = { (timetable, additional) -> + timetable.filter { item -> + item.date in start..end + } to additional.filter { item -> + item.date in start..end + } + } + ) + + private suspend fun refreshTimetable(student: Student, old: List, new: List) { + timetableDb.deleteAll(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) }) + timetableDb.insertAll(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item -> + item.also { new -> + old.singleOrNull { new.start == it.start }?.let { old -> + return@map new.copy( + room = if (new.room.isEmpty()) old.room else new.room, + teacher = if (new.teacher.isEmpty() && !new.changes && !old.changes) old.teacher else new.teacher + ) + } + } + }) + } + + private suspend fun refreshAdditional(old: List, new: List) { + timetableAdditionalDb.deleteAll(old.uniqueSubtract(new)) + timetableAdditionalDb.insertAll(new.uniqueSubtract(old)) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt deleted file mode 100644 index 9aaa5230..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import io.github.wulkanowy.data.db.dao.AttendanceDao -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) { - - suspend fun saveAttendance(attendance: List) { - attendanceDb.insertAll(attendance) - } - - suspend fun deleteAttendance(attendance: List) { - attendanceDb.deleteAll(attendance) - } - - fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> { - return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt deleted file mode 100644 index 870690ec..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.sdk.pojo.Absent -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getAttendance(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getAttendance(startDate, endDate, semester.semesterId) - .map { - Attendance( - studentId = semester.studentId, - diaryId = semester.diaryId, - date = it.date, - timeId = it.timeId, - number = it.number, - subject = it.subject, - name = it.name, - presence = it.presence, - absence = it.absence, - exemption = it.exemption, - lateness = it.lateness, - excused = it.excused, - deleted = it.deleted, - excusable = it.excusable, - excuseStatus = it.excuseStatus?.name - ) - } - } - - suspend fun excuseAbsence(student: Student, semester: Semester, absenceList: List, reason: String?): Boolean { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance -> - Absent( - date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)), - timeId = attendance.timeId - ) - }, reason) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt deleted file mode 100644 index 60f864f2..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceRepository @Inject constructor( - private val local: AttendanceLocal, - private val remote: AttendanceRemote -) { - - fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getAttendance(semester, start.monday, end.sunday) }, - fetch = { remote.getAttendance(student, semester, start.monday, end.sunday) }, - saveFetchResult = { old, new -> - local.deleteAttendance(old uniqueSubtract new) - local.saveAttendance(new uniqueSubtract old) - }, - filterResult = { it.filter { item -> item.date in start..end } } - ) - - suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List, reason: String? = null) { - remote.excuseAbsence(student, semester, attendanceList, reason) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt deleted file mode 100644 index 703bc947..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendancesummary - -import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: AttendanceSummaryDao) { - - suspend fun saveAttendanceSummary(attendance: List) { - attendanceDb.insertAll(attendance) - } - - suspend fun deleteAttendanceSummary(attendance: List) { - attendanceDb.deleteAll(attendance) - } - - fun getAttendanceSummary(semester: Semester, subjectId: Int): Flow> { - return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt deleted file mode 100644 index 29a0b9a7..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendancesummary - -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getAttendanceSummary(subjectId) - .map { - AttendanceSummary( - studentId = semester.studentId, - diaryId = semester.diaryId, - subjectId = subjectId, - month = it.month, - presence = it.presence, - absence = it.absence, - absenceExcused = it.absenceExcused, - absenceForSchoolReasons = it.absenceForSchoolReasons, - lateness = it.lateness, - latenessExcused = it.latenessExcused, - exemption = it.exemption - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt deleted file mode 100644 index 5dbe1ab0..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendancesummary - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryRepository @Inject constructor( - private val local: AttendanceSummaryLocal, - private val remote: AttendanceSummaryRemote -) { - - fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getAttendanceSummary(semester, subjectId) }, - fetch = { remote.getAttendanceSummary(student, semester, subjectId) }, - saveFetchResult = { old, new -> - local.deleteAttendanceSummary(old uniqueSubtract new) - local.saveAttendanceSummary(new uniqueSubtract old) - } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt deleted file mode 100644 index 51a1bdbf..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import io.github.wulkanowy.data.db.dao.CompletedLessonsDao -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb: CompletedLessonsDao) { - - suspend fun saveCompletedLessons(completedLessons: List) { - completedLessonsDb.insertAll(completedLessons) - } - - suspend fun deleteCompleteLessons(completedLessons: List) { - completedLessonsDb.deleteAll(completedLessons) - } - - fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Flow> { - return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt deleted file mode 100644 index d15a2762..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getCompletedLessons(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getCompletedLessons(startDate, endDate) - .map { - it.absence - CompletedLesson( - studentId = semester.studentId, - diaryId = semester.diaryId, - date = it.date, - number = it.number, - subject = it.subject, - topic = it.topic, - teacher = it.teacher, - teacherSymbol = it.teacherSymbol, - substitution = it.substitution, - absence = it.absence, - resources = it.resources - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt deleted file mode 100644 index 61268a66..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsRepository @Inject constructor( - private val local: CompletedLessonsLocal, - private val remote: CompletedLessonsRemote -) { - - fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getCompletedLessons(semester, start.monday, end.sunday) }, - fetch = { remote.getCompletedLessons(student, semester, start.monday, end.sunday) }, - saveFetchResult = { old, new -> - local.deleteCompleteLessons(old uniqueSubtract new) - local.saveCompletedLessons(new uniqueSubtract old) - }, - filterResult = { it.filter { item -> item.date in start..end } } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt deleted file mode 100644 index 9f56641f..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.conference - -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 kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConferenceLocal @Inject constructor(private val conferenceDb: ConferenceDao) { - - fun getConferences(student: Student, semester: Semester): Flow> { - return conferenceDb.loadAll(semester.diaryId, student.studentId) - } - - suspend fun saveConferences(items: List) { - conferenceDb.insertAll(items) - } - - suspend fun deleteConferences(items: List) { - conferenceDb.deleteAll(items) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt deleted file mode 100644 index 50e869a9..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.data.repositories.conference - -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.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConferenceRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getConferences(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getConferences() - .map { - it.agenda - Conference( - studentId = student.studentId, - diaryId = semester.diaryId, - agenda = it.agenda, - conferenceId = it.id, - date = it.date, - presentOnConference = it.presentOnConference, - subject = it.subject, - title = it.title - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt deleted file mode 100644 index 187ecf58..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.conference - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConferenceRepository @Inject constructor( - private val local: ConferenceLocal, - private val remote: ConferenceRemote -) { - - fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getConferences(student, semester) }, - fetch = { remote.getConferences(student, semester) }, - saveFetchResult = { old, new -> - local.deleteConferences(old uniqueSubtract new) - local.saveConferences(new uniqueSubtract old) - } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt deleted file mode 100644 index acc55b5e..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.exam - -import io.github.wulkanowy.data.db.dao.ExamDao -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExamLocal @Inject constructor(private val examDb: ExamDao) { - - fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> { - return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate) - } - - suspend fun saveExams(exams: List) { - examDb.insertAll(exams) - } - - suspend fun deleteExams(exams: List) { - examDb.deleteAll(exams) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt deleted file mode 100644 index ac4aa93d..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.wulkanowy.data.repositories.exam - -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExamRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getExams(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getExams(startDate, endDate, semester.semesterId) - .map { - Exam( - studentId = semester.studentId, - diaryId = semester.diaryId, - date = it.date, - entryDate = it.entryDate, - subject = it.subject, - group = it.group, - type = it.type, - description = it.description, - teacher = it.teacher, - teacherSymbol = it.teacherSymbol - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt deleted file mode 100644 index 3f4591a2..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.exam - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.endExamsDay -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.startExamsDay -import io.github.wulkanowy.utils.uniqueSubtract -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExamRepository @Inject constructor( - private val local: ExamLocal, - private val remote: ExamRemote -) { - - fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getExams(semester, start.startExamsDay, start.endExamsDay) }, - fetch = { remote.getExams(student, semester, start.startExamsDay, start.endExamsDay) }, - saveFetchResult = { old, new -> - local.deleteExams(old uniqueSubtract new) - local.saveExams(new uniqueSubtract old) - }, - filterResult = { it.filter { item -> item.date in start..end } } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt deleted file mode 100644 index ed363542..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import io.github.wulkanowy.data.db.dao.GradeDao -import io.github.wulkanowy.data.db.dao.GradeSummaryDao -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeLocal @Inject constructor( - private val gradeDb: GradeDao, - private val gradeSummaryDb: GradeSummaryDao -) { - - suspend fun saveGrades(grades: List) { - gradeDb.insertAll(grades) - } - - suspend fun deleteGrades(grades: List) { - gradeDb.deleteAll(grades) - } - - suspend fun updateGrades(grades: List) { - gradeDb.updateAll(grades) - } - - suspend fun updateGradesSummary(gradesSummary: List) { - gradeSummaryDb.updateAll(gradesSummary) - } - - fun getGradesDetails(semester: Semester): Flow> { - return gradeDb.loadAll(semester.semesterId, semester.studentId) - } - - suspend fun saveGradesSummary(gradesSummary: List) { - gradeSummaryDb.insertAll(gradesSummary) - } - - suspend fun deleteGradesSummary(gradesSummary: List) { - gradeSummaryDb.deleteAll(gradesSummary) - } - - fun getGradesSummary(semester: Semester): Flow> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt deleted file mode 100644 index 9534a891..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getGrades(student: Student, semester: Semester): Pair, List> { - val (details, summary) = sdk - .init(student) - .switchDiary(semester.diaryId, semester.schoolYear) - .getGrades(semester.semesterId) - - return details.map { - Grade( - studentId = semester.studentId, - semesterId = semester.semesterId, - subject = it.subject, - entry = it.entry, - value = it.value, - modifier = it.modifier, - comment = it.comment, - color = it.color, - gradeSymbol = it.symbol, - description = it.description, - weight = it.weight, - weightValue = it.weightValue, - date = it.date, - teacher = it.teacher - ) - } to summary.map { - GradeSummary( - semesterId = semester.semesterId, - studentId = semester.studentId, - position = 0, - subject = it.name, - predictedGrade = it.predicted, - finalGrade = it.final, - pointsSum = it.pointsSum, - proposedPoints = it.proposedPoints, - finalPoints = it.finalPoints, - average = it.average - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt deleted file mode 100644 index 3e3c819f..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao -import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao -import io.github.wulkanowy.data.db.entities.GradePartialStatistics -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeStatisticsLocal @Inject constructor( - private val gradePartialStatisticsDb: GradePartialStatisticsDao, - private val gradePointsStatisticsDb: GradePointsStatisticsDao, - private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao -) { - - // partial - fun getGradePartialStatistics(semester: Semester): Flow> { - return gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) - } - - suspend fun saveGradePartialStatistics(items: List) { - gradePartialStatisticsDb.insertAll(items) - } - - suspend fun deleteGradePartialStatistics(items: List) { - gradePartialStatisticsDb.deleteAll(items) - } - - // points - fun getGradePointsStatistics(semester: Semester): Flow> { - return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) - } - - suspend fun saveGradePointsStatistics(gradePointsStatistics: List) { - gradePointsStatisticsDb.insertAll(gradePointsStatistics) - } - - suspend fun deleteGradePointsStatistics(gradesPointsStatistics: List) { - gradePointsStatisticsDb.deleteAll(gradesPointsStatistics) - } - - // semester - fun getGradeSemesterStatistics(semester: Semester): Flow> { - return gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) - } - - suspend fun saveGradeSemesterStatistics(items: List) { - gradeSemesterStatisticsDb.insertAll(items) - } - - suspend fun deleteGradeSemesterStatistics(items: List) { - gradeSemesterStatisticsDb.deleteAll(items) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt deleted file mode 100644 index 144df8a0..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt +++ /dev/null @@ -1,63 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import io.github.wulkanowy.data.db.entities.GradePartialStatistics -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getGradePartialStatistics(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getGradesPartialStatistics(semester.semesterId) - .map { - GradePartialStatistics( - semesterId = semester.semesterId, - studentId = student.studentId, - subject = it.subject, - classAverage = it.classAverage, - studentAverage = it.studentAverage, - classAmounts = it.classItems - .sortedBy { item -> item.grade } - .map { item -> item.amount }, - studentAmounts = it.studentItems.map { item -> item.amount } - ) - } - } - - suspend fun getGradeSemesterStatistics(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getGradesSemesterStatistics(semester.semesterId) - .map { - GradeSemesterStatistics( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - amounts = it.items - .sortedBy { item -> item.grade } - .map { item -> item.amount }, - studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0 - ) - } - } - - suspend fun getGradePointsStatistics(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getGradesPointsStatistics(semester.semesterId) - .map { - GradePointsStatistics( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - others = it.others, - student = it.student - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt deleted file mode 100644 index f2cbb803..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.homework - -import io.github.wulkanowy.data.db.dao.HomeworkDao -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) { - - suspend fun saveHomework(homework: List) { - homeworkDb.insertAll(homework) - } - - suspend fun deleteHomework(homework: List) { - homeworkDb.deleteAll(homework) - } - - suspend fun updateHomework(homework: List) { - homeworkDb.updateAll(homework) - } - - fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> { - return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt deleted file mode 100644 index 32109877..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.data.repositories.homework - -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getHomework(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getHomework(startDate, endDate) - .map { - Homework( - semesterId = semester.semesterId, - studentId = semester.studentId, - date = it.date, - entryDate = it.entryDate, - subject = it.subject, - content = it.content, - teacher = it.teacher, - teacherSymbol = it.teacherSymbol, - attachments = it.attachments.map { attachment -> attachment.url to attachment.name } - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt deleted file mode 100644 index 54397ea0..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.data.repositories.homework - -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkRepository @Inject constructor( - private val local: HomeworkLocal, - private val remote: HomeworkRemote -) { - - fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getHomework(semester, start.monday, end.sunday) }, - fetch = { remote.getHomework(student, semester, start.monday, end.sunday) }, - saveFetchResult = { old, new -> - local.deleteHomework(old uniqueSubtract new) - local.saveHomework(new uniqueSubtract old) - } - ) - - suspend fun toggleDone(homework: Homework) { - local.updateHomework(listOf(homework.apply { - isDone = !isDone - })) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt deleted file mode 100644 index 0c3156d1..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import io.github.wulkanowy.data.db.dao.LuckyNumberDao -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) { - - suspend fun saveLuckyNumber(luckyNumber: LuckyNumber?) { - luckyNumberDb.insertAll(listOfNotNull(luckyNumber)) - } - - suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) { - luckyNumberDb.updateAll(listOfNotNull(luckyNumber)) - } - - suspend fun deleteLuckyNumber(luckyNumber: LuckyNumber?) { - luckyNumberDb.deleteAll(listOfNotNull(luckyNumber)) - } - - fun getLuckyNumber(student: Student, date: LocalDate): Flow { - return luckyNumberDb.load(student.studentId, date) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt deleted file mode 100644 index 2872957d..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getLuckyNumber(student: Student): LuckyNumber? { - return sdk.init(student).getLuckyNumber(student.schoolShortName)?.let { - LuckyNumber( - studentId = student.studentId, - date = LocalDate.now(), - luckyNumber = it - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt deleted file mode 100644 index 173ce7e4..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map -import java.time.LocalDate.now -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberRepository @Inject constructor( - private val local: LuckyNumberLocal, - private val remote: LuckyNumberRemote -) { - - fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - shouldFetch = { it == null || forceRefresh }, - query = { local.getLuckyNumber(student, now()) }, - fetch = { remote.getLuckyNumber(student) }, - saveFetchResult = { old, new -> - if (new != old) { - old?.let { local.deleteLuckyNumber(it) } - local.saveLuckyNumber(new?.apply { - if (notify) isNotified = false - }) - } - } - ) - - suspend fun getNotNotifiedLuckyNumber(student: Student) = - local.getLuckyNumber(student, now()).map { if (it?.isNotified == false) it else null }.first() - - suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) = local.updateLuckyNumber(luckyNumber) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt deleted file mode 100644 index f1c8eaf0..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.data.repositories.message - -import io.github.wulkanowy.data.db.dao.MessageAttachmentDao -import io.github.wulkanowy.data.db.dao.MessagesDao -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.github.wulkanowy.data.db.entities.Student -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageLocal @Inject constructor( - private val messagesDb: MessagesDao, - private val messageAttachmentDao: MessageAttachmentDao -) { - - suspend fun saveMessages(messages: List) { - messagesDb.insertAll(messages) - } - - suspend fun updateMessages(messages: List) { - messagesDb.updateAll(messages) - } - - suspend fun deleteMessages(messages: List) { - messagesDb.deleteAll(messages) - } - - fun getMessageWithAttachment(student: Student, message: Message): Flow { - return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) - } - - suspend fun saveMessageAttachments(attachments: List) { - messageAttachmentDao.insertAttachments(attachments) - } - - fun getMessages(student: Student, folder: MessageFolder): Flow> { - return messagesDb.loadAll(student.id.toInt(), folder.id) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt deleted file mode 100644 index 044a13a2..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt +++ /dev/null @@ -1,78 +0,0 @@ -package io.github.wulkanowy.data.repositories.message - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.sdk.pojo.Folder -import io.github.wulkanowy.sdk.pojo.SentMessage -import io.github.wulkanowy.utils.init -import java.time.LocalDateTime.now -import javax.inject.Inject -import javax.inject.Singleton -import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient - -@Singleton -class MessageRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder): List { - return sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).map { - Message( - studentId = student.id.toInt(), - realId = it.id ?: 0, - messageId = it.messageId ?: 0, - sender = it.sender?.name.orEmpty(), - senderId = it.sender?.loginId ?: 0, - recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów", - subject = it.subject.trim(), - date = it.date ?: now(), - folderId = it.folderId, - unread = it.unread ?: false, - removed = it.removed, - hasAttachments = it.hasAttachments - ).apply { - content = it.content.orEmpty() - unreadBy = it.unreadBy ?: 0 - readBy = it.readBy ?: 0 - } - } - } - - suspend fun getMessagesContentDetails(student: Student, message: Message, markAsRead: Boolean = false): Pair> { - return sdk.init(student).getMessageDetails(message.messageId, message.folderId, markAsRead, message.realId).let { details -> - details.content to details.attachments.map { - MessageAttachment( - realId = it.id, - messageId = it.messageId, - oneDriveId = it.oneDriveId, - url = it.url, - filename = it.filename - ) - } - } - } - - suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage { - return sdk.init(student).sendMessage( - subject = subject, - content = content, - recipients = recipients.map { - SdkRecipient( - id = it.realId, - name = it.realName, - loginId = it.loginId, - reportingUnitId = it.unitId, - role = it.role, - hash = it.hash, - shortName = it.name - ) - } - ) - } - - suspend fun deleteMessage(student: Student, message: Message): Boolean { - return sdk.init(student).deleteMessages(listOf(message.messageId), message.folderId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt deleted file mode 100644 index bb932699..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt +++ /dev/null @@ -1,76 +0,0 @@ -package io.github.wulkanowy.data.repositories.message - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED -import io.github.wulkanowy.sdk.pojo.SentMessage -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import timber.log.Timber -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageRepository @Inject constructor( - private val local: MessageLocal, - private val remote: MessageRemote -) { - - fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getMessages(student, folder) }, - fetch = { remote.getMessages(student, semester, folder) }, - saveFetchResult = { old, new -> - local.deleteMessages(old uniqueSubtract new) - local.saveMessages((new uniqueSubtract old).onEach { - it.isNotified = !notify - }) - } - ) - - fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource( - shouldFetch = { - checkNotNull(it, { "This message no longer exist!" }) - Timber.d("Message content in db empty: ${it.message.content.isEmpty()}") - it.message.unread || it.message.content.isEmpty() - }, - query = { local.getMessageWithAttachment(student, message) }, - fetch = { remote.getMessagesContentDetails(student, it!!.message, markAsRead) }, - saveFetchResult = { old, (downloadedMessage, attachments) -> - checkNotNull(old, { "Fetched message no longer exist!" }) - local.updateMessages(listOf(old.message.copy(unread = !markAsRead).apply { - id = old.message.id - content = content.ifBlank { downloadedMessage } - })) - local.saveMessageAttachments(attachments) - Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read") - } - ) - - fun getNotNotifiedMessages(student: Student): Flow> { - return local.getMessages(student, RECEIVED).map { it.filter { message -> !message.isNotified && message.unread } } - } - - suspend fun updateMessages(messages: List) { - return local.updateMessages(messages) - } - - suspend fun sendMessage(student: Student, subject: String, content: String, recipients: List): SentMessage { - return remote.sendMessage(student, subject, content, recipients) - } - - suspend fun deleteMessage(student: Student, message: Message) { - val isDeleted = remote.deleteMessage(student, message) - - if (message.folderId != MessageFolder.TRASHED.id) { - if (isDeleted) local.updateMessages(listOf(message.copy(folderId = MessageFolder.TRASHED.id).apply { - id = message.id - content = message.content - })) - } else local.deleteMessages(listOf(message)) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt deleted file mode 100644 index 0ccb3d7e..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.mobiledevice - -import io.github.wulkanowy.data.db.dao.MobileDeviceDao -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDao) { - - suspend fun saveDevices(devices: List) { - mobileDb.insertAll(devices) - } - - suspend fun deleteDevices(devices: List) { - mobileDb.deleteAll(devices) - } - - fun getDevices(semester: Semester): Flow> { - return mobileDb.loadAll(semester.studentId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt deleted file mode 100644 index 907e965c..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.data.repositories.mobiledevice - -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.pojos.MobileDeviceToken -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getDevices(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getRegisteredDevices() - .map { - MobileDevice( - studentId = semester.studentId, - date = it.createDate, - deviceId = it.id, - name = it.name - ) - } - } - - suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Boolean { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .unregisterDevice(device.deviceId) - } - - suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getToken() - .let { - MobileDeviceToken( - token = it.token, - symbol = it.symbol, - pin = it.pin, - qr = it.qrCodeImage - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt deleted file mode 100644 index 65526ef8..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.data.repositories.mobiledevice - -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.pojos.MobileDeviceToken -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceRepository @Inject constructor( - private val local: MobileDeviceLocal, - private val remote: MobileDeviceRemote -) { - - fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getDevices(semester) }, - fetch = { remote.getDevices(student, semester) }, - saveFetchResult = { old, new -> - local.deleteDevices(old uniqueSubtract new) - local.saveDevices(new uniqueSubtract old) - } - ) - - suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) { - remote.unregisterDevice(student, semester, device) - local.deleteDevices(listOf(device)) - } - - suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken { - return remote.getToken(student, semester) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt deleted file mode 100644 index 85ba5e22..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.wulkanowy.data.repositories.note - -import io.github.wulkanowy.data.db.dao.NoteDao -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Student -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteLocal @Inject constructor(private val noteDb: NoteDao) { - - suspend fun saveNotes(notes: List) { - noteDb.insertAll(notes) - } - - suspend fun updateNotes(notes: List) { - noteDb.updateAll(notes) - } - - suspend fun deleteNotes(notes: List) { - noteDb.deleteAll(notes) - } - - fun getNotes(student: Student): Flow> { - return noteDb.loadAll(student.studentId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt deleted file mode 100644 index 0e488b7d..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.data.repositories.note - -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getNotes(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getNotes(semester.semesterId) - .map { - Note( - studentId = semester.studentId, - date = it.date, - teacher = it.teacher, - teacherSymbol = it.teacherSymbol, - category = it.category, - categoryType = it.categoryType.id, - isPointsShow = it.showPoints, - points = it.points, - content = it.content - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt deleted file mode 100644 index 6cf62ba2..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.data.repositories.note - -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteRepository @Inject constructor( - private val local: NoteLocal, - private val remote: NoteRemote -) { - - fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getNotes(student) }, - fetch = { remote.getNotes(student, semester) }, - saveFetchResult = { old, new -> - local.deleteNotes(old uniqueSubtract new) - local.saveNotes((new uniqueSubtract old).onEach { - if (it.date >= student.registrationDate.toLocalDate()) it.apply { - isRead = false - if (notify) isNotified = false - } - }) - } - ) - - fun getNotNotifiedNotes(student: Student): Flow> { - return local.getNotes(student).map { it.filter { note -> !note.isNotified } } - } - - suspend fun updateNote(note: Note) { - local.updateNotes(listOf(note)) - } - - suspend fun updateNotes(notes: List) { - return local.updateNotes(notes) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt deleted file mode 100644 index fac1645e..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.recipient - -import io.github.wulkanowy.data.db.dao.RecipientDao -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao) { - - suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List { - return recipientDb.load(student.studentId, role, unit.realId) - } - - suspend fun saveRecipients(recipients: List): List { - return recipientDb.insertAll(recipients) - } - - suspend fun deleteRecipients(recipients: List) { - recipientDb.deleteAll(recipients) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt deleted file mode 100644 index a5318e77..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.data.repositories.recipient - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton -import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient - -@Singleton -class RecipientRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List { - return sdk.init(student).getRecipients(unit.realId, role) - .map { it.toRecipient() } - } - - suspend fun getMessageRecipients(student: Student, message: Message): List { - return sdk.init(student).getMessageRecipients(message.messageId, message.senderId) - .map { it.toRecipient() } - } - - private fun SdkRecipient.toRecipient(): Recipient { - return Recipient( - studentId = sdk.studentId, - realId = id, - realName = name, - name = shortName, - hash = hash, - loginId = loginId, - role = role, - unitId = reportingUnitId ?: 0 - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt deleted file mode 100644 index f5e876b0..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.data.repositories.recipient - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecipientRepository @Inject constructor( - private val local: RecipientLocal, - private val remote: RecipientRemote -) { - - suspend fun refreshRecipients(student: Student, role: Int, unit: ReportingUnit) { - val new = remote.getRecipients(student, role, unit) - val old = local.getRecipients(student, role, unit) - - local.deleteRecipients(old uniqueSubtract new) - local.saveRecipients(new uniqueSubtract old) - } - - suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List { - return local.getRecipients(student, role, unit).ifEmpty { - refreshRecipients(student, role, unit) - - local.getRecipients(student, role, unit) - } - } - - suspend fun getMessageRecipients(student: Student, message: Message): List { - return remote.getMessageRecipients(student, message) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt deleted file mode 100644 index 3117a606..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.repositories.recover - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecoverRepository @Inject constructor(private val remote: RecoverRemote) { - - suspend fun getReCaptchaSiteKey(host: String, symbol: String): Pair { - return remote.getReCaptchaSiteKey(host, symbol) - } - - suspend fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): String { - return remote.sendRecoverRequest(url, symbol, email, reCaptchaResponse) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt deleted file mode 100644 index 737f1a04..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.repositories.reportingunit - -import io.github.wulkanowy.data.db.dao.ReportingUnitDao -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) { - - suspend fun getReportingUnits(student: Student): List { - return reportingUnitDb.load(student.studentId) - } - - suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? { - return reportingUnitDb.loadOne(student.studentId, unitId) - } - - suspend fun saveReportingUnits(reportingUnits: List): List { - return reportingUnitDb.insertAll(reportingUnits) - } - - suspend fun deleteReportingUnits(reportingUnits: List) { - reportingUnitDb.deleteAll(reportingUnits) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt deleted file mode 100644 index 6b11c2cc..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.reportingunit - -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getReportingUnits(student: Student): List { - return sdk.init(student).getReportingUnits().map { unit -> - ReportingUnit( - studentId = sdk.studentId, - realId = unit.id, - roles = unit.roles, - senderId = unit.senderId, - senderName = unit.senderName, - shortName = unit.short - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt deleted file mode 100644 index ff583946..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.data.repositories.reportingunit - -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitRepository @Inject constructor( - private val local: ReportingUnitLocal, - private val remote: ReportingUnitRemote -) { - - suspend fun refreshReportingUnits(student: Student) { - val new = remote.getReportingUnits(student) - val old = local.getReportingUnits(student) - - local.deleteReportingUnits(old.uniqueSubtract(new)) - local.saveReportingUnits(new.uniqueSubtract(old)) - } - - suspend fun getReportingUnits(student: Student): List { - return local.getReportingUnits(student).ifEmpty { - refreshReportingUnits(student) - - local.getReportingUnits(student) - } - } - - suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? { - return local.getReportingUnit(student, unitId) ?: run { - refreshReportingUnits(student) - - return local.getReportingUnit(student, unitId) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt deleted file mode 100644 index bc1b2f44..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.data.repositories.school - -import io.github.wulkanowy.data.db.dao.SchoolDao -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.Semester -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject - -class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) { - - suspend fun saveSchool(school: School) { - schoolDb.insertAll(listOf(school)) - } - - suspend fun deleteSchool(school: School) { - schoolDb.deleteAll(listOf(school)) - } - - fun getSchool(semester: Semester): Flow { - return schoolDb.load(semester.studentId, semester.classId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt deleted file mode 100644 index 4d2e0cd6..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.repositories.school - -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject - -class SchoolRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getSchoolInfo(student: Student, semester: Semester): School { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getSchool() - .let { - School( - studentId = semester.studentId, - classId = semester.classId, - name = it.name, - address = it.address, - contact = it.contact, - headmaster = it.headmaster, - pedagogue = it.pedagogue - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt deleted file mode 100644 index 4c84c319..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.repositories.school - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SchoolRepository @Inject constructor( - private val local: SchoolLocal, - private val remote: SchoolRemote -) { - - fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it == null || forceRefresh }, - query = { local.getSchool(semester) }, - fetch = { remote.getSchoolInfo(student, semester) }, - saveFetchResult = { old, new -> - if (new != old && old != null) { - local.deleteSchool(old) - local.saveSchool(new) - } - local.saveSchool(new) - } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt deleted file mode 100644 index 8ecf1595..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.data.repositories.semester - -import io.github.wulkanowy.data.db.dao.SemesterDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) { - - suspend fun saveSemesters(semesters: List) { - semesterDb.insertSemesters(semesters) - } - - suspend fun deleteSemesters(semesters: List) { - semesterDb.deleteAll(semesters) - } - - suspend fun getSemesters(student: Student): List { - return semesterDb.loadAll(student.studentId, student.classId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt deleted file mode 100644 index e1a920b6..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.semester - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SemesterRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getSemesters(student: Student): List { - return sdk.init(student).getSemesters().map { - Semester( - studentId = student.studentId, - diaryId = it.diaryId, - diaryName = it.diaryName, - schoolYear = it.schoolYear, - semesterId = it.semesterId, - semesterName = it.semesterNumber, - start = it.start, - end = it.end, - classId = it.classId, - unitId = it.unitId - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt deleted file mode 100644 index c01d1d04..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import android.content.Context -import dagger.hilt.android.qualifiers.ApplicationContext -import io.github.wulkanowy.data.db.dao.StudentDao -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.DispatchersProvider -import io.github.wulkanowy.utils.security.decrypt -import io.github.wulkanowy.utils.security.encrypt -import kotlinx.coroutines.withContext -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StudentLocal @Inject constructor( - private val studentDb: StudentDao, - private val dispatchers: DispatchersProvider, - @ApplicationContext private val context: Context -) { - - suspend fun saveStudents(students: List) = withContext(dispatchers.backgroundThread) { - studentDb.insertAll(students.map { - if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context)) - else it - }) - } - - suspend fun getStudents(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) { - studentDb.loadStudentsWithSemesters().map { - it.apply { - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) student.password = decrypt(student.password) - } - } - } - - suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) { - studentDb.loadById(id)?.apply { - if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) - } - } - - suspend fun getCurrentStudent(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) { - studentDb.loadCurrent()?.apply { - if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) - } - } - - suspend fun setCurrentStudent(student: Student) = withContext(dispatchers.backgroundThread) { - studentDb.run { - resetCurrent() - updateCurrent(student.id) - } - } - - suspend fun logoutStudent(student: Student) = withContext(dispatchers.backgroundThread) { - studentDb.delete(student) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt deleted file mode 100644 index dcb12623..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import io.github.wulkanowy.data.mappers.mapToEntities -import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.sdk.Sdk -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StudentRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getStudentsMobileApi(token: String, pin: String, symbol: String): List { - return sdk.getStudentsFromMobileApi(token, pin, symbol, "").mapToEntities() - } - - suspend fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): List { - return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).mapToEntities(password) - } - - suspend fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): List { - return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).mapToEntities(password) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt deleted file mode 100644 index 19e0e208..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt +++ /dev/null @@ -1,57 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.repositories.semester.SemesterLocal -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StudentRepository @Inject constructor( - private val local: StudentLocal, - private val semestersLocal: SemesterLocal, - private val remote: StudentRemote -) { - - suspend fun isStudentSaved(): Boolean = local.getStudents(false).isNotEmpty() - - suspend fun isCurrentStudentSet(): Boolean = local.getCurrentStudent(false)?.isCurrent ?: false - - suspend fun getStudentsApi(pin: String, symbol: String, token: String): List { - return remote.getStudentsMobileApi(token, pin, symbol) - } - - suspend fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String): List { - return remote.getStudentsScrapper(email, password, endpoint, symbol) - } - - suspend fun getStudentsHybrid(email: String, password: String, endpoint: String, symbol: String): List { - return remote.getStudentsHybrid(email, password, endpoint, symbol) - } - - suspend fun getSavedStudents(decryptPass: Boolean = true): List { - return local.getStudents(decryptPass) - } - - suspend fun getStudentById(id: Int): Student { - return local.getStudentById(id) ?: throw NoCurrentStudentException() - } - - suspend fun getCurrentStudent(decryptPass: Boolean = true): Student { - return local.getCurrentStudent(decryptPass) ?: throw NoCurrentStudentException() - } - - suspend fun saveStudents(studentsWithSemesters: List): List { - semestersLocal.saveSemesters(studentsWithSemesters.flatMap { it.semesters }) - return local.saveStudents(studentsWithSemesters.map { it.student }) - } - - suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) { - return local.setCurrentStudent(studentWithSemesters.student) - } - - suspend fun logoutStudent(student: Student) { - return local.logoutStudent(student) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt deleted file mode 100644 index e225a381..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.subject - -import io.github.wulkanowy.data.db.dao.SubjectDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Subject -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectLocal @Inject constructor(private val subjectDao: SubjectDao) { - - fun getSubjects(semester: Semester): Flow> { - return subjectDao.loadAll(semester.diaryId, semester.studentId) - } - - suspend fun saveSubjects(subjects: List) { - subjectDao.insertAll(subjects) - } - - suspend fun deleteSubjects(subjects: List) { - subjectDao.deleteAll(subjects) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt deleted file mode 100644 index 624a5a00..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.data.repositories.subject - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Subject -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getSubjects(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getSubjects() - .map { - Subject( - studentId = semester.studentId, - diaryId = semester.diaryId, - name = it.name, - realId = it.id - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt deleted file mode 100644 index 60a0c3e7..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.subject - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectRepository @Inject constructor( - private val local: SubjectLocal, - private val remote: SubjectRemote -) { - - fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getSubjects(semester) }, - fetch = { remote.getSubjects(student, semester) }, - saveFetchResult = { old, new -> - local.deleteSubjects(old uniqueSubtract new) - local.saveSubjects(new uniqueSubtract old) - } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt deleted file mode 100644 index 908f45a1..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.data.repositories.teacher - -import io.github.wulkanowy.data.db.dao.TeacherDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Teacher -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject - -class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) { - - suspend fun saveTeachers(teachers: List) { - teacherDb.insertAll(teachers) - } - - suspend fun deleteTeachers(teachers: List) { - teacherDb.deleteAll(teachers) - } - - fun getTeachers(semester: Semester): Flow> { - return teacherDb.loadAll(semester.studentId, semester.classId) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt deleted file mode 100644 index 1d1caa68..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.repositories.teacher - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TeacherRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getTeachers(student: Student, semester: Semester): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getTeachers(semester.semesterId) - .map { - Teacher( - studentId = semester.studentId, - name = it.name, - subject = it.subject, - shortName = it.short, - classId = semester.classId - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt deleted file mode 100644 index df25a53e..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.teacher - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.uniqueSubtract -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TeacherRepository @Inject constructor( - private val local: TeacherLocal, - private val remote: TeacherRemote -) { - - fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getTeachers(semester) }, - fetch = { remote.getTeachers(student, semester) }, - saveFetchResult = { old, new -> - local.deleteTeachers(old uniqueSubtract new) - local.saveTeachers(new uniqueSubtract old) - } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt deleted file mode 100644 index df4bfb20..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import io.github.wulkanowy.data.db.dao.TimetableDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Timetable -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao) { - - suspend fun saveTimetable(timetables: List) { - timetableDb.insertAll(timetables) - } - - suspend fun deleteTimetable(timetables: List) { - timetableDb.deleteAll(timetables) - } - - fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow> { - return timetableDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt deleted file mode 100644 index 9fb80e77..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableRemote @Inject constructor(private val sdk: Sdk) { - - suspend fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getTimetable(startDate, endDate).first - .map { - Timetable( - studentId = semester.studentId, - diaryId = semester.diaryId, - number = it.number, - start = it.start, - end = it.end, - date = it.date, - subject = it.subject, - subjectOld = it.subjectOld, - group = it.group, - room = it.room, - roomOld = it.roomOld, - teacher = it.teacher, - teacherOld = it.teacherOld, - info = it.info, - isStudentPlan = it.studentPlan, - changes = it.changes, - canceled = it.canceled - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt deleted file mode 100644 index ee2734aa..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.networkBoundResource -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.flow.map -import java.time.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableRepository @Inject constructor( - private val local: TimetableLocal, - private val remote: TimetableRemote, - private val schedulerHelper: TimetableNotificationSchedulerHelper -) { - - fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getTimetable(semester, start.monday, end.sunday).map { schedulerHelper.scheduleNotifications(it, student); it } }, - fetch = { remote.getTimetable(student, semester, start.monday, end.sunday) }, - saveFetchResult = { old, new -> - local.deleteTimetable(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) }) - local.saveTimetable(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item -> - item.also { new -> - old.singleOrNull { new.start == it.start }?.let { old -> - return@map new.copy( - room = if (new.room.isEmpty()) old.room else new.room, - teacher = if (new.teacher.isEmpty() && !new.changes && !old.changes) old.teacher else new.teacher - ) - } - } - }) - }, - filterResult = { it.filter { item -> item.date in start..end } } - ) -} diff --git a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt index 592d0919..8eefc032 100644 --- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt +++ b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt @@ -12,7 +12,7 @@ import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.HiltBroadcastReceiver import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID import io.github.wulkanowy.ui.modules.main.MainActivity diff --git a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt index 2593a555..c0eba2f9 100644 --- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt +++ b/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt @@ -11,7 +11,7 @@ import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_END import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_NEXT_ROOM import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_NEXT_TITLE 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 47a94927..b94d97e3 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt @@ -18,7 +18,7 @@ import androidx.work.WorkInfo import androidx.work.WorkManager import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.services.sync.channels.Channel import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.isHolidays diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt index 13326ca0..a428b702 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt @@ -11,9 +11,9 @@ import androidx.work.CoroutineWorker import androidx.work.Data import androidx.work.WorkerParameters import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException import io.github.wulkanowy.services.sync.channels.DebugChannel diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt index 9e4ab902..cbe1fe6b 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository +import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository import io.github.wulkanowy.utils.waitForResult import javax.inject.Inject diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt index ecf0be01..788e4ea2 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository +import io.github.wulkanowy.data.repositories.AttendanceRepository import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.waitForResult diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt index 212ea632..17bd6129 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository +import io.github.wulkanowy.data.repositories.CompletedLessonsRepository import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.waitForResult diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt index 899d45cb..b7549930 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.exam.ExamRepository +import io.github.wulkanowy.data.repositories.ExamRepository import io.github.wulkanowy.utils.waitForResult import java.time.LocalDate.now import javax.inject.Inject diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt index 461836b8..4575b419 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository +import io.github.wulkanowy.data.repositories.GradeStatisticsRepository import io.github.wulkanowy.utils.waitForResult import javax.inject.Inject 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 00bce109..19c26edd 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt @@ -13,8 +13,8 @@ import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.grade.GradeRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.GradeRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.services.sync.channels.NewGradesChannel import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt index a07f1107..a16841e9 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.homework.HomeworkRepository +import io.github.wulkanowy.data.repositories.HomeworkRepository import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.waitForResult diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt index 7b9f5ab3..9f536553 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt @@ -12,8 +12,8 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.LuckyNumber import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.LuckyNumberRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.services.sync.channels.LuckyNumberChannel import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt index 7b32f13b..93c30b57 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt @@ -12,9 +12,9 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED -import io.github.wulkanowy.data.repositories.message.MessageRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED +import io.github.wulkanowy.data.repositories.MessageRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.services.sync.channels.NewMessagesChannel import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt index b0889696..50f418ed 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt @@ -12,8 +12,8 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Note import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.note.NoteRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.NoteRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.NEUTRAL import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory.POSITIVE diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt index c433c0ac..34ab3db0 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt @@ -2,8 +2,8 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.recipient.RecipientRepository -import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository +import io.github.wulkanowy.data.repositories.RecipientRepository +import io.github.wulkanowy.data.repositories.ReportingUnitRepository import javax.inject.Inject class RecipientWork @Inject constructor( @@ -16,7 +16,7 @@ class RecipientWork @Inject constructor( reportingUnitRepository.getReportingUnits(student).let { units -> units.map { - recipientRepository.refreshRecipients(student, 2, it) + recipientRepository.refreshRecipients(student, it, 2) } } } diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt index a9abdaa7..7c614c6c 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.teacher.TeacherRepository +import io.github.wulkanowy.data.repositories.TeacherRepository import io.github.wulkanowy.utils.waitForResult import javax.inject.Inject diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt index 3b8c6f5d..2df2c9dc 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.services.sync.works import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.timetable.TimetableRepository +import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.waitForResult diff --git a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt index 42c6d3bf..45cd2b04 100644 --- a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt +++ b/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt @@ -4,10 +4,10 @@ import android.content.Intent import android.widget.RemoteViewsService import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.SharedPrefProvider -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.timetable.TimetableRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetFactory import timber.log.Timber import javax.inject.Inject diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt index ba8bfd85..b222b0ab 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt @@ -1,7 +1,7 @@ package io.github.wulkanowy.ui.base import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.utils.flowWithResource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt index 946e661b..34dd3ec1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt @@ -1,7 +1,6 @@ package io.github.wulkanowy.ui.base import android.content.res.Resources -import com.chuckerteam.chucker.api.ChuckerCollector import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException import io.github.wulkanowy.utils.getString @@ -9,7 +8,7 @@ import io.github.wulkanowy.utils.security.ScramblerException import timber.log.Timber import javax.inject.Inject -open class ErrorHandler @Inject constructor(protected val resources: Resources, private val chuckerCollector: ChuckerCollector) { +open class ErrorHandler @Inject constructor(protected val resources: Resources) { var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> } @@ -18,7 +17,6 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources, var onNoCurrentStudent: () -> Unit = {} fun dispatch(error: Throwable) { - chuckerCollector.onError(error.javaClass.simpleName, error) Timber.e(error, "An exception occurred while the Wulkanowy was running") proceed(error) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt index 50134861..a2379c3e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt @@ -7,7 +7,7 @@ import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt index 76ba8212..fde20267 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.about -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt index 78fdb43a..ef4b540e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt @@ -2,8 +2,8 @@ package io.github.wulkanowy.ui.modules.about.contributor import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.pojos.Contributor -import io.github.wulkanowy.data.repositories.appcreator.AppCreatorRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.AppCreatorRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.flowWithResource diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt index 18d257ee..cc430fc2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.about.license import com.mikepenz.aboutlibraries.entity.Library import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.DispatchersProvider diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt index 85eae8e6..80020c81 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt @@ -1,8 +1,8 @@ package io.github.wulkanowy.ui.modules.about.logviewer import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.logger.LoggerRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.LoggerRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.flowWithResource diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt index 4eaee429..be01f7c5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.account import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt index 8e8a6149..03ec1c84 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt @@ -7,7 +7,7 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.repositories.attendance.SentExcuseStatus +import io.github.wulkanowy.data.enums.SentExcuseStatus import io.github.wulkanowy.databinding.ItemAttendanceBinding import io.github.wulkanowy.utils.description import javax.inject.Inject diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt index c7caef06..a106bc50 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt @@ -191,8 +191,8 @@ class AttendanceFragment : BaseFragment(R.layout.frag binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE } - override fun hideRefresh() { - binding.attendanceSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.attendanceSwipe.isRefreshing = show } override fun showPreButton(show: Boolean) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt index 19f8523d..68802c0c 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,10 +3,10 @@ package io.github.wulkanowy.ui.modules.attendance import android.annotation.SuppressLint import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.AttendanceRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -51,23 +51,23 @@ class AttendancePresenter @Inject constructor( view.initView() Timber.i("Attendance view was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) + loadData() if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() } fun onPreviousDay() { view?.finishActionMode() attendanceToExcuseList.clear() - loadData(currentDate.previousSchoolDay) - reloadView() + reloadView(currentDate.previousSchoolDay) + loadData() } fun onNextDay() { view?.finishActionMode() attendanceToExcuseList.clear() - loadData(currentDate.nextSchoolDay) - reloadView() + reloadView(currentDate.nextSchoolDay) + loadData() } fun onPickDate() { @@ -75,13 +75,13 @@ class AttendancePresenter @Inject constructor( } fun onDateSet(year: Int, month: Int, day: Int) { - loadData(LocalDate.of(year, month, day)) - reloadView() + reloadView(LocalDate.of(year, month, day)) + loadData() } fun onSwipeRefresh() { Timber.i("Force refreshing the attendance") - loadData(currentDate, true) + loadData(true) } fun onRetry() { @@ -89,7 +89,7 @@ class AttendancePresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(currentDate, true) + loadData(true) } fun onDetailsClick() { @@ -102,8 +102,8 @@ class AttendancePresenter @Inject constructor( if (view.currentStackSize == 1) { baseDate.also { if (currentDate != it) { - loadData(it) - reloadView() + reloadView(it) + loadData() } else if (!view.isViewEmpty) view.resetView() } } else view.popView() @@ -184,17 +184,30 @@ class AttendancePresenter @Inject constructor( }.launch("holidays") } - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { + private fun loadData(forceRefresh: Boolean = false) { Timber.i("Loading attendance data started") - currentDate = date flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - attendanceRepository.getAttendance(student, semester, date, date, forceRefresh) + attendanceRepository.getAttendance(student, semester, currentDate, currentDate, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> view?.showExcuseButton(false) + Status.LOADING -> { + view?.showExcuseButton(false) + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data.let { items -> + if (prefRepository.isShowPresent) items + else items.filter { item -> !item.presence } + }.sortedBy { item -> item.number }) + } + } + } Status.SUCCESS -> { Timber.i("Loading attendance result: Success") view?.apply { @@ -220,7 +233,7 @@ class AttendancePresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } @@ -250,12 +263,12 @@ class AttendancePresenter @Inject constructor( showContent(true) showProgress(false) } - loadData(currentDate, forceRefresh = true) + loadData(forceRefresh = true) } Status.ERROR -> { Timber.i("Excusing for absence result: An exception occurred") errorHandler.dispatch(it.error!!) - loadData(currentDate) + loadData() } } }.launch("excuse") @@ -272,11 +285,14 @@ class AttendancePresenter @Inject constructor( } } - private fun reloadView() { + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) enableSwipe(false) + showRefresh(false) showContent(false) showEmpty(false) showErrorView(false) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt index d54fb8bf..0459dfcf 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt @@ -24,7 +24,7 @@ interface AttendanceView : BaseView { fun clearData() - fun hideRefresh() + fun showRefresh(show: Boolean) fun resetView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt index 2f862237..6b971f26 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt @@ -121,8 +121,8 @@ class AttendanceSummaryFragment : binding.attendanceSummarySubjectsContainer.visibility = if (show) VISIBLE else INVISIBLE } - override fun hideRefresh() { - binding.attendanceSummarySwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.attendanceSummarySwipe.isRefreshing = show } override fun onSaveInstanceState(outState: Bundle) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt index 4ce49d96..e53cda74 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt @@ -1,11 +1,12 @@ package io.github.wulkanowy.ui.modules.attendance.summary import io.github.wulkanowy.data.Status +import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.Subject -import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.subject.SubjectRepository +import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.SubjectRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -74,6 +75,8 @@ class AttendanceSummaryPresenter @Inject constructor( } private fun loadData(subjectId: Int, forceRefresh: Boolean = false) { + Timber.i("Loading attendance summary data started") + currentSubjectId = subjectId flowWithResourceIn { @@ -82,15 +85,23 @@ class AttendanceSummaryPresenter @Inject constructor( attendanceSummaryRepository.getAttendanceSummary(student, semester, subjectId, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading attendance summary data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateDataSet(sortItems(it.data)) + } + } + } Status.SUCCESS -> { Timber.i("Loading attendance summary result: Success") view?.apply { showEmpty(it.data!!.isEmpty()) showContent(it.data.isNotEmpty()) - updateDataSet(it.data.sortedByDescending { item -> - if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value - }) + updateDataSet(sortItems(it.data)) } analytics.logEvent( "load_data", @@ -106,13 +117,17 @@ class AttendanceSummaryPresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } }.launch() } + private fun sortItems(items: List) = items.sortedByDescending { item -> + if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value + } + private fun showErrorViewOnError(message: String, error: Throwable) { view?.run { if (isViewEmpty) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt index dd4053c7..66f370c5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt @@ -9,7 +9,7 @@ interface AttendanceSummaryView : BaseView { fun initView() - fun hideRefresh() + fun showRefresh(show: Boolean) fun showContent(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt index 74d93897..6173c15b 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 @@ -67,8 +67,8 @@ class ConferenceFragment : BaseFragment(R.layout.frag } } - override fun hideRefresh() { - binding.conferenceSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.conferenceSwipe.isRefreshing = show } override fun showProgress(show: Boolean) { 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 71b412da..cc7e50db 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 @@ -1,9 +1,9 @@ package io.github.wulkanowy.ui.modules.conference import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.conference.ConferenceRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.ConferenceRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -59,13 +59,25 @@ class ConferencePresenter @Inject constructor( } private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading conference data started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) conferenceRepository.getConferences(student, semester, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading conference data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data.sortedByDescending { conference -> conference.date }) + } + } + } Status.SUCCESS -> { Timber.i("Loading conference result: Success") view?.run { @@ -87,7 +99,7 @@ class ConferencePresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } 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 37845a6f..f3d1b3b3 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 @@ -13,7 +13,7 @@ interface ConferenceView : BaseView { fun clearData() - fun hideRefresh() + fun showRefresh(show: Boolean) fun showEmpty(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt index 000da00f..9cc1aeda 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt @@ -65,8 +65,8 @@ class ExamFragment : BaseFragment(R.layout.fragment_exam), } } - override fun hideRefresh() { - binding.examSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.examSwipe.isRefreshing = show } override fun updateData(data: List>) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt index 406d011c..b70a648f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt @@ -2,9 +2,9 @@ package io.github.wulkanowy.ui.modules.exam import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.repositories.exam.ExamRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.ExamRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -45,24 +45,24 @@ class ExamPresenter @Inject constructor( view.initView() Timber.i("Exam view was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) + loadData() if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() } fun onPreviousWeek() { - loadData(currentDate.minusDays(7)) - reloadView() + reloadView(currentDate.minusDays(7)) + loadData() } fun onNextWeek() { - loadData(currentDate.plusDays(7)) - reloadView() + reloadView(currentDate.plusDays(7)) + loadData() } fun onSwipeRefresh() { Timber.i("Force refreshing the exam") - loadData(currentDate, true) + loadData(true) } fun onRetry() { @@ -70,7 +70,7 @@ class ExamPresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(currentDate, true) + loadData(true) } fun onDetailsClick() { @@ -86,8 +86,8 @@ class ExamPresenter @Inject constructor( Timber.i("Exam view is reselected") baseDate.also { if (currentDate != it) { - loadData(it) - reloadView() + reloadView(it) + loadData() } else if (view?.isViewEmpty == false) view?.resetView() } } @@ -105,8 +105,8 @@ class ExamPresenter @Inject constructor( }.launch("holidays") } - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - currentDate = date + private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading exam data started") flowWithResourceIn { val student = studentRepository.getCurrentStudent() @@ -114,7 +114,17 @@ class ExamPresenter @Inject constructor( examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading exam data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(createExamItems(it.data)) + } + } + } Status.SUCCESS -> { Timber.i("Loading exam result: Success") view?.apply { @@ -136,7 +146,7 @@ class ExamPresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } @@ -162,7 +172,9 @@ class ExamPresenter @Inject constructor( }.flatten() } - private fun reloadView() { + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload exam view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt index 00429bae..ac1a87fe 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt @@ -15,7 +15,7 @@ interface ExamView : BaseView { fun clearData() - fun hideRefresh() + fun showRefresh(show: Boolean) fun resetView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt index 5d0a310f..0bd971ec 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt @@ -1,14 +1,13 @@ package io.github.wulkanowy.ui.modules.grade import io.github.wulkanowy.data.Resource -import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.grade.GradeRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository +import io.github.wulkanowy.data.repositories.GradeRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ALL_YEAR import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.BOTH_SEMESTERS @@ -18,10 +17,8 @@ import io.github.wulkanowy.utils.changeModifier import io.github.wulkanowy.utils.flowWithResourceIn import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flatMapConcat -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -50,20 +47,20 @@ class GradeAverageProvider @Inject constructor( val selectedSemester = semesters.single { it.semesterId == semesterId } val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } - return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails -> - val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 } + val selectedSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh) - if (selectedSemester != firstSemester) { - getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails -> - secondDetails.copy(data = selectedDetails.data?.map { selected -> - val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject } - selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) { - val selectedGrades = selected.grades.updateModifiers(student).calcAverage() - (selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2 - } else (selected.average + (second?.average ?: selected.average)) / 2) - }) - }.filter { it.status != Status.LOADING }.filter { it.data != null } - } else flowOf(selectedDetails) + return if (selectedSemester == firstSemester) selectedSemesterDetailsWithAverage else { + val firstSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, firstSemester, forceRefresh) + selectedSemesterDetailsWithAverage.combine(firstSemesterDetailsWithAverage) { selectedDetails, secondDetails -> + val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 } + secondDetails.copy(data = selectedDetails.data?.map { selected -> + val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject } + selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) { + val selectedGrades = selected.grades.updateModifiers(student).calcAverage() + (selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2 + } else (selected.average + (second?.average ?: selected.average)) / 2) + }) + } } } @@ -71,19 +68,19 @@ class GradeAverageProvider @Inject constructor( val selectedSemester = semesters.single { it.semesterId == semesterId } val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } - return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails -> - val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 } + val selectedSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh) - if (selectedSemester != firstSemester) { - getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails -> - secondDetails.copy(data = selectedDetails.data?.map { selected -> - val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject } - selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) { - (selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage() - } else selected.average) - }) - }.filter { it.status != Status.LOADING }.filter { it.data != null } - } else flowOf(selectedDetails) + return if (selectedSemester == firstSemester) selectedSemesterDetailsWithAverage else { + val firstSemesterDetailsWithAverage = getSemesterDetailsWithAverage(student, firstSemester, forceRefresh) + selectedSemesterDetailsWithAverage.combine(firstSemesterDetailsWithAverage) { selectedDetails, secondDetails -> + val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 } + secondDetails.copy(data = selectedDetails.data?.map { selected -> + val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject } + selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) { + (selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage() + } else selected.average) + }) + } } } @@ -93,7 +90,7 @@ class GradeAverageProvider @Inject constructor( val isAnyAverage = summaries.orEmpty().any { it.average != .0 } val allGrades = details.orEmpty().groupBy { it.subject } - Resource(res.status, summaries?.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage)?.map { summary -> + val items = summaries?.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage)?.map { summary -> val grades = allGrades[summary.subject].orEmpty() GradeDetailsWithAverage( subject = summary.subject, @@ -104,7 +101,9 @@ class GradeAverageProvider @Inject constructor( summary = summary, grades = grades ) - }, res.error) + } + + Resource(res.status, items, res.error) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt index e91c94eb..d64613c0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt @@ -2,8 +2,8 @@ package io.github.wulkanowy.ui.modules.grade import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 a34dd7ac..afec6b5e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt @@ -3,10 +3,10 @@ package io.github.wulkanowy.ui.modules.grade.details import android.annotation.SuppressLint import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.repositories.grade.GradeRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.GradeRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider @@ -137,15 +137,37 @@ class GradeDetailsPresenter @Inject constructor( } private fun loadData(semesterId: Int, forceRefresh: Boolean) { + Timber.i("Loading grade details data started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh) }.onEach { + Timber.d("Loading grade details status: ${it.status}, data: ${it.data != null}") when (it.status) { - Status.LOADING -> Timber.i("Loading grade details data started") + Status.LOADING -> { + val items = createGradeItems(it.data.orEmpty()) + if (items.isNotEmpty()) { + Timber.i("Loading grade details result: load cached data") + view?.run { + updateNewGradesAmount(it.data.orEmpty()) + enableSwipe(true) + showRefresh(true) + showProgress(false) + showEmpty(false) + showContent(true) + updateData( + data = items, + isGradeExpandable = preferencesRepository.isGradeExpandable, + gradeColorTheme = preferencesRepository.gradeColorTheme + ) + notifyParentDataLoaded(semesterId) + } + } + } Status.SUCCESS -> { Timber.i("Loading grade details result: Success") - newGradesAmount = it.data!!.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } } + updateNewGradesAmount(it.data!!) updateMarkAsDoneButton() val items = createGradeItems(it.data) view?.run { @@ -179,6 +201,10 @@ class GradeDetailsPresenter @Inject constructor( }.launch() } + private fun updateNewGradesAmount(grades: List) { + newGradesAmount = grades.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } } + } + private fun showErrorViewOnError(message: String, error: Throwable) { view?.run { if (isViewEmpty) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt index aca3ec96..37f47869 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt @@ -2,11 +2,12 @@ package io.github.wulkanowy.ui.modules.grade.statistics import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Subject -import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.subject.SubjectRepository +import io.github.wulkanowy.data.pojos.GradeStatisticsItem +import io.github.wulkanowy.data.repositories.GradeStatisticsRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.SubjectRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -143,6 +144,8 @@ class GradeStatisticsPresenter @Inject constructor( } private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) { + Timber.i("Loading grade stats data started") + currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName currentType = type @@ -160,17 +163,24 @@ class GradeStatisticsPresenter @Inject constructor( } }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading grade stats data started") + Status.LOADING -> { + val isNoContent = it.data == null || checkIsNoContent(it.data, type) + if (!isNoContent) { + view?.run { + showEmpty(isNoContent) + showContent(!isNoContent) + showErrorView(false) + enableSwipe(true) + showRefresh(true) + updateData(it.data!!, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) + showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) + } + } + } Status.SUCCESS -> { Timber.i("Loading grade stats result: Success") view?.run { - val isNoContent = it.data!!.isEmpty() || when (type) { - ViewType.SEMESTER -> it.data.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0 - ViewType.PARTIAL -> it.data.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0 - ViewType.POINTS -> it.data.firstOrNull()?.points?.let { points -> - points.student == .0 && points.others == .0 - } ?: false - } + val isNoContent = checkIsNoContent(it.data!!, type) showEmpty(isNoContent) showContent(!isNoContent) showErrorView(false) @@ -198,6 +208,16 @@ class GradeStatisticsPresenter @Inject constructor( }.launch("load") } + private fun checkIsNoContent(items: List, type: ViewType): Boolean { + return items.isEmpty() || when (type) { + ViewType.SEMESTER -> items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0 + ViewType.PARTIAL -> items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0 + ViewType.POINTS -> items.firstOrNull()?.points?.let { points -> + points.student == .0 && points.others == .0 + } ?: false + } + } + private fun showErrorViewOnError(message: String, error: Throwable) { view?.run { if (isViewEmpty) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt index 7ce98d10..17c14b85 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.grade.summary import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider @@ -37,12 +37,28 @@ class GradeSummaryPresenter @Inject constructor( } private fun loadData(semesterId: Int, forceRefresh: Boolean) { + Timber.i("Loading grade summary started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh) }.onEach { + Timber.d("Loading grade summary status: ${it.status}, data: ${it.data != null}") when (it.status) { - Status.LOADING -> Timber.i("Loading grade summary started") + Status.LOADING -> { + val items = createGradeSummaryItems(it.data.orEmpty()) + if (items.isNotEmpty()) { + Timber.i("Loading grade summary result: load cached data") + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showEmpty(false) + showContent(true) + updateData(items) + } + } + } Status.SUCCESS -> { Timber.i("Loading grade summary result: Success") val items = createGradeSummaryItems(it.data!!) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt index e1d7ac52..85173e91 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt @@ -83,8 +83,8 @@ class HomeworkFragment : BaseFragment(R.layout.fragment binding.homeworkNavDate.text = date } - override fun hideRefresh() { - binding.homeworkSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.homeworkSwipe.isRefreshing = show } override fun showEmpty(show: Boolean) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt index f264d58e..11c54dc2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt @@ -2,9 +2,9 @@ package io.github.wulkanowy.ui.modules.homework import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.repositories.homework.HomeworkRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.HomeworkRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -44,24 +44,24 @@ class HomeworkPresenter @Inject constructor( view.initView() Timber.i("Homework view was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) + loadData() if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() } fun onPreviousDay() { - loadData(currentDate.minusDays(7)) - reloadView() + reloadView(currentDate.minusDays(7)) + loadData() } fun onNextDay() { - loadData(currentDate.plusDays(7)) - reloadView() + reloadView(currentDate.plusDays(7)) + loadData() } fun onSwipeRefresh() { Timber.i("Force refreshing the homework") - loadData(currentDate, true) + loadData(true) } fun onRetry() { @@ -69,7 +69,7 @@ class HomeworkPresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(currentDate, true) + loadData(true) } fun onDetailsClick() { @@ -94,16 +94,26 @@ class HomeworkPresenter @Inject constructor( }.launch("holidays") } - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - currentDate = date + private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading homework data started") flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - homeworkRepository.getHomework(student, semester, date, date, forceRefresh) + homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading homework data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(createHomeworkItem(it.data)) + } + } + } Status.SUCCESS -> { Timber.i("Loading homework result: Success") view?.apply { @@ -125,7 +135,7 @@ class HomeworkPresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } @@ -151,7 +161,9 @@ class HomeworkPresenter @Inject constructor( }.flatten() } - private fun reloadView() { + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload homework view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt index 2a678cd4..a1d6a04a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt @@ -15,7 +15,7 @@ interface HomeworkView : BaseView { fun updateNavigationWeek(date: String) - fun hideRefresh() + fun showRefresh(show: Boolean) fun showEmpty(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt index 1d4dac2c..ca6fc71e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt @@ -2,9 +2,9 @@ package io.github.wulkanowy.ui.modules.homework.details import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.repositories.homework.HomeworkRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.HomeworkRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 f30825cf..ed456324 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt @@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.modules.login import android.content.res.Resources import android.database.sqlite.SQLiteConstraintException -import com.chuckerteam.chucker.api.ChuckerCollector import io.github.wulkanowy.R import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException @@ -12,10 +11,7 @@ import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException import io.github.wulkanowy.ui.base.ErrorHandler import javax.inject.Inject -class LoginErrorHandler @Inject constructor( - resources: Resources, - chuckerCollector: ChuckerCollector -) : ErrorHandler(resources, chuckerCollector) { +class LoginErrorHandler @Inject constructor(resources: Resources) : ErrorHandler(resources) { var onBadCredentials: () -> Unit = {} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt index 7e731772..aa1e7ece 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt @@ -1,7 +1,7 @@ package io.github.wulkanowy.ui.modules.login import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import timber.log.Timber diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt index 9dfc3011..891a6b0b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt @@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.login.advanced import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginErrorHandler 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 e165d264..f6a528ae 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 @@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.modules.login.form import androidx.core.net.toUri import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 319541b8..271e8a8a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt @@ -1,8 +1,8 @@ package io.github.wulkanowy.ui.modules.login.recover import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.recover.RecoverRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.RecoverRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.afterLoading diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt index 110dd82e..8619369d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt @@ -1,17 +1,13 @@ package io.github.wulkanowy.ui.modules.login.recover import android.content.res.Resources -import com.chuckerteam.chucker.api.ChuckerCollector import io.github.wulkanowy.sdk.scrapper.exception.InvalidCaptchaException import io.github.wulkanowy.sdk.scrapper.exception.InvalidEmailException import io.github.wulkanowy.sdk.scrapper.exception.NoAccountFoundException import io.github.wulkanowy.ui.base.ErrorHandler import javax.inject.Inject -class RecoverErrorHandler @Inject constructor( - resources: Resources, - chuckerCollector: ChuckerCollector -) : ErrorHandler(resources, chuckerCollector) { +class RecoverErrorHandler @Inject constructor(resources: Resources) : ErrorHandler(resources) { var onInvalidUsername: (String) -> Unit = {} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt index dc824199..c344bf44 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt @@ -3,7 +3,7 @@ package io.github.wulkanowy.ui.modules.login.studentselect import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.StudentWithSemesters -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 9f19539a..4593d880 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,7 +1,7 @@ package io.github.wulkanowy.ui.modules.login.symbol import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.modules.login.LoginErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 cfd793f2..fd0598d8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt @@ -1,8 +1,8 @@ package io.github.wulkanowy.ui.modules.luckynumber import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.LuckyNumberRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 574120b3..f4041e9e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt @@ -3,7 +3,7 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt index b7f4b740..49a19943 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt @@ -16,8 +16,8 @@ import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.LuckyNumberRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.toFirstResult diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt index cc525c29..59937b33 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt @@ -1,7 +1,7 @@ package io.github.wulkanowy.ui.modules.main -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler 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 16e0184a..72fc627f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt @@ -6,9 +6,9 @@ import android.view.View.INVISIBLE import android.view.View.VISIBLE import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED -import io.github.wulkanowy.data.repositories.message.MessageFolder.SENT -import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED +import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED +import io.github.wulkanowy.data.enums.MessageFolder.SENT +import io.github.wulkanowy.data.enums.MessageFolder.TRASHED import io.github.wulkanowy.databinding.FragmentMessageBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt index 0fb454b3..7b8c3d0f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.message -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import kotlinx.coroutines.delay diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt index b35731ca..74f8f57e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt @@ -65,6 +65,9 @@ class MessagePreviewFragment : override val printHTML: String get() = requireContext().assets.open("message-print-page.html").bufferedReader().use { it.readText() } + override val messageNotExists: String + get() = getString(R.string.message_not_exists) + companion object { const val MESSAGE_ID_KEY = "message_id" 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 039c7f14..55b9631a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt @@ -5,13 +5,13 @@ import android.os.Build import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.repositories.message.MessageFolder -import io.github.wulkanowy.data.repositories.message.MessageRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.enums.MessageFolder +import io.github.wulkanowy.data.repositories.MessageRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.flowWithResourceIn @@ -65,18 +65,24 @@ class MessagePreviewPresenter @Inject constructor( Status.LOADING -> Timber.i("Loading message ${message.messageId} preview started") Status.SUCCESS -> { Timber.i("Loading message ${message.messageId} preview result: Success ") - checkNotNull(it.data, { "Can't find message in local db! Probably no longer exist in this folder" }) - this@MessagePreviewPresenter.message = it.data.message - this@MessagePreviewPresenter.attachments = it.data.attachments - view?.apply { - setMessageWithAttachment(it.data) - initOptions() + if (it.data != null) { + this@MessagePreviewPresenter.message = it.data.message + this@MessagePreviewPresenter.attachments = it.data.attachments + view?.apply { + setMessageWithAttachment(it.data) + initOptions() + } + analytics.logEvent( + "load_item", + "type" to "message_preview", + "length" to it.data.message.content.length + ) + } else { + view?.run { + showMessage(messageNotExists) + popView() + } } - analytics.logEvent( - "load_item", - "type" to "message_preview", - "length" to it.data.message.content.length - ) } Status.ERROR -> { Timber.i("Loading message ${message.messageId} preview result: An exception occurred ") 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 fa6d735e..583ba687 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 @@ -14,6 +14,8 @@ interface MessagePreviewView : BaseView { val printHTML: String + val messageNotExists: String + fun initView() fun setMessageWithAttachment(item: MessageWithAttachment) 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 e06c4963..77bd0f5e 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 @@ -3,12 +3,12 @@ package io.github.wulkanowy.ui.modules.message.send import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.repositories.message.MessageRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.recipient.RecipientRepository -import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.MessageRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.RecipientRepository +import io.github.wulkanowy.data.repositories.ReportingUnitRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -100,7 +100,7 @@ class SendMessagePresenter @Inject constructor( Timber.i("Loading recipients started") val recipients = when { - unit != null -> recipientRepository.getRecipients(student, 2, unit) + unit != null -> recipientRepository.getRecipients(student, unit, 2) else -> listOf() }.let { createChips(it) } Timber.i("Loading recipients result: Success, fetched %d recipients", recipients.size) 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 e9b34da3..f0f65e08 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 @@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.NO_POSITION import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.repositories.message.MessageFolder +import io.github.wulkanowy.data.enums.MessageFolder import io.github.wulkanowy.databinding.ItemMessageBinding import io.github.wulkanowy.utils.toFormattedString import javax.inject.Inject 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 44ad4bf1..48a2cee2 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 @@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.repositories.message.MessageFolder +import io.github.wulkanowy.data.enums.MessageFolder import io.github.wulkanowy.databinding.FragmentMessageTabBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.main.MainActivity 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 2143a488..c560a77d 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 @@ -2,10 +2,10 @@ package io.github.wulkanowy.ui.modules.message.tab import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.repositories.message.MessageFolder -import io.github.wulkanowy.data.repositories.message.MessageRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.enums.MessageFolder +import io.github.wulkanowy.data.repositories.MessageRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -85,13 +85,27 @@ class MessageTabPresenter @Inject constructor( } private fun loadData(forceRefresh: Boolean) { + Timber.i("Loading $folder message data started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) messageRepository.getMessages(student, semester, folder, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading $folder message data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + messages = it.data + updateData(getFilteredData(lastSearchQuery)) + notifyParentDataLoaded() + } + } + } Status.SUCCESS -> { Timber.i("Loading $folder message result: Success") messages = it.data!! 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 8065e9b6..48737d7b 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 @@ -100,8 +100,8 @@ class MobileDeviceFragment : } } - override fun hideRefresh() { - binding.mobileDevicesSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.mobileDevicesSwipe.isRefreshing = show } override fun showProgress(show: Boolean) { 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 456609e4..9591867d 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 @@ -2,9 +2,9 @@ package io.github.wulkanowy.ui.modules.mobiledevice import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.repositories.mobiledevice.MobileDeviceRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.MobileDeviceRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -51,13 +51,25 @@ class MobileDevicePresenter @Inject constructor( } private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading mobile devices data started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) mobileDeviceRepository.getDevices(student, semester, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading mobile devices data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data) + } + } + } Status.SUCCESS -> { Timber.i("Loading mobile devices result: Success") view?.run { @@ -79,7 +91,7 @@ class MobileDevicePresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } 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 ec2d3f87..b94646a7 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 @@ -17,7 +17,7 @@ interface MobileDeviceView : BaseView { fun showUndo(device: MobileDevice, position: Int) - fun hideRefresh() + fun showRefresh(show: Boolean) fun showProgress(show: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenPresenter.kt index 8270693d..5e7110ee 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenPresenter.kt @@ -1,9 +1,9 @@ package io.github.wulkanowy.ui.modules.mobiledevice.token import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.mobiledevice.MobileDeviceRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.MobileDeviceRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 d083c981..d119000d 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,6 +1,6 @@ package io.github.wulkanowy.ui.modules.more -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import timber.log.Timber diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt index 079285a8..40378265 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 @@ -105,8 +105,8 @@ class NoteFragment : BaseFragment(R.layout.fragment_note), binding.noteRecycler.visibility = if (show) VISIBLE else GONE } - override fun hideRefresh() { - binding.noteSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.noteSwipe.isRefreshing = show } override fun 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 2e8bec5d..e80f5494 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 @@ -2,9 +2,9 @@ package io.github.wulkanowy.ui.modules.note import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.repositories.note.NoteRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.NoteRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -52,13 +52,25 @@ class NotePresenter @Inject constructor( } private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading note data started") + flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) noteRepository.getNotes(student, semester, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading note data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data) + } + } + } Status.SUCCESS -> { Timber.i("Loading note result: Success") view?.apply { @@ -80,7 +92,7 @@ class NotePresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } 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 a7cbab8f..9fc0be94 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 @@ -27,7 +27,7 @@ interface NoteView : BaseView { fun showContent(show: Boolean) - fun hideRefresh() + fun showRefresh(show: Boolean) fun showNoteDialog(note: Note) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt index 305f4e7d..915cc421 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.schoolandteachers -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import kotlinx.coroutines.delay diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt index 554d422d..491a19ec 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt @@ -1,9 +1,9 @@ package io.github.wulkanowy.ui.modules.schoolandteachers.school import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.school.SchoolRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.SchoolRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper 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 0c58317b..c83cfe76 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 @@ -1,9 +1,9 @@ package io.github.wulkanowy.ui.modules.schoolandteachers.teacher import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.teacher.TeacherRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.TeacherRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt index 6f4a695d..bda07e34 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.settings -import android.content.Context import android.content.SharedPreferences import android.os.Bundle import androidx.appcompat.app.AlertDialog @@ -42,10 +41,6 @@ class SettingsFragment : PreferenceFragmentCompat(), override val syncFailedString get() = getString(R.string.pref_services_message_sync_failed) - override fun onAttach(context: Context) { - super.onAttach(context) - } - override fun initView() { findPreference(getString(R.string.pref_key_services_force_sync))?.run { onPreferenceClickListener = Preference.OnPreferenceClickListener { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt index e640dd60..f9ad74a1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt @@ -2,14 +2,14 @@ package io.github.wulkanowy.ui.modules.settings import androidx.work.WorkInfo import com.chuckerteam.chucker.api.ChuckerCollector -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.isHolidays import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.onEach @@ -46,7 +46,10 @@ class SettingsPresenter @Inject constructor( appThemeKey -> view?.recreateView() isUpcomingLessonsNotificationsEnableKey -> if (!isUpcomingLessonsNotificationsEnable) timetableNotificationHelper.cancelNotification() appLanguageKey -> view?.run { - updateLanguage(if (appLanguage == "system") appInfo.systemLanguage else appLanguage) + val newLang = if (appLanguage == "system") appInfo.systemLanguage else appLanguage + analytics.logEvent("language", "setting_changed" to newLang) + + updateLanguage(newLang) recreateView() } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt index 7fc20d23..80138175 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt @@ -8,6 +8,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.main.MainActivity +import io.github.wulkanowy.utils.openInternetBrowser import javax.inject.Inject @AndroidEntryPoint @@ -18,7 +19,7 @@ class SplashActivity : BaseActivity(), SplashView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - presenter.onAttachView(this) + presenter.onAttachView(this, intent?.getStringExtra("external_url")) } override fun openLoginView() { @@ -31,6 +32,11 @@ class SplashActivity : BaseActivity(), SplashView finish() } + override fun openExternalUrlAndFinish(url: String) { + openInternetBrowser(url, ::showMessage) + finish() + } + override fun showError(text: String, error: Throwable) { Toast.makeText(this, text, LENGTH_LONG).show() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt index d16ca4a8..79588917 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt @@ -1,7 +1,7 @@ package io.github.wulkanowy.ui.modules.splash import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.flowWithResource @@ -14,8 +14,13 @@ class SplashPresenter @Inject constructor( studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { - override fun onAttachView(view: SplashView) { + fun onAttachView(view: SplashView, externalUrl: String?) { super.onAttachView(view) + + if (!externalUrl.isNullOrBlank()) { + return view.openExternalUrlAndFinish(externalUrl) + } + flowWithResource { studentRepository.isCurrentStudentSet() }.onEach { when (it.status) { Status.LOADING -> Timber.d("Is current user set check started") diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt index 9efd8123..a5aa1409 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt @@ -7,4 +7,6 @@ interface SplashView : BaseView { fun openLoginView() fun openMainView() + + fun openExternalUrlAndFinish(url: String) } 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 4aa375c2..1bb9c920 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 @@ -16,6 +16,7 @@ import io.github.wulkanowy.databinding.FragmentTimetableBinding 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.timetable.additional.AdditionalLessonsFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.utils.SchooldaysRangeLimiter @@ -84,8 +85,11 @@ class TimetableFragment : BaseFragment(R.layout.fragme } override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.timetableMenuCompletedLessons) presenter.onCompletedLessonsSwitchSelected() - else false + return when (item.itemId) { + R.id.timetableMenuAdditionalLessons -> presenter.onAdditionalLessonsSwitchSelected() + R.id.timetableMenuCompletedLessons -> presenter.onCompletedLessonsSwitchSelected() + else -> false + } } override fun updateData(data: List, showWholeClassPlanType: String, showGroupsInPlanType: Boolean, showTimetableTimers: Boolean) { @@ -109,8 +113,8 @@ class TimetableFragment : BaseFragment(R.layout.fragme binding.timetableNavDate.text = date } - override fun hideRefresh() { - binding.timetableSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.timetableSwipe.isRefreshing = show } override fun resetView() { @@ -176,6 +180,10 @@ class TimetableFragment : BaseFragment(R.layout.fragme } } + override fun openAdditionalLessonsView() { + (activity as? MainActivity)?.pushView(AdditionalLessonsFragment.newInstance()) + } + override fun openCompletedLessonsView() { (activity as? MainActivity)?.pushView(CompletedLessonsFragment.newInstance()) } 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 0e913acf..3cd15bcf 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 @@ -3,10 +3,10 @@ package io.github.wulkanowy.ui.modules.timetable import android.annotation.SuppressLint import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.timetable.TimetableRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper @@ -34,7 +34,7 @@ class TimetablePresenter @Inject constructor( private val timetableRepository: TimetableRepository, private val semesterRepository: SemesterRepository, private val prefRepository: PreferencesRepository, - private val analytics: AnalyticsHelper + private val analytics: AnalyticsHelper, ) : BasePresenter(errorHandler, studentRepository) { private var baseDate: LocalDate = now().nextOrSameSchoolDay @@ -49,19 +49,19 @@ class TimetablePresenter @Inject constructor( view.initView() Timber.i("Timetable was initialized") errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) + loadData() if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() } fun onPreviousDay() { - loadData(currentDate.previousSchoolDay) - reloadView() + reloadView(currentDate.previousSchoolDay) + loadData() } fun onNextDay() { - loadData(currentDate.nextSchoolDay) - reloadView() + reloadView(currentDate.nextSchoolDay) + loadData() } fun onPickDate() { @@ -69,13 +69,13 @@ class TimetablePresenter @Inject constructor( } fun onDateSet(year: Int, month: Int, day: Int) { - loadData(of(year, month, day)) - reloadView() + reloadView(of(year, month, day)) + loadData() } fun onSwipeRefresh() { Timber.i("Force refreshing the timetable") - loadData(currentDate, true) + loadData(true) } fun onRetry() { @@ -83,7 +83,7 @@ class TimetablePresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(currentDate, true) + loadData(true) } fun onDetailsClick() { @@ -96,8 +96,8 @@ class TimetablePresenter @Inject constructor( if (view.currentStackSize == 1) { baseDate.also { if (currentDate != it) { - loadData(it) - reloadView() + reloadView(it) + loadData() } else if (!view.isViewEmpty) view.resetView() } } else view.popView() @@ -109,6 +109,11 @@ class TimetablePresenter @Inject constructor( view?.showTimetableDialog(lesson) } + fun onAdditionalLessonsSwitchSelected(): Boolean { + view?.openAdditionalLessonsView() + return true + } + fun onCompletedLessonsSwitchSelected(): Boolean { view?.openCompletedLessonsView() return true @@ -127,35 +132,38 @@ class TimetablePresenter @Inject constructor( }.launch("holidays") } - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - currentDate = date + private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading timetable data started") flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - timetableRepository.getTimetable(student, semester, date, date, forceRefresh) + timetableRepository.getTimetable(student, semester, currentDate, currentDate, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading timetable data started") + Status.LOADING -> { + if (!it.data?.first.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data!!.first) + } + } + } Status.SUCCESS -> { Timber.i("Loading timetable result: Success") view?.apply { - updateData( - showWholeClassPlanType = prefRepository.showWholeClassPlan, - showGroupsInPlanType = prefRepository.showGroupsInPlan, - showTimetableTimers = prefRepository.showTimetableTimers, - data = it.data!! - .filter { item -> if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true } - .sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan })) - ) - showEmpty(it.data.isEmpty()) + updateData(it.data!!.first) + showEmpty(it.data.first.isEmpty()) showErrorView(false) - showContent(it.data.isNotEmpty()) + showContent(it.data.first.isNotEmpty()) } analytics.logEvent( "load_data", "type" to "timetable", - "items" to it.data!!.size + "items" to it.data!!.first.size ) } Status.ERROR -> { @@ -165,13 +173,26 @@ class TimetablePresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } }.launch() } + private fun updateData(lessons: List) { + view?.updateData( + showWholeClassPlanType = prefRepository.showWholeClassPlan, + showGroupsInPlanType = prefRepository.showGroupsInPlan, + showTimetableTimers = prefRepository.showTimetableTimers, + data = createItems(lessons) + ) + } + + private fun createItems(items: List) = items.filter { item -> + if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true + }.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan })) + private fun showErrorViewOnError(message: String, error: Throwable) { view?.run { if (isViewEmpty) { @@ -183,7 +204,9 @@ class TimetablePresenter @Inject constructor( } } - private fun reloadView() { + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload timetable view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(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 24412017..c6bceb9e 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 @@ -18,7 +18,7 @@ interface TimetableView : BaseView { fun clearData() - fun hideRefresh() + fun showRefresh(show: Boolean) fun resetView() @@ -44,5 +44,7 @@ interface TimetableView : BaseView { fun popView() + fun openAdditionalLessonsView() + fun openCompletedLessonsView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsAdapter.kt new file mode 100644 index 00000000..fdc8b887 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsAdapter.kt @@ -0,0 +1,35 @@ +package io.github.wulkanowy.ui.modules.timetable.additional + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import io.github.wulkanowy.databinding.ItemTimetableAdditionalBinding +import io.github.wulkanowy.utils.toFormattedString +import javax.inject.Inject + +class AdditionalLessonsAdapter @Inject constructor() : + RecyclerView.Adapter() { + + var items = emptyList() + + override fun getItemCount() = items.size + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( + ItemTimetableAdditionalBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val item = items[position] + + with(holder.binding) { + additionalLessonItemTime.text = "${item.start.toFormattedString("HH:mm")} - ${item.end.toFormattedString("HH:mm")}" + additionalLessonItemSubject.text = item.subject + } + } + + class ItemViewHolder(val binding: ItemTimetableAdditionalBinding) : + RecyclerView.ViewHolder(binding.root) +} 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 new file mode 100644 index 00000000..17a1cabe --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt @@ -0,0 +1,144 @@ +package io.github.wulkanowy.ui.modules.timetable.additional + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import com.wdullaer.materialdatetimepicker.date.DatePickerDialog +import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import io.github.wulkanowy.databinding.FragmentTimetableAdditionalBinding +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.widgets.DividerItemDecoration +import io.github.wulkanowy.utils.SchooldaysRangeLimiter +import io.github.wulkanowy.utils.dpToPx +import java.time.LocalDate +import javax.inject.Inject + +@AndroidEntryPoint +class AdditionalLessonsFragment : + BaseFragment(R.layout.fragment_timetable_additional), + AdditionalLessonsView, MainView.TitledView { + + @Inject + lateinit var presenter: AdditionalLessonsPresenter + + @Inject + lateinit var additionalLessonsAdapter: AdditionalLessonsAdapter + + companion object { + private const val SAVED_DATE_KEY = "CURRENT_DATE" + + fun newInstance() = AdditionalLessonsFragment() + } + + override val titleStringId get() = R.string.additional_lessons_title + + override val isViewEmpty get() = additionalLessonsAdapter.items.isEmpty() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding = FragmentTimetableAdditionalBinding.bind(view) + messageContainer = binding.additionalLessonsRecycler + presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) + } + + override fun initView() { + with(binding.additionalLessonsRecycler) { + layoutManager = LinearLayoutManager(context) + adapter = additionalLessonsAdapter + addItemDecoration(DividerItemDecoration(context)) + } + + with(binding) { + additionalLessonsSwipe.setOnRefreshListener(presenter::onSwipeRefresh) + additionalLessonsErrorRetry.setOnClickListener { presenter.onRetry() } + + additionalLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() } + additionalLessonsNavDate.setOnClickListener { presenter.onPickDate() } + additionalLessonsNextButton.setOnClickListener { presenter.onNextDay() } + + additionalLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f)) + } + } + + override fun updateData(data: List) { + with(additionalLessonsAdapter) { + items = data + notifyDataSetChanged() + } + } + + override fun clearData() { + with(additionalLessonsAdapter) { + items = emptyList() + notifyDataSetChanged() + } + } + + override fun updateNavigationDay(date: String) { + binding.additionalLessonsNavDate.text = date + } + + override fun hideRefresh() { + binding.additionalLessonsSwipe.isRefreshing = false + } + + override fun showEmpty(show: Boolean) { + binding.additionalLessonsEmpty.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showErrorView(show: Boolean) { + binding.additionalLessonsError.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun setErrorDetails(message: String) { + binding.additionalLessonsErrorMessage.text = message + } + + override fun showProgress(show: Boolean) { + binding.additionalLessonsProgress.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun enableSwipe(enable: Boolean) { + binding.additionalLessonsSwipe.isEnabled = enable + } + + override fun showContent(show: Boolean) { + binding.additionalLessonsRecycler.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showPreButton(show: Boolean) { + binding.additionalLessonsPreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE + } + + override fun showNextButton(show: Boolean) { + binding.additionalLessonsNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE + } + + override fun showDatePickerDialog(currentDate: LocalDate) { + val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth -> + presenter.onDateSet(year, month + 1, dayOfMonth) + } + val datePickerDialog = DatePickerDialog.newInstance(dateSetListener, + currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth) + + with(datePickerDialog) { + setDateRangeLimiter(SchooldaysRangeLimiter()) + version = DatePickerDialog.Version.VERSION_2 + scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL + show(this@AdditionalLessonsFragment.parentFragmentManager, null) + } + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay()) + } + + override fun onDestroyView() { + presenter.onDetachView() + super.onDestroyView() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt new file mode 100644 index 00000000..623160e7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt @@ -0,0 +1,166 @@ +package io.github.wulkanowy.ui.modules.timetable.additional + +import android.annotation.SuppressLint +import io.github.wulkanowy.data.Status +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.TimetableRepository +import io.github.wulkanowy.ui.base.BasePresenter +import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.afterLoading +import io.github.wulkanowy.utils.flowWithResourceIn +import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday +import io.github.wulkanowy.utils.isHolidays +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 kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.onEach +import timber.log.Timber +import java.time.LocalDate +import javax.inject.Inject + +class AdditionalLessonsPresenter @Inject constructor( + studentRepository: StudentRepository, + errorHandler: ErrorHandler, + private val semesterRepository: SemesterRepository, + private val timetableRepository: TimetableRepository, + private val analytics: AnalyticsHelper +) : BasePresenter(errorHandler, studentRepository) { + + private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay + + lateinit var currentDate: LocalDate + private set + + private lateinit var lastError: Throwable + + fun onAttachView(view: AdditionalLessonsView, date: Long?) { + super.onAttachView(view) + view.initView() + Timber.i("Additional lessons was initialized") + errorHandler.showErrorMessage = ::showErrorViewOnError + loadData(LocalDate.ofEpochDay(date ?: baseDate.toEpochDay())) + if (currentDate.isHolidays) setBaseDateOnHolidays() + reloadView() + } + + fun onPreviousDay() { + loadData(currentDate.previousSchoolDay) + reloadView() + } + + fun onNextDay() { + loadData(currentDate.nextSchoolDay) + reloadView() + } + + fun onPickDate() { + view?.showDatePickerDialog(currentDate) + } + + fun onDateSet(year: Int, month: Int, day: Int) { + loadData(LocalDate.of(year, month, day)) + reloadView() + } + + fun onSwipeRefresh() { + Timber.i("Force refreshing the additional lessons") + loadData(currentDate, true) + } + + fun onRetry() { + view?.run { + showErrorView(false) + showProgress(true) + } + loadData(currentDate, 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(date: LocalDate, forceRefresh: Boolean = false) { + currentDate = date + + flowWithResourceIn { + val student = studentRepository.getCurrentStudent() + val semester = semesterRepository.getCurrentSemester(student) + timetableRepository.getTimetable(student, semester, date, date, forceRefresh, true) + }.onEach { + when (it.status) { + Status.LOADING -> Timber.i("Loading additional lessons data started") + Status.SUCCESS -> { + Timber.i("Loading additional lessons lessons result: Success") + view?.apply { + updateData(it.data!!.second.sortedBy { item -> item.date }) + showEmpty(it.data.second.isEmpty()) + showErrorView(false) + showContent(it.data.second.isNotEmpty()) + } + analytics.logEvent( + "load_data", + "type" to "additional_lessons", + "items" to it.data!!.second.size + ) + } + Status.ERROR -> { + Timber.i("Loading additional lessons result: An exception occurred") + errorHandler.dispatch(it.error!!) + } + } + }.afterLoading { + view?.run { + hideRefresh() + showProgress(false) + enableSwipe(true) + } + }.launch() + } + + private fun showErrorViewOnError(message: String, error: Throwable) { + view?.run { + if (isViewEmpty) { + lastError = error + setErrorDetails(message) + showErrorView(true) + showEmpty(false) + } else showError(message, error) + } + } + + private fun reloadView() { + Timber.i("Reload additional lessons view with the date ${currentDate.toFormattedString()}") + view?.apply { + showProgress(true) + enableSwipe(false) + showContent(false) + showEmpty(false) + showErrorView(false) + clearData() + reloadNavigation() + } + } + + @SuppressLint("DefaultLocale") + private fun reloadNavigation() { + view?.apply { + showPreButton(!currentDate.minusDays(1).isHolidays) + showNextButton(!currentDate.plusDays(1).isHolidays) + updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalize()) + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsView.kt new file mode 100644 index 00000000..97eb2ae7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsView.kt @@ -0,0 +1,38 @@ +package io.github.wulkanowy.ui.modules.timetable.additional + +import io.github.wulkanowy.data.db.entities.TimetableAdditional +import io.github.wulkanowy.ui.base.BaseView +import java.time.LocalDate + +interface AdditionalLessonsView : BaseView { + + val isViewEmpty: Boolean + + fun initView() + + fun updateData(data: List) + + fun clearData() + + fun updateNavigationDay(date: String) + + fun hideRefresh() + + fun showEmpty(show: Boolean) + + fun showErrorView(show: Boolean) + + fun setErrorDetails(message: String) + + fun showProgress(show: Boolean) + + fun enableSwipe(enable: Boolean) + + fun showContent(show: Boolean) + + fun showPreButton(show: Boolean) + + fun showNextButton(show: Boolean) + + fun showDatePickerDialog(currentDate: LocalDate) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsErrorHandler.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsErrorHandler.kt index 767c2f31..00ba0bad 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsErrorHandler.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsErrorHandler.kt @@ -1,15 +1,11 @@ package io.github.wulkanowy.ui.modules.timetable.completed import android.content.res.Resources -import com.chuckerteam.chucker.api.ChuckerCollector import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException import io.github.wulkanowy.ui.base.ErrorHandler import javax.inject.Inject -class CompletedLessonsErrorHandler @Inject constructor( - resources: Resources, - chuckerCollector: ChuckerCollector -) : ErrorHandler(resources, chuckerCollector) { +class CompletedLessonsErrorHandler @Inject constructor(resources: Resources) : ErrorHandler(resources) { var onFeatureDisabled: () -> Unit = {} 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 5b77fc1f..828e1001 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 @@ -89,8 +89,8 @@ class CompletedLessonsFragment : binding.completedLessonsNavDate.text = date } - override fun hideRefresh() { - binding.completedLessonsSwipe.isRefreshing = false + override fun showRefresh(show: Boolean) { + binding.completedLessonsSwipe.isRefreshing = show } override fun showEmpty(show: Boolean) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt index e5551ed5..04e2a5cd 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt @@ -3,9 +3,9 @@ package io.github.wulkanowy.ui.modules.timetable.completed import android.annotation.SuppressLint import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.CompletedLessonsRepository +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.utils.AnalyticsHelper import io.github.wulkanowy.utils.afterLoading @@ -50,19 +50,19 @@ class CompletedLessonsPresenter @Inject constructor( this.view?.showEmpty(true) Timber.i("Completed lessons feature disabled by school") } - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) + reloadView(ofEpochDay(date ?: baseDate.toEpochDay())) + loadData() if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() } fun onPreviousDay() { - loadData(currentDate.previousSchoolDay) - reloadView() + reloadView(currentDate.previousSchoolDay) + loadData() } fun onNextDay() { - loadData(currentDate.nextSchoolDay) - reloadView() + reloadView(currentDate.nextSchoolDay) + loadData() } fun onPickDate() { @@ -70,13 +70,13 @@ class CompletedLessonsPresenter @Inject constructor( } fun onDateSet(year: Int, month: Int, day: Int) { - loadData(LocalDate.of(year, month, day)) - reloadView() + reloadView(LocalDate.of(year, month, day)) + loadData() } fun onSwipeRefresh() { Timber.i("Force refreshing the completed lessons") - loadData(currentDate, true) + loadData(true) } fun onRetry() { @@ -84,7 +84,7 @@ class CompletedLessonsPresenter @Inject constructor( showErrorView(false) showProgress(true) } - loadData(currentDate, true) + loadData(true) } fun onDetailsClick() { @@ -109,16 +109,26 @@ class CompletedLessonsPresenter @Inject constructor( }.launch("holidays") } - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - currentDate = date + private fun loadData(forceRefresh: Boolean = false) { + Timber.i("Loading completed lessons data started") flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - completedLessonsRepository.getCompletedLessons(student, semester, date, date, forceRefresh) + completedLessonsRepository.getCompletedLessons(student, semester, currentDate, currentDate, forceRefresh) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Loading completed lessons data started") + Status.LOADING -> { + if (!it.data.isNullOrEmpty()) { + view?.run { + enableSwipe(true) + showRefresh(true) + showProgress(false) + showContent(true) + updateData(it.data.sortedBy { item -> item.number }) + } + } + } Status.SUCCESS -> { Timber.i("Loading completed lessons lessons result: Success") view?.apply { @@ -140,7 +150,7 @@ class CompletedLessonsPresenter @Inject constructor( } }.afterLoading { view?.run { - hideRefresh() + showRefresh(false) showProgress(false) enableSwipe(true) } @@ -158,7 +168,9 @@ class CompletedLessonsPresenter @Inject constructor( } } - private fun reloadView() { + private fun reloadView(date: LocalDate) { + currentDate = date + Timber.i("Reload completed lessons view with the date ${currentDate.toFormattedString()}") view?.apply { showProgress(true) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt index 7e92cc63..7a98874e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt @@ -16,7 +16,7 @@ interface CompletedLessonsView : BaseView { fun updateNavigationDay(date: String) - fun hideRefresh() + fun showRefresh(show: Boolean) fun showEmpty(show: Boolean) 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 2274ecb9..67805fe0 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 @@ -3,7 +3,7 @@ package io.github.wulkanowy.ui.modules.timetablewidget import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey 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 c7b4d4a8..df656c00 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 @@ -14,10 +14,10 @@ import android.widget.RemoteViewsService import io.github.wulkanowy.R import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.timetable.TimetableRepository +import io.github.wulkanowy.data.repositories.PreferencesRepository +import io.github.wulkanowy.data.repositories.SemesterRepository +import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getCurrentThemeWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey @@ -107,7 +107,7 @@ class TimetableWidgetFactory( val semester = semesterRepository.getCurrentSemester(student) timetableRepository.getTimetable(student, semester, date, date, false) - .toFirstResult().data.orEmpty() + .toFirstResult().data?.first.orEmpty() .sortedWith(compareBy({ it.number }, { !it.isStudentPlan })) .filter { if (prefRepository.showWholeClassPlan == "no") it.isStudentPlan else true } } 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 18e0ea56..938be98d 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 @@ -19,7 +19,7 @@ import io.github.wulkanowy.R import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.HiltBroadcastReceiver import io.github.wulkanowy.services.widgets.TimetableWidgetService import io.github.wulkanowy.ui.modules.main.MainActivity diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 724458c0..2d074b22 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -18,7 +18,7 @@ inline fun networkBoundResource( crossinline query: () -> Flow, crossinline fetch: suspend (ResultType) -> RequestType, crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, - crossinline onFetchFailed: (Throwable) -> Unit = { Unit }, + crossinline onFetchFailed: (Throwable) -> Unit = { }, crossinline shouldFetch: (ResultType) -> Boolean = { true }, crossinline filterResult: (ResultType) -> ResultType = { it } ) = flow { @@ -29,7 +29,8 @@ inline fun networkBoundResource( if (showSavedOnLoading) emit(Resource.loading(filterResult(data))) try { - saveFetchResult(data, fetch(data)) + val newData = fetch(data) + saveFetchResult(data, newData) query().map { Resource.success(filterResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) @@ -83,7 +84,7 @@ fun flowWithResourceIn(block: suspend () -> Flow>) = flow { block() .catch { emit(Resource.error(it)) } .collect { - if (it.status != Status.LOADING) { // LOADING is already emitted + if (it.status != Status.LOADING || (it.status == Status.LOADING && it.data != null)) { // LOADING without data is already emitted emit(it) } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt new file mode 100644 index 00000000..cd59b864 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt @@ -0,0 +1,50 @@ +package io.github.wulkanowy.utils + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import io.github.wulkanowy.R +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.enums.MessageFolder +import timber.log.Timber +import java.time.LocalDate +import java.time.LocalDateTime +import javax.inject.Inject + +fun getRefreshKey(name: String, semester: Semester, start: LocalDate, end: LocalDate): String { + return "${name}_${semester.studentId}_${semester.semesterId}_${start.monday}_${end.sunday}" +} + +fun getRefreshKey(name: String, semester: Semester): String { + return "${name}_${semester.studentId}_${semester.semesterId}" +} + +fun getRefreshKey(name: String, student: Student): String { + return "${name}_${student.userLoginId}" +} + +fun getRefreshKey(name: String, student: Student, folder: MessageFolder): String { + return "${name}_${student.id}_${folder.id}" +} + +class AutoRefreshHelper @Inject constructor( + @ApplicationContext private val context: Context, + private val sharedPref: SharedPrefProvider +) { + + fun isShouldBeRefreshed(key: String): Boolean { + val timestamp = sharedPref.getLong(key, 0).toLocalDateTime() + val servicesInterval = sharedPref.getString(context.getString(R.string.pref_key_services_interval), context.getString(R.string.pref_default_services_interval)).toLong() + + val shouldBeRefreshed = timestamp < LocalDateTime.now().minusMinutes(servicesInterval) + + Timber.d("Check if $key need to be refreshed: $shouldBeRefreshed (last refresh: $timestamp, interval: $servicesInterval min)") + + return shouldBeRefreshed + } + + fun updateLastRefreshTimestamp(key: String) { + sharedPref.putLong(key, LocalDateTime.now().toTimestamp()) + } +} 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 908a97d5..4499fa0f 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,8 @@ -Wersja 0.23.1 -- naprawiliśmy opis pola na email/login przy wyborze niestandardowych dzienników -- naprawiliśmy obsługę dziennika lubelskiego i koszalińskiego na starszych urządzeniach (z Androidem 5 i starszymi) +Wersja 0.24.0 +- naprawiliśmy niekończące się ładowanie w ocenach na drugim semestrze +- naprawiliśmy ciemny motyw na MIUI 12 +- dodaliśmy automatyczne odświeżanie danych w aplikacji +- naprawiliśmy wysyłanie wiadomości kiedy uczeń zalogowany był/jest przez konto ucznia i rodzica +- dodaliśmy zakładkę lekcji dodatkowych (na górnym pasku w planie lekcji) Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases diff --git a/app/src/main/res/drawable/ic_menu_timetable_lessons_additional.xml b/app/src/main/res/drawable/ic_menu_timetable_lessons_additional.xml new file mode 100644 index 00000000..169395e9 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_timetable_lessons_additional.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_timetable_additional.xml b/app/src/main/res/layout/fragment_timetable_additional.xml new file mode 100644 index 00000000..d70306c9 --- /dev/null +++ b/app/src/main/res/layout/fragment_timetable_additional.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_timetable_additional.xml b/app/src/main/res/layout/item_timetable_additional.xml new file mode 100644 index 00000000..cc39db5d --- /dev/null +++ b/app/src/main/res/layout/item_timetable_additional.xml @@ -0,0 +1,41 @@ + + + + + + + diff --git a/app/src/main/res/menu/action_menu_timetable.xml b/app/src/main/res/menu/action_menu_timetable.xml index c3d0222c..47257f5b 100644 --- a/app/src/main/res/menu/action_menu_timetable.xml +++ b/app/src/main/res/menu/action_menu_timetable.xml @@ -1,6 +1,13 @@ + Téma Nepřítomnost Zdroje + + Další lekce + Zobrazit další lekce + Žádné informace o dalších lekcích Souhrn docházky Nepřítomen ze školních důvodů @@ -211,6 +215,7 @@ Téma Obsah Zpráva úspěšně odeslána + Message does not exist Musíte vybrat alespoň 1 příjemce Obsah zprávy musí mít alespoň 3 znaky diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index a16b18e5..7ba35734 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -145,6 +145,10 @@ Thema Abwesenheit Ressourcen + + Additional lessons + Show additional lessons + No info about additional lessons Übersicht über die Schulbesuch Aus schulischen Gründen abwesend @@ -195,6 +199,7 @@ Thema Inhalt Nachricht erfolgreich gesendet + Message does not exist Sie müssen mindestens 1 Empfänger auswählen. Der Inhalt der Nachricht muss mindestens 3 Zeichen lang sein. diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index a06a46f0..32f7cdf1 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -1,6 +1,7 @@ -