diff --git a/.bettercodehub.yml b/.bettercodehub.yml index d7be51695..cce850d71 100644 --- a/.bettercodehub.yml +++ b/.bettercodehub.yml @@ -1,3 +1,5 @@ -component_depth: 10 +exclude: +- /app/src/main/java/io/github/wulkanowy/data/db/dao/entities/.* +component_depth: 1 languages: -- kotlin +- java diff --git a/.circleci/config.yml b/.circleci/config.yml index ce2922ba3..841ff9e09 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,11 +7,11 @@ references: container_config: &container_config docker: - - image: circleci/android@sha256:5cdc8626cc6f13efe5ed982cdcdb432b0472f8740fed8743a6461e025ad6cdfc + - image: circleci/android:api-27-alpha working_directory: *workspace_root environment: environment: - _JAVA_OPTS: -Xmx3072m + JVM_OPTS: -Xmx3200m attach_workspace: &attach_workspace attach_workspace: @@ -25,8 +25,6 @@ jobs: build: <<: *container_config steps: - - run: | - curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash - checkout - restore_cache: <<: *general_cache_key @@ -35,10 +33,10 @@ jobs: command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true - run: name: Initial build - command: ./gradlew build -x test -x lint -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease -x packageRelease --no-daemon --stacktrace --console=plain -PdisablePreDex - - run: - name: Run FOSSA - command: fossa --no-ansi || true + command: ./gradlew build assembleDebug -x test -x lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex + - store_artifacts: + path: ./app/build/outputs/apk/ + destination: apks/ - persist_to_workspace: root: *workspace_root paths: @@ -56,7 +54,7 @@ jobs: <<: *general_cache_key - run: name: Run lint - command: ./gradlew lint -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease --no-daemon --stacktrace --console=plain -PdisablePreDex + command: ./gradlew lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex - store_artifacts: path: ./app/build/reports/ destination: lint_reports/app/ @@ -75,13 +73,16 @@ jobs: <<: *general_cache_key - run: name: Run app tests - command: ./gradlew :app:test :app:jacocoTestReport -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease --no-daemon --stacktrace --console=plain -PdisablePreDex + command: ./gradlew :app:test :app:jacocoTestReport -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex - run: name: Upload unit code coverage to codecov command: bash <(curl -s https://codecov.io/bash) -F app - store_artifacts: - path: ./app/build/reports/ - destination: reports/ + path: ./app/build/reports/tests/ + destination: tests_reports/ + - store_artifacts: + path: ./app/build/reports/jacoco/jacocoTestDebugUnitTestReport/ + destination: coverage_reports/ - store_test_results: path: ./app/build/test-results - persist_to_workspace: @@ -89,23 +90,42 @@ jobs: paths: - "./app/build/jacoco" + api-test: + <<: *container_config + steps: + - *attach_workspace + - restore_cache: + <<: *general_cache_key + - run: + name: Run api tests + command: ./gradlew :api:test :api:jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex + - run: + name: Upload code coverage to codecov + command: bash <(curl -s https://codecov.io/bash) -F api + - store_artifacts: + path: ./api/build/reports/tests/ + destination: tests_reports/ + - store_artifacts: + path: ./api/build/reports/jacoco/test/ + destination: coverage_reports/ + - store_test_results: + path: ./api/build/test-results + - persist_to_workspace: + root: *workspace_root + paths: + - "./api/build/jacoco" + instrumented: <<: *container_config steps: - *attach_workspace - - run: - name: Accept licenses - command: yes | sdkmanager --licenses && yes | sdkmanager --update - run: name: Setup emulator - command: sdkmanager "system-images;android-22;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-22;default;armeabi-v7a" + command: sdkmanager "system-images;android-19;google_apis;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;google_apis;armeabi-v7a" - run: name: Launch emulator command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on background: true - - run: - name: Change circle-android script file permissions - command: sudo chmod +rx /bin/circle-android - run: name: Wait emulator command: | @@ -114,13 +134,15 @@ jobs: # unlock the emulator screen sleep 30 adb shell input keyevent 82 + - run: + name: Clean project + command: ./gradlew clean --no-daemon --stacktrace --console=plain -PdisablePreDex - run: name: Run instrumented tests - command: ./gradlew clean createFdroidDebugCoverageReport jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex + command: ./gradlew createDebugCoverageReport --no-daemon --stacktrace --console=plain -PdisablePreDex - run: name: Collect logs from emulator command: adb logcat -d > ./app/build/reports/logcat_emulator.txt - when: always - run: name: Upload code covarage to codecov command: bash <(curl -s https://codecov.io/bash) -F instrumented @@ -145,66 +167,32 @@ jobs: command: ./gradlew jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex - run: name: Run sonarqube runner - command: if [ -z ${SONAR_HOST+x} ]; then echo "sonar scan skipped"; else ./gradlew -x test -x lint sonarqube -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=$CIRCLE_BRANCH --no-daemon --stacktrace --console=plain -PdisablePreDex; fi - command: "[[ -v CIRCLE_PR_NUMBER ]] && ./gradlew -x test -x lint sonarqube -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=$CIRCLE_BRANCH --no-daemon --stacktrace --console=plain -PdisablePreDex || true" - - deploy: - <<: *container_config - steps: - - *attach_workspace - - restore_cache: - <<: *general_cache_key - - run: - name: Decrypt keys - command: | - gpg --yes --batch --passphrase=$SERVICES_ENCRYPT_KEY ./app/src/release/google-services.json.gpg - openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12 - openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks - - run: - name: Publish release - command: ./gradlew publishPlayRelease --no-daemon --stacktrace --console=plain -PenableCrashlytics -PdisablePreDex + command: ./gradlew -x test -x lint sonarqube -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=$CIRCLE_BRANCH --no-daemon --stacktrace --console=plain -PdisablePreDex workflows: version: 2 - build-test-deploy: + build_check_tests: jobs: - - build: - filters: - tags: - only: /.*/ + - build - lint: - filters: - tags: - only: /.*/ requires: - build - app-test: - filters: - tags: - only: /.*/ + requires: + - build + - api-test: requires: - build - instrumented: - filters: - tags: - only: /.*/ + requires: + - build requires: - build - sonarcube: - filters: - tags: - only: /.*/ requires: - build - lint - app-test + - api-test - instrumented - - deploy: - requires: - - instrumented - filters: - tags: - only: /\d+\.\d+\.\d+/ - branches: - ignore: /.*/ diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 27d57f599..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ -## Co powinno się dziać - - -## Co się dzieje - - -## Jak to zrobić kolejny raz: - - 1. - 2. - 3. - -## Informacje o urządzeniu i dzienniku - - - Wersja aplikacji: - - Wersja Androida: - - Adres URL dziennika: diff --git a/.gitignore b/.gitignore index d3fb6e4e9..3b524b65e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,91 +1,38 @@ -# Created by https://www.gitignore.io +/captures +.externalNativeBuild + +## https://gist.github.com/iainconnor/8605514 # Built application files -*.apk -*.ap_ -*.aab +/build +/*/build/ -# Files for the ART/Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -bin/ -gen/ -out/ - -# Gradle files -.gradle/ -build/ +# Crashlytics configuations +com_crashlytics_export_strings.xml # Local configuration file (sdk path, etc) local.properties -# Proguard folder generated by Eclipse -proguard/ +# Gradle generated files +.gradle/ -# Log Files -*.log +# Signing files +.signing/ -# Android Studio Navigation editor temp files -.navigation/ - -# Android Studio captures folder -captures/ - -# IntelliJ configurations -*.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -.idea/caches -.idea/modules.xml -.idea/navEditor.xml -.idea/caches/ +# User-specific configurations +.idea/copyright/profiles_settings.xml .idea/libraries/ -.idea/shelf/ +.idea/inspectionProfiles/ .idea/.name .idea/compiler.xml -.idea/copyright/profiles_settings.xml .idea/encodings.xml .idea/misc.xml +.idea/modules.xml .idea/scopes/scope_settings.xml +.idea/tasks.xml .idea/vcs.xml -.idea/jsLibraryMappings.xml -.idea/datasources.xml -.idea/dataSources.ids -.idea/sqlDataSources.xml -.idea/dynamic.xml -.idea/uiDesigner.xml -.idea/runConfigurations.xml -.idea/discord.xml - -# Keystore files -*.jks -*.keystore -*.p12 - -# External native build folder generated in Android Studio 2.2 and later -.externalNativeBuild - -# Version control -vcs.xml - -# lint -lint/intermediates/ -lint/generated/ -lint/outputs/ -lint/tmp/ -lint/reports/ - -### Android Patch ### -gen-external-apklibs -output.json +.idea/workspace.xml +*.iml # OS-specific files .DS_Store @@ -95,21 +42,3 @@ output.json .Trashes ehthumbs.db Thumbs.db - -# Legacy Eclipse project files -.classpath -.project -.cproject -.settings/ - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.war -*.ear - -### AndroidStudio Patch ### - -!/gradle/wrapper/gradle-wrapper.jar -.idea/jarRepositories.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a84ac8396..d8fdd0587 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: circleci/android:api-28-alpha +image: circleci/android:api-27-alpha before_script: - export GRADLE_USER_HOME=`pwd`/.gradle @@ -12,7 +12,7 @@ build: script: - ./gradlew --no-daemon --stacktrace dependencies || true - ./gradlew --no-daemon --stacktrace assembleDebug - - mv app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk . + - mv app/build/outputs/apk/app-debug.apk . artifacts: name: "${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}-${CI_BUILD_ID}" paths: @@ -26,7 +26,7 @@ tests: - .gradle policy: pull script: - - ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease test + - ./gradlew --no-daemon --stacktrace test artifacts: paths: - app/build/reports/tests @@ -39,7 +39,7 @@ lint: - .gradle policy: pull script: - - ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesFdroidRelease -x fabricGenerateResourcesPlayRelease lint + - ./gradlew --no-daemon --stacktrace lint artifacts: paths: - app/build/reports diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 000000000..f5bd97e62 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,226 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index d66c3361f..000000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 0f7bc519d..000000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 000000000..48777522e --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 000000000..7f68460d8 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a24058083..000000000 --- a/.travis.yml +++ /dev/null @@ -1,63 +0,0 @@ -language: android -jdk: oraclejdk8 - -env: - global: - - ANDROID_API_LEVEL=29 - - ANDROID_BUILD_TOOLS_VERSION=29.0.3 - -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - -branches: - only: - - develop - - 0.19.0 - -android: - licenses: - - android-sdk-preview-license-.+ - - android-sdk-license-.+ - - google-gdk-license-.+ - components: - - tools - - platform-tools - # The BuildTools version used by your project - - build-tools-$ANDROID_BUILD_TOOLS_VERSION - # The SDK version used to compile your project - - android-$ANDROID_API_LEVEL - # Additional components - - extra-google-google_play_services - - extra-google-m2repository - - extra-android-m2repository - - addon-google_apis-google-$ANDROID_API_LEVEL - # Android emulator - - android-22 - - sys-img-armeabi-v7a-android-22 - -before_script: - # Launch emulator before the execution - - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a - - emulator -avd test -no-audio -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & - - "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | sudo bash" - -script: - - ./gradlew dependencies --stacktrace --daemon - - fossa --no-ansi || true - - ./gradlew -Pcoverage testPlayDebugUnitTest --stacktrace --daemon - - ./gradlew -Pcoverage createFdroidDebugCoverageReport --stacktrace --daemon - - ./gradlew -Pcoverage jacocoTestReport --stacktrace --daemon - - | - if [ $TRAVIS_TAG ]; then - 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; - ./gradlew publishPlayRelease -PenableFirebase --stacktrace; - fi - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/LICENSE b/LICENSE index 5dd9cacf7..f48b21143 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2019 Wulkanowy + Copyright 2017 wulkanowy Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 7444cccae..000000000 --- a/README.en.md +++ /dev/null @@ -1,61 +0,0 @@ -[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) -[![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/) -[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases) - -Unofficial android VULCAN UONET+ register client for both students and their parents - -## Features - -* logging in using the email and password OR using token and pin -* functions from the register website: - * grades - * grade statistics - * attendance - * percentage of attendance - * exams - * timetable - * completed lessons - * messages - * homework - * notes - * lucky number -* calculation of the average independently of school's preferences -* notifications, e.g. about a new grade -* dark and black (AMOLED) theme -* offline mode -* no ads - -## Download - -You can download the current beta version from the Google Play or the F-Droid store - -[Get it on Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy) -[Get it on F-Droid](https://f-droid.org/packages/io.github.wulkanowy/) - -You can also download a [development version](https://wulkanowy.github.io/#download) that includes new features being prepared for the next release - -## Built With - - -* [Wulkanowy SDK](https://github.com/wulkanowy/sdk) -* [RxJava 2](https://github.com/ReactiveX/RxJava) -* [Dagger 2](https://github.com/google/dagger) -* [Room](https://developer.android.com/topic/libraries/architecture/room) -* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) - -## Contributing - -Please contribute to the project either by creating a PR or submitting an issue on GitHub. - -## License - -This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details diff --git a/README.md b/README.md index 61b13444a..76a8d6e63 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,12 @@ -[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) -[![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/) -[![Last release](https://img.shields.io/github/release/wulkanowy/wulkanowy.svg?logo=github&style=flat-square)](https://github.com/wulkanowy/wulkanowy/releases) -Nieoficjalny klient dziennika VULCAN UONET+ dla ucznia i rodzica +[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy) +[![Dependency Status](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/5969ff0b0fb24f004f8c711b) +[![CircleCI](https://img.shields.io/circleci/project/github/wulkanowy/wulkanowy.svg?style=flat-square)](https://circleci.com/gh/wulkanowy/wulkanowy) +[![Bitrise](https://img.shields.io/bitrise/daeff1893f3c8128/master.svg?token=Hjm1ACamk86JDeVVJHOeqQ&style=flat-square)](https://www.bitrise.io/app/daeff1893f3c8128) +[![BCH compliance](https://bettercodehub.com/edge/badge/wulkanowy/wulkanowy?branch=master)](https://bettercodehub.com/) +[![Bintray](https://img.shields.io/bintray/v/wulkanowy/wulkanowy/api.svg?style=flat-square)](https://bintray.com/wulkanowy/wulkanowy/api) -## Funkcje +[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-release-bitrise-signed.apk) -* logowanie za pomocą e-maila i hasła LUB tokena i pinu -* funkcje ze strony internetowej dziennika: - * oceny - * statystyki ocen - * frekwencja - * procent frekwencji - * sprawdziany - * plan lekcji - * lekcje zrealizowane - * wiadomości - * zadania domowe - * uwagi - * szczęśliwy numerek -* obliczanie średniej niezależnie od preferencji szkoły -* powiadomienia np. o nowej ocenie -* ciemny i czarny (AMOLED) motyw -* tryb offilne -* brak reklam - -## Pobierz - -Aktualną wersję beta możesz pobrać ze sklepu Google Play lub F-Droid - -[Pobierz z Google Play](https://play.google.com/store/apps/details?id=io.github.wulkanowy) -[Pobierz z F-Droid](https://f-droid.org/packages/io.github.wulkanowy/) - - -Możesz także pobrać [wersję rozwojową](https://wulkanowy.github.io/#download), która zawiera nowe funkcje przygotowywane do następnego wydania - - -## Zbudowana za pomocą - -* [Wulkanowy SDK](https://github.com/wulkanowy/SDK) -* [RxJava 2](https://github.com/ReactiveX/RxJava) -* [Dagger 2](https://github.com/google/dagger) -* [Room](https://developer.android.com/topic/libraries/architecture/room) -* [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) - -## Współpraca - -Wnieś swój wkład w projekt, tworząc PR lub wysyłając issue na GitHub. - -## Licencja - -Ten projekt udostępniany jest na licencji Apache License 2.0 - szczegóły w pliku [LICENSE](LICENSE) +Wulkanowy to projekt aplikacji na androida ułatwiającej używanie dziennika VULCANa. diff --git a/app/sonarqube.gradle b/android-sonarqube.gradle similarity index 73% rename from app/sonarqube.gradle rename to android-sonarqube.gradle index 3dad10344..b9284eeac 100644 --- a/app/sonarqube.gradle +++ b/android-sonarqube.gradle @@ -4,13 +4,16 @@ sonarqube { //noinspection GroovyAssignabilityCheck properties { - def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-28/android.jar" + def files = fileTree("${rootProject.projectDir}/api/build/libs/").filter { it.isFile() }.files.name + def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-27/android.jar," + + "${project.rootDir}/api/build/libs/" + files[0] - property "sonar.projectName", "io.github.wulkanowy:app" - property "sonar.projectKey", "io.github.wulkanowy:app" + property "sonar.projectName", GROUP_ID + ":app" + property "sonar.projectKey", GROUP_ID + ":app" property "sonar.sources", "src/main/java" - property "sonar.exclusions", "build/**,**/*.png,*.iml, **/*generated*," + property "sonar.exclusions", "build/**,**/*.png,*.iml, **/*generated*," + + "src/**/entities/*.java, src/androidTest/**/entities/*.java" property "sonar.import_unknown_files", true // Defines where the java files are @@ -29,6 +32,5 @@ sonarqube { property "sonar.java.coveragePlugin", "jacoco" property "sonar.android.lint.report", "build/reports/lint-results.xml" property "sonar.jacoco.reportPaths", fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec']) - property "sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacocoTestReport/jacocoTestReport.xml" } } diff --git a/api/build.gradle b/api/build.gradle new file mode 100644 index 000000000..ebaca4c87 --- /dev/null +++ b/api/build.gradle @@ -0,0 +1,117 @@ +apply plugin: 'java-library' +apply plugin: 'org.sonarqube' +apply plugin: 'jacoco' +apply plugin: 'com.jfrog.bintray' +apply plugin: 'com.github.dcendents.android-maven' + +compileJava.options.encoding = "UTF-8" +compileTestJava.options.encoding = "UTF-8" + +ext { + PUBLISH_GROUP_ID = GROUP_ID + PUBLISH_ARTIFACT_ID = 'api' + PUBLISH_VERSION = System.getenv('GIT_TAG') +} + +test { + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true + } +} + +jacocoTestReport { + reports { + xml.enabled true + } +} + +dependencies { + implementation 'org.jsoup:jsoup:1.10.3' + implementation 'org.apache.commons:commons-lang3:3.7' + implementation 'com.google.code.gson:gson:2.8.2' + + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.13.0' +} + +version = PUBLISH_VERSION +group = GROUP_ID + +sonarqube { + properties { + property "sonar.projectName", GROUP_ID + ":api" + property "sonar.projectKey", GROUP_ID + ":wulkanowy-api" + } +} + +def siteUrl = 'https://github.com/wulkanowy/wulkanowy' +def gitUrl = 'https://github.com/wulkanowy/wulkanowy.git' + +bintray { + user = System.getenv('BINTRAY_USER') + key = System.getenv('BINTRAY_KEY') + configurations = ['archives'] + pkg { + repo = 'wulkanowy' + name = 'api' + userOrg = 'wulkanowy' + licenses = ['Apache-2.0'] + vcsUrl = gitUrl + labels = ['aar', 'android', 'wulkanowy', 'api'] + publicDownloadNumbers = true + publish = true + + version { + name = PUBLISH_VERSION + vcsTag = PUBLISH_VERSION + released = new Date() + } + } +} + +install { + repositories.mavenInstaller { + pom { + project { + packaging 'aar' + name 'Bintray publish Gradle aar' + url siteUrl + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + developers { + developer { + id 'mklkj' + name 'Mikołaj Pich' + email 'm.pich@outlook.com' + } + } + scm { + connection gitUrl + developerConnection gitUrl + url siteUrl + } + } + } + } +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +artifacts { + archives sourcesJar + archives javadocJar +} diff --git a/api/src/main/java/io/github/wulkanowy/api/Client.java b/api/src/main/java/io/github/wulkanowy/api/Client.java new file mode 100644 index 000000000..f7a663ecd --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/Client.java @@ -0,0 +1,104 @@ +package io.github.wulkanowy.api; + +import org.jsoup.Connection; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +import java.io.IOException; +import java.util.Map; + +public class Client { + + private String protocol; + + private String host; + + private String symbol; + + private Cookies cookies = new Cookies(); + + Client(String protocol, String host, String symbol) { + this.protocol = protocol; + this.host = host; + this.symbol = symbol; + } + + String getHost() { + return host; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + Map getCookies() { + return cookies.getItems(); + } + + private String getFilledUrl(String url) { + return url + .replace("{schema}", protocol) + .replace("{host}", host.replace(":", "%253A")) + .replace("{symbol}", symbol == null ? "Default" : symbol); + } + + Document getPageByUrl(String url) throws IOException { + Connection.Response response = Jsoup.connect(getFilledUrl(url)) + .followRedirects(true) + .cookies(getCookies()) + .execute(); + + this.cookies.addItems(response.cookies()); + + return response.parse(); + } + + public Document postPageByUrl(String url, String[][] params) throws IOException { + Connection connection = Jsoup.connect(getFilledUrl(url)); + + for (String[] data : params) { + connection.data(data[0], data[1]); + } + + Connection.Response response = connection + .followRedirects(true) + .method(Connection.Method.POST) + .cookies(getCookies()) + .execute(); + + this.cookies.addItems(response.cookies()); + + return response.parse(); + } + + public String getJsonStringByUrl(String url) throws IOException { + Connection.Response response = Jsoup.connect(getFilledUrl(url)) + .followRedirects(true) + .ignoreContentType(true) + .cookies(getCookies()) + .execute(); + + this.cookies.addItems(response.cookies()); + + return response.body(); + } + + public String postJsonStringByUrl(String url, String[][] params) throws IOException { + Connection connection = Jsoup.connect(getFilledUrl(url)); + + for (String[] data : params) { + connection.data(data[0], data[1]); + } + + Connection.Response response = connection + .followRedirects(true) + .ignoreContentType(true) + .method(Connection.Method.POST) + .cookies(getCookies()) + .execute(); + + this.cookies.addItems(response.cookies()); + + return response.body(); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/Cookies.java b/api/src/main/java/io/github/wulkanowy/api/Cookies.java new file mode 100644 index 000000000..c97d96588 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/Cookies.java @@ -0,0 +1,23 @@ +package io.github.wulkanowy.api; + +import java.util.HashMap; +import java.util.Map; + +public class Cookies { + + private Map jar = new HashMap<>(); + + public Map getItems() { + return jar; + } + + public Cookies setItems(Map items) { + this.jar = items; + return this; + } + + public Cookies addItems(Map items) { + this.jar.putAll(items); + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/Semester.java b/api/src/main/java/io/github/wulkanowy/api/Semester.java new file mode 100644 index 000000000..64a07c976 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/Semester.java @@ -0,0 +1,37 @@ +package io.github.wulkanowy.api; + +public class Semester { + + private String number = ""; + + private String id = ""; + + private boolean isCurrent = false; + + public String getNumber() { + return number; + } + + public Semester setNumber(String number) { + this.number = number; + return this; + } + + public String getId() { + return id; + } + + public Semester setId(String id) { + this.id = id; + return this; + } + + public boolean isCurrent() { + return isCurrent; + } + + public Semester setCurrent(boolean current) { + isCurrent = current; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/SnP.java b/api/src/main/java/io/github/wulkanowy/api/SnP.java new file mode 100644 index 000000000..614b77b60 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/SnP.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.io.IOException; +import java.util.List; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public interface SnP { + + String getId(); + + void storeContextCookies() throws IOException, NotLoggedInErrorException; + + String getRowDataChildValue(Element e, int index); + + Document getSnPPageDocument(String url) throws IOException; + + List getSemesters() throws IOException; + + List getSemesters(Document gradesPage); + + Semester getCurrentSemester(List semesterList); +} diff --git a/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java b/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java new file mode 100644 index 000000000..a8d619136 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java @@ -0,0 +1,119 @@ +package io.github.wulkanowy.api; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public class StudentAndParent implements SnP { + + private static final String START_PAGE_URL = "{schema}://uonetplus.{host}/{symbol}/Start.mvc/Index"; + + private static final String BASE_URL = "{schema}://uonetplus-opiekun.{host}/{symbol}/{ID}/"; + + private static final String GRADES_PAGE_URL = "Oceny/Wszystkie"; + + private Client client; + + private String id; + + StudentAndParent(Client client) { + this.client = client; + } + + StudentAndParent(Client client, String id) { + this(client); + this.id = id; + } + + private String getBaseUrl() { + return BASE_URL.replace("{ID}", getId()); + } + + public String getId() { + return id; + } + + public void storeContextCookies() throws IOException, NotLoggedInErrorException { + client.getPageByUrl(getSnpHomePageUrl()); + } + + String getSnpHomePageUrl() throws IOException, NotLoggedInErrorException { + if (null != getId()) { + return getBaseUrl(); + } + + // get url to uonetplus-opiekun.vulcan.net.pl + Document startPage = client.getPageByUrl(START_PAGE_URL); + Element studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a").first(); + + if (null == studentTileLink) { + throw new NotLoggedInErrorException(); + } + + String snpPageUrl = studentTileLink.attr("href"); + + this.id = getExtractedIdFromUrl(snpPageUrl); + + return snpPageUrl; + } + + String getExtractedIdFromUrl(String snpPageUrl) throws NotLoggedInErrorException { + String[] path = snpPageUrl.split(client.getHost())[1].split("/"); + + if (5 != path.length) { + throw new NotLoggedInErrorException(); + } + + return path[2]; + } + + public String getRowDataChildValue(Element e, int index) { + return e.select(".daneWiersz .wartosc").get(index - 1).text(); + } + + public Document getSnPPageDocument(String url) throws IOException { + return client.getPageByUrl(getBaseUrl() + url); + } + + public List getSemesters() throws IOException { + return getSemesters(getSnPPageDocument(GRADES_PAGE_URL)); + } + + public List getSemesters(Document gradesPage) { + Elements semesterOptions = gradesPage.select("#okresyKlasyfikacyjneDropDownList option"); + + List semesters = new ArrayList<>(); + + for (Element e : semesterOptions) { + Semester semester = new Semester() + .setId(e.text()) + .setNumber(e.attr("value")); + + if ("selected".equals(e.attr("selected"))) { + semester.setCurrent(true); + } + + semesters.add(semester); + } + + return semesters; + } + + public Semester getCurrentSemester(List semesterList) { + Semester current = null; + for (Semester s : semesterList) { + if (s.isCurrent()) { + current = s; + break; + } + } + + return current; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/Vulcan.java b/api/src/main/java/io/github/wulkanowy/api/Vulcan.java new file mode 100644 index 000000000..a44e868f7 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/Vulcan.java @@ -0,0 +1,196 @@ +package io.github.wulkanowy.api; + +import java.io.IOException; + +import io.github.wulkanowy.api.attendance.AttendanceStatistics; +import io.github.wulkanowy.api.attendance.AttendanceTable; +import io.github.wulkanowy.api.exams.ExamsWeek; +import io.github.wulkanowy.api.grades.GradesList; +import io.github.wulkanowy.api.grades.SubjectsList; +import io.github.wulkanowy.api.login.AccountPermissionException; +import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.api.login.Login; +import io.github.wulkanowy.api.login.LoginErrorException; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.api.login.VulcanOfflineException; +import io.github.wulkanowy.api.messages.Messages; +import io.github.wulkanowy.api.notes.AchievementsList; +import io.github.wulkanowy.api.notes.NotesList; +import io.github.wulkanowy.api.school.SchoolInfo; +import io.github.wulkanowy.api.school.TeachersInfo; +import io.github.wulkanowy.api.timetable.Timetable; +import io.github.wulkanowy.api.user.BasicInformation; +import io.github.wulkanowy.api.user.FamilyInformation; + +public class Vulcan { + + private String id; + + private String symbol; + + private SnP snp; + + private String protocolSchema = "https"; + + private String logHost = "vulcan.net.pl"; + + private String email; + + private Client client; + + private Login login; + + public void setClient(Client client) { + this.client = client; + } + + public void setLogin(Login login) { + this.login = login; + } + + public void login(String email, String password, String symbol) + throws BadCredentialsException, AccountPermissionException, + LoginErrorException, IOException, VulcanOfflineException { + + setFullEndpointInfo(email); + login = getLogin(); + + this.symbol = login.login(this.email, password, symbol); + } + + public Vulcan login(String email, String password, String symbol, String id) + throws BadCredentialsException, AccountPermissionException, + LoginErrorException, IOException, VulcanOfflineException { + login(email, password, symbol); + + this.id = id; + + return this; + } + + String getProtocolSchema() { + return protocolSchema; + } + + String getLogHost() { + return logHost; + } + + public String getEmail() { + return email; + } + + public String getSymbol() { + return symbol; + } + + private void setFullEndpointInfo(String email) { + String[] creds = email.split("\\\\"); + + this.email = email; + + if (creds.length >= 2) { + String[] url = creds[0].split("://"); + + this.protocolSchema = url[0]; + this.logHost = url[1]; + this.email = creds[2]; + } + } + + protected Client getClient() { + if (null != client) { + return client; + } + + client = new Client(getProtocolSchema(), getLogHost(), symbol); + + return client; + } + + protected Login getLogin() { + if (null != login) { + return login; + } + + login = new Login(getClient()); + + return login; + } + + public SnP getStudentAndParent() throws IOException, NotLoggedInErrorException { + if (0 == getClient().getCookies().size()) { + throw new NotLoggedInErrorException(); + } + + if (null != snp) { + return snp; + } + + snp = createSnp(getClient(), id); + + snp.storeContextCookies(); + + return snp; + } + + SnP createSnp(Client client, String id) { + if (null == id) { + return new StudentAndParent(client); + } + + return new StudentAndParent(client, id); + } + + public AttendanceStatistics getAttendanceStatistics() throws IOException, NotLoggedInErrorException { + return new AttendanceStatistics(getStudentAndParent()); + } + + public AttendanceTable getAttendanceTable() throws IOException, NotLoggedInErrorException { + return new AttendanceTable(getStudentAndParent()); + } + + public ExamsWeek getExamsList() throws IOException, NotLoggedInErrorException { + return new ExamsWeek(getStudentAndParent()); + } + + public GradesList getGradesList() throws IOException, NotLoggedInErrorException { + return new GradesList(getStudentAndParent()); + } + + public SubjectsList getSubjectsList() throws IOException, NotLoggedInErrorException { + return new SubjectsList(getStudentAndParent()); + } + + public AchievementsList getAchievementsList() throws IOException, NotLoggedInErrorException { + return new AchievementsList(getStudentAndParent()); + } + + public NotesList getNotesList() throws IOException, NotLoggedInErrorException { + return new NotesList(getStudentAndParent()); + } + + public SchoolInfo getSchoolInfo() throws IOException, NotLoggedInErrorException { + return new SchoolInfo(getStudentAndParent()); + } + + public TeachersInfo getTeachersInfo() throws IOException, NotLoggedInErrorException { + return new TeachersInfo(getStudentAndParent()); + } + + public Timetable getTimetable() throws IOException, NotLoggedInErrorException { + return new Timetable(getStudentAndParent()); + } + + public BasicInformation getBasicInformation() throws IOException, NotLoggedInErrorException { + return new BasicInformation(getStudentAndParent()); + } + + public FamilyInformation getFamilyInformation() throws IOException, NotLoggedInErrorException { + return new FamilyInformation(getStudentAndParent()); + } + + public Messages getMessages() { + return new Messages(getClient()); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceStatistics.java b/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceStatistics.java new file mode 100644 index 000000000..023a436e4 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceStatistics.java @@ -0,0 +1,88 @@ +package io.github.wulkanowy.api.attendance; + +import org.apache.commons.lang3.math.NumberUtils; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; +import io.github.wulkanowy.api.generic.Month; +import io.github.wulkanowy.api.generic.Subject; + +public class AttendanceStatistics { + + private SnP snp; + + private String attendancePageUrl = "Frekwencja.mvc"; + + public AttendanceStatistics(SnP snp) { + this.snp = snp; + } + + public Types getTypesTable() throws IOException { + return getTypesTable(""); + } + + public Types getTypesTable(String tick) throws IOException { + return getTypesTable(tick, -1); + } + + public List getSubjectList() throws IOException { + Element mainContainer = snp.getSnPPageDocument(attendancePageUrl) + .select(".mainContainer #idPrzedmiot").first(); + + List subjectList = new ArrayList<>(); + + for (Element subject : mainContainer.select("option")) { + subjectList.add(new Subject() + .setId(Integer.parseInt(subject.attr("value"))) + .setName(subject.text()) + ); + } + + return subjectList; + } + + public Types getTypesTable(String tick, Integer subjectId) throws IOException { + Element mainContainer = snp.getSnPPageDocument((attendancePageUrl + + "?data={tick}&idPrzedmiot={subject}") + .replace("{tick}", tick) + .replace("{subject}", subjectId.toString()) + ).select(".mainContainer").first(); + + Element table = mainContainer.select("table:nth-of-type(2)").first(); + + Elements headerCells = table.select("thead th"); + List typeList = new ArrayList<>(); + + Elements typesRows = table.select("tbody tr"); + + // fill types with months + for (Element row : typesRows) { + Elements monthsCells = row.select("td"); + + List monthList = new ArrayList<>(); + + // iterate over month in type, first column is empty, last is `total`; (0, n-1) + for (int i = 1; i < monthsCells.size() - 1; i++) { + monthList.add(new Month() + .setValue(NumberUtils.toInt(monthsCells.get(i).text(), 0)) + .setName(headerCells.get(i).text())); + } + + typeList.add(new Type() + .setTotal(NumberUtils.toInt(monthsCells.last().text(), 0)) + .setName(monthsCells.get(0).text()) + .setMonthList(monthList)); + } + + String total = mainContainer.select("h2").text().split(": ")[1]; + + return new Types() + .setTotal(NumberUtils.toDouble(total.replace("%", "").replace(",", "."))) + .setTypeList(typeList); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceTable.java b/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceTable.java new file mode 100644 index 000000000..7c9fc27f5 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/attendance/AttendanceTable.java @@ -0,0 +1,101 @@ +package io.github.wulkanowy.api.attendance; + +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; +import io.github.wulkanowy.api.generic.Day; +import io.github.wulkanowy.api.generic.Lesson; +import io.github.wulkanowy.api.generic.Week; + +public class AttendanceTable { + + private SnP snp; + + private String attendancePageUrl = "Frekwencja.mvc?data="; + + public AttendanceTable(SnP snp) { + this.snp = snp; + } + + public Week getWeekTable() throws IOException { + return getWeekTable(""); + } + + public Week getWeekTable(String tick) throws IOException { + Element table = snp.getSnPPageDocument(attendancePageUrl + tick) + .select(".mainContainer .presentData").first(); + + Elements headerCells = table.select("thead th"); + List days = new ArrayList<>(); + + for (int i = 1; i < headerCells.size(); i++) { + days.add(new Day().setDate(headerCells.get(i).html().split("
")[1])); + } + + Elements hoursInDays = table.select("tbody tr"); + + // fill days in week with lessons + for (Element row : hoursInDays) { + Elements hours = row.select("td"); + + // fill hours in day + int size = hours.size(); + for (int i = 1; i < size; i++) { + days.get(i - 1).setLesson(getNewLesson(hours.get(i))); + } + } + + String[] dayDescription = headerCells.get(1).html().split("
"); + + return new Week() + .setStartDayDate(dayDescription[1]) + .setDays(days); + } + + private Lesson getNewLesson(Element cell) { + Lesson lesson = new Lesson(); + lesson.setSubject(cell.select("span").text()); + + if (LessonTypes.CLASS_NOT_EXIST.equals(cell.attr("class"))) { + lesson.setNotExist(true); + lesson.setEmpty(true); + + return lesson; + } + + switch (cell.select("div").attr("class")) { + case LessonTypes.CLASS_PRESENCE: + lesson.setPresence(true); + break; + case LessonTypes.CLASS_ABSENCE_UNEXCUSED: + lesson.setAbsenceUnexcused(true); + break; + case LessonTypes.CLASS_ABSENCE_EXCUSED: + lesson.setAbsenceExcused(true); + break; + case LessonTypes.CLASS_ABSENCE_FOR_SCHOOL_REASONS: + lesson.setAbsenceForSchoolReasons(true); + break; + case LessonTypes.CLASS_UNEXCUSED_LATENESS: + lesson.setUnexcusedLateness(true); + break; + case LessonTypes.CLASS_EXCUSED_LATENESS: + lesson.setExcusedLateness(true); + break; + case LessonTypes.CLASS_EXEMPTION: + lesson.setExemption(true); + break; + + default: + lesson.setEmpty(true); + break; + } + + return lesson; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/attendance/LessonTypes.java b/api/src/main/java/io/github/wulkanowy/api/attendance/LessonTypes.java new file mode 100644 index 000000000..a9a1fac4e --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/attendance/LessonTypes.java @@ -0,0 +1,24 @@ +package io.github.wulkanowy.api.attendance; + +class LessonTypes { + + static final String CLASS_NOT_EXIST = "x-sp-nieobecny-w-oddziale"; + + static final String CLASS_PRESENCE = "x-obecnosc"; + + static final String CLASS_ABSENCE_UNEXCUSED = "x-nieobecnosc-nieuspr"; + + static final String CLASS_ABSENCE_EXCUSED = "x-nieobecnosc-uspr"; + + static final String CLASS_ABSENCE_FOR_SCHOOL_REASONS = "x-nieobecnosc-przycz-szkol"; + + static final String CLASS_UNEXCUSED_LATENESS = "x-sp-nieusprawiedliwione"; + + static final String CLASS_EXCUSED_LATENESS = "x-sp-spr"; + + static final String CLASS_EXEMPTION = "x-sp-zwolnienie"; + + private LessonTypes() { + throw new IllegalStateException("Utility class"); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/attendance/Type.java b/api/src/main/java/io/github/wulkanowy/api/attendance/Type.java new file mode 100644 index 000000000..6deb003e1 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/attendance/Type.java @@ -0,0 +1,42 @@ +package io.github.wulkanowy.api.attendance; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.generic.Month; + +public class Type { + + private String name = ""; + + private int total = 0; + + private List monthList = new ArrayList<>(); + + public String getName() { + return name; + } + + public Type setName(String name) { + this.name = name; + return this; + } + + public int getTotal() { + return total; + } + + public Type setTotal(int total) { + this.total = total; + return this; + } + + public List getMonthList() { + return monthList; + } + + public Type setMonthList(List monthList) { + this.monthList = monthList; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/attendance/Types.java b/api/src/main/java/io/github/wulkanowy/api/attendance/Types.java new file mode 100644 index 000000000..d1b1777de --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/attendance/Types.java @@ -0,0 +1,29 @@ +package io.github.wulkanowy.api.attendance; + +import java.util.ArrayList; +import java.util.List; + +public class Types { + + private double total = 0; + + private List typeList = new ArrayList<>(); + + public double getTotal() { + return total; + } + + public Types setTotal(double total) { + this.total = total; + return this; + } + + public List getTypeList() { + return typeList; + } + + public Types setTypeList(List typeList) { + this.typeList = typeList; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/exams/Exam.java b/api/src/main/java/io/github/wulkanowy/api/exams/Exam.java new file mode 100644 index 000000000..466bfe4f7 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/exams/Exam.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.api.exams; + +public class Exam { + + private String subjectAndGroup = ""; + + private String type = ""; + + private String description = ""; + + private String teacher = ""; + + private String entryDate = ""; + + public String getSubjectAndGroup() { + return subjectAndGroup; + } + + public Exam setSubjectAndGroup(String subjectAndGroup) { + this.subjectAndGroup = subjectAndGroup; + return this; + } + + public String getType() { + return type; + } + + public Exam setType(String type) { + this.type = type; + return this; + } + + public String getDescription() { + return description; + } + + public Exam setDescription(String description) { + this.description = description; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Exam setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getEntryDate() { + return entryDate; + } + + public Exam setEntryDate(String entryDate) { + this.entryDate = entryDate; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/exams/ExamDay.java b/api/src/main/java/io/github/wulkanowy/api/exams/ExamDay.java new file mode 100644 index 000000000..8127e631e --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/exams/ExamDay.java @@ -0,0 +1,19 @@ +package io.github.wulkanowy.api.exams; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.generic.Day; + +public class ExamDay extends Day { + + private List examList = new ArrayList<>(); + + public List getExamList() { + return examList; + } + + public void addExam(Exam exam) { + this.examList.add(exam); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java b/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java new file mode 100644 index 000000000..b4921b8b0 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java @@ -0,0 +1,64 @@ +package io.github.wulkanowy.api.exams; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; +import io.github.wulkanowy.api.generic.Week; + +public class ExamsWeek { + + private static final String EXAMS_PAGE_URL = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data="; + + private final SnP snp; + + public ExamsWeek(SnP snp) { + this.snp = snp; + } + + public Week getCurrent() throws IOException { + return getWeek("", true); + } + + public Week getWeek(String tick, final boolean onlyNotEmpty) throws IOException { + Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick); + Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)"); + + List days = new ArrayList<>(); + + for (Element item : examsDays) { + ExamDay day = new ExamDay(); + Element dayHeading = item.select("h2").first(); + + if (null == dayHeading && onlyNotEmpty) { + continue; + } + + if (null != dayHeading) { + day.setDate(dayHeading.text().split(", ")[1]); + } + + Elements exams = item.select("article"); + for (Element e : exams) { + day.addExam(new Exam() + .setSubjectAndGroup(snp.getRowDataChildValue(e, 1)) + .setType(snp.getRowDataChildValue(e, 2)) + .setDescription(snp.getRowDataChildValue(e, 3)) + .setTeacher(snp.getRowDataChildValue(e, 4).split(", ")[0]) + .setEntryDate(snp.getRowDataChildValue(e, 4).split(", ")[1]) + ); + } + + days.add(day); + } + + return new Week() + .setStartDayDate(examsDays.select("h2").first().text().split(" ")[1]) + .setDays(days); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Day.java b/api/src/main/java/io/github/wulkanowy/api/generic/Day.java new file mode 100644 index 000000000..6bf26c040 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Day.java @@ -0,0 +1,63 @@ +package io.github.wulkanowy.api.generic; + +import java.util.ArrayList; +import java.util.List; + +public class Day { + + private List lessons = new ArrayList<>(); + + protected String date = ""; + + private String dayName = ""; + + private boolean isFreeDay = false; + + private String freeDayName = ""; + + public Lesson getLesson(int index) { + return lessons.get(index); + } + + public List getLessons() { + return lessons; + } + + public Day setLesson(Lesson lesson) { + this.lessons.add(lesson); + return this; + } + + public String getDate() { + return date; + } + + public Day setDate(String date) { + this.date = date; + return this; + } + + public String getDayName() { + return dayName; + } + + public void setDayName(String dayName) { + this.dayName = dayName; + } + + public boolean isFreeDay() { + return isFreeDay; + } + + public void setFreeDay(boolean freeDay) { + isFreeDay = freeDay; + } + + public String getFreeDayName() { + return freeDayName; + } + + public void setFreeDayName(String freeDayName) { + this.freeDayName = freeDayName; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Lesson.java b/api/src/main/java/io/github/wulkanowy/api/generic/Lesson.java new file mode 100644 index 000000000..8dd653277 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Lesson.java @@ -0,0 +1,240 @@ +package io.github.wulkanowy.api.generic; + +public class Lesson { + + private String number = ""; + + private String subject = ""; + + private String teacher = ""; + + private String room = ""; + + private String description = ""; + + private String groupName = ""; + + private String startTime = ""; + + private String endTime = ""; + + private String date = ""; + + private boolean isEmpty = false; + + private boolean isDivisionIntoGroups = false; + + private boolean isPlanning = false; + + private boolean isRealized = false; + + private boolean isMovedOrCanceled = false; + + private boolean isNewMovedInOrChanged = false; + + private boolean isNotExist = false; + + private boolean isPresence = false; + + private boolean isAbsenceUnexcused = false; + + private boolean isAbsenceExcused = false; + + private boolean isUnexcusedLateness = false; + + private boolean isAbsenceForSchoolReasons = false; + + private boolean isExcusedLateness = false; + + private boolean isExemption = false; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public String getSubject() { + return subject; + } + + public Lesson setSubject(String subject) { + this.subject = subject; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Lesson setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getRoom() { + return room; + } + + public Lesson setRoom(String room) { + this.room = room; + return this; + } + + public String getDescription() { + return description; + } + + public Lesson setDescription(String description) { + this.description = description; + return this; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public String getDate() { + return date; + } + + public Lesson setDate(String date) { + this.date = date; + return this; + } + + public boolean isEmpty() { + return isEmpty; + } + + public Lesson setEmpty(boolean empty) { + isEmpty = empty; + return this; + } + + public boolean isDivisionIntoGroups() { + return isDivisionIntoGroups; + } + + public void setDivisionIntoGroups(boolean divisionIntoGroups) { + isDivisionIntoGroups = divisionIntoGroups; + } + + public boolean isPlanning() { + return isPlanning; + } + + public void setPlanning(boolean planning) { + isPlanning = planning; + } + + public boolean isRealized() { + return isRealized; + } + + public void setRealized(boolean realized) { + isRealized = realized; + } + + public boolean isMovedOrCanceled() { + return isMovedOrCanceled; + } + + public void setMovedOrCanceled(boolean movedOrCanceled) { + isMovedOrCanceled = movedOrCanceled; + } + + public boolean isNewMovedInOrChanged() { + return isNewMovedInOrChanged; + } + + public void setNewMovedInOrChanged(boolean newMovedInOrChanged) { + isNewMovedInOrChanged = newMovedInOrChanged; + } + + public boolean isNotExist() { + return isNotExist; + } + + public void setNotExist(boolean notExist) { + isNotExist = notExist; + } + + public boolean isPresence() { + return isPresence; + } + + public void setPresence(boolean presence) { + isPresence = presence; + } + + public boolean isAbsenceUnexcused() { + return isAbsenceUnexcused; + } + + public void setAbsenceUnexcused(boolean absenceUnexcused) { + isAbsenceUnexcused = absenceUnexcused; + } + + public boolean isAbsenceExcused() { + return isAbsenceExcused; + } + + public void setAbsenceExcused(boolean absenceExcused) { + isAbsenceExcused = absenceExcused; + } + + public boolean isUnexcusedLateness() { + return isUnexcusedLateness; + } + + public void setUnexcusedLateness(boolean unexcusedLateness) { + isUnexcusedLateness = unexcusedLateness; + } + + public boolean isAbsenceForSchoolReasons() { + return isAbsenceForSchoolReasons; + } + + public void setAbsenceForSchoolReasons(boolean absenceForSchoolReasons) { + isAbsenceForSchoolReasons = absenceForSchoolReasons; + } + + public boolean isExcusedLateness() { + return isExcusedLateness; + } + + public void setExcusedLateness(boolean excusedLateness) { + isExcusedLateness = excusedLateness; + } + + public boolean isExemption() { + return isExemption; + } + + public void setExemption(boolean exemption) { + isExemption = exemption; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Month.java b/api/src/main/java/io/github/wulkanowy/api/generic/Month.java new file mode 100644 index 000000000..e38ef3a32 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Month.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api.generic; + +public class Month { + + private String name = ""; + + private int value = 0; + + public String getName() { + return name; + } + + public Month setName(String name) { + this.name = name; + return this; + } + + public int getValue() { + return value; + } + + public Month setValue(int value) { + this.value = value; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Subject.java b/api/src/main/java/io/github/wulkanowy/api/generic/Subject.java new file mode 100644 index 000000000..fcf27bef3 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Subject.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api.generic; + +public class Subject { + + private int id = -1; + + private String name = ""; + + public int getId() { + return id; + } + + public Subject setId(int id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public Subject setName(String name) { + this.name = name; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Week.java b/api/src/main/java/io/github/wulkanowy/api/generic/Week.java new file mode 100644 index 000000000..1e46f3948 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Week.java @@ -0,0 +1,33 @@ +package io.github.wulkanowy.api.generic; + +import java.util.ArrayList; +import java.util.List; + +public class Week { + + private List days = new ArrayList<>(); + + private String startDayDate = ""; + + public T getDay(int index) { + return days.get(index); + } + + public List getDays() { + return days; + } + + public Week setDays(List days) { + this.days = days; + return this; + } + + public String getStartDayDate() { + return startDayDate; + } + + public Week setStartDayDate(String startDayDate) { + this.startDayDate = startDayDate; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/grades/Grade.java b/api/src/main/java/io/github/wulkanowy/api/grades/Grade.java new file mode 100644 index 000000000..564b3e47c --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/grades/Grade.java @@ -0,0 +1,112 @@ +package io.github.wulkanowy.api.grades; + +public class Grade { + + protected String value = ""; + + private String subject = ""; + + private String color = ""; + + private String symbol = ""; + + private String description = ""; + + private String weight = ""; + + private String date = ""; + + private String teacher = ""; + + private String semester = ""; + + public String getSubject() { + return subject; + } + + public Grade setSubject(String subject) { + this.subject = subject; + + return this; + } + + public String getValue() { + return value; + } + + public Grade setValue(String value) { + this.value = value; + + return this; + } + + public String getColor() { + return color; + } + + public Grade setColor(String color) { + this.color = color; + + return this; + } + + public String getSymbol() { + return symbol; + } + + public Grade setSymbol(String symbol) { + this.symbol = symbol; + + return this; + } + + public String getDescription() { + return description; + } + + public Grade setDescription(String description) { + this.description = description; + + return this; + } + + public String getWeight() { + return weight; + } + + public Grade setWeight(String weight) { + this.weight = weight; + + return this; + } + + public String getDate() { + return date; + } + + public Grade setDate(String date) { + this.date = date; + + return this; + } + + public String getTeacher() { + return teacher; + } + + public Grade setTeacher(String teacher) { + this.teacher = teacher; + + return this; + } + + public String getSemester() { + return semester; + } + + public Grade setSemester(String semester) { + this.semester = semester; + + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/grades/GradesList.java b/api/src/main/java/io/github/wulkanowy/api/grades/GradesList.java new file mode 100644 index 000000000..44c45c9a1 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/grades/GradesList.java @@ -0,0 +1,82 @@ +package io.github.wulkanowy.api.grades; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.github.wulkanowy.api.Semester; +import io.github.wulkanowy.api.SnP; + +public class GradesList { + + private static final String GRADES_PAGE_URL = "Oceny/Wszystkie?details=2&okres="; + + private SnP snp = null; + + private List grades = new ArrayList<>(); + + public GradesList(SnP snp) { + this.snp = snp; + } + + private String getGradesPageUrl() { + return GRADES_PAGE_URL; + } + + public List getAll() throws IOException, ParseException { + return getAll(""); + } + + public List getAll(String semester) throws IOException, ParseException { + Document gradesPage = snp.getSnPPageDocument(getGradesPageUrl() + semester); + Elements gradesRows = gradesPage.select(".ocenySzczegoly-table > tbody > tr"); + Semester currentSemester = snp.getCurrentSemester(snp.getSemesters(gradesPage)); + + for (Element row : gradesRows) { + if ("Brak ocen".equals(row.select("td:nth-child(2)").text())) { + continue; + } + + String descriptions = row.select("td:nth-child(3)").text(); + String symbol = descriptions.split(", ")[0]; + String description = descriptions.replaceFirst(symbol, "").replaceFirst(", ", ""); + + Pattern pattern = Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"); + Matcher matcher = pattern.matcher(row.select("td:nth-child(2) span.ocenaCzastkowa") + .attr("style")); + + String color = ""; + while (matcher.find()) { + color = matcher.group(1); + } + + SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT); + Date d = sdf.parse(row.select("td:nth-child(5)").text()); + sdf.applyPattern("yyyy-MM-dd"); + + grades.add(new Grade() + .setSubject(row.select("td:nth-child(1)").text()) + .setValue(row.select("td:nth-child(2)").text()) + .setColor(color) + .setSymbol(symbol) + .setDescription(description) + .setWeight(row.select("td:nth-child(4)").text()) + .setDate(sdf.format(d)) + .setTeacher(row.select("td:nth-child(6)").text()) + .setSemester(currentSemester.getNumber()) + ); + } + + return grades; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/grades/Subject.java b/api/src/main/java/io/github/wulkanowy/api/grades/Subject.java new file mode 100644 index 000000000..c7917810e --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/grades/Subject.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.api.grades; + +public class Subject { + + private String name; + + private String predictedRating; + + private String finalRating; + + public String getName() { + return name; + } + + public Subject setName(String name) { + this.name = name; + + return this; + } + + public String getPredictedRating() { + return predictedRating; + } + + public Subject setPredictedRating(String predictedRating) { + this.predictedRating = predictedRating; + + return this; + } + + public String getFinalRating() { + return finalRating; + } + + public Subject setFinalRating(String finalRating) { + this.finalRating = finalRating; + + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/grades/SubjectsList.java b/api/src/main/java/io/github/wulkanowy/api/grades/SubjectsList.java new file mode 100644 index 000000000..decf44686 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/grades/SubjectsList.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.api.grades; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; + +public class SubjectsList { + + private static final String SUBJECTS_PAGE_URL = "Oceny/Wszystkie?details=1"; + + private SnP snp = null; + + public SubjectsList(SnP snp) { + this.snp = snp; + } + + public List getAll() throws IOException { + Document subjectPage = snp.getSnPPageDocument(SUBJECTS_PAGE_URL); + + Elements rows = subjectPage.select(".ocenyZwykle-table > tbody > tr"); + + List subjects = new ArrayList<>(); + + for (Element subjectRow : rows) { + subjects.add(new Subject() + .setName(subjectRow.select("td:nth-child(1)").text()) + .setPredictedRating(subjectRow.select("td:nth-last-child(2)").text()) + .setFinalRating(subjectRow.select("td:nth-last-child(1)").text()) + ); + } + + return subjects; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/login/AccountPermissionException.java b/api/src/main/java/io/github/wulkanowy/api/login/AccountPermissionException.java new file mode 100644 index 000000000..15be359c2 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/AccountPermissionException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.login; + +public class AccountPermissionException extends Exception { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/login/BadCredentialsException.java b/api/src/main/java/io/github/wulkanowy/api/login/BadCredentialsException.java new file mode 100644 index 000000000..4502bb157 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/BadCredentialsException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.login; + +public class BadCredentialsException extends Exception { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/login/Login.java b/api/src/main/java/io/github/wulkanowy/api/login/Login.java new file mode 100644 index 000000000..e680804ae --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/Login.java @@ -0,0 +1,97 @@ +package io.github.wulkanowy.api.login; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.parser.Parser; +import org.jsoup.select.Elements; + +import java.io.IOException; + +import io.github.wulkanowy.api.Client; + +public class Login { + + private static final String LOGIN_PAGE_URL = "{schema}://cufs.{host}/{symbol}/Account/LogOn" + + "?ReturnUrl=%2F{symbol}%2FFS%2FLS%3Fwa%3Dwsignin1.0%26wtrealm%3D" + + "{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx%26wctx%3D" + + "{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx"; + + private static final String LOGIN_ENDPOINT_PAGE_URL = + "{schema}://uonetplus.{host}/{symbol}/LoginEndpoint.aspx"; + + private Client client; + + private String symbol; + + public Login(Client client) { + this.client = client; + } + + public String login(String email, String password, String symbol) + throws BadCredentialsException, LoginErrorException, + AccountPermissionException, IOException, VulcanOfflineException { + String certificate = sendCredentials(email, password, symbol); + + return sendCertificate(certificate, symbol); + } + + String sendCredentials(String email, String password, String symbol) + throws IOException, BadCredentialsException { + this.symbol = symbol; + + Document html = client.postPageByUrl(LOGIN_PAGE_URL, new String[][]{ + {"LoginName", email}, + {"Password", password} + }); + + if (null != html.select(".ErrorMessage").first()) { + throw new BadCredentialsException(); + } + + return html.select("input[name=wresult]").attr("value"); + } + + String sendCertificate(String certificate, String defaultSymbol) + throws IOException, LoginErrorException, AccountPermissionException, VulcanOfflineException { + this.symbol = findSymbol(defaultSymbol, certificate); + client.setSymbol(this.symbol); + + Document html = client.postPageByUrl(LOGIN_ENDPOINT_PAGE_URL, new String[][]{ + {"wa", "wsignin1.0"}, + {"wresult", certificate} + }); + + if (html.getElementsByTag("title").text().equals("Logowanie")) { + throw new AccountPermissionException(); + } + + if (html.getElementsByTag("title").text().equals("Przerwa techniczna")) { + throw new VulcanOfflineException(); + } + + if (!html.select("title").text().equals("Uonet+")) { + throw new LoginErrorException(); + } + + return this.symbol; + } + + private String findSymbol(String symbol, String certificate) { + if ("Default".equals(symbol)) { + return findSymbolInCertificate(certificate); + } + + return symbol; + } + + String findSymbolInCertificate(String certificate) { + Elements els = Jsoup.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser()) + .select("[AttributeName=\"UserInstance\"] samlAttributeValue"); + + if (els.isEmpty()) { + return ""; + } + + return els.get(1).text(); + } +} \ No newline at end of file diff --git a/api/src/main/java/io/github/wulkanowy/api/login/LoginErrorException.java b/api/src/main/java/io/github/wulkanowy/api/login/LoginErrorException.java new file mode 100644 index 000000000..eec2b4e41 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/LoginErrorException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.login; + +public class LoginErrorException extends NotLoggedInErrorException { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/login/NotLoggedInErrorException.java b/api/src/main/java/io/github/wulkanowy/api/login/NotLoggedInErrorException.java new file mode 100644 index 000000000..d33b892d4 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/NotLoggedInErrorException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.login; + +public class NotLoggedInErrorException extends Exception { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/login/VulcanOfflineException.java b/api/src/main/java/io/github/wulkanowy/api/login/VulcanOfflineException.java new file mode 100644 index 000000000..45cf64583 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/VulcanOfflineException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.login; + +public class VulcanOfflineException extends Exception { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/messages/BadRequestException.java b/api/src/main/java/io/github/wulkanowy/api/messages/BadRequestException.java new file mode 100644 index 000000000..90af17cee --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/messages/BadRequestException.java @@ -0,0 +1,4 @@ +package io.github.wulkanowy.api.messages; + +class BadRequestException extends Exception { +} diff --git a/api/src/main/java/io/github/wulkanowy/api/messages/Message.java b/api/src/main/java/io/github/wulkanowy/api/messages/Message.java new file mode 100644 index 000000000..331ec8196 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/messages/Message.java @@ -0,0 +1,30 @@ +package io.github.wulkanowy.api.messages; + +import com.google.gson.annotations.SerializedName; + +public class Message { + + @SerializedName("Nieprzeczytana") + public boolean unread; + + @SerializedName("Data") + public String date; + + @SerializedName("Tresc") + public String content; + + @SerializedName("Temat") + public String subject; + + @SerializedName("NadawcaNazwa") + public String sender; + + @SerializedName("IdWiadomosci") + public int messageID; + + @SerializedName("IdNadawca") + public int senderID; + + @SerializedName("Id") + public int id; +} diff --git a/api/src/main/java/io/github/wulkanowy/api/messages/Messages.java b/api/src/main/java/io/github/wulkanowy/api/messages/Messages.java new file mode 100644 index 000000000..4eb969cda --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/messages/Messages.java @@ -0,0 +1,98 @@ +package io.github.wulkanowy.api.messages; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; + +import java.io.IOException; +import java.util.List; + +import io.github.wulkanowy.api.Client; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public class Messages { + + private static final String BASE_URL = "{schema}://uonetplus-uzytkownik.{host}/{symbol}/"; + + private static final String LIST_BASE_URL = BASE_URL + "Wiadomosc.mvc/"; + + private static final String RECEIVED_URL = LIST_BASE_URL + "GetWiadomosciOdebrane"; + + private static final String SENT_URL = LIST_BASE_URL + "GetWiadomosciWyslane"; + + private static final String DELETED_URL = LIST_BASE_URL + "GetWiadomosciUsuniete"; + + private static final String MESSAGE_URL = LIST_BASE_URL + "GetTrescWiadomosci"; + + public static final int RECEIVED_FOLDER = 1; + + public static final int SENT_FOLDER = 2; + + public static final int DELETED_FOLDER = 3; + + private static final String ERROR_TITLE = "Błąd strony"; + + private Client client; + + public Messages(Client client) { + this.client = client; + } + + public List getReceived() throws IOException, NotLoggedInErrorException, BadRequestException { + return getMessages(RECEIVED_URL); + } + + public List getSent() throws IOException, NotLoggedInErrorException, BadRequestException { + return getMessages(SENT_URL); + } + + public List getDeleted() throws IOException, NotLoggedInErrorException, BadRequestException { + return getMessages(DELETED_URL); + } + + private List getMessages(String url) throws IOException, NotLoggedInErrorException, BadRequestException { + String res = client.getJsonStringByUrl(url); + + List messages; + + try { + messages = new Gson().fromJson(res, MessagesContainer.class).data; + } catch (JsonParseException e) { + if (res.contains(ERROR_TITLE)) { + throw new BadRequestException(); + } + + throw new NotLoggedInErrorException(); + } + + return messages; + } + + public Message getMessage(int id, int folder) throws IOException, BadRequestException, NotLoggedInErrorException { + String res = client.postJsonStringByUrl(MESSAGE_URL, new String[][]{ + {"idWiadomosc", String.valueOf(id)}, + {"Folder", String.valueOf(folder)} + }); + + Message message; + + try { + message = new Gson().fromJson(res, MessageContainer.class).data; + } catch (JsonParseException e) { + if (res.contains(ERROR_TITLE)) { + throw new BadRequestException(); + } + + throw new NotLoggedInErrorException(); + } + + return message; + } + + private static class MessagesContainer { + private List data; + } + + private static class MessageContainer { + private Message data; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/notes/AchievementsList.java b/api/src/main/java/io/github/wulkanowy/api/notes/AchievementsList.java new file mode 100644 index 000000000..c821e8bec --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/notes/AchievementsList.java @@ -0,0 +1,35 @@ +package io.github.wulkanowy.api.notes; + +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; + +public class AchievementsList { + + private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie"; + + private SnP snp = null; + + private List achievements = new ArrayList<>(); + + public AchievementsList(SnP snp) { + this.snp = snp; + } + + public List getAllAchievements() throws IOException { + Element pageFragment = snp.getSnPPageDocument(NOTES_PAGE_URL) + .select(".mainContainer > div").get(1); + Elements items = pageFragment.select("article"); + + for (Element item : items) { + achievements.add(item.text()); + } + + return achievements; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/notes/Note.java b/api/src/main/java/io/github/wulkanowy/api/notes/Note.java new file mode 100644 index 000000000..b1fa68b93 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/notes/Note.java @@ -0,0 +1,48 @@ +package io.github.wulkanowy.api.notes; + +public class Note { + + private String date; + + private String teacher; + + private String category; + + private String content; + + public String getDate() { + return date; + } + + public Note setDate(String date) { + this.date = date; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Note setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getCategory() { + return category; + } + + public Note setCategory(String category) { + this.category = category; + return this; + } + + public String getContent() { + return content; + } + + public Note setContent(String content) { + this.content = content; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/notes/NotesList.java b/api/src/main/java/io/github/wulkanowy/api/notes/NotesList.java new file mode 100644 index 000000000..34b8540d9 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/notes/NotesList.java @@ -0,0 +1,42 @@ +package io.github.wulkanowy.api.notes; + +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; + +public class NotesList { + + private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie"; + + private SnP snp = null; + + private List notes = new ArrayList<>(); + + public NotesList(SnP snp) { + this.snp = snp; + } + + public List getAllNotes() throws IOException { + Element pageFragment = snp.getSnPPageDocument(NOTES_PAGE_URL) + .select(".mainContainer > div").get(0); + Elements items = pageFragment.select("article"); + Elements dates = pageFragment.select("h2"); + + int index = 0; + for (Element item : items) { + notes.add(new Note() + .setDate(dates.get(index++).text()) + .setTeacher(snp.getRowDataChildValue(item, 1)) + .setCategory(snp.getRowDataChildValue(item, 2)) + .setContent(snp.getRowDataChildValue(item, 3)) + ); + } + + return notes; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/school/SchoolData.java b/api/src/main/java/io/github/wulkanowy/api/school/SchoolData.java new file mode 100644 index 000000000..f135163a2 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/school/SchoolData.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.api.school; + +public class SchoolData { + + private String name = ""; + + private String address = ""; + + private String phoneNumber = ""; + + private String headmaster = ""; + + private String[] pedagogue; + + public String getName() { + return name; + } + + public SchoolData setName(String name) { + this.name = name; + return this; + } + + public String getAddress() { + return address; + } + + public SchoolData setAddress(String address) { + this.address = address; + return this; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public SchoolData setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + return this; + } + + public String getHeadmaster() { + return headmaster; + } + + public SchoolData setHeadmaster(String headmaster) { + this.headmaster = headmaster; + return this; + } + + public String[] getPedagogues() { + return pedagogue; + } + + public SchoolData setPedagogue(String[] pedagogue) { + this.pedagogue = pedagogue; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/school/SchoolInfo.java b/api/src/main/java/io/github/wulkanowy/api/school/SchoolInfo.java new file mode 100644 index 000000000..4eeb641cc --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/school/SchoolInfo.java @@ -0,0 +1,30 @@ +package io.github.wulkanowy.api.school; + +import org.jsoup.nodes.Element; + +import java.io.IOException; + +import io.github.wulkanowy.api.SnP; + +public class SchoolInfo { + + private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele"; + + private SnP snp = null; + + public SchoolInfo(SnP snp) { + this.snp = snp; + } + + public SchoolData getSchoolData() throws IOException { + Element e = snp.getSnPPageDocument(SCHOOL_PAGE_URL) + .select(".mainContainer > article").get(0); + + return new SchoolData() + .setName(snp.getRowDataChildValue(e, 1)) + .setAddress(snp.getRowDataChildValue(e, 2)) + .setPhoneNumber(snp.getRowDataChildValue(e, 3)) + .setHeadmaster(snp.getRowDataChildValue(e, 4)) + .setPedagogue(snp.getRowDataChildValue(e, 5).split(", ")); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/school/Subject.java b/api/src/main/java/io/github/wulkanowy/api/school/Subject.java new file mode 100644 index 000000000..0a3c0957d --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/school/Subject.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api.school; + +public class Subject { + + private String name = ""; + + private String[] teachers; + + public String getName() { + return name; + } + + public Subject setName(String name) { + this.name = name; + return this; + } + + public String[] getTeachers() { + return teachers; + } + + public Subject setTeachers(String[] teachers) { + this.teachers = teachers; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/school/TeachersData.java b/api/src/main/java/io/github/wulkanowy/api/school/TeachersData.java new file mode 100644 index 000000000..7d41162e5 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/school/TeachersData.java @@ -0,0 +1,39 @@ +package io.github.wulkanowy.api.school; + +import java.util.List; + +public class TeachersData { + + private String className = ""; + + private String[] classTeacher; + + private List subjects; + + public String getClassName() { + return className; + } + + public TeachersData setClassName(String className) { + this.className = className; + return this; + } + + public String[] getClassTeacher() { + return classTeacher; + } + + public TeachersData setClassTeacher(String[] classTeacher) { + this.classTeacher = classTeacher; + return this; + } + + public List getSubjects() { + return subjects; + } + + public TeachersData setSubjects(List subjects) { + this.subjects = subjects; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/school/TeachersInfo.java b/api/src/main/java/io/github/wulkanowy/api/school/TeachersInfo.java new file mode 100644 index 000000000..e8af67446 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/school/TeachersInfo.java @@ -0,0 +1,42 @@ +package io.github.wulkanowy.api.school; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; + +public class TeachersInfo { + + private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele"; + + private SnP snp = null; + + public TeachersInfo(SnP snp) { + this.snp = snp; + } + + public TeachersData getTeachersData() throws IOException { + Document doc = snp.getSnPPageDocument(SCHOOL_PAGE_URL); + Elements rows = doc.select(".mainContainer > table tbody tr"); + String description = doc.select(".mainContainer > p").first().text(); + + List subjects = new ArrayList<>(); + + for (Element subject : rows) { + subjects.add(new Subject() + .setName(subject.select("td").get(1).text()) + .setTeachers(subject.select("td").get(2).text().split(", ")) + ); + } + + return new TeachersData() + .setClassName(description.split(", ")[0].split(": ")[1].trim()) + .setClassTeacher(description.split("Wychowawcy:")[1].trim().split(", ")) + .setSubjects(subjects); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/timetable/LessonTypes.java b/api/src/main/java/io/github/wulkanowy/api/timetable/LessonTypes.java new file mode 100644 index 000000000..be1f44e91 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/timetable/LessonTypes.java @@ -0,0 +1,16 @@ +package io.github.wulkanowy.api.timetable; + +class LessonTypes { + + static final String CLASS_PLANNING = "x-treelabel-ppl"; + + static final String CLASS_REALIZED = "x-treelabel-rlz"; + + static final String CLASS_MOVED_OR_CANCELED = "x-treelabel-inv"; + + static final String CLASS_NEW_MOVED_IN_OR_CHANGED = "x-treelabel-zas"; + + private LessonTypes() { + throw new IllegalStateException("Utility class"); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java b/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java new file mode 100644 index 000000000..1d5264943 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java @@ -0,0 +1,215 @@ +package io.github.wulkanowy.api.timetable; + +import org.apache.commons.lang3.StringUtils; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import io.github.wulkanowy.api.SnP; +import io.github.wulkanowy.api.generic.Day; +import io.github.wulkanowy.api.generic.Lesson; +import io.github.wulkanowy.api.generic.Week; + +public class Timetable { + + private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanLekcji?data="; + + private SnP snp; + + public Timetable(SnP snp) { + this.snp = snp; + } + + public Week getWeekTable() throws IOException, ParseException { + return getWeekTable(""); + } + + public Week getWeekTable(final String tick) throws IOException, ParseException { + Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick) + .select(".mainContainer .presentData").first(); + + List days = getDays(table.select("thead th")); + + setLessonToDays(table, days); + + return new Week() + .setStartDayDate(days.get(0).getDate()) + .setDays(days); + } + + private List getDays(Elements tableHeaderCells) throws ParseException { + List days = new ArrayList<>(); + + for (int i = 2; i < 7; i++) { + String[] dayHeaderCell = tableHeaderCells.get(i).html().split("
"); + + SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT); + Date d = sdf.parse(dayHeaderCell[1].trim()); + sdf.applyPattern("yyyy-MM-dd"); + + Day day = new Day(); + day.setDayName(dayHeaderCell[0]); + day.setDate(sdf.format(d)); + + if (tableHeaderCells.get(i).hasClass("free-day")) { + day.setFreeDay(true); + day.setFreeDayName(dayHeaderCell[2]); + } + + days.add(day); + } + + return days; + } + + private void setLessonToDays(Element table, List days) { + for (Element row : table.select("tbody tr")) { + Elements hours = row.select("td"); + + // fill hours in day + for (int i = 2; i < hours.size(); i++) { + Lesson lesson = new Lesson(); + + String[] startEndEnd = hours.get(1).text().split(" "); + lesson.setStartTime(startEndEnd[0]); + lesson.setEndTime(startEndEnd[1]); + lesson.setDate(days.get(i - 2).getDate()); + lesson.setNumber(hours.get(0).text()); + + addLessonDetails(lesson, hours.get(i).select("div")); + + days.get(i - 2).setLesson(lesson); + } + } + } + + private void addLessonDetails(Lesson lesson, Elements e) { + moveWarningToLessonNode(e); + + switch (e.size()) { + case 1: + addLessonInfoFromElement(lesson, e.first()); + break; + case 2: + addLessonInfoFromElement(lesson, e.last()); + break; + case 3: + addLessonInfoFromElement(lesson, e.get(1)); + break; + default: + lesson.setEmpty(true); + break; + } + } + + private void moveWarningToLessonNode(Elements e) { + Elements warn = e.select(".uwaga-panel"); + + if (!warn.isEmpty()) { + e.select(".x-treelabel-rlz").last().text("(" + warn.text() + ")"); + e.remove(1); + } + } + + private void addLessonInfoFromElement(Lesson lesson, Element e) { + Elements spans = e.select("span"); + + addTypeInfo(lesson, spans); + addNormalLessonInfo(lesson, spans); + addChangesInfo(lesson, spans); + addGroupLessonInfo(lesson, spans); + } + + private void addTypeInfo(Lesson lesson, Elements spans) { + if (spans.first().hasClass(LessonTypes.CLASS_PLANNING)) { + lesson.setPlanning(true); + } + + if (spans.first().hasClass(LessonTypes.CLASS_MOVED_OR_CANCELED)) { + lesson.setMovedOrCanceled(true); + } + + if (spans.first().hasClass(LessonTypes.CLASS_NEW_MOVED_IN_OR_CHANGED)) { + lesson.setNewMovedInOrChanged(true); + } + + if (spans.last().hasClass(LessonTypes.CLASS_REALIZED) || "".equals(spans.first().attr("class"))) { + lesson.setRealized(true); + } + } + + private void addNormalLessonInfo(Lesson lesson, Elements spans) { + if (3 == spans.size()) { + lesson.setSubject(spans.get(0).text()); + lesson.setTeacher(spans.get(1).text()); + lesson.setRoom(spans.get(2).text()); + } + } + + private void addChangesInfo(Lesson lesson, Elements spans) { + if (!spans.last().hasClass(LessonTypes.CLASS_REALIZED)) { + return; + } + + if (7 == spans.size()) { + lesson.setSubject(spans.get(3).text()); + lesson.setTeacher(spans.get(4).text()); + lesson.setRoom(spans.get(5).text()); + lesson.setMovedOrCanceled(false); + lesson.setNewMovedInOrChanged(true); + lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")") + + " (poprzednio: " + spans.get(0).text() + ")"); + } else if (9 == spans.size()) { + String[] subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans.get(4)); + lesson.setSubject(subjectAndGroupInfo[0]); + lesson.setGroupName(subjectAndGroupInfo[1]); + lesson.setTeacher(spans.get(6).text()); + lesson.setRoom(spans.get(7).text()); + lesson.setMovedOrCanceled(false); + lesson.setNewMovedInOrChanged(true); + lesson.setDivisionIntoGroups(true); + lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")") + + " (poprzednio: " + getLessonAndGroupInfoFromSpan(spans.get(0))[0] + ")"); + } else if (4 <= spans.size()) { + lesson.setSubject(spans.get(0).text()); + lesson.setTeacher(spans.get(1).text()); + lesson.setRoom(spans.get(2).text()); + lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")")); + } + } + + private void addGroupLessonInfo(Lesson lesson, Elements spans) { + if (4 == spans.size() && !spans.last().hasClass(LessonTypes.CLASS_REALIZED)) { + lesson.setRoom(spans.last().text()); + } + + if ((4 == spans.size() && !spans.last().hasClass(LessonTypes.CLASS_REALIZED) || 5 == spans.size())) { + String[] subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans.get(0)); + lesson.setSubject(subjectAndGroupInfo[0]); + lesson.setGroupName(subjectAndGroupInfo[1]); + lesson.setTeacher(spans.get(2).text()); + lesson.setDivisionIntoGroups(true); + } + + if (5 == spans.size()) { + lesson.setRoom(spans.get(3).text()); + } + } + + private String[] getLessonAndGroupInfoFromSpan(Element span) { + String[] subjectNameArray = span.text().split(" "); + String groupName = subjectNameArray[subjectNameArray.length - 1]; + + return new String[]{ + span.text().replace(" " + groupName, ""), + StringUtils.substringBetween(groupName, "[", "]") + }; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/AddressData.java b/api/src/main/java/io/github/wulkanowy/api/user/AddressData.java new file mode 100644 index 000000000..3d6fc6d54 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/AddressData.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.api.user; + +public class AddressData { + + private String address = ""; + + private String registeredAddress = ""; + + private String correspondenceAddress = ""; + + public String getAddress() { + return address; + } + + public AddressData setAddress(String address) { + this.address = address; + + return this; + } + + public String getRegisteredAddress() { + return registeredAddress; + } + + public AddressData setRegisteredAddress(String registeredAddress) { + this.registeredAddress = registeredAddress; + + return this; + } + + public String getCorrespondenceAddress() { + return correspondenceAddress; + } + + public AddressData setCorrespondenceAddress(String correspondenceAddress) { + this.correspondenceAddress = correspondenceAddress; + + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/BasicInformation.java b/api/src/main/java/io/github/wulkanowy/api/user/BasicInformation.java new file mode 100644 index 000000000..875cc8da0 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/BasicInformation.java @@ -0,0 +1,69 @@ +package io.github.wulkanowy.api.user; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.io.IOException; + +import io.github.wulkanowy.api.SnP; + +public class BasicInformation { + + private static final String STUDENT_DATA_PAGE_URL = "Uczen.mvc/DanePodstawowe"; + + private static final String CONTENT_QUERY = ".mainContainer > article"; + + private Document studentDataPageDocument; + + private SnP snp; + + public BasicInformation(SnP snp) { + this.snp = snp; + } + + public Document getStudentDataPageDocument() throws IOException { + if (null == studentDataPageDocument) { + studentDataPageDocument = snp.getSnPPageDocument(STUDENT_DATA_PAGE_URL); + } + + return studentDataPageDocument; + } + + public PersonalData getPersonalData() throws IOException { + Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(0); + + String name = snp.getRowDataChildValue(e, 1); + String[] names = name.split(" "); + + return new PersonalData() + .setName(name) + .setFirstName(names[0]) + .setSurname(names[names.length - 1]) + .setFirstAndLastName(names[0] + " " + names[names.length - 1]) + .setDateAndBirthPlace(snp.getRowDataChildValue(e, 2)) + .setPesel(snp.getRowDataChildValue(e, 3)) + .setGender(snp.getRowDataChildValue(e, 4)) + .setPolishCitizenship("Tak".equals(snp.getRowDataChildValue(e, 5))) + .setFamilyName(snp.getRowDataChildValue(e, 6)) + .setParentsNames(snp.getRowDataChildValue(e, 7)); + } + + public AddressData getAddressData() throws IOException { + Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(1); + + return new AddressData() + .setAddress(snp.getRowDataChildValue(e, 1)) + .setRegisteredAddress(snp.getRowDataChildValue(e, 2)) + .setCorrespondenceAddress(snp.getRowDataChildValue(e, 3)); + + } + + public ContactDetails getContactDetails() throws IOException { + Element e = getStudentDataPageDocument().select(CONTENT_QUERY).get(2); + + return new ContactDetails() + .setPhoneNumber(snp.getRowDataChildValue(e, 1)) + .setCellPhoneNumber(snp.getRowDataChildValue(e, 2)) + .setEmail(snp.getRowDataChildValue(e, 3)); + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/ContactDetails.java b/api/src/main/java/io/github/wulkanowy/api/user/ContactDetails.java new file mode 100644 index 000000000..c8556944e --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/ContactDetails.java @@ -0,0 +1,37 @@ +package io.github.wulkanowy.api.user; + +public class ContactDetails { + + private String phoneNumber = ""; + + private String cellPhoneNumber = ""; + + private String email = ""; + + public String getPhoneNumber() { + return phoneNumber; + } + + public ContactDetails setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + return this; + } + + public String getCellPhoneNumber() { + return cellPhoneNumber; + } + + public ContactDetails setCellPhoneNumber(String cellPhoneNumber) { + this.cellPhoneNumber = cellPhoneNumber; + return this; + } + + public String getEmail() { + return email; + } + + public ContactDetails setEmail(String email) { + this.email = email; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/FamilyInformation.java b/api/src/main/java/io/github/wulkanowy/api/user/FamilyInformation.java new file mode 100644 index 000000000..555de8664 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/FamilyInformation.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.api.user; + +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.SnP; + +public class FamilyInformation { + + private static final String STUDENT_DATA_PAGE_URL = "Uczen.mvc/DanePodstawowe"; + + private SnP snp; + + public FamilyInformation(SnP snp) { + this.snp = snp; + } + + public List getFamilyMembers() throws IOException { + Elements membersElements = snp.getSnPPageDocument(STUDENT_DATA_PAGE_URL) + .select(".mainContainer > article:nth-of-type(n+4)"); + + List familyMembers = new ArrayList<>(); + + for (Element e : membersElements) { + familyMembers.add(new FamilyMember() + .setName(snp.getRowDataChildValue(e, 1)) + .setKinship(snp.getRowDataChildValue(e, 2)) + .setAddress(snp.getRowDataChildValue(e, 3)) + .setTelephones(snp.getRowDataChildValue(e, 4)) + .setEmail(snp.getRowDataChildValue(e, 5)) + ); + } + + return familyMembers; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/FamilyMember.java b/api/src/main/java/io/github/wulkanowy/api/user/FamilyMember.java new file mode 100644 index 000000000..dfb966745 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/FamilyMember.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.api.user; + +public class FamilyMember { + + private String name = ""; + + private String kinship = ""; + + private String address = ""; + + private String telephones = ""; + + private String email = ""; + + public String getName() { + return name; + } + + public FamilyMember setName(String name) { + this.name = name; + return this; + } + + public String getKinship() { + return kinship; + } + + public FamilyMember setKinship(String kinship) { + this.kinship = kinship; + return this; + } + + public String getAddress() { + return address; + } + + public FamilyMember setAddress(String address) { + this.address = address; + return this; + } + + public String getTelephones() { + return telephones; + } + + public FamilyMember setTelephones(String telephones) { + this.telephones = telephones; + return this; + } + + public String getEmail() { + return email; + } + + public FamilyMember setEmail(String email) { + this.email = email; + return this; + } +} diff --git a/api/src/main/java/io/github/wulkanowy/api/user/PersonalData.java b/api/src/main/java/io/github/wulkanowy/api/user/PersonalData.java new file mode 100644 index 000000000..d2991e613 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/user/PersonalData.java @@ -0,0 +1,114 @@ +package io.github.wulkanowy.api.user; + +public class PersonalData { + + private String name = ""; + + private String firstName = ""; + + private String surname = ""; + + private String firstAndLastName = ""; + + private String dateAndBirthPlace = ""; + + private String pesel = ""; + + private String gender = ""; + + private boolean isPolishCitizenship; + + private String familyName = ""; + + private String parentsNames = ""; + + public String getName() { + return name; + } + + public PersonalData setName(String name) { + this.name = name; + return this; + } + + public String getFirstName() { + return firstName; + } + + public PersonalData setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String getSurname() { + return surname; + } + + public PersonalData setSurname(String surname) { + this.surname = surname; + return this; + } + + public String getFirstAndLastName() { + return firstAndLastName; + } + + public PersonalData setFirstAndLastName(String firstAndLastName) { + this.firstAndLastName = firstAndLastName; + return this; + } + + public String getDateAndBirthPlace() { + return dateAndBirthPlace; + } + + public PersonalData setDateAndBirthPlace(String dateAndBirthPlace) { + this.dateAndBirthPlace = dateAndBirthPlace; + return this; + } + + public String getPesel() { + return pesel; + } + + public PersonalData setPesel(String pesel) { + this.pesel = pesel; + return this; + } + + public String getGender() { + return gender; + } + + public PersonalData setGender(String gender) { + this.gender = gender; + return this; + } + + public boolean isPolishCitizenship() { + return isPolishCitizenship; + } + + public PersonalData setPolishCitizenship(boolean polishCitizenship) { + isPolishCitizenship = polishCitizenship; + return this; + } + + public String getFamilyName() { + return familyName; + } + + public PersonalData setFamilyName(String familyName) { + this.familyName = familyName; + return this; + } + + public String getParentsNames() { + return parentsNames; + } + + public PersonalData setParentsNames(String parentsNames) { + this.parentsNames = parentsNames; + return this; + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/FixtureHelper.java b/api/src/test/java/io/github/wulkanowy/api/FixtureHelper.java new file mode 100644 index 000000000..94dd47b87 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/FixtureHelper.java @@ -0,0 +1,12 @@ +package io.github.wulkanowy.api; + +import java.io.InputStream; +import java.util.Scanner; + +public class FixtureHelper { + + public static String getAsString(InputStream inputStream) { + Scanner s = new Scanner(inputStream).useDelimiter("\\A"); + return s.hasNext() ? s.next() : ""; + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java new file mode 100644 index 000000000..89a5b1905 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java @@ -0,0 +1,125 @@ +package io.github.wulkanowy.api; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public class StudentAndParentTest { + + private Client client; + + @Before + public void setUp() throws Exception { + String input = FixtureHelper.getAsString( + getClass().getResourceAsStream("OcenyWszystkie-semester.html")); + Document gradesPageDocument = Jsoup.parse(input); + + client = Mockito.mock(Client.class); + Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(gradesPageDocument); + } + + @Test + public void snpTest() throws Exception { + StudentAndParent snp = new StudentAndParent(client, "id123"); + Assert.assertEquals("id123", snp.getId()); + } + + @Test + public void getSnpPageUrlWithIdTest() throws Exception { + Assert.assertEquals("{schema}://uonetplus-opiekun.{host}/{symbol}/123456/", + (new StudentAndParent(client, "123456")).getSnpHomePageUrl()); + } + + @Test + public void getSnpPageUrlWithoutIdTest() throws Exception { + String input = FixtureHelper.getAsString(getClass().getResourceAsStream("Start.html")); + Document startPageDocument = Jsoup.parse(input); + + Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); + Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(startPageDocument); + StudentAndParent snp = new StudentAndParent(client); + + Assert.assertEquals("https://uonetplus-opiekun.vulcan.net.pl/symbol/534213/Start/Index/", + snp.getSnpHomePageUrl()); + } + + @Test(expected = NotLoggedInErrorException.class) + public void getSnpPageUrlWithWrongPage() throws Exception { + Document wrongPageDocument = Jsoup.parse( + FixtureHelper.getAsString(getClass().getResourceAsStream("OcenyWszystkie-semester.html")) + ); + + Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(wrongPageDocument); + StudentAndParent snp = new StudentAndParent(client); + + snp.getSnpHomePageUrl(); + } + + @Test + public void getExtractedIDStandardTest() throws Exception { + Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); + StudentAndParent snp = new StudentAndParent(client, "symbol"); + Assert.assertEquals("123456", snp.getExtractedIdFromUrl("https://uonetplus-opiekun" + + ".vulcan.net.pl/powiat/123456/Start/Index/")); + } + + @Test + public void getExtractedIDDemoTest() throws Exception { + Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); + StudentAndParent snp = new StudentAndParent(client, "symbol"); + Assert.assertEquals("demo12345", + snp.getExtractedIdFromUrl("https://uonetplus-opiekun.vulcan.net.pl/demoupowiat/demo12345/Start/Index/")); + } + + @Test(expected = NotLoggedInErrorException.class) + public void getExtractedIDNotLoggedTest() throws Exception { + Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); + StudentAndParent snp = new StudentAndParent(client, "symbol"); + Assert.assertEquals("123", + snp.getExtractedIdFromUrl("https://uonetplus.vulcan.net.pl/powiat/")); + } + + @Test + public void getSemestersTest() throws Exception { + SnP snp = new StudentAndParent(client, "123456"); + List semesters = snp.getSemesters(); + + Assert.assertEquals(2, semesters.size()); + + Assert.assertEquals("1", semesters.get(0).getId()); + Assert.assertEquals("1234", semesters.get(0).getNumber()); + Assert.assertFalse(semesters.get(0).isCurrent()); + + Assert.assertEquals("2", semesters.get(1).getId()); + Assert.assertEquals("1235", semesters.get(1).getNumber()); + Assert.assertTrue(semesters.get(1).isCurrent()); + } + + @Test + public void getCurrentSemesterTest() throws Exception { + List semesters = new ArrayList<>(); + semesters.add(new Semester().setNumber("1500100900").setId("1").setCurrent(false)); + semesters.add(new Semester().setNumber("1500100901").setId("2").setCurrent(true)); + + SnP snp = new StudentAndParent(client, ""); + Assert.assertTrue(snp.getCurrentSemester(semesters).isCurrent()); + Assert.assertEquals("2", snp.getCurrentSemester(semesters).getId()); + Assert.assertEquals("1500100901", snp.getCurrentSemester(semesters).getNumber()); + } + + @Test + public void getCurrentSemesterFromEmptyTest() throws Exception { + SnP snp = new StudentAndParent(client, ""); + List semesters = new ArrayList<>(); + + Assert.assertNull(snp.getCurrentSemester(semesters)); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTestCase.java b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTestCase.java new file mode 100644 index 000000000..b18076cfa --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTestCase.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.mockito.Mockito; + +public abstract class StudentAndParentTestCase { + + protected StudentAndParent getSnp(String fixtureFileName) throws Exception { + String input = FixtureHelper.getAsString(getClass().getResourceAsStream(fixtureFileName)); + + Document tablePageDocument = Jsoup.parse(input); + + StudentAndParent snp = Mockito.mock(StudentAndParent.class); + Mockito.when(snp.getSnPPageDocument(Mockito.anyString())) + .thenReturn(tablePageDocument); + Mockito.when(snp.getSemesters(Mockito.any(Document.class))).thenCallRealMethod(); + Mockito.when(snp.getCurrentSemester(Mockito.anyList())) + .thenCallRealMethod(); + Mockito.when(snp.getRowDataChildValue(Mockito.any(Element.class), + Mockito.anyInt())).thenCallRealMethod(); + + return snp; + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/VulcanTest.java b/api/src/test/java/io/github/wulkanowy/api/VulcanTest.java new file mode 100644 index 000000000..a80c798ac --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/VulcanTest.java @@ -0,0 +1,86 @@ +package io.github.wulkanowy.api; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.Map; + +import io.github.wulkanowy.api.login.Login; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public class VulcanTest { + + private Vulcan vulcan; + + @Before + public void setUp() throws Exception { + vulcan = new Vulcan(); + vulcan.setClient(Mockito.mock(Client.class)); + vulcan.setLogin(Mockito.mock(Login.class)); + } + + @Test + public void setFullEndpointInfoTest() throws Exception { + vulcan.login("http://fakelog.net\\\\admin", "pass", "Default", "123"); + + Assert.assertEquals("http", vulcan.getProtocolSchema()); + Assert.assertEquals("fakelog.net", vulcan.getLogHost()); + Assert.assertEquals("admin", vulcan.getEmail()); + } + + @Test + public void getClientTwiceTest() throws Exception { + Vulcan vulcan = new Vulcan(); + Assert.assertTrue(vulcan.getClient().equals(vulcan.getClient())); + } + + @Test + public void getLoginTwiceTest() throws Exception { + Vulcan vulcan = new Vulcan(); + Assert.assertTrue(vulcan.getLogin().equals(vulcan.getLogin())); + } + + @Test(expected = NotLoggedInErrorException.class) + public void getStudentAndParentNotLoggedInTest() throws Exception { + vulcan.getStudentAndParent(); + } + + @Test + public void getStudentAndParentTwiceTest() throws Exception { + Client client = Mockito.mock(Client.class); + Map cookies = new HashMap<>(); + cookies.put("test", "test"); + Mockito.when(client.getCookies()).thenReturn(cookies); + + SnP snp = Mockito.mock(StudentAndParent.class); + Mockito.doNothing().when(snp).storeContextCookies(); + + Vulcan vulcan = Mockito.mock(Vulcan.class); + Mockito.when(vulcan.getClient()).thenReturn(client); + Mockito.when(vulcan.getStudentAndParent()).thenCallRealMethod(); + Mockito.when(vulcan.createSnp(Mockito.any(Client.class), Mockito.any())).thenReturn(snp); + + vulcan.getStudentAndParent(); + vulcan.getStudentAndParent(); + } + + @Test + public void createSnPTest() throws Exception { + vulcan.login("wulkanowy@wulkanowy.io", "wulkanowy123", "wulkan"); + + SnP snp1 = vulcan.createSnp(Mockito.mock(Client.class), null); + Assert.assertEquals(null, snp1.getId()); + + SnP snp2 = vulcan.createSnp(Mockito.mock(Client.class), "wulkan"); + Assert.assertEquals("wulkan", snp2.getId()); + + } + + @Test(expected = NotLoggedInErrorException.class) + public void getAttendanceExceptionText() throws Exception { + vulcan.getAttendanceTable(); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceStatisticsTest.java b/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceStatisticsTest.java new file mode 100644 index 000000000..ca50f3789 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceStatisticsTest.java @@ -0,0 +1,144 @@ +package io.github.wulkanowy.api.attendance; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; +import io.github.wulkanowy.api.generic.Month; + +public class AttendanceStatisticsTest extends StudentAndParentTestCase { + + private AttendanceStatistics excellent; + + private AttendanceStatistics full; + + @Before + public void setUp() throws Exception { + this.excellent = new AttendanceStatistics(getSnp("Frekwencja-excellent.html")); + this.full = new AttendanceStatistics(getSnp("Frekwencja-full.html")); + } + + @Test + public void getSubjectList() throws Exception { + Assert.assertEquals(26, excellent.getSubjectList().size()); + Assert.assertEquals(23, full.getSubjectList().size()); + } + + @Test + public void getSubjectListId() throws Exception { + Assert.assertEquals(-1, excellent.getSubjectList().get(0).getId()); + Assert.assertEquals(63, excellent.getSubjectList().get(10).getId()); + Assert.assertEquals(0, excellent.getSubjectList().get(25).getId()); + + Assert.assertEquals(-1, full.getSubjectList().get(0).getId()); + Assert.assertEquals(108, full.getSubjectList().get(14).getId()); + Assert.assertEquals(492, full.getSubjectList().get(21).getId()); + } + + @Test + public void getSubjectListName() throws Exception { + Assert.assertEquals("Wszystkie", excellent.getSubjectList().get(0).getName()); + Assert.assertEquals("Fizyka", excellent.getSubjectList().get(8).getName()); + Assert.assertEquals("Sieci komputerowe i administrowanie sieciami", + excellent.getSubjectList().get(21).getName()); + + Assert.assertEquals("Praktyka zawodowa", full.getSubjectList().get(11).getName()); + Assert.assertEquals("Użytkowanie urządzeń peryferyjnych komputera", + full.getSubjectList().get(16).getName()); + Assert.assertEquals("Brak opisu lekcji", full.getSubjectList().get(22).getName()); + } + + @Test + public void getTypesTotal() throws Exception { + Assert.assertEquals(100.0, excellent.getTypesTable().getTotal(), 0); + Assert.assertEquals(80.94, full.getTypesTable().getTotal(), 0); + } + + @Test + public void getTypeName() throws Exception { + List typeList1 = excellent.getTypesTable().getTypeList(); + Assert.assertEquals("Obecność", typeList1.get(0).getName()); + Assert.assertEquals("Nieobecność nieusprawiedliwiona", typeList1.get(1).getName()); + Assert.assertEquals("Nieobecność usprawiedliwiona", typeList1.get(2).getName()); + Assert.assertEquals("Nieobecność z przyczyn szkolnych", typeList1.get(3).getName()); + + List typeList2 = full.getTypesTable().getTypeList(); + Assert.assertEquals("Spóźnienie nieusprawiedliwione", typeList2.get(4).getName()); + Assert.assertEquals("Spóźnienie usprawiedliwione", typeList2.get(5).getName()); + Assert.assertEquals("Zwolnienie", typeList2.get(6).getName()); + } + + @Test + public void getTypeTotal() throws Exception { + List typeList1 = excellent.getTypesTable().getTypeList(); + Assert.assertEquals(1211, typeList1.get(0).getTotal()); + Assert.assertEquals(0, typeList1.get(1).getTotal()); + Assert.assertEquals(0, typeList1.get(2).getTotal()); + Assert.assertEquals(0, typeList1.get(3).getTotal()); + Assert.assertEquals(0, typeList1.get(4).getTotal()); + Assert.assertEquals(0, typeList1.get(5).getTotal()); + Assert.assertEquals(0, typeList1.get(6).getTotal()); + + List typeList2 = full.getTypesTable().getTypeList(); + Assert.assertEquals(822, typeList2.get(0).getTotal()); + Assert.assertEquals(6, typeList2.get(1).getTotal()); + Assert.assertEquals(192, typeList2.get(2).getTotal()); + Assert.assertEquals(7, typeList2.get(3).getTotal()); + Assert.assertEquals(12, typeList2.get(4).getTotal()); + Assert.assertEquals(1, typeList2.get(5).getTotal()); + Assert.assertEquals(2, typeList2.get(6).getTotal()); + } + + @Test + public void getTypeList() throws Exception { + List typesList1 = excellent.getTypesTable().getTypeList(); + Assert.assertEquals(12, typesList1.get(0).getMonthList().size()); + Assert.assertEquals(12, typesList1.get(5).getMonthList().size()); + + List typesList2 = full.getTypesTable().getTypeList(); + Assert.assertEquals(12, typesList2.get(0).getMonthList().size()); + Assert.assertEquals(12, typesList2.get(5).getMonthList().size()); + } + + @Test + public void getMonthList() throws Exception { + List typeList1 = excellent.getTypesTable().getTypeList(); + Assert.assertEquals(12, typeList1.get(0).getMonthList().size()); + + List typeList2 = full.getTypesTable().getTypeList(); + Assert.assertEquals(12, typeList2.get(0).getMonthList().size()); + } + + @Test + public void getMonthName() throws Exception { + List monthsList1 = excellent.getTypesTable().getTypeList().get(0).getMonthList(); + Assert.assertEquals("IX", monthsList1.get(0).getName()); + Assert.assertEquals("III", monthsList1.get(6).getName()); + Assert.assertEquals("VIII", monthsList1.get(11).getName()); + + List monthsList2 = full.getTypesTable().getTypeList().get(0).getMonthList(); + Assert.assertEquals("XI", monthsList2.get(2).getName()); + Assert.assertEquals("II", monthsList2.get(5).getName()); + Assert.assertEquals("VI", monthsList2.get(9).getName()); + } + + @Test + public void getMonthValue() throws Exception { + List monthsList1 = excellent.getTypesTable().getTypeList().get(0).getMonthList(); + Assert.assertEquals(142, monthsList1.get(0).getValue()); + Assert.assertEquals(131, monthsList1.get(4).getValue()); + Assert.assertEquals(139, monthsList1.get(7).getValue()); + Assert.assertEquals(114, monthsList1.get(9).getValue()); + Assert.assertEquals(0, monthsList1.get(11).getValue()); + + List typeList1 = full.getTypesTable().getTypeList(); + Assert.assertEquals(135, typeList1.get(0).getMonthList().get(0).getValue()); + Assert.assertEquals(7, typeList1.get(3).getMonthList().get(5).getValue()); + Assert.assertEquals(1, typeList1.get(5).getMonthList().get(0).getValue()); + Assert.assertEquals(27, typeList1.get(2).getMonthList().get(9).getValue()); + Assert.assertEquals(0, typeList1.get(0).getMonthList().get(11).getValue()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceTableTest.java b/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceTableTest.java new file mode 100644 index 000000000..1420a4752 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/attendance/AttendanceTableTest.java @@ -0,0 +1,165 @@ +package io.github.wulkanowy.api.attendance; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class AttendanceTableTest extends StudentAndParentTestCase { + + private AttendanceTable excellent; + + private AttendanceTable full; + + @Before + public void setUp() throws Exception { + excellent = new AttendanceTable(getSnp("Frekwencja-excellent.html")); + full = new AttendanceTable(getSnp("Frekwencja-full.html")); + } + + @Test + public void getWeekStartByDate() throws Exception { + Assert.assertEquals("31.08.2015", excellent.getWeekTable().getStartDayDate()); + Assert.assertEquals("05.09.2016", full.getWeekTable().getStartDayDate()); + } + + @Test + public void getWeekDaysNumber() throws Exception { + Assert.assertEquals(5, excellent.getWeekTable().getDays().size()); + Assert.assertEquals(5, full.getWeekTable().getDays().size()); + } + + @Test + public void getDayLessonsNumber() throws Exception { + Assert.assertEquals(14, excellent.getWeekTable().getDay(0).getLessons().size()); + Assert.assertEquals(14, full.getWeekTable().getDay(0).getLessons().size()); + } + + @Test + public void getDayDate() throws Exception { + Assert.assertEquals("31.08.2015", excellent.getWeekTable().getDay(0).getDate()); + Assert.assertEquals("02.09.2015", excellent.getWeekTable().getDay(2).getDate()); + Assert.assertEquals("04.09.2015", excellent.getWeekTable().getDay(4).getDate()); + + Assert.assertEquals("05.09.2016", full.getWeekTable().getDay(0).getDate()); + Assert.assertEquals("07.09.2016", full.getWeekTable().getDay(2).getDate()); + Assert.assertEquals("09.09.2016", full.getWeekTable().getDay(4).getDate()); + } + + @Test + public void getLessonSubject() throws Exception { + Assert.assertEquals("", + excellent.getWeekTable().getDay(0).getLesson(7).getSubject()); + Assert.assertEquals("Uroczyste rozpoczęcie roku szkolnego 2015/2016", + excellent.getWeekTable().getDay(1).getLesson(1).getSubject()); + Assert.assertEquals("Geografia", + excellent.getWeekTable().getDay(3).getLesson(4).getSubject()); + + Assert.assertEquals("Naprawa komputera", + full.getWeekTable().getDay(1).getLesson(8).getSubject()); + Assert.assertEquals("Religia", + full.getWeekTable().getDay(3).getLesson(1).getSubject()); + Assert.assertEquals("Metodologia programowania", + full.getWeekTable().getDay(4).getLesson(5).getSubject()); + } + + @Test + public void getLessonIsNotExist() throws Exception { + Assert.assertTrue(excellent.getWeekTable().getDay(0).getLesson(5).isNotExist()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(1).isNotExist()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(12).isNotExist()); + + Assert.assertFalse(full.getWeekTable().getDay(1).getLesson(12).isAbsenceUnexcused()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isAbsenceUnexcused()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(5).isAbsenceUnexcused()); + } + + @Test + public void getLessonIsEmpty() throws Exception { + Assert.assertTrue(excellent.getWeekTable().getDay(0).getLesson(0).isEmpty()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(6).isEmpty()); + Assert.assertTrue(excellent.getWeekTable().getDay(4).getLesson(12).isEmpty()); + + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(9).isEmpty()); + Assert.assertFalse(full.getWeekTable().getDay(2).getLesson(5).isEmpty()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(2).isEmpty()); + } + + @Test + public void getLessonIsPresence() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(7).isPresence()); + Assert.assertTrue(excellent.getWeekTable().getDay(1).getLesson(1).isPresence()); + Assert.assertTrue(excellent.getWeekTable().getDay(3).getLesson(7).isPresence()); + + Assert.assertTrue(full.getWeekTable().getDay(0).getLesson(1).isPresence()); + Assert.assertTrue(full.getWeekTable().getDay(2).getLesson(6).isPresence()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(7).isPresence()); + } + + @Test + public void getLessonIsAbsenceUnexcused() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(7).isAbsenceUnexcused()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(0).isAbsenceUnexcused()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(4).isAbsenceUnexcused()); + + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(8).isAbsenceUnexcused()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isAbsenceUnexcused()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(8).isAbsenceUnexcused()); + } + + @Test + public void getLessonIsAbsenceExcused() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(7).isAbsenceExcused()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(0).isAbsenceExcused()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(4).isAbsenceExcused()); + + Assert.assertFalse(full.getWeekTable().getDay(2).getLesson(5).isAbsenceExcused()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isAbsenceExcused()); + Assert.assertTrue(full.getWeekTable().getDay(4).getLesson(3).isAbsenceExcused()); + } + + @Test + public void getLessonIsAbsenceForSchoolReasons() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(4).isAbsenceForSchoolReasons()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(8).isAbsenceForSchoolReasons()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(12).isAbsenceForSchoolReasons()); + + Assert.assertTrue(full.getWeekTable().getDay(2).getLesson(5).isAbsenceForSchoolReasons()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isAbsenceForSchoolReasons()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(8).isAbsenceForSchoolReasons()); + } + + @Test + public void getLessonIsUnexcusedLateness() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(4).isUnexcusedLateness()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(8).isUnexcusedLateness()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(12).isUnexcusedLateness()); + + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(6).isUnexcusedLateness()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isUnexcusedLateness()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(8).isUnexcusedLateness()); + } + + @Test + public void getLessonIsExcusedLateness() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(4).isExcusedLateness()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(8).isExcusedLateness()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(12).isExcusedLateness()); + + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(7).isExcusedLateness()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isExcusedLateness()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(8).isExcusedLateness()); + } + + @Test + public void getLessonIsExemption() throws Exception { + Assert.assertFalse(excellent.getWeekTable().getDay(0).getLesson(4).isExemption()); + Assert.assertFalse(excellent.getWeekTable().getDay(2).getLesson(8).isExemption()); + Assert.assertFalse(excellent.getWeekTable().getDay(4).getLesson(12).isExemption()); + + Assert.assertFalse(full.getWeekTable().getDay(2).getLesson(5).isExemption()); + Assert.assertFalse(full.getWeekTable().getDay(3).getLesson(1).isExemption()); + Assert.assertTrue(full.getWeekTable().getDay(4).getLesson(8).isExemption()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java b/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java new file mode 100644 index 000000000..9b57ddd68 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java @@ -0,0 +1,97 @@ +package io.github.wulkanowy.api.exams; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class ExamsWeekTest extends StudentAndParentTestCase { + + private ExamsWeek onePerDay; + + @Before + public void getCurrent() throws Exception { + onePerDay = new ExamsWeek(getSnp("Sprawdziany-one-per-day.html")); + } + + @Test + public void getWeekTest() throws Exception { + Assert.assertEquals("23.10.2017", onePerDay.getCurrent().getStartDayDate()); + } + + @Test + public void getDaysListTest() throws Exception { + Assert.assertEquals(3, onePerDay.getCurrent().getDays().size()); + Assert.assertEquals(7, onePerDay.getWeek("", false).getDays().size()); + } + + @Test + public void getExamsListTest() throws Exception { + List notEmpty = onePerDay.getCurrent().getDays(); + Assert.assertEquals(1, notEmpty.get(0).getExamList().size()); + Assert.assertEquals(1, notEmpty.get(1).getExamList().size()); + Assert.assertEquals(1, notEmpty.get(2).getExamList().size()); + + List emptyToo = onePerDay.getWeek("", false).getDays(); + Assert.assertEquals(1, emptyToo.get(0).getExamList().size()); + Assert.assertEquals(1, emptyToo.get(1).getExamList().size()); + Assert.assertEquals(1, emptyToo.get(4).getExamList().size()); + } + + @Test + public void getDayDateTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("23.10.2017", dayList.get(0).getDate()); + Assert.assertEquals("24.10.2017", dayList.get(1).getDate()); + Assert.assertEquals("27.10.2017", dayList.get(2).getDate()); + } + + @Test + public void getExamSubjectAndGroupTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("Sieci komputerowe 3Ti|zaw2", dayList.get(0).getExamList().get(0).getSubjectAndGroup()); + Assert.assertEquals("Język angielski 3Ti|J1", dayList.get(1).getExamList().get(0).getSubjectAndGroup()); + Assert.assertEquals("Metodologia programowania 3Ti|zaw2", dayList.get(2).getExamList().get(0).getSubjectAndGroup()); + } + + @Test + public void getExamTypeTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("Sprawdzian", dayList.get(0).getExamList().get(0).getType()); + Assert.assertEquals("Sprawdzian", dayList.get(1).getExamList().get(0).getType()); + Assert.assertEquals("Sprawdzian", dayList.get(2).getExamList().get(0).getType()); + } + + @Test + public void getExamDescriptionTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("Łącza danych", dayList.get(0).getExamList().get(0).getDescription()); + Assert.assertEquals("Czasy teraźniejsze", dayList.get(1).getExamList().get(0).getDescription()); + Assert.assertEquals("", dayList.get(2).getExamList().get(0).getDescription()); + } + + @Test + public void getExamTeacherTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("Adam Wiśniewski [AW]", dayList.get(0).getExamList().get(0).getTeacher()); + Assert.assertEquals("Natalia Nowak [NN]", dayList.get(1).getExamList().get(0).getTeacher()); + Assert.assertEquals("Małgorzata Nowacka [MN]", dayList.get(2).getExamList().get(0).getTeacher()); + } + + @Test + public void getExamEntryDateTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("16.10.2017", dayList.get(0).getExamList().get(0).getEntryDate()); + Assert.assertEquals("17.10.2017", dayList.get(1).getExamList().get(0).getEntryDate()); + Assert.assertEquals("16.10.2017", dayList.get(2).getExamList().get(0).getEntryDate()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/grades/GradesListTest.java b/api/src/test/java/io/github/wulkanowy/api/grades/GradesListTest.java new file mode 100644 index 000000000..bee5b4fee --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/grades/GradesListTest.java @@ -0,0 +1,114 @@ +package io.github.wulkanowy.api.grades; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class GradesListTest extends StudentAndParentTestCase { + + private GradesList filled; + + @Before + public void setUp() throws Exception { + filled = new GradesList(getSnp("OcenyWszystkie-filled.html")); + } + + @Test + public void getAllTest() throws Exception { + Assert.assertEquals(6, filled.getAll().size()); // 2 items are skipped + } + + @Test + public void getSubjectTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("Zajęcia z wychowawcą", list.get(0).getSubject()); + Assert.assertEquals("Język angielski", list.get(3).getSubject()); + Assert.assertEquals("Wychowanie fizyczne", list.get(4).getSubject()); + Assert.assertEquals("Język polski", list.get(5).getSubject()); + } + + @Test + public void getValueTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("5", list.get(0).getValue()); + Assert.assertEquals("5", list.get(3).getValue()); + Assert.assertEquals("1", list.get(4).getValue()); + Assert.assertEquals("1", list.get(5).getValue()); + } + + @Test + public void getColorTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("000000", list.get(0).getColor()); + Assert.assertEquals("1289F7", list.get(3).getColor()); + Assert.assertEquals("6ECD07", list.get(4).getColor()); + Assert.assertEquals("6ECD07", list.get(5).getColor()); + } + + @Test + public void getSymbolTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("A1", list.get(0).getSymbol()); + Assert.assertEquals("BW3", list.get(3).getSymbol()); + Assert.assertEquals("STR", list.get(4).getSymbol()); + Assert.assertEquals("K", list.get(5).getSymbol()); + } + + @Test + public void getDescriptionTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("Dzień Kobiet w naszej klasie", list.get(0).getDescription()); + Assert.assertEquals("Writing", list.get(3).getDescription()); + Assert.assertEquals("", list.get(4).getDescription()); + Assert.assertEquals("Kordian", list.get(5).getDescription()); + } + + @Test + public void getWeightTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("1,00", list.get(0).getWeight()); + Assert.assertEquals("3,00", list.get(3).getWeight()); + Assert.assertEquals("8,00", list.get(4).getWeight()); + Assert.assertEquals("5,00", list.get(5).getWeight()); + } + + @Test + public void getDateTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("2017-03-21", list.get(0).getDate()); + Assert.assertEquals("2017-06-02", list.get(3).getDate()); + Assert.assertEquals("2017-04-02", list.get(4).getDate()); + Assert.assertEquals("2017-02-06", list.get(5).getDate()); + } + + @Test + public void getTeacherTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("Patryk Maciejewski", list.get(0).getTeacher()); + Assert.assertEquals("Oliwia Woźniak", list.get(3).getTeacher()); + Assert.assertEquals("Klaudia Dziedzic", list.get(4).getTeacher()); + Assert.assertEquals("Amelia Stępień", list.get(5).getTeacher()); + } + + @Test + public void getSemesterTest() throws Exception { + List list = filled.getAll(); + + Assert.assertEquals("7654321", list.get(0).getSemester()); + Assert.assertEquals("7654321", list.get(3).getSemester()); + Assert.assertEquals("7654321", list.get(4).getSemester()); + Assert.assertEquals("7654321", list.get(5).getSemester()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/grades/SubjectsListTest.java b/api/src/test/java/io/github/wulkanowy/api/grades/SubjectsListTest.java new file mode 100644 index 000000000..d32283781 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/grades/SubjectsListTest.java @@ -0,0 +1,82 @@ +package io.github.wulkanowy.api.grades; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class SubjectsListTest extends StudentAndParentTestCase { + + private SubjectsList std; + + private SubjectsList average; + + @Before + public void setUp() throws Exception { + std = new SubjectsList(getSnp("OcenyWszystkie-subjects.html")); + average = new SubjectsList(getSnp("OcenyWszystkie-subjects-average.html")); + } + + @Test + public void getAllTest() throws Exception { + Assert.assertEquals(5, std.getAll().size()); + Assert.assertEquals(5, average.getAll().size()); + } + + @Test + public void getNameTest() throws Exception { + List stdList = std.getAll(); + + Assert.assertEquals("Zachowanie", stdList.get(0).getName()); + Assert.assertEquals("Praktyka zawodowa", stdList.get(1).getName()); + Assert.assertEquals("Metodologia programowania", stdList.get(2).getName()); + Assert.assertEquals("Podstawy przedsiębiorczości", stdList.get(3).getName()); + Assert.assertEquals("Wychowanie do życia w rodzinie", stdList.get(4).getName()); + + List averageList = average.getAll(); + Assert.assertEquals("Zachowanie", averageList.get(0).getName()); + Assert.assertEquals("Język polski", averageList.get(1).getName()); + Assert.assertEquals("Wychowanie fizyczne", averageList.get(2).getName()); + Assert.assertEquals("Język angielski", averageList.get(3).getName()); + Assert.assertEquals("Wiedza o społeczeństwie", averageList.get(4).getName()); + } + + @Test + public void getPredictedRatingTest() throws Exception { + List stdList = std.getAll(); + + Assert.assertEquals("bardzo dobre", stdList.get(0).getPredictedRating()); + Assert.assertEquals("-", stdList.get(1).getPredictedRating()); + Assert.assertEquals("bardzo dobry", stdList.get(2).getPredictedRating()); + Assert.assertEquals("3/4", stdList.get(3).getPredictedRating()); + Assert.assertEquals("-", stdList.get(4).getPredictedRating()); + + List averageList = average.getAll(); + Assert.assertEquals("bardzo dobre", averageList.get(0).getPredictedRating()); + Assert.assertEquals("-", averageList.get(1).getPredictedRating()); + Assert.assertEquals("bardzo dobry", averageList.get(2).getPredictedRating()); + Assert.assertEquals("4/5", averageList.get(3).getPredictedRating()); + Assert.assertEquals("-", averageList.get(4).getPredictedRating()); + } + + @Test + public void getFinalRatingTest() throws Exception { + List stdList = std.getAll(); + + Assert.assertEquals("bardzo dobre", stdList.get(0).getFinalRating()); + Assert.assertEquals("celujący", stdList.get(1).getFinalRating()); + Assert.assertEquals("celujący", stdList.get(2).getFinalRating()); + Assert.assertEquals("dostateczny", stdList.get(3).getFinalRating()); + Assert.assertEquals("-", stdList.get(4).getFinalRating()); + + List averageList = average.getAll(); + Assert.assertEquals("bardzo dobre", averageList.get(0).getFinalRating()); + Assert.assertEquals("dobry", averageList.get(1).getFinalRating()); + Assert.assertEquals("celujący", averageList.get(2).getFinalRating()); + Assert.assertEquals("bardzo dobry", averageList.get(3).getFinalRating()); + Assert.assertEquals("-", averageList.get(4).getFinalRating()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java b/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java new file mode 100644 index 000000000..335ab84b6 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java @@ -0,0 +1,104 @@ +package io.github.wulkanowy.api.login; + + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import io.github.wulkanowy.api.Client; +import io.github.wulkanowy.api.FixtureHelper; + +public class LoginTest { + + private String getFixtureAsString(String fixtureFileName) { + return FixtureHelper.getAsString(getClass().getResourceAsStream(fixtureFileName)); + } + + private Client getClient(String fixtureFileName) throws Exception { + Document doc = Jsoup.parse(getFixtureAsString(fixtureFileName)); + + Client client = Mockito.mock(Client.class); + Mockito.when(client.postPageByUrl(Mockito.anyString(), Mockito.any(String[][].class))).thenReturn(doc); + + return client; + } + + @Test + public void loginTest() throws Exception { + Login login = new Login(getClient("Logowanie-success.html")); + + Assert.assertEquals("d123", login.login("a@a", "pswd", "d123")); + } + + @Test(expected = BadCredentialsException.class) + public void sendWrongCredentialsTest() throws Exception { + Login login = new Login(getClient("Logowanie-error.html")); + + login.sendCredentials("a@a", "pswd", "d123"); + } + + @Test + public void sendCredentialsCertificateTest() throws Exception { + Login login = new Login(getClient("Logowanie-certyfikat.html")); + + Assert.assertEquals( + getFixtureAsString("cert.xml").replaceAll("\\s+",""), + login.sendCredentials("a@a", "passwd", "d123").replaceAll("\\s+","") + ); + } + + @Test + public void sendCertificateNotDefaultSymbolSuccessTest() throws Exception { + Login login = new Login(getClient("Logowanie-success.html")); + + Assert.assertEquals("wulkanowyschool321", + login.sendCertificate("", "wulkanowyschool321")); + } + + @Test + public void sendCertificateDefaultSymbolSuccessTest() throws Exception { + Login login = new Login(getClient("Logowanie-success.html")); + + Assert.assertEquals("demo12345", + login.sendCertificate(getFixtureAsString("cert.xml"), "Default")); + } + + @Test(expected = AccountPermissionException.class) + public void sendCertificateAccountPermissionTest() throws Exception { + Login login = new Login(getClient("Logowanie-brak-dostepu.html")); + + login.sendCertificate(getFixtureAsString("cert.xml"), "demo123"); + } + + @Test(expected = LoginErrorException.class) + public void sendCertificateLoginErrorTest() throws Exception { + Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document + + login.sendCertificate(getFixtureAsString("cert.xml"), "demo123"); + } + + @Test(expected = VulcanOfflineException.class) + public void sendCertificateVulcanOfflineTest() throws Exception { + Login login = new Login(getClient("PrzerwaTechniczna.html")); + + login.sendCertificate(getFixtureAsString("cert.xml"), "demo123"); + } + + @Test + public void findSymbolInCertificateTest() throws Exception { + Login login = new Login(getClient("Logowanie-certyfikat.html")); + + String certificate = getFixtureAsString("cert.xml"); + + Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate)); + } + + @Test + public void findSymbolInInvalidCertificateTest() throws Exception { + Login login = new Login(getClient("Logowanie-certyfikat.html")); + + Assert.assertEquals("", login.findSymbolInCertificate("")); // change to real cert with empty symbols + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/messages/MessagesTest.java b/api/src/test/java/io/github/wulkanowy/api/messages/MessagesTest.java new file mode 100644 index 000000000..44880a88d --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/messages/MessagesTest.java @@ -0,0 +1,89 @@ +package io.github.wulkanowy.api.messages; + +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.List; + +import io.github.wulkanowy.api.Client; +import io.github.wulkanowy.api.FixtureHelper; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public class MessagesTest { + + private Client getFixtureAsString(String fixtureFileName) throws Exception { + Client client = Mockito.mock(Client.class); + Mockito.when(client.getJsonStringByUrl(Mockito.anyString())) + .thenReturn(FixtureHelper.getAsString(getClass().getResourceAsStream(fixtureFileName))); + Mockito.when(client.postJsonStringByUrl(Mockito.anyString(), Mockito.any())) + .thenReturn(FixtureHelper.getAsString(getClass().getResourceAsStream(fixtureFileName))); + return client; + } + + @Test + public void getMessages() throws Exception { + Client client = getFixtureAsString("GetWiadomosciOdebrane.json"); + + Messages messages = new Messages(client); + List messageList = messages.getReceived(); + + Assert.assertEquals(true, messageList.get(1).unread); + Assert.assertEquals("2016-03-15 09:00:00", messageList.get(0).date); + Assert.assertEquals(null, messageList.get(0).content); + Assert.assertEquals("Kowalski Jan", messageList.get(0).sender); + Assert.assertEquals(12347, messageList.get(2).id); + } + + @Test + public void getMessagesEmpty() throws Exception { + Client client = getFixtureAsString("GetWiadomosciUsuniete-empty.json"); + + Messages messages = new Messages(client); + List messageList = messages.getSent(); + + Assert.assertTrue(messageList.isEmpty()); + } + + @Test(expected = NotLoggedInErrorException.class) + public void getMessagesError() throws Exception { + Client client = getFixtureAsString("UndefinedError.txt"); + + Messages messages = new Messages(client); + messages.getDeleted(); + } + + @Test(expected = BadRequestException.class) + public void getMessagesBadRequest() throws Exception { + Client client = getFixtureAsString("PageError.html"); + + Messages messages = new Messages(client); + messages.getDeleted(); + } + + @Test + public void getMessage() throws Exception { + Client client = getFixtureAsString("GetTrescWiadomosci.json"); + + Messages messages = new Messages(client); + Message message = messages.getMessage(123, Messages.RECEIVED_FOLDER); + Assert.assertEquals(12345, message.id); + Assert.assertEquals("Witam, …. \nPozdrawiam Krzysztof Czerkas", message.content); + } + + @Test(expected = NotLoggedInErrorException.class) + public void getMessageError() throws Exception { + Client client = getFixtureAsString("UndefinedError.txt"); + + Messages messages = new Messages(client); + messages.getMessage(321, Messages.SENT_FOLDER); + } + + @Test(expected = BadRequestException.class) + public void getMessageBadRequest() throws Exception { + Client client = getFixtureAsString("PageError.html"); + + Messages messages = new Messages(client); + messages.getMessage(1, Messages.DELETED_FOLDER); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/notes/AchievementsListTest.java b/api/src/test/java/io/github/wulkanowy/api/notes/AchievementsListTest.java new file mode 100644 index 000000000..0d7774bb4 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/notes/AchievementsListTest.java @@ -0,0 +1,36 @@ +package io.github.wulkanowy.api.notes; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class AchievementsListTest extends StudentAndParentTestCase { + + private AchievementsList filledAchievementsList; + + private AchievementsList emptyAchievementsList; + + @Before + public void setUp() throws Exception { + filledAchievementsList = new AchievementsList(getSnp("UwagiOsiagniecia-filled.html")); + emptyAchievementsList = new AchievementsList(getSnp("UwagiOsiagniecia-empty.html")); + } + + @Test + public void getAllAchievementsTest() throws Exception { + Assert.assertEquals(2, filledAchievementsList.getAllAchievements().size()); + Assert.assertEquals(0, emptyAchievementsList.getAllAchievements().size()); + } + + @Test + public void getAchievements() throws Exception { + List filledList = filledAchievementsList.getAllAchievements(); + + Assert.assertEquals("I miejsce w ogólnopolskim konkursie ortograficznym", filledList.get(0)); + Assert.assertEquals("III miejsce w ogólnopolskim konkursie plastycznym", filledList.get(1)); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/notes/NotesListTest.java b/api/src/test/java/io/github/wulkanowy/api/notes/NotesListTest.java new file mode 100644 index 000000000..d76c06486 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/notes/NotesListTest.java @@ -0,0 +1,60 @@ +package io.github.wulkanowy.api.notes; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class NotesListTest extends StudentAndParentTestCase { + + private NotesList filled; + + private NotesList empty; + + @Before + public void setUp() throws Exception { + filled = new NotesList(getSnp("UwagiOsiagniecia-filled.html")); + empty = new NotesList(getSnp("UwagiOsiagniecia-empty.html")); + } + + @Test + public void getAllNotesTest() throws Exception { + Assert.assertEquals(3, filled.getAllNotes().size()); + Assert.assertEquals(0, empty.getAllNotes().size()); + } + + @Test + public void getDateTest() throws Exception { + List filledList = filled.getAllNotes(); + + Assert.assertEquals("06.06.2017", filledList.get(0).getDate()); + Assert.assertEquals("01.10.2016", filledList.get(2).getDate()); + } + + @Test + public void getTeacherTest() throws Exception { + List filledList = filled.getAllNotes(); + + Assert.assertEquals("Jan Kowalski [JK]", filledList.get(0).getTeacher()); + Assert.assertEquals("Kochański Leszek [KL]", filledList.get(2).getTeacher()); + } + + @Test + public void getCategoryTest() throws Exception { + List filledList = filled.getAllNotes(); + + Assert.assertEquals("Zaangażowanie społeczne", filledList.get(0).getCategory()); + Assert.assertEquals("Zachowanie na lekcji", filledList.get(2).getCategory()); + } + + @Test + public void getContentTest() throws Exception { + List filledList = filled.getAllNotes(); + + Assert.assertEquals("Pomoc przy pikniku charytatywnym", filledList.get(0).getContent()); + Assert.assertEquals("Przeszkadzanie w prowadzeniu lekcji", filledList.get(2).getContent()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/school/SchoolInfoTest.java b/api/src/test/java/io/github/wulkanowy/api/school/SchoolInfoTest.java new file mode 100644 index 000000000..947db9b8f --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/school/SchoolInfoTest.java @@ -0,0 +1,48 @@ +package io.github.wulkanowy.api.school; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class SchoolInfoTest extends StudentAndParentTestCase { + + private SchoolInfo schoolInfo; + + @Before + public void setUp() throws Exception { + schoolInfo = new SchoolInfo(getSnp("Szkola.html")); + } + + @Test + public void getNameTest() throws Exception { + Assert.assertEquals("Zespół Szkół nr 64", schoolInfo.getSchoolData().getName()); + } + + @Test + public void getAddressTest() throws Exception { + Assert.assertEquals("ul. Wiśniowa 128, 01-234 Rogalowo, Nibylandia", + schoolInfo.getSchoolData().getAddress()); + } + + @Test + public void getPhoneNumberTest() throws Exception { + Assert.assertEquals("55 5555555", schoolInfo.getSchoolData().getPhoneNumber()); + } + + @Test + public void getHeadmasterTest() throws Exception { + Assert.assertEquals("Antoni Sobczyk", schoolInfo.getSchoolData().getHeadmaster()); + } + + @Test + public void getPedagoguesTest() throws Exception { + Assert.assertArrayEquals(new String[]{ + "Zofia Czerwińska [ZC]", + "Aleksander Krzemiński [AK]", + "Karolina Kowalska [KK]", + "Bartek Dąbrowski [BD]" + }, schoolInfo.getSchoolData().getPedagogues()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/school/TeachersInfoTest.java b/api/src/test/java/io/github/wulkanowy/api/school/TeachersInfoTest.java new file mode 100644 index 000000000..b0da356b1 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/school/TeachersInfoTest.java @@ -0,0 +1,56 @@ +package io.github.wulkanowy.api.school; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class TeachersInfoTest extends StudentAndParentTestCase { + + private TeachersInfo teachersInfo; + + @Before + public void setUp() throws Exception { + teachersInfo = new TeachersInfo(getSnp("Szkola.html")); + } + + @Test + public void getClassNameTest() throws Exception { + Assert.assertEquals("1a", teachersInfo.getTeachersData().getClassName()); + } + + @Test + public void getClassTeacherTest() throws Exception { + Assert.assertArrayEquals(new String[]{ + "Karolina Kowalska [AN]", + "Antoni Sobczyk [AS]" + }, teachersInfo.getTeachersData().getClassTeacher()); + } + + @Test + public void getTeachersDataSubjectsNameTest() throws Exception { + List subjects = teachersInfo.getTeachersData().getSubjects(); + + Assert.assertEquals("Biologia", subjects.get(0).getName()); + Assert.assertEquals("Język angielski", subjects.get(6).getName()); + } + + @Test + public void getTeachersDataSubjectsTeachersTest() throws Exception { + List subjects = teachersInfo.getTeachersData().getSubjects(); + + Assert.assertArrayEquals(new String[]{"Karolina Kowalska [AN]"}, + subjects.get(0).getTeachers()); + Assert.assertEquals("Karolina Kowalska [AN]", + subjects.get(0).getTeachers()[0]); + + Assert.assertArrayEquals(new String[]{ + "Karolina Kowalska [AN]", + "Mateusz Kowal [MK]", + "Amelia Mazur [AM]" + }, subjects.get(6).getTeachers()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/timetable/TimetableTest.java b/api/src/test/java/io/github/wulkanowy/api/timetable/TimetableTest.java new file mode 100644 index 000000000..652676348 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/timetable/TimetableTest.java @@ -0,0 +1,242 @@ +package io.github.wulkanowy.api.timetable; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class TimetableTest extends StudentAndParentTestCase { + + private Timetable std; + + private Timetable full; + + private Timetable holidays; + + @Before + public void setUp() throws Exception { + std = new Timetable(getSnp("PlanLekcji-std.html")); + full = new Timetable(getSnp("PlanLekcji-full.html")); + holidays = new Timetable(getSnp("PlanLekcji-holidays.html")); + } + + // Week + + @Test + public void getWeekTableTest() throws Exception { + Assert.assertEquals(5, std.getWeekTable().getDays().size()); + Assert.assertEquals(5, full.getWeekTable().getDays().size()); + Assert.assertEquals(5, holidays.getWeekTable().getDays().size()); + } + + @Test + public void getStartDayDateTest() throws Exception { + Assert.assertEquals("2017-06-19", std.getWeekTable().getStartDayDate()); + Assert.assertEquals("2017-06-19", full.getWeekTable().getStartDayDate()); + Assert.assertEquals("2017-07-31", holidays.getWeekTable().getStartDayDate()); + } + + // ExamDay + + @Test + public void getDayNameTest() throws Exception { + Assert.assertEquals("poniedziałek", std.getWeekTable().getDay(0).getDayName()); + Assert.assertEquals("piątek", std.getWeekTable().getDay(4).getDayName()); + Assert.assertEquals("wtorek", full.getWeekTable().getDay(1).getDayName()); + Assert.assertEquals("czwartek", full.getWeekTable().getDay(3).getDayName()); + Assert.assertEquals("środa", holidays.getWeekTable().getDay(2).getDayName()); + } + + @Test + public void getDayDateTest() throws Exception { + Assert.assertEquals("2017-06-19", std.getWeekTable().getDay(0).getDate()); + Assert.assertEquals("2017-06-23", std.getWeekTable().getDay(4).getDate()); + Assert.assertEquals("2017-06-20", full.getWeekTable().getDay(1).getDate()); + Assert.assertEquals("2017-06-22", full.getWeekTable().getDay(3).getDate()); + Assert.assertEquals("2017-08-02", holidays.getWeekTable().getDay(2).getDate()); + } + + @Test + public void getDayIsFreeTest() throws Exception { + Assert.assertFalse(std.getWeekTable().getDay(0).isFreeDay()); + Assert.assertFalse(full.getWeekTable().getDay(2).isFreeDay()); + Assert.assertTrue(holidays.getWeekTable().getDay(4).isFreeDay()); + } + + @Test + public void getDayFreeDayName() throws Exception { + Assert.assertNotEquals("Wakacje", std.getWeekTable().getDay(0).getFreeDayName()); + Assert.assertNotEquals("Ferie letnie", full.getWeekTable().getDay(1).getFreeDayName()); + Assert.assertNotEquals("Wakacje", holidays.getWeekTable().getDay(2).getFreeDayName()); + Assert.assertEquals("Ferie letnie", holidays.getWeekTable().getDay(4).getFreeDayName()); + } + + @Test + public void getDayLessonsTest() throws Exception { + Assert.assertEquals(8, std.getWeekTable().getDay(0).getLessons().size()); + Assert.assertEquals(14, full.getWeekTable().getDay(2).getLessons().size()); + Assert.assertEquals(14, holidays.getWeekTable().getDay(4).getLessons().size()); + } + + // Lesson + + @Test + public void getLessonNumberTest() throws Exception { + Assert.assertEquals("2", std.getWeekTable().getDay(0).getLesson(1).getNumber()); + Assert.assertEquals("5", std.getWeekTable().getDay(2).getLesson(4).getNumber()); + Assert.assertEquals("0", full.getWeekTable().getDay(0).getLesson(0).getNumber()); + Assert.assertEquals("13", full.getWeekTable().getDay(4).getLesson(13).getNumber()); + Assert.assertEquals("3", holidays.getWeekTable().getDay(3).getLesson(3).getNumber()); + } + + @Test + public void getLessonDayTest() throws Exception { + Assert.assertEquals("2017-06-19", std.getWeekTable().getDay(0).getLesson(1).getDate()); + Assert.assertEquals("2017-06-23", std.getWeekTable().getDay(4).getLesson(4).getDate()); + Assert.assertEquals("2017-06-20", full.getWeekTable().getDay(1).getLesson(6).getDate()); + Assert.assertEquals("2017-06-22", full.getWeekTable().getDay(3).getLesson(3).getDate()); + Assert.assertEquals("2017-08-02", holidays.getWeekTable().getDay(2).getLesson(8).getDate()); + } + + @Test + public void getLessonSubjectTest() throws Exception { + Assert.assertEquals("Historia", std.getWeekTable().getDay(0).getLesson(1).getSubject()); + Assert.assertEquals("Zajęcia techniczne", std.getWeekTable().getDay(2).getLesson(4).getSubject()); + Assert.assertEquals("Wychowanie fizyczne", std.getWeekTable().getDay(1).getLesson(1).getSubject()); + Assert.assertEquals("Język angielski", full.getWeekTable().getDay(0).getLesson(1).getSubject()); + Assert.assertEquals("Wychowanie do życia w rodzinie", full.getWeekTable().getDay(2).getLesson(0).getSubject()); + Assert.assertEquals("Wychowanie fizyczne", full.getWeekTable().getDay(3).getLesson(1).getSubject()); + Assert.assertEquals("Uroczyste zakończenie roku szkolnego", full.getWeekTable().getDay(4).getLesson(0).getSubject()); + Assert.assertEquals("Fizyka", full.getWeekTable().getDay(0).getLesson(0).getSubject()); + Assert.assertEquals("Metodologia programowania", full.getWeekTable().getDay(1).getLesson(0).getSubject()); + Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getSubject()); + } + + @Test + public void getLessonTeacherTest() throws Exception { + Assert.assertEquals("Bogatka Katarzyna", std.getWeekTable().getDay(0).getLesson(1).getTeacher()); + Assert.assertEquals("Chlebowski Stanisław", std.getWeekTable().getDay(2).getLesson(4).getTeacher()); + Assert.assertEquals("Kobczyk Iwona", full.getWeekTable().getDay(0).getLesson(1).getTeacher()); + Assert.assertEquals("Bączek Grzegorz", full.getWeekTable().getDay(0).getLesson(7).getTeacher()); + Assert.assertEquals("Nowak Jadwiga", full.getWeekTable().getDay(2).getLesson(0).getTeacher()); + Assert.assertEquals("Nowicka Irena", full.getWeekTable().getDay(3).getLesson(1).getTeacher()); + Assert.assertEquals("Baran Małgorzata", full.getWeekTable().getDay(4).getLesson(0).getTeacher()); + Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getTeacher()); + } + + @Test + public void getLessonRoomTest() throws Exception { + Assert.assertEquals("", std.getWeekTable().getDay(3).getLesson(3).getRoom()); + Assert.assertEquals("33", full.getWeekTable().getDay(0).getLesson(7).getRoom()); + Assert.assertEquals("19", full.getWeekTable().getDay(0).getLesson(0).getRoom()); + Assert.assertEquals("32", full.getWeekTable().getDay(1).getLesson(0).getRoom()); + Assert.assertEquals("32", full.getWeekTable().getDay(1).getLesson(8).getRoom()); + Assert.assertEquals("32", full.getWeekTable().getDay(2).getLesson(8).getRoom()); + Assert.assertEquals("G4", full.getWeekTable().getDay(3).getLesson(1).getRoom()); + Assert.assertEquals("37", full.getWeekTable().getDay(4).getLesson(0).getRoom()); + Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getRoom()); + } + + @Test + public void getLessonDescriptionTest() throws Exception { + Assert.assertEquals("", std.getWeekTable().getDay(3).getLesson(3).getDescription()); + Assert.assertEquals("przeniesiona z lekcji 7, 01.12.2017", full.getWeekTable().getDay(1).getLesson(1).getDescription()); + Assert.assertEquals("okienko dla uczniów", full.getWeekTable().getDay(0).getLesson(7).getDescription()); + Assert.assertEquals("przeniesiona z lekcji 7, 20.06.2017", full.getWeekTable().getDay(1).getLesson(2).getDescription()); + Assert.assertEquals("przeniesiona z lekcji 4, 20.06.2017", full.getWeekTable().getDay(1).getLesson(3).getDescription()); + Assert.assertEquals("zastępstwo (poprzednio: Religia)", full.getWeekTable().getDay(2).getLesson(0).getDescription()); + Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription()); + Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription()); + Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription()); + Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getDescription()); + } + + @Test + public void getLessonGroupNameTest() throws Exception { + Assert.assertEquals("CH", std.getWeekTable().getDay(0).getLesson(2).getGroupName()); + Assert.assertEquals("JNPW", std.getWeekTable().getDay(4).getLesson(0).getGroupName()); + Assert.assertEquals("", full.getWeekTable().getDay(0).getLesson(7).getGroupName()); + Assert.assertEquals("zaw2", full.getWeekTable().getDay(1).getLesson(0).getGroupName()); + Assert.assertEquals("wf2", full.getWeekTable().getDay(1).getLesson(3).getGroupName()); + Assert.assertEquals("zaw1", full.getWeekTable().getDay(3).getLesson(1).getGroupName()); + Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getGroupName()); + } + + @Test + public void getLessonStartTimeTest() throws Exception { + Assert.assertEquals("08:00", std.getWeekTable().getDay(0).getLesson(0).getStartTime()); + Assert.assertEquals("14:10", std.getWeekTable().getDay(3).getLesson(7).getStartTime()); + Assert.assertEquals("07:10", full.getWeekTable().getDay(0).getLesson(0).getStartTime()); + Assert.assertEquals("12:20", full.getWeekTable().getDay(2).getLesson(6).getStartTime()); + Assert.assertEquals("12:20", holidays.getWeekTable().getDay(2).getLesson(6).getStartTime()); + } + + @Test + public void getLessonEndTimeTest() throws Exception { + Assert.assertEquals("08:45", std.getWeekTable().getDay(1).getLesson(0).getEndTime()); + Assert.assertEquals("12:15", std.getWeekTable().getDay(2).getLesson(4).getEndTime()); + Assert.assertEquals("07:55", full.getWeekTable().getDay(1).getLesson(0).getEndTime()); + Assert.assertEquals("19:00", full.getWeekTable().getDay(3).getLesson(13).getEndTime()); + Assert.assertEquals("19:00", holidays.getWeekTable().getDay(3).getLesson(13).getEndTime()); + } + + @Test + public void getLessonIsEmptyTest() throws Exception { + Assert.assertFalse(std.getWeekTable().getDay(1).getLesson(4).isEmpty()); + Assert.assertTrue(std.getWeekTable().getDay(3).getLesson(7).isEmpty()); + Assert.assertFalse(full.getWeekTable().getDay(1).getLesson(1).isEmpty()); + Assert.assertFalse(full.getWeekTable().getDay(1).getLesson(2).isEmpty()); + Assert.assertFalse(full.getWeekTable().getDay(0).getLesson(7).isEmpty()); + Assert.assertTrue(full.getWeekTable().getDay(2).getLesson(9).isEmpty()); + Assert.assertTrue(holidays.getWeekTable().getDay(0).getLesson(5).isEmpty()); + Assert.assertTrue(holidays.getWeekTable().getDay(4).getLesson(13).isEmpty()); + } + + @Test + public void getLessonIsDivisionIntoGroupsTest() throws Exception { + Assert.assertTrue(std.getWeekTable().getDay(0).getLesson(2).isDivisionIntoGroups()); + Assert.assertTrue(std.getWeekTable().getDay(4).getLesson(0).isDivisionIntoGroups()); + Assert.assertFalse(full.getWeekTable().getDay(0).getLesson(7).isDivisionIntoGroups()); + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isDivisionIntoGroups()); + Assert.assertTrue(full.getWeekTable().getDay(3).getLesson(1).isDivisionIntoGroups()); + Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isDivisionIntoGroups()); + } + + @Test + public void getLessonIsPlanningTest() throws Exception { + Assert.assertFalse(std.getWeekTable().getDay(4).getLesson(4).isPlanning()); + Assert.assertFalse(full.getWeekTable().getDay(0).getLesson(1).isPlanning()); + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isPlanning()); + Assert.assertTrue(full.getWeekTable().getDay(4).getLesson(0).isPlanning()); + Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isPlanning()); + } + + @Test + public void getLessonIsRealizedTest() throws Exception { + Assert.assertTrue(std.getWeekTable().getDay(3).getLesson(3).isRealized()); + Assert.assertTrue(full.getWeekTable().getDay(0).getLesson(1).isRealized()); + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isRealized()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(0).isRealized()); + Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isRealized()); + } + + @Test + public void getLessonIsMovedOrCanceledTest() throws Exception { + Assert.assertFalse(std.getWeekTable().getDay(3).getLesson(3).isMovedOrCanceled()); + Assert.assertTrue(full.getWeekTable().getDay(0).getLesson(7).isMovedOrCanceled()); + Assert.assertFalse(full.getWeekTable().getDay(1).getLesson(3).isMovedOrCanceled()); + Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(0).isMovedOrCanceled()); + Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isMovedOrCanceled()); + } + + @Test + public void getLessonIsNewMovedInOrChangedTest() throws Exception { + Assert.assertFalse(std.getWeekTable().getDay(3).getLesson(3).isNewMovedInOrChanged()); + Assert.assertFalse(full.getWeekTable().getDay(0).getLesson(1).isNewMovedInOrChanged()); + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(2).isNewMovedInOrChanged()); + Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isNewMovedInOrChanged()); + Assert.assertTrue(full.getWeekTable().getDay(3).getLesson(1).isNewMovedInOrChanged()); + Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isNewMovedInOrChanged()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/user/BasicInformationTest.java b/api/src/test/java/io/github/wulkanowy/api/user/BasicInformationTest.java new file mode 100644 index 000000000..6b729c95a --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/user/BasicInformationTest.java @@ -0,0 +1,106 @@ +package io.github.wulkanowy.api.user; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class BasicInformationTest extends StudentAndParentTestCase { + + private BasicInformation basicInformation; + + @Before + public void setUp() throws Exception { + basicInformation = new BasicInformation(getSnp("UczenDanePodstawowe.html")); + } + + @Test + public void getPersonalFirstNameTest() throws Exception { + Assert.assertEquals("Maria", basicInformation.getPersonalData().getFirstName()); + } + + @Test + public void getPersonalSurnameTest() throws Exception { + Assert.assertEquals("Kamińska", basicInformation.getPersonalData().getSurname()); + } + + @Test + public void getPersonalFirstAndLastNameTest() throws Exception { + Assert.assertEquals("Maria Kamińska", + basicInformation.getPersonalData().getFirstAndLastName()); + } + + @Test + public void getPersonalNameTest() throws Exception { + Assert.assertEquals("Maria Aneta Kamińska", basicInformation.getPersonalData().getName()); + } + + @Test + public void getPersonalDateAndBirthPlaceTest() throws Exception { + Assert.assertEquals("01.01.1900, Warszawa", + basicInformation.getPersonalData().getDateAndBirthPlace()); + } + + @Test + public void getPersonalPeselTest() throws Exception { + Assert.assertEquals("12345678900", basicInformation.getPersonalData().getPesel()); + } + + @Test + public void getPersonalGenderTest() throws Exception { + Assert.assertEquals("Kobieta", basicInformation.getPersonalData().getGender()); + } + + @Test + public void isPersonalPolishCitizenshipTest() throws Exception { + Assert.assertTrue(basicInformation.getPersonalData().isPolishCitizenship()); + } + + @Test + public void getPersonalFamilyNameTest() throws Exception { + Assert.assertEquals("Nowak", basicInformation.getPersonalData().getFamilyName()); + } + + @Test + public void getPersonalParentsNames() throws Exception { + Assert.assertEquals("Gabriela, Kamil", + basicInformation.getPersonalData().getParentsNames()); + } + + @Test + public void getBasicAddressTest() throws Exception { + Assert.assertEquals("ul. Sportowa 16, 00-123 Warszawa", + basicInformation.getAddressData().getAddress()); + } + + @Test + public void getBasicRegisteredAddressTest() throws Exception { + Assert.assertEquals("ul. Sportowa 17, 00-123 Warszawa", + basicInformation.getAddressData().getRegisteredAddress()); + } + + @Test + public void getBasicCorrespondenceAddressTest() throws Exception { + Assert.assertEquals("ul. Sportowa 18, 00-123 Warszawa", + basicInformation.getAddressData().getCorrespondenceAddress()); + } + + @Test + public void getContactPhoneNumberTest() throws Exception { + Assert.assertEquals("005554433", + basicInformation.getContactDetails().getPhoneNumber()); + } + + @Test + public void getContactCellPhoneNumberTest() throws Exception { + Assert.assertEquals("555444333", + basicInformation.getContactDetails().getCellPhoneNumber()); + } + + @Test + public void getContactEmailTest() throws Exception { + Assert.assertEquals("wulkanowy@example.null", + basicInformation.getContactDetails().getEmail()); + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/user/FamilyInformationTest.java b/api/src/test/java/io/github/wulkanowy/api/user/FamilyInformationTest.java new file mode 100644 index 000000000..b4f858ece --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/user/FamilyInformationTest.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.api.user; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import io.github.wulkanowy.api.StudentAndParentTestCase; + +public class FamilyInformationTest extends StudentAndParentTestCase { + + private FamilyInformation familyInformation; + + @Before + public void setUp() throws Exception { + familyInformation = new FamilyInformation(getSnp("UczenDanePodstawowe.html")); + } + + @Test + public void getFamilyMembers() throws Exception { + Assert.assertEquals(2, familyInformation.getFamilyMembers().size()); + } + + @Test + public void getNameTest() throws Exception { + List list = familyInformation.getFamilyMembers(); + Assert.assertEquals("Marianna Pająk", list.get(0).getName()); + Assert.assertEquals("Dawid Świątek", list.get(1).getName()); + } + + @Test + public void getKinshipTest() throws Exception { + List list = familyInformation.getFamilyMembers(); + Assert.assertEquals("matka", list.get(0).getKinship()); + Assert.assertEquals("ojciec", list.get(1).getKinship()); + } + + @Test + public void getAddressTest() throws Exception { + List list = familyInformation.getFamilyMembers(); + Assert.assertEquals("ul. Sportowa 16, 00-123 Warszawa", list.get(0).getAddress()); + Assert.assertEquals("ul. Sportowa 18, 00-123 Warszawa", list.get(1).getAddress()); + } + + @Test + public void getTelephonesTest() throws Exception { + List list = familyInformation.getFamilyMembers(); + Assert.assertEquals("555111222", list.get(0).getTelephones()); + Assert.assertEquals("555222111", list.get(1).getTelephones()); + } + + @Test + public void getEmailTest() throws Exception { + List list = familyInformation.getFamilyMembers(); + Assert.assertEquals("wulkanowy@example.null", list.get(0).getEmail()); + Assert.assertEquals("wulkanowy@example.null", list.get(1).getEmail()); + } +} diff --git a/api/src/test/resources/io/github/wulkanowy/api/OcenyWszystkie-semester.html b/api/src/test/resources/io/github/wulkanowy/api/OcenyWszystkie-semester.html new file mode 100644 index 000000000..f4b712c17 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/OcenyWszystkie-semester.html @@ -0,0 +1,21 @@ + + + + + Witryna ucznia i rodzica – Oceny + + +
+

Oceny

+
+
+ + +
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/Start.html b/api/src/test/resources/io/github/wulkanowy/api/Start.html new file mode 100644 index 000000000..40e691610 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/Start.html @@ -0,0 +1,24 @@ + + + + + Uonet+ + + +
+ +
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-excellent.html b/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-excellent.html new file mode 100644 index 000000000..5eaf50dfe --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-excellent.html @@ -0,0 +1,408 @@ + + + + + Witryna ucznia i rodzica – Frekwencja + + + +
+

Frekwencja

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lekcjaponiedziałek
31.08.2015
wtorek
01.09.2015
środa
02.09.2015
czwartek
03.09.2015
piątek
04.09.2015
0
1 +
+ Uroczyste rozpoczęcie roku szkolnego 2015/2016 +
+
+
+ Wychowanie do życia w rodzinie +
+
+
+ Urządzenia techniki komputerowej +
+
2 +
+ Język angielski +
+
+
+ Język niemiecki +
+
+
+ Urządzenia techniki komputerowej +
+
3 +
+ Systemy operacyjne +
+
+
+ Chemia +
+
+
+ Urządzenia techniki komputerowej +
+
4 +
+ Systemy operacyjne +
+
+
+ Geografia +
+
+
+ Urządzenia techniki komputerowej +
+
5 +
+ Tworzenie stron internetowych +
+
+
+ Matematyka +
+
+
+ Język polski +
+
6 +
+ Tworzenie stron internetowych +
+
+
+ Fizyka +
+
+
+ Matematyka +
+
7 +
+ Wychowanie fizyczne +
+
+
+ Język polski +
+
+
+ Historia +
+
8 +
+ Wychowanie fizyczne +
+
9
10
11
12
13
+

Statystyki

+
+ + +
+

Frekwencja od początku roku szkolnego: 100,00%

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IXXXIXIIIIIIIIIVVVIVIIVIIIRazem
Obecność14214313911013175126139921141211
Nieobecność nieusprawiedliwiona
Nieobecność usprawiedliwiona
Nieobecność z przyczyn szkolnych
Spóźnienie nieusprawiedliwione
Spóźnienie usprawiedliwione
Zwolnienie
+
+
wersja: 17.07.0002.24480
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-full.html b/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-full.html new file mode 100644 index 000000000..aa9953053 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/attendance/Frekwencja-full.html @@ -0,0 +1,498 @@ + + + + + Witryna ucznia i rodzica – Frekwencja + + + +
+

Frekwencja

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lekcjaponiedziałek
05.09.2016
wtorek
06.09.2016
środa
07.09.2016
czwartek
08.09.2016
piątek
09.09.2016
0
1 +
+ Urządzenia techniki komputerowej +
+
+
+ Multimedia i grafika komputerowa +
+
+
+ Użytkowanie urządzeń peryferyjnych komputera +
+
+
+ Religia +
+
2 +
+ Urządzenia techniki komputerowej +
+
+
+ Język niemiecki +
+
+
+ Użytkowanie urządzeń peryferyjnych komputera +
+
+
+ Język niemiecki +
+
+
+ Sieci komputerowe i administrowanie sieciami +
+
3 +
+ Urządzenia techniki komputerowej +
+
+
+ Fizyka +
+
+
+ Historia +
+
+
+ Wychowanie fizyczne +
+
+
+ Wiedza o kulturze +
+
4 +
+ Naprawa komputera +
+
+
+ Wychowanie fizyczne +
+
+
+ Język angielski +
+
+
+ Wychowanie fizyczne +
+
+
+ Język polski +
+
5 +
+ Sieci komputerowe i administrowanie sieciami +
+
+
+ Metodologia programowania +
+
+
+ Urządzenia techniki komputerowej +
+
+
+ Matematyka +
+
+
+ Metodologia programowania +
+
6 +
+ Język niemiecki +
+
+
+ Sieci komputerowe i administrowanie sieciami +
+
+
+ Język polski +
+
+
+ Podstawy przedsiębiorczości +
+
+
+ Matematyka +
+
7 +
+ Fizyka +
+
+
+ Język polski +
+
+
+ Systemy operacyjne +
+
+
+ Zajęcia z wychowawcą +
+
+
+ Religia +
+
8 +
+ Naprawa komputera +
+
+
+ Systemy operacyjne +
+
+
+ Urządzenia techniki komputerowej +
+
+
+ Zajęcia z wychowawcą +
+
9
10
11
12
13
+

Statystyki

+
+ + +
+

Frekwencja od początku roku szkolnego: 80,94%

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IXXXIXIIIIIIIIIVVVIVIIVIIIRazem
Obecność1351031085437100339010359822
Nieobecność nieusprawiedliwiona246
Nieobecność usprawiedliwiona627293044161327192
Nieobecność z przyczyn szkolnych77
Spóźnienie nieusprawiedliwione41222112
Spóźnienie usprawiedliwione11
Zwolnienie112
+
+
wersja: 17.07.0002.24480
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-one-per-day.html b/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-one-per-day.html new file mode 100644 index 000000000..ecc48cf16 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-one-per-day.html @@ -0,0 +1,85 @@ + + + + + Witryna ucznia i rodzica – Terminarz sprawdzianów + + +
+

Sprawdziany

+

Tydzień 23.10.2017 - 29.10.2017

+
+

poniedziałek, 23.10.2017

+
+
+
Przedmiot i grupa:
+
Sieci komputerowe 3Ti|zaw2
+
+
+
Rodzaj sprawdzianu:
+
Sprawdzian
+
+
+
Opis:
+
Łącza danych
+
+
+
Nauczyciel i data wpisu:
+
Adam Wiśniewski [AW], 16.10.2017
+
+
+
+
+

wtorek, 24.10.2017

+
+
+
Przedmiot i grupa:
+
Język angielski 3Ti|J1
+
+
+
Rodzaj sprawdzianu:
+
Sprawdzian
+
+
+
Opis:
+
Czasy teraźniejsze
+
+
+
Nauczyciel i data wpisu:
+
Natalia Nowak [NN], 17.10.2017
+
+
+
+
+
+
+

piątek, 27.10.2017

+
+
+
Przedmiot i grupa:
+
Metodologia programowania 3Ti|zaw2
+
+
+
Rodzaj sprawdzianu:
+
Sprawdzian
+
+
+
Opis:
+
+
+
+
Nauczyciel i data wpisu:
+
Małgorzata Nowacka [MN], 16.10.2017
+
+
+
+
+
+ +
+
wersja: 17.08.0001.24874
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-filled.html b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-filled.html new file mode 100644 index 000000000..a229d1d53 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-filled.html @@ -0,0 +1,108 @@ + + + + + Witryna ucznia i rodzica – Oceny + + +
+

Oceny

+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PrzedmiotOcena cząstkowaOpisWagaDataNauczyciel
ZachowanieBrak ocen
Zajęcia z wychowawcą + 5 + A1, Dzień Kobiet w naszej klasie1,0021.03.2017Patryk Maciejewski
Edukacja dla bezpieczeństwa + 4- + S1, PIERWSZA POMOC I RESUSCYTACJA5,0031.03.2017Weronika Ratajczak
Fizyka + 2 + O, Odpowiedź3,0025.06.2017Jakub Michalak
Język angielski + 5 + BW3, Writing3,0002.06.2017Oliwia Woźniak
Wiedza o społeczeństwieBrak ocen
Wychowanie fizyczne1STR8,0002.04.2017Klaudia Dziedzic
Język polski1K, Kordian5,0006.02.2017Amelia Stępień
+
+
wersja: 17.02.0000.23328
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects-average.html b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects-average.html new file mode 100644 index 000000000..023b5405e --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects-average.html @@ -0,0 +1,70 @@ + + + + + Witryna ucznia i rodzica – Oceny + + +
+

Oceny

+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PrzedmiotOceny cząstkoweŚredniaPrzewidywana ocena rocznaOcena roczna
ZachowanieBrak ocen-bardzo dobrebardzo dobre
Język polski03,53-dobry
Wychowanie fizyczne05,05bardzo dobrycelujący
Język angielski04,44/5bardzo dobry
Wiedza o społeczeństwieBrak ocen---
+
+
wersja: 17.02.0000.23328
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects.html b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects.html new file mode 100644 index 000000000..0f6da4148 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/grades/OcenyWszystkie-subjects.html @@ -0,0 +1,64 @@ + + + + + Witryna ucznia i rodzica – Oceny + + +
+

Oceny

+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PrzedmiotOceny cząstkowePrzewidywana ocena rocznaOcena roczna
Zachowanie-bardzo dobrebardzo dobre
Praktyka zawodowa--celujący
Metodologia programowania-bardzo dobrycelujący
Podstawy przedsiębiorczości-3/4dostateczny
Wychowanie do życia w rodzinie---
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-brak-dostepu.html b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-brak-dostepu.html new file mode 100644 index 000000000..2911f1d24 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-brak-dostepu.html @@ -0,0 +1,15 @@ + + + + Logowanie + + +
+
+ Adres example@wulkanowy.io nie został zarejestrowany w dzienniku uczniowskim jako adres rodzica, bądź ucznia. + Jeśli jesteś rodzicem (prawnym opiekunem) ucznia (lub uczniem) szkoły korzystającej z dziennika „UONET +” udaj się do + wychowawcy i poproś o wprowadzenie Twojego adresu e-mail do Twoich danych. +
+
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-certyfikat.html b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-certyfikat.html new file mode 100644 index 000000000..a8496cd1b --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-certyfikat.html @@ -0,0 +1,17 @@ + + + Working... + + +
+ + + + +
+ + + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-error.html b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-error.html new file mode 100644 index 000000000..087131882 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-error.html @@ -0,0 +1,18 @@ + + + + Logowanie (demo123) + + +
+
+
+ Zła nazwa użytkownika lub hasło +
+
+
+ + + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html new file mode 100644 index 000000000..23c27a3fe --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html @@ -0,0 +1,16 @@ + + + + + Uonet+ + + +
+
+
+ example@wulkanowy.io (wyloguj) +
+
+
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/PrzerwaTechniczna.html b/api/src/test/resources/io/github/wulkanowy/api/login/PrzerwaTechniczna.html new file mode 100644 index 000000000..062f9b60c --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/PrzerwaTechniczna.html @@ -0,0 +1,23 @@ + + + + + Przerwa techniczna + + +
+
+
+

Przerwa techniczna

+

Aktualnie trwają prace konserwacyjne. Witryna będzie dostępna za kilka minut.

> +
+ +
+
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/cert.xml b/api/src/test/resources/io/github/wulkanowy/api/login/cert.xml new file mode 100644 index 000000000..549b2d424 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/login/cert.xml @@ -0,0 +1,18 @@ + + + + + + + Default + demo12345 + incorrect value + warszawa + asdf + asdfsdf + + + + + + diff --git a/api/src/test/resources/io/github/wulkanowy/api/messages/GetTrescWiadomosci.json b/api/src/test/resources/io/github/wulkanowy/api/messages/GetTrescWiadomosci.json new file mode 100644 index 000000000..1ba54a32c --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/messages/GetTrescWiadomosci.json @@ -0,0 +1,7 @@ +{ + "success": true, + "data": { + "Id": 12345, + "Tresc": "Witam, …. \nPozdrawiam Krzysztof Czerkas" + } +} diff --git a/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciOdebrane.json b/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciOdebrane.json new file mode 100644 index 000000000..326390ed6 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciOdebrane.json @@ -0,0 +1,35 @@ +{ + "success": true, + "data": [ + { + "Nieprzeczytana": false, + "Data": "2016-03-15 09:00:00", + "Tresc": null, + "Temat": "Wycieczka", + "NadawcaNazwa": "Kowalski Jan", + "IdWiadomosci": 1234, + "IdNadawca": 4321, + "Id": 12345 + }, + { + "Nieprzeczytana": true, + "Data": "2016-04-20 22:00:00", + "Tresc": null, + "Temat": "\"Dzień dobrego słowa\"", + "NadawcaNazwa": "Pazura Agnieszka", + "IdWiadomosci": 1235, + "IdNadawca": 12, + "Id": 12346 + }, + { + "Nieprzeczytana": false, + "Data": "2016-04-29 10:00:00", + "Tresc": null, + "Temat": "Rozdajemy oceny celujące", + "NadawcaNazwa": "Kowalski Jan", + "IdWiadomosci": 1236, + "IdNadawca": 4321, + "Id": 12347 + } + ] +} diff --git a/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciUsuniete-empty.json b/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciUsuniete-empty.json new file mode 100644 index 000000000..36f89aa1e --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/messages/GetWiadomosciUsuniete-empty.json @@ -0,0 +1,4 @@ +{ + "success": true, + "data": [] +} diff --git a/api/src/test/resources/io/github/wulkanowy/api/messages/PageError.html b/api/src/test/resources/io/github/wulkanowy/api/messages/PageError.html new file mode 100644 index 000000000..ae976af1f --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/messages/PageError.html @@ -0,0 +1,88 @@ + + + + + + + + + + Błąd strony + + + +
+ +
+
+ Wystąpił nieoczekiwany błąd +
+
Wystąpił błąd aplikacji. Prosimy zalogować się ponownie. Jeśli problem będzie się powtarzał, prosimy o kontakt z serwisem.
+
+
+
+ +
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/messages/UndefinedError.txt b/api/src/test/resources/io/github/wulkanowy/api/messages/UndefinedError.txt new file mode 100644 index 000000000..c8d55a96c --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/messages/UndefinedError.txt @@ -0,0 +1 @@ +The custom error module does not recognize this error. \ No newline at end of file diff --git a/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-empty.html b/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-empty.html new file mode 100644 index 000000000..b15bb6e70 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-empty.html @@ -0,0 +1,20 @@ + + + + + Witryna ucznia i rodzica – Uwagi i osiągnięcia + + +
+
+

Uwagi

+

Brak informacji do wyświetlenia

+
+
+

Osiągnięcia

+

Brak informacji do wyświetlenia

+
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-filled.html b/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-filled.html new file mode 100644 index 000000000..50e740585 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/notes/UwagiOsiagniecia-filled.html @@ -0,0 +1,65 @@ + + + + + Witryna ucznia i rodzica – Uwagi i osiągnięcia + + +
+
+

Uwagi

+

06.06.2017

+
+
+
Nauczyciel:
+
Jan Kowalski [JK]
+
+
+
Kategoria:
+
Zaangażowanie społeczne
+
+
+
Treść:
+
Pomoc przy pikniku charytatywnym
+
+
+

01.12.2016

+
+
+
Nauczyciel:
+
Ochocka Zofia [PZ]
+
+
+
Kategoria:
+
Reprezentowanie szkoły
+
+
+
Treść:
+
Udział w przygotowaniu spektaklu
+
+
+

01.10.2016

+
+
+
Nauczyciel:
+
Kochański Leszek [KL]
+
+
+
Kategoria:
+
Zachowanie na lekcji
+
+
+
Treść:
+
Przeszkadzanie w prowadzeniu lekcji
+
+
+
+
+

Osiągnięcia

+
I miejsce w ogólnopolskim konkursie ortograficznym
+
III miejsce w ogólnopolskim konkursie plastycznym
+
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/school/Szkola.html b/api/src/test/resources/io/github/wulkanowy/api/school/Szkola.html new file mode 100644 index 000000000..05a698a04 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/school/Szkola.html @@ -0,0 +1,136 @@ + + + + + Witryna ucznia i rodzica – Szkoła i nauczyciele + + +
+

Szkoła

+
+
+ Nazwa szkoły: + Zespół Szkół nr 64 +
+
+ Adres szkoły: + ul. Wiśniowa 128, 01-234 Rogalowo, Nibylandia +
+
+ Telefon: + 55 5555555 +
+
+ Imię i nazwisko dyrektora: + Antoni Sobczyk +
+
+ Imię i nazwisko pedagoga: + Zofia Czerwińska [ZC], Aleksander Krzemiński [AK], Karolina Kowalska [KK], Bartek Dąbrowski [BD] +
+
+

Nauczyciele

+

+ Klasa: 1a, Wychowawcy: + Karolina Kowalska [AN], Antoni Sobczyk [AS]

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Lp.PrzedmiotNauczyciel
1BiologiaKarolina Kowalska [AN]
2ChemiaZofia Czerwińska [NA]
3Edukacja dla bezpieczeństwaAleksandra Krajewska [AK]
4FizykaStanisław Krupa [BS]
5GeografiaAleksandra Wójtowicz [AW]
6HistoriaSara Wierzbicka [KB]
7Język angielskiKarolina Kowalska [AN], Mateusz Kowal [MK], Amelia Mazur [AM]
8Język niemieckiMateusz Kowal [MK], Barbara Markowska [BM]
9Język polskiMichał Mazur [MM]
10MatematykaSzymon Wojciechowski [SW]
11PlastykaMichał Mazur [MM]
12ReligiaMaja Wiśniewska [M]
13Wiedza o społeczeństwieKarolina Kowalska [AN]
14Wychowanie do życia w rodzinieZofia Czerwińska [NA]
15Wychowanie fizyczneKarolina Kowalska [AN], Liliana Kowal [LK]
16Zajęcia techniczneBartek Dąbrowski [BD]
17Zajęcia z wychowawcąKarolina Kowalska [AN]
+
+
wersja: 17.02.0000.23328
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-full.html b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-full.html new file mode 100644 index 000000000..53eb04857 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-full.html @@ -0,0 +1,466 @@ + + + + + Witryna ucznia i rodzica – Plan lekcji + + +
+

Plan lekcji

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LekcjaPora lekcjiponiedziałek
19.06.2017
wtorek
20.06.2017
środa
21.06.2017
czwartek
22.06.2017
piątek
23.06.2017
007:10 07:55 +
+ Fizyka [zaw2] + + Bączek Grzegorz + 19 + (uczniowie zwolnieni do domu) +
+
+
+ Metodologia programowania [zaw2] + + + 32 +
+
+
+ Religia + Cyranka Krystian + 3 + Wychowanie do życia w rodzinie + Nowak Jadwiga + 3 + (zastępstwo) +
+
+
+ Język polski + + 16 + (oddział nieobecny) +
+ +
egzamin
+
+
+ Uroczyste zakończenie roku szkolnego + Baran Małgorzata + 37 +
+
108:00 08:45 +
+ Język angielski [J1] + + Kobczyk Iwona + +
+
+
+ Metodologia programowania [zaw2] + + Baran Małgorzata + 36 + (zmiana organizacji zajęć) +
+
+ Wychowanie fizyczne [zaw2] + + + G3 + (przeniesiona z lekcji 7, 01.12.2017) +
+
+
+ Użytkowanie urządzeń peryferyjnych komputera [zaw2] + + Bączek Robert + +
+
+
+ Wychowanie fizyczne [zaw1] + + Jarocki Krzysztof + G4 + Wychowanie fizyczne [zaw1] + + Nowicka Irena + G4 + (zastępstwo) +
+
208:50 09:35 +
+ Język polski + Bocian Natalia + +
+
+
+ Język niemiecki [J1] + + Rożeniec Honorata + 25 + (okienko dla uczniów) +
+
+ Język polski + Bocian Natalia + + (przeniesiona z lekcji 7, 20.06.2017) +
+
+ Język polski + Bocian Natalia + +
+
+
+ Urządzenia techniki komputerowej [zaw2] + + Bocian Grzegorz + +
+
+
+ Matematyka + Baran Małgorzata + +
+
309:40 10:25 +
+ Język polski + Bocian Natalia + +
+
+
+ Fizyka + Bączek Grzegorz + 19 + (okienko dla uczniów) +
+
+ Wychowanie fizyczne [wf2] + + Nowicka Irena + + (przeniesiona z lekcji 4, 20.06.2017) +
+
+ Wychowanie fizyczne [wf2] + + Nowicka Irena + +
+
+
+ Metodologia programowania [zaw2] + + Baran Małgorzata + +
+
+
+ Wychowanie fizyczne [wf2] + + Nowicka Irena + +
+
410:40 11:25 +
+ Urządzenia techniki komputerowej [zaw2] + + Bocian Grzegorz + +
+
+
+ Wychowanie fizyczne [wf2] + + Nowicka Irena + + (przeniesiona na lekcję 3, 20.06.2017) +
+
+
+ Matematyka + Baran Małgorzata + +
+
+
+ Wychowanie fizyczne [wf2] + + Nowicka Irena + +
+
511:30 12:15 +
+ Urządzenia techniki komputerowej [zaw2] + + Bocian Grzegorz + +
+
+
+ Podstawy przedsiębiorczości + Bogatka Anna + W12 + (okienko dla uczniów) +
+
+
+ Religia + Cyranka Krystian + +
+
+
+ Sieci komputerowe i administrowanie sieciami [zaw2] + + Rożeniec Piotr + +
+
612:20 13:05 +
+ Matematyka + Baran Małgorzata + +
+
+
+ Podstawy przedsiębiorczości + Bogatka Anna + W12 + (okienko dla uczniów) +
+
+
+ Język angielski [J1] + + Brodziec Sylwia + +
+
+
+ Religia + Cyranka Krystian + +
+
713:10 13:55 +
+ Fizyka + Bączek Grzegorz + 33 + (okienko dla uczniów) +
+
+
+ Język polski + Bocian Natalia + + (przeniesiona na lekcję 2, 20.06.2017) +
+
+
+ Multimedia i grafika komputerowa [zaw2] + + Bocian Konrad + +
+
+
+ Wiedza o kulturze + Bocian Natalia + +
+
814:00 14:45 +
+ Zajęcia z wychowawcą + Baran Małgorzata + +
+
+
+ Naprawa komputera [zaw2] + + Kraska Maciej + 32 + (okienko dla uczniów) +
+
+
+ Systemy operacyjne [zaw2] + + Kraska Maciej + 32 +
+
914:50 15:35 +
+ Język niemiecki [J1] + + Rożeniec Honorata + 25 + (uczniowie zwolnieni do domu) +
+
1015:40 16:25
1116:35 17:20
1217:25 18:10
1318:15 19:00
+
+
+
+ Kursywa- planowane +
+
+ Zwykła czcionka- zrealizowane +
+
+ Przekreślone- odwołane lub przeniesione +
+
+ Pogrubione- nowe lekcje, przeniesione z innego terminu, zastępstwa +
+
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-holidays.html b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-holidays.html new file mode 100644 index 000000000..09555cf3f --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-holidays.html @@ -0,0 +1,156 @@ + + + + + Witryna ucznia i rodzica – Plan lekcji + + +
+

Plan lekcji

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LekcjaPora lekcjiponiedziałek
31.07.2017
Ferie letnie
wtorek
01.08.2017
Ferie letnie
środa
02.08.2017
Ferie letnie
czwartek
03.08.2017
Ferie letnie
piątek
04.08.2017
Ferie letnie
007:10 07:55
108:00 08:45
208:50 09:35
309:40 10:25
410:40 11:25
511:30 12:15
612:20 13:05
713:10 13:55
814:00 14:45
914:50 15:35
1015:40 16:25
1116:35 17:20
1217:25 18:10
1318:15 19:00
+
+
+
wersja: 17.05.0000.24042
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-std.html b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-std.html new file mode 100644 index 000000000..8bcc9794e --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/timetable/PlanLekcji-std.html @@ -0,0 +1,303 @@ + + + + + Witryna ucznia i rodzica – Plan lekcji + + +
+

Plan lekcji

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LekcjaPora lekcjiponiedziałek
19.06.2017
wtorek
20.06.2017
środa
21.06.2017
czwartek
22.06.2017
piątek
23.06.2017
108:00 08:45 +
+ Edukacja dla bezpieczeństwa + Kobczyk Iwona + +
+
+
+ Język niemiecki [JNPW] + + Dzwoniec Ewa + +
+
+
+ Wychowanie do życia w rodzinie + Baran Dominika + +
+
+
+ Język niemiecki [JNPW] + + Dzwoniec Ewa + +
+
208:50 09:35 +
+ Historia + Bogatka Katarzyna + +
+
+
+ Wychowanie fizyczne [CH] + + Brodziec Dominika + +
+
+
+ Fizyka + Bocian Łukasz + +
+
+
+ Biologia + Kowalska Anna + +
+
+
+ Religia + Kraska Maciej + +
+
309:40 10:25 +
+ Wychowanie fizyczne [CH] + + Brodziec Dominika + +
+
+
+ Język polski + Rożeniec Paulina + +
+
+
+ Matematyka + Bączek Dominika + +
+
+
+ Plastyka + Rożeniec Paulina + +
+
+
+ Zajęcia z wychowawcą + Kowalska Anna + +
+
410:30 11:15 +
+ Geografia + Orłowski Konrad + +
+
+
+ Matematyka + Bączek Dominika + +
+
+
+ Język angielski [JAPN] + + Biegus Kazimiera + +
+
+
+ Matematyka + Bączek Dominika + +
+
+
+ Historia + Bogatka Katarzyna + +
+
511:30 12:15 +
+ Matematyka + Bączek Dominika + +
+
+
+ Biologia + Kowalska Anna + +
+
+
+ Zajęcia techniczne + Chlebowski Stanisław + +
+
+
+ Język angielski [JAPN] + + Biegus Kazimiera + +
+
+
+ Język polski + Rożeniec Paulina + +
+
612:30 13:15 +
+ Matematyka + Bączek Dominika + +
+
+
+ Fizyka + Bocian Łukasz + +
+
+
+ Język polski + Rożeniec Paulina + +
+
+
+ Wychowanie fizyczne [CH] + + Brodziec Dominika + +
+
+
+ Język polski + Rożeniec Paulina + +
+
713:20 14:05 +
+ Język angielski [JAPN] + + Biegus Kazimiera + +
+
+
+ Religia + Kraska Maciej + +
+
+
+ Wychowanie fizyczne [CH] + + Brodziec Dominika + +
+
814:10 14:55
+
+
+
wersja: 17.02.0000.23328
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/user/UczenDanePodstawowe.html b/api/src/test/resources/io/github/wulkanowy/api/user/UczenDanePodstawowe.html new file mode 100644 index 000000000..c54dd8614 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/user/UczenDanePodstawowe.html @@ -0,0 +1,119 @@ + + + + + Witryna ucznia i rodzica – Dane ucznia + + +
+

Dane podstawowe

+

Dane osobowe

+
+
+ Imię (imiona) nazwisko: + Maria Aneta Kamińska +
+
+ Data i miejsce urodzenia: + 01.01.1900, Warszawa +
+
+ PESEL: + 12345678900 +
+
+ Płeć: + Kobieta +
+
+ Obywatelstwo polskie: + Tak +
+
+ Nazwisko rodowe: + Nowak +
+
+ Imię matki i ojca: + Gabriela, Kamil +
+
+

Dane adresowe

+
+
+ Adres zamieszkania: + ul. Sportowa 16, 00-123 Warszawa +
+
+ Adres zameldowania: + ul. Sportowa 17, 00-123 Warszawa +
+
+ Adres korespondencji: + ul. Sportowa 18, 00-123 Warszawa +
+
+

Kontakt

+
+
+ Telefon: + 005554433 +
+
+ Telefon komórkowy: + 555444333 +
+
+ E-mail: + wulkanowy@example.null +
+
+

Rodzina

+
+
+ Nazwisko i imię: + Marianna Pająk +
+
+ Stopień pokrewieństwa: + matka +
+
+ Adres: + ul. Sportowa 16, 00-123 Warszawa +
+
+ Telefony: + 555111222 +
+
+ E-mail: + wulkanowy@example.null +
+
+
+
+ Nazwisko i imię: + Dawid Świątek +
+
+ Stopień pokrewieństwa: + ojciec +
+
+ Adres: + ul. Sportowa 18, 00-123 Warszawa +
+
+ Telefony: + 555222111 +
+
+ E-mail: + wulkanowy@example.null +
+
+
+
wersja: 17.02.0000.23328
+ + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle index 621e5a4fe..1887df3ab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,211 +1,106 @@ +buildscript { + repositories { + maven { url "https://plugins.gradle.org/m2/" } + maven { url 'https://maven.fabric.io/public' } + } + + dependencies { + classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' + classpath 'io.fabric.tools:gradle:1.25.1' + } +} + +repositories { + maven { url 'https://maven.fabric.io/public' } +} + apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' -apply plugin: 'com.google.firebase.crashlytics' -apply plugin: 'com.github.triplet.play' -apply plugin: 'com.mikepenz.aboutlibraries.plugin' -apply from: 'jacoco.gradle' -apply from: 'sonarqube.gradle' -apply from: 'hooks.gradle' +apply plugin: 'org.greenrobot.greendao' +apply plugin: 'io.fabric' +apply from: '../jacoco.gradle' +apply from: '../android-sonarqube.gradle' android { - compileSdkVersion 29 - buildToolsVersion '29.0.3' - + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { applicationId "io.github.wulkanowy" testApplicationId "io.github.tests.wulkanowy" - minSdkVersion 17 - targetSdkVersion 29 - versionCode 63 - versionName "0.19.0" - multiDexEnabled true - resValue "string", "app_name", "Wulkanowy" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + minSdkVersion 15 + targetSdkVersion 27 + versionCode 2 + versionName "0.1.1" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true manifestPlaceholders = [ - firebase_enabled: project.hasProperty("enableFirebase") + fabricApiKey: System.getenv("FABRIC_API_KEY") ?: "null" ] - javaCompileOptions { - annotationProcessorOptions { - arguments = [ - "room.schemaLocation": "$projectDir/schemas".toString(), - "room.incremental" : "true" - ] - } - } - } - - sourceSets { - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - - signingConfigs { - release { - storeFile file("upload-key.jks") - storePassword System.getenv("PLAY_STORE_PASSWORD") - keyAlias System.getenv("PLAY_KEY_ALIAS") - keyPassword System.getenv("PLAY_KEY_PASSWORD") - } } buildTypes { release { - minifyEnabled true - shrinkResources true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release } debug { - resValue "string", "app_name", "Wulkanowy DEV " + defaultConfig.versionCode - applicationIdSuffix ".dev" - versionNameSuffix "-dev" - testCoverageEnabled = project.hasProperty('coverage') - ext.enableCrashlytics = project.hasProperty("enableFirebase") + testCoverageEnabled = true + ext.enableCrashlytics = false } } - flavorDimensions "platform" - - productFlavors { - play { - dimension "platform" - } - - fdroid { - dimension "platform" + testOptions { + unitTests.all { + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen { false } + showStandardStreams = true + } } } - - buildFeatures { - viewBinding = true - } - - lintOptions { - disable 'HardwareIds' - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = "1.8" - } - - packagingOptions { - exclude 'META-INF/library_release.kotlin_module' - exclude 'META-INF/library-core_release.kotlin_module' - } - - aboutLibraries { - configPath = "app/src/main/res/raw" - } } -play { - serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL") ?: "jan@fakelog.cf" - serviceAccountCredentials = file('key.p12') - defaultToAppBundles = false - track = 'alpha' -} - -ext { - work_manager = "2.3.4" - room = "2.2.5" - dagger = "2.28" - chucker = "3.2.0" - mockk = "1.9.2" -} - -configurations.all { - resolutionStrategy.force "androidx.constraintlayout:constraintlayout:1.1.3" +greendao { + schemaVersion 20 + generateTests = true } dependencies { - implementation "io.github.wulkanowy:sdk:0.19.0" + implementation project(':api') + implementation 'com.android.support:appcompat-v7:27.1.0' + implementation 'com.android.support:design:27.1.0' + implementation 'com.android.support:support-v4:27.1.0' + implementation 'com.android.support:recyclerview-v7:27.1.0' + implementation 'com.android.support:cardview-v7:27.1.0' + implementation 'com.android.support:customtabs:27.1.0' + implementation 'com.firebase:firebase-jobdispatcher:0.8.5' + implementation 'org.apache.commons:commons-lang3:3.7' + implementation 'eu.davidea:flexible-adapter:5.0.0-rc4' + implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b1' + implementation 'org.apache.commons:commons-collections4:4.1' + implementation 'org.greenrobot:greendao:3.2.2' + implementation 'com.jakewharton:butterknife:8.8.1' + implementation 'joda-time:joda-time:2.9.9' + implementation 'com.google.dagger:dagger-android:2.14.1' + implementation 'com.google.dagger:dagger-android-support:2.14.1' + implementation 'com.aurelhubert:ahbottomnavigation:2.1.0' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation "androidx.core:core-ktx:1.2.0" - implementation "androidx.activity:activity-ktx:1.1.0" - implementation "androidx.appcompat:appcompat:1.2.0-rc01" - implementation "androidx.appcompat:appcompat-resources:1.1.0" - implementation "androidx.fragment:fragment-ktx:1.2.5" - implementation "androidx.annotation:annotation:1.1.0" - implementation "androidx.multidex:multidex:2.0.1" + implementation('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') { + transitive = true + } + implementation('com.crashlytics.sdk.android:answers:1.4.1@aar') { + transitive = true + } - implementation "androidx.preference:preference-ktx:1.1.1" - implementation "androidx.recyclerview:recyclerview:1.1.0" - implementation "androidx.viewpager:viewpager:1.0.0" - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-rc01" - implementation "androidx.constraintlayout:constraintlayout:1.1.3" - implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" - implementation "com.google.android.material:material:1.1.0" - implementation "com.github.wulkanowy:material-chips-input:2.1.1" - implementation "com.github.PhilJay:MPAndroidChart:v3.1.0" - implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" + annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1' + annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' - implementation "androidx.work:work-runtime-ktx:$work_manager" - implementation "androidx.work:work-rxjava2:$work_manager" - implementation "androidx.work:work-gcm:$work_manager" + debugImplementation 'com.amitshekhar.android:debug-db:1.0.1' + debugImplementation 'net.zetetic:android-database-sqlcipher:3.5.9' - implementation 'com.github.PaulinaSadowska:RxWorkManagerObservers:1.0.0' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.13.0' - implementation "androidx.room:room-runtime:$room" - implementation "androidx.room:room-rxjava2:$room" - implementation "androidx.room:room-ktx:$room" - kapt "androidx.room:room-compiler:$room" - - implementation "com.google.dagger:dagger-android-support:$dagger" - kapt "com.google.dagger:dagger-compiler:$dagger" - kapt "com.google.dagger:dagger-android-processor:$dagger" - implementation "com.squareup.inject:assisted-inject-annotations-dagger2:0.5.2" - kapt "com.squareup.inject:assisted-inject-processor-dagger2:0.5.2" - - implementation "com.aurelhubert:ahbottomnavigation:2.3.4" - implementation "com.ncapdevi:frag-nav:3.3.0" - implementation "com.github.YarikSOffice:lingver:1.2.2" - - implementation "com.github.pwittchen:reactivenetwork-rx2:3.0.8" - implementation "io.reactivex.rxjava2:rxandroid:2.1.1" - implementation "io.reactivex.rxjava2:rxjava:2.2.19" - - implementation "com.google.code.gson:gson:2.8.6" - implementation "com.jakewharton.threetenabp:threetenabp:1.2.4" - implementation "com.jakewharton.timber:timber:4.7.1" - implementation "at.favre.lib:slf4j-timber:1.0.1" - 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:0.11.0" - implementation "io.github.wulkanowy:AppKillerManager:3.0.0" - implementation 'me.xdrop:fuzzywuzzy:1.3.1' - - playImplementation 'com.google.firebase:firebase-analytics:17.4.3' - playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.0.7' - playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.0.7" - playImplementation 'com.google.firebase:firebase-messaging:20.2.0' - playImplementation 'com.google.firebase:firebase-crashlytics:17.0.1' - playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - - releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" - - debugImplementation "com.github.ChuckerTeam.Chucker:library:$chucker" - debugImplementation "com.amitshekhar.android:debug-db:1.0.6" - - testImplementation "junit:junit:4.13" - testImplementation "io.mockk:mockk:$mockk" - testImplementation "org.threeten:threetenbp:1.4.4" - testImplementation "org.mockito:mockito-inline:3.3.3" - - androidTestImplementation "androidx.test:core:1.2.0" - androidTestImplementation "androidx.test:runner:1.2.0" - androidTestImplementation "androidx.test.ext:junit:1.1.1" - androidTestImplementation "io.mockk:mockk-android:$mockk" - androidTestImplementation "androidx.room:room-testing:$room" - androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" - androidTestImplementation "org.mockito:mockito-android:3.3.3" + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'org.mockito:mockito-android:2.13.0' } - -apply plugin: 'com.google.gms.google-services' diff --git a/app/hooks.gradle b/app/hooks.gradle deleted file mode 100644 index 038fa9fb2..000000000 --- a/app/hooks.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply plugin: "com.star-zero.gradle.githook" - -githook { - failOnMissingHooksDir = false - hooks { - "pre-push" { - shell = "./app/play-publish-lint.sh" - } - } -} diff --git a/app/jacoco.gradle b/app/jacoco.gradle deleted file mode 100644 index e9abfb613..000000000 --- a/app/jacoco.gradle +++ /dev/null @@ -1,50 +0,0 @@ -apply plugin: "jacoco" - -jacoco { - toolVersion "0.8.5" - reportsDir = file("$buildDir/reports") -} - -tasks.withType(Test) { - jacoco.includeNoLocationClasses = true -} - -task jacocoTestReport(type: JacocoReport) { - - group = "Reporting" - description = "Generate Jacoco coverage reports" - - reports { - xml.enabled = true - html.enabled = true - } - - def excludes = ['**/R.class', - '**/R$*.class', - '**/BuildConfig.*', - '**/Manifest*.*', - '**/*Test*.*', - 'android/**/*.*', - '**/*Module.*', - '**/*Dagger*.*', - '**/*MembersInjector*.*', - '**/*_Provide*Factory*.*', - '**/*_Factory.*'] - - classDirectories.setFrom(fileTree( - dir: "$buildDir/intermediates/classes/debug", - excludes: excludes - ) + fileTree( - dir: "$buildDir/tmp/kotlin-classes/playDebug", - excludes: excludes - )) - - sourceDirectories.setFrom(files([ - "src/main/java", - "src/play/java" - ])) - executionData.setFrom(fileTree( - dir: project.projectDir, - includes: ["**/*.exec", "**/*.ec"] - )) -} diff --git a/app/key.p12.gpg b/app/key.p12.gpg deleted file mode 100644 index e9b6d06eb..000000000 Binary files a/app/key.p12.gpg and /dev/null differ diff --git a/app/play-publish-lint.sh b/app/play-publish-lint.sh deleted file mode 100755 index d3354b1ad..000000000 --- a/app/play-publish-lint.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - - -content=$(cat < "app/src/main/play/release-notes/pl-PL/default.txt") || exit -if [[ "${#content}" -gt 500 ]]; then - echo >&2 "Release notes content has reached the limit of 500 characters" - exit 1 -fi diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 1a8b8c329..34ed4c38c 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,52 +1,25 @@ -# Optimizations --optimizationpasses 5 --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontskipnonpubliclibraryclassmembers --dontpreverify --dontobfuscate --allowaccessmodification --repackageclasses '' --verbose +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\RicomenPL\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html +# Add any project specific keep options here: -#Keep all wulkanowy files --keep class io.github.wulkanowy.** {*;} +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable -#Config for anallitycs --keepattributes *Annotation* --keepattributes SourceFile,LineNumberTable --keep class com.crashlytics.** {*;} --keep public class * extends java.lang.Exception --dontwarn com.crashlytics.** - - -#Config for OkHttp --keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase --dontwarn org.codehaus.mojo.animal_sniffer.* --dontwarn okhttp3.internal.platform.ConscryptPlatform --dontwarn javax.annotation.** - - -#Config for ReactiveNetwork --dontwarn com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork --dontwarn io.reactivex.functions.Function --dontwarn rx.internal.util.** --dontwarn sun.misc.Unsafe - - -#Config for MPAndroidChart --keep class com.github.mikephil.charting.** { *; } - - -#Config for Material Components --keep class com.google.android.material.tabs.** { *; } - - -#Config for About Libraries --keep class .R --keep class **.R$* { - ; -} +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json deleted file mode 100644 index e42a4a719..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/11.json +++ /dev/null @@ -1,1325 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 11, - "identityHash": "478af7daed6ac4563e71826fb70cc8c8", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_name` TEXT NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolName", - "columnName": "school_name", - "affinity": "TEXT", - "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", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id" - ], - "createSql": "CREATE UNIQUE INDEX `index_Students_email_symbol_student_id_school_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Semesters", - "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, `diary_name` TEXT NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` 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": "diaryName", - "columnName": "diary_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterName", - "columnName": "semester_name", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isCurrent", - "columnName": "is_current", - "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 `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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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": "predictedGrade", - "columnName": "predictedGrade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "finalGrade", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, \"478af7daed6ac4563e71826fb70cc8c8\")" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json deleted file mode 100644 index 32f943554..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/12.json +++ /dev/null @@ -1,1332 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 12, - "identityHash": "972ad26e6488d9a8239f6bd8597af61d", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolName", - "columnName": "school_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 `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, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` 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": "diaryName", - "columnName": "diary_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterName", - "columnName": "semester_name", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isCurrent", - "columnName": "is_current", - "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 `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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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": "predictedGrade", - "columnName": "predictedGrade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "finalGrade", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, \"972ad26e6488d9a8239f6bd8597af61d\")" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json deleted file mode 100644 index ab554665e..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/13.json +++ /dev/null @@ -1,1356 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 13, - "identityHash": "18643bb64804b8268ec9395e3dd55ecb", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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 `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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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 `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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predictedGrade` TEXT NOT NULL, `finalGrade` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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": "predictedGrade", - "columnName": "predictedGrade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "finalGrade", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, \"18643bb64804b8268ec9395e3dd55ecb\")" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/14.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/14.json deleted file mode 100644 index 82b764922..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/14.json +++ /dev/null @@ -1,1386 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 14, - "identityHash": "b22945c41e7841ff2e6b16af346dde0c", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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 `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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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 `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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, 'b22945c41e7841ff2e6b16af346dde0c')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/15.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/15.json deleted file mode 100644 index 6f2d1d1da..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/15.json +++ /dev/null @@ -1,1430 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 15, - "identityHash": "84b300bf53c7dd70b60a29a842275bb2", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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 `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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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 `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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '84b300bf53c7dd70b60a29a842275bb2')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/16.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/16.json deleted file mode 100644 index 34df45ebe..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/16.json +++ /dev/null @@ -1,1480 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 16, - "identityHash": "1eccdcb09adc922713ef67f298ec77a7", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '1eccdcb09adc922713ef67f298ec77a7')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/17.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/17.json deleted file mode 100644 index 8b777b7bf..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/17.json +++ /dev/null @@ -1,1530 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 17, - "identityHash": "8bcb3c86f1ddbdf7e20cfa8050525b95", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '8bcb3c86f1ddbdf7e20cfa8050525b95')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json deleted file mode 100644 index 4f7497fe0..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/18.json +++ /dev/null @@ -1,1592 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 18, - "identityHash": "73b1dcfe0cf84170ba102b2818dd0191", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `endpoint` TEXT NOT NULL, `loginType` TEXT NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `student_name` TEXT NOT NULL, `school_id` 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": "endpoint", - "columnName": "endpoint", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "loginType", - "affinity": "TEXT", - "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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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, `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": "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, `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)", - "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": "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 - } - ], - "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` INTEGER 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": "INTEGER", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT, `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, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": false - }, - { - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '73b1dcfe0cf84170ba102b2818dd0191')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/19.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/19.json deleted file mode 100644 index 1e4593bb3..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/19.json +++ /dev/null @@ -1,1628 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 19, - "identityHash": "294f40cebf8314f9776208827240e65f", - "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, `student_name` TEXT NOT NULL, `school_id` 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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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, `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": "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, `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)", - "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": "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 - } - ], - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '294f40cebf8314f9776208827240e65f')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/20.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/20.json deleted file mode 100644 index 925d787aa..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/20.json +++ /dev/null @@ -1,1634 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 20, - "identityHash": "37a216a7afcea922b66001ca5ed6cf74", - "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, `student_name` TEXT NOT NULL, `school_id` 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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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": "studentPlan", - "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, `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)", - "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": "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 - } - ], - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '37a216a7afcea922b66001ca5ed6cf74')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/21.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/21.json deleted file mode 100644 index dfad69f5d..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/21.json +++ /dev/null @@ -1,1652 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 21, - "identityHash": "f905d8a3ff4718d30ae7413a5a717b1f", - "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, `student_name` TEXT NOT NULL, `school_id` 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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "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, `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, `is_current` 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": "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": "isCurrent", - "columnName": "is_current", - "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": "studentPlan", - "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, 'f905d8a3ff4718d30ae7413a5a717b1f')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/22.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/22.json deleted file mode 100644 index 1eb8bc19c..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/22.json +++ /dev/null @@ -1,1658 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 22, - "identityHash": "798956844fdb3f64073921184e3acbfd", - "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, `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": "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `category` TEXT 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": "category", - "columnName": "category", - "affinity": "TEXT", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '798956844fdb3f64073921184e3acbfd')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/23.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/23.json deleted file mode 100644 index f75a72acf..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/23.json +++ /dev/null @@ -1,1682 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 23, - "identityHash": "f2505bf0c76c3ae4567856536d790909", - "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, `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": "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `removed` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, 'f2505bf0c76c3ae4567856536d790909')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/24.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/24.json deleted file mode 100644 index 17ae7d798..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/24.json +++ /dev/null @@ -1,1732 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 24, - "identityHash": "9bbf60310b56a855839164e2aae031f9", - "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, `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": "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "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, `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)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "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 - } - ], - "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": [] - } - ], - "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, '9bbf60310b56a855839164e2aae031f9')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/25.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/25.json deleted file mode 100644 index 474824df6..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/25.json +++ /dev/null @@ -1,1744 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 25, - "identityHash": "d101f5a26a024f62e6fee161e421b882", - "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, `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": "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, `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": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "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": [] - } - ], - "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, 'd101f5a26a024f62e6fee161e421b882')" - ] - } -} diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json deleted file mode 100644 index 21005f9c6..000000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json +++ /dev/null @@ -1,1768 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 26, - "identityHash": "43f8777ffe95a5a2850ee981db3dbe2e", - "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, `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": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "school_short", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolName", - "columnName": "school_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "className", - "columnName": "class_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isCurrent", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "registrationDate", - "columnName": "registration_date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Semesters", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryName", - "columnName": "diary_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolYear", - "columnName": "school_year", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterName", - "columnName": "semester_name", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unitId", - "columnName": "unit_id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "semester_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "entryDate", - "columnName": "entry_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subjectOld", - "columnName": "subjectOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "room", - "columnName": "room", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "roomOld", - "columnName": "roomOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherOld", - "columnName": "teacherOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "info", - "columnName": "info", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isStudentPlan", - "columnName": "student_plan", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "changes", - "columnName": "changes", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "canceled", - "columnName": "canceled", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "timeId", - "columnName": "time_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excused", - "columnName": "excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "deleted", - "columnName": "deleted", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excusable", - "columnName": "excusable", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excuseStatus", - "columnName": "excuse_status", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subjectId", - "columnName": "subject_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "month", - "columnName": "month", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceExcused", - "columnName": "absence_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceForSchoolReasons", - "columnName": "absence_for_school_reasons", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "latenessExcused", - "columnName": "lateness_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isRead", - "columnName": "is_read", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "entry", - "columnName": "entry", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "value", - "columnName": "value", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "modifier", - "columnName": "modifier", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "comment", - "columnName": "comment", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "color", - "columnName": "color", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gradeSymbol", - "columnName": "grade_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weight", - "columnName": "weight", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weightValue", - "columnName": "weightValue", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isPredictedGradeNotified", - "columnName": "is_predicted_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isFinalGradeNotified", - "columnName": "is_final_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "predictedGradeLastChange", - "columnName": "predicted_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "finalGradeLastChange", - "columnName": "final_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "grade", - "columnName": "grade", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "amount", - "columnName": "amount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semester", - "columnName": "is_semester", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `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, `content` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` 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": "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": "content", - "columnName": "content", - "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": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "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": [] - } - ], - "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, '43f8777ffe95a5a2850ee981db3dbe2e')" - ] - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/AccountTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/AccountTest.java new file mode 100644 index 000000000..e5330b621 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/AccountTest.java @@ -0,0 +1,18 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class AccountTest extends AbstractDaoTestLongPk { + + public AccountTest() { + super(AccountDao.class); + } + + @Override + protected Account createEntity(Long key) { + Account entity = new Account(); + entity.setId(key); + return entity; + } + +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/DayTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/DayTest.java new file mode 100644 index 000000000..34c4c4c5e --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/DayTest.java @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class DayTest extends AbstractDaoTestLongPk { + + public DayTest() { + super(DayDao.class); + } + + @Override + protected Day createEntity(Long key) { + Day entity = new Day(); + entity.setId(key); + entity.setIsFreeDay(false); + return entity; + } + +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/GradeTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/GradeTest.java new file mode 100644 index 000000000..ea0265591 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/GradeTest.java @@ -0,0 +1,20 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class GradeTest extends AbstractDaoTestLongPk { + + public GradeTest() { + super(GradeDao.class); + } + + @Override + protected Grade createEntity(Long key) { + Grade entity = new Grade(); + entity.setId(key); + entity.setIsNew(false); + entity.setRead(false); + return entity; + } + +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/LessonTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/LessonTest.java new file mode 100644 index 000000000..c8690ff94 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/LessonTest.java @@ -0,0 +1,24 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class LessonTest extends AbstractDaoTestLongPk { + + public LessonTest() { + super(LessonDao.class); + } + + @Override + protected Lesson createEntity(Long key) { + Lesson entity = new Lesson(); + entity.setId(key); + entity.setIsEmpty(false); + entity.setIsDivisionIntoGroups(false); + entity.setIsPlanning(false); + entity.setIsRealized(false); + entity.setIsMovedOrCanceled(false); + entity.setIsNewMovedInOrChanged(false); + return entity; + } + +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SubjectTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SubjectTest.java new file mode 100644 index 000000000..81a2e724f --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SubjectTest.java @@ -0,0 +1,18 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class SubjectTest extends AbstractDaoTestLongPk { + + public SubjectTest() { + super(SubjectDao.class); + } + + @Override + protected Subject createEntity(Long key) { + Subject entity = new Subject(); + entity.setId(key); + return entity; + } + +} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/WeekTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/WeekTest.java new file mode 100644 index 000000000..86e7a8be5 --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/WeekTest.java @@ -0,0 +1,18 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class WeekTest extends AbstractDaoTestLongPk { + + public WeekTest() { + super(WeekDao.class); + } + + @Override + protected Week createEntity(Long key) { + Week entity = new Week(); + entity.setId(key); + return entity; + } + +} 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 deleted file mode 100644 index 611161e58..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.preference.PreferenceManager -import androidx.room.Room -import androidx.room.testing.MigrationTestHelper -import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory -import androidx.test.core.app.ApplicationProvider -import androidx.test.platform.app.InstrumentationRegistry -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.SharedPrefProvider -import org.junit.Rule - -abstract class AbstractMigrationTest { - - val dbName = "migration-test" - - @get:Rule - val helper: MigrationTestHelper = MigrationTestHelper( - InstrumentationRegistry.getInstrumentation(), - AppDatabase::class.java.canonicalName, - FrameworkSQLiteOpenHelperFactory() - ) - - fun getMigratedRoomDatabase(): AppDatabase { - val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), - AppDatabase::class.java, dbName) - .addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager - .getDefaultSharedPreferences(ApplicationProvider.getApplicationContext()))) - ) - .build() - // close the database and release any stream resources when the test finishes - helper.closeWhenFinished(database) - return database - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt deleted file mode 100644 index 0bbcc4271..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt +++ /dev/null @@ -1,133 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import android.content.ContentValues -import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL -import androidx.sqlite.db.SupportSQLiteDatabase -import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class Migration12Test : AbstractMigrationTest() { - - @Test - fun twoNotRelatedStudents() { - helper.createDatabase(dbName, 11).apply { - // user 1 - createStudent(this, 1, true) - createSemester(this, 1, false, 5, 1) - createSemester(this, 1, true, 5, 2) - - // user 2 - createStudent(this, 2, true) - createSemester(this, 2, false, 6, 1) - createSemester(this, 2, true, 6, 2) - close() - } - - helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) - - val db = getMigratedRoomDatabase() - val students = db.studentDao.loadAll().blockingGet() - - assertEquals(2, students.size) - - students[0].run { - assertEquals(1, studentId) - assertEquals(5, classId) - } - - students[1].run { - assertEquals(2, studentId) - assertEquals(6, classId) - } - } - - @Test - fun removeStudentsWithoutClassId() { - helper.createDatabase(dbName, 11).apply { - // user 1 - createStudent(this, 1, true) - createSemester(this, 1, false, 0, 2) - createStudent(this, 2, true) - createSemester(this, 2, true, 1, 2) - close() - } - - helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) - - val db = getMigratedRoomDatabase() - val students = db.studentDao.loadAll().blockingGet() - - assertEquals(1, students.size) - - students[0].run { - assertEquals(2, studentId) - assertEquals(1, classId) - } - } - - @Test - fun ensureThereIsOnlyOneCurrentStudent() { - helper.createDatabase(dbName, 11).apply { - // user 1 - createStudent(this, 1, true) - createSemester(this, 1, true, 5, 2) - createStudent(this, 2, true) - createSemester(this, 2, true, 6, 2) - createStudent(this, 3, true) - createSemester(this, 3, false, 7, 2) - close() - } - - helper.runMigrationsAndValidate(dbName, 12, true, Migration12()) - - val db = getMigratedRoomDatabase() - val students = db.studentDao.loadAll().blockingGet() - - assertEquals(3, students.size) - - students[0].run { - assertEquals(studentId, 1) - assertEquals(false, isCurrent) - } - students[1].run { - assertEquals(studentId, 2) - assertEquals(false, isCurrent) - } - students[2].run { - assertEquals(studentId, 3) - assertEquals(true, isCurrent) - } - } - - private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean) { - db.insert("Students", CONFLICT_FAIL, ContentValues().apply { - put("endpoint", "https://fakelog.cf") - put("loginType", "STANDARD") - put("email", "jan@fakelog.cf") - put("password", "******") - put("symbol", "Default") - put("student_id", studentId) - put("student_name", "Jan Kowalski") - put("school_id", "000123") - put("school_name", "") - put("is_current", isCurrent) - put("registration_date", "0") - }) - } - - private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, isCurrent: Boolean, classId: Int, diaryId: Int) { - db.insert("Semesters", CONFLICT_FAIL, ContentValues().apply { - put("student_id", studentId) - put("diary_id", diaryId) - put("diary_name", "IA") - put("semester_id", diaryId * 5) - put("semester_name", "1") - put("is_current", isCurrent) - put("class_id", classId) - put("unit_id", "99") - }) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt deleted file mode 100644 index da4284b02..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt +++ /dev/null @@ -1,195 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import android.content.ContentValues -import android.database.sqlite.SQLiteDatabase -import androidx.sqlite.db.SupportSQLiteDatabase -import io.github.wulkanowy.data.db.Converters -import io.github.wulkanowy.data.db.entities.Semester -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.threeten.bp.LocalDate.of -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class Migration13Test : AbstractMigrationTest() { - - @Test - fun studentsWithSchoolNameWithClassName() { - helper.createDatabase(dbName, 12).apply { - createStudent(this, 1, "Klasa A - Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", 1, 1) - createStudent(this, 2, "Klasa B - Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", 2, 1) - createStudent(this, 2, "Klasa C - Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", 1, 2) - close() - } - - helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) - - val db = getMigratedRoomDatabase() - val students = db.studentDao.loadAll().blockingGet() - - assertEquals(3, students.size) - - students[0].run { - assertEquals(1, studentId) - assertEquals("A", className) - assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", schoolName) - } - - students[1].run { - assertEquals(2, studentId) - assertEquals("B", className) - assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName) - } - - students[2].run { - assertEquals(2, studentId) - assertEquals("C", className) - assertEquals("Publiczna szkoła Wulkanowego-fejka nr 2 w fakelog.cf", schoolName) - } - } - - @Test - fun studentsWithSchoolNameWithoutClassName() { - helper.createDatabase(dbName, 12).apply { - createStudent(this, 1, "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", 1) - createStudent(this, 2, "Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", 1) - close() - } - - helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) - - val db = getMigratedRoomDatabase() - val students = db.studentDao.loadAll().blockingGet() - - assertEquals(2, students.size) - - students[0].run { - assertEquals(1, studentId) - assertEquals("", className) - assertEquals("Publiczna szkoła Wulkanowego nr 1 w fakelog.cf", schoolName) - } - - students[1].run { - assertEquals(2, studentId) - assertEquals("", className) - assertEquals("Publiczna szkoła Wulkanowego-fejka nr 1 w fakelog.cf", schoolName) - } - } - - @Test - fun markAtLeastAndOnlyOneSemesterAtCurrent() { - helper.createDatabase(dbName, 12).apply { - createStudent(this, 1, "", 5) - createSemester(this, 1, 5, 1, 1, false) - createSemester(this, 1, 5, 2, 1, false) - createSemester(this, 1, 5, 3, 2, false) - createSemester(this, 1, 5, 4, 2, false) - - createStudent(this, 2, "", 5) - createSemester(this, 2, 5, 5, 5, true) - createSemester(this, 2, 5, 6, 5, true) - createSemester(this, 2, 5, 7, 55, true) - createSemester(this, 2, 5, 8, 55, true) - - createStudent(this, 3, "", 5) - createSemester(this, 3, 5, 11, 99, false) - createSemester(this, 3, 5, 12, 99, false) - createSemester(this, 3, 5, 13, 100, false) - createSemester(this, 3, 5, 14, 100, true) - close() - } - - val db = helper.runMigrationsAndValidate(dbName, 13, true, Migration13()) - - val semesters1 = getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 1 AND class_id = 5") - assertTrue { semesters1.single { it.second }.second } - semesters1[0].run { - assertFalse(second) - assertEquals(1, first.semesterId) - assertEquals(1, first.diaryId) - } - semesters1[2].run { - assertFalse(second) - assertEquals(3, first.semesterId) - assertEquals(2, first.diaryId) - } - semesters1[3].run { - assertTrue(second) - assertEquals(4, first.semesterId) - assertEquals(2, first.diaryId) - } - - getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters -> - assertTrue { semesters.single { it.second }.second } - assertEquals(1970, semesters[0].first.schoolYear) - assertEquals(of(1970, 1, 1), semesters[0].first.end) - assertEquals(of(1970, 1, 1), semesters[0].first.start) - assertFalse(semesters[0].second) - assertFalse(semesters[1].second) - assertFalse(semesters[2].second) - assertTrue(semesters[3].second) - } - - getSemesters(db, "SELECT * FROM Semesters WHERE student_id = 2 AND class_id = 5").let { semesters -> - assertTrue { semesters.single { it.second }.second } - assertFalse(semesters[0].second) - assertFalse(semesters[1].second) - assertFalse(semesters[2].second) - assertTrue(semesters[3].second) - } - } - - private fun getSemesters(db: SupportSQLiteDatabase, query: String): List> { - val semesters = mutableListOf>() - - val cursor = db.query(query) - if (cursor.moveToFirst()) { - do { - semesters.add(Semester( - studentId = cursor.getInt(1), - diaryId = cursor.getInt(2), - diaryName = cursor.getString(3), - semesterId = cursor.getInt(4), - semesterName = cursor.getInt(5), - classId = cursor.getInt(7), - unitId = cursor.getInt(8), - schoolYear = cursor.getInt(9), - start = Converters().timestampToDate(cursor.getLong(10))!!, - end = Converters().timestampToDate(cursor.getLong(11))!! - ) to (cursor.getInt(6) == 1)) - } while (cursor.moveToNext()) - } - return semesters.toList() - } - - private fun createStudent(db: SupportSQLiteDatabase, studentId: Int, schoolName: String = "", classId: Int = -1, schoolId: Int = 123) { - db.insert("Students", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { - put("endpoint", "https://fakelog.cf") - put("loginType", "STANDARD") - put("email", "jan@fakelog.cf") - put("password", "******") - put("symbol", "Default") - put("student_id", studentId) - put("class_id", classId) - put("student_name", "Jan Kowalski") - put("school_id", schoolId) - put("school_name", schoolName) - put("is_current", false) - put("registration_date", "0") - }) - } - - private fun createSemester(db: SupportSQLiteDatabase, studentId: Int, classId: Int, semesterId: Int, diaryId: Int, isCurrent: Boolean = false) { - db.insert("Semesters", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { - put("student_id", studentId) - put("diary_id", diaryId) - put("diary_name", "IA") - put("semester_id", semesterId) - put("semester_name", "1") - put("is_current", isCurrent) - put("class_id", classId) - put("unit_id", "99") - }) - } -} 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 bbbfd83dd..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestEntityCreator.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories - -import io.github.wulkanowy.data.db.entities.Student -import org.threeten.bp.LocalDateTime - -fun getStudent(): Student { - return Student( - email = "test", - password = "test123", - schoolSymbol = "23", - scrapperBaseUrl = "fakelog.cf", - loginType = "AUTO", - isCurrent = true, - studentName = "", - schoolShortName = "", - schoolName = "", - studentId = 0, - classId = 1, - symbol = "", - registrationDate = LocalDateTime.now(), - className = "", - loginMode = "API", - certificateKey = "", - privateKey = "", - mobileBaseUrl = "", - userLoginId = 0, - isParent = false - ) -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt deleted file mode 100644 index 7dc93c4a4..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/TestInternetObservingStrategy.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.data.repositories - -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.error.ErrorHandler -import io.reactivex.Observable -import io.reactivex.Single - -class TestInternetObservingStrategy : InternetObservingStrategy { - - override fun checkInternetConnectivity(host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Single { - return Single.just(true) - } - - override fun observeInternetConnectivity(initialIntervalInMs: Int, intervalInMs: Int, host: String?, port: Int, timeoutInMs: Int, httpResponse: Int, errorHandler: ErrorHandler?): Observable { - return Observable.just(true) - } - - override fun getDefaultPingHost() = "localhost" -} 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 cdfc524ad..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocalTest.kt +++ /dev/null @@ -1,84 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.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() { - attendanceLocal.saveAttendance(listOf( - getAttendanceEntity( - of(2018, 9, 10), - SentExcuseStatus.ACCEPTED - ), - getAttendanceEntity( - of(2018, 9, 14), - SentExcuseStatus.WAITING - ), - getAttendanceEntity( - of(2018, 9, 17), - SentExcuseStatus.ACCEPTED - ) - )) - - val attendance = attendanceLocal - .getAttendance(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1), - of(2018, 9, 10), - of(2018, 9, 14) - ) - .blockingGet() - 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 50badc468..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocalTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.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() { - completedLessonsLocal.saveCompletedLessons(listOf( - getCompletedLesson(of(2018, 9, 10), 1), - getCompletedLesson(of(2018, 9, 14), 2), - getCompletedLesson(of(2018, 9, 17), 3) - )) - - val completed = completedLessonsLocal - .getCompletedLessons(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1), - of(2018, 9, 10), - of(2018, 9, 14) - ) - .blockingGet() - 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 98dfc88eb..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/exam/ExamLocalTest.kt +++ /dev/null @@ -1,53 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate.now -import org.threeten.bp.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() { - examLocal.saveExams(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(), "", "", "", "", "", "") - )) - - val exams = examLocal - .getExams(Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1), - of(2018, 9, 10), - of(2018, 9, 14) - ) - .blockingGet() - 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 eb1a55480..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeLocalTest.kt +++ /dev/null @@ -1,53 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.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() { - gradeLocal.saveGrades(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) - )) - - val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1) - - val grades = gradeLocal - .getGradesDetails(semester) - .blockingGet() - - 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 cdd514772..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/GradeRepositoryTest.kt +++ /dev/null @@ -1,182 +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 com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.sdk.pojo.Grade -import io.mockk.MockKAnnotations -import io.mockk.every -import io.mockk.impl.annotations.MockK -import io.reactivex.Single -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate.of -import org.threeten.bp.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 mockSdk: Sdk - - private val settings = InternetObservingSettings.builder() - .strategy(TestInternetObservingStrategy()) - .build() - - @MockK - private lateinit var semesterMock: Semester - - @MockK - private lateinit var studentMock: Student - - 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) - gradeRemote = GradeRemote(mockSdk) - - every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0) - every { semesterMock.studentId } returns 1 - every { semesterMock.diaryId } returns 1 - every { semesterMock.schoolYear } returns 2019 - every { semesterMock.semesterId } returns 1 - every { mockSdk.switchDiary(any(), any()) } returns mockSdk - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun markOlderThanRegisterDateAsRead() { - every { mockSdk.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"), - createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"), - createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"), - createGradeApi(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza") - ) to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet().first.sortedByDescending { it.date } - - assertFalse { grades[0].isRead } - assertFalse { grades[1].isRead } - assertTrue { grades[2].isRead } - assertTrue { grades[3].isRead } - } - - @Test - fun mitigateOldGradesNotifications() { - gradeLocal.saveGrades(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") - )) - - every { mockSdk.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"), - createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"), - createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"), - createGradeApi(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa") - ) to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet().first.sortedByDescending { it.date } - - assertFalse { grades[0].isRead } - assertFalse { grades[1].isRead } - assertTrue { grades[2].isRead } - assertTrue { grades[3].isRead } - } - - @Test - fun subtractLocaleDuplicateGrades() { - gradeLocal.saveGrades(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") - )) - - every { mockSdk.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet() - - assertEquals(2, grades.first.size) - } - - @Test - fun subtractRemoteDuplicateGrades() { - gradeLocal.saveGrades(listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - )) - - every { mockSdk.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet() - - assertEquals(3, grades.first.size) - } - - @Test - fun emptyLocal() { - gradeLocal.saveGrades(listOf()) - - every { mockSdk.getGrades(1) } returns Single.just(listOf( - createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - ) to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet() - - assertEquals(3, grades.first.size) - } - - @Test - fun emptyRemote() { - gradeLocal.saveGrades(listOf( - createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"), - createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena") - )) - - every { mockSdk.getGrades(1) } returns Single.just(emptyList() to emptyList()) - - val grades = GradeRepository(settings, gradeLocal, gradeRemote) - .getGrades(studentMock, semesterMock, true).blockingGet() - - assertEquals(0, grades.first.size) - } -} 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 9146934bf..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/grade/TestGradeEntityCreator.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import org.threeten.bp.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 bd3635fea..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt +++ /dev/null @@ -1,106 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import androidx.room.Room -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.db.entities.Semester -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate.now -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -class GradeStatisticsLocalTest { - - private lateinit var gradeStatisticsLocal: GradeStatisticsLocal - - private lateinit var testDb: AppDatabase - - @Before - fun createDb() { - testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) - .build() - gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndRead_subject() { - gradeStatisticsLocal.saveGradesStatistics(listOf( - getGradeStatistics("Matematyka", 2, 1), - getGradeStatistics("Fizyka", 1, 2) - )) - - val stats = gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Matematyka").blockingGet() - assertEquals(1, stats.size) - assertEquals(stats[0].subject, "Matematyka") - } - - @Test - fun saveAndRead_all() { - gradeStatisticsLocal.saveGradesStatistics(listOf( - getGradeStatistics("Matematyka", 2, 1), - getGradeStatistics("Chemia", 2, 1), - getGradeStatistics("Fizyka", 1, 2) - )) - - val stats = gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Wszystkie").blockingGet() - assertEquals(3, stats.size) - assertEquals(stats[0].subject, "Wszystkie") - assertEquals(stats[1].subject, "Matematyka") - assertEquals(stats[2].subject, "Chemia") - } - - @Test - fun saveAndRead_points() { - gradeStatisticsLocal.saveGradesPointsStatistics(listOf( - getGradePointsStatistics("Matematyka", 2, 1), - getGradePointsStatistics("Chemia", 2, 1), - getGradePointsStatistics("Fizyka", 1, 2) - )) - - val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka").blockingGet() - with(stats[0]) { - assertEquals(subject, "Matematyka") - assertEquals(others, 5.0) - assertEquals(student, 5.0) - } - } - - @Test - fun saveAndRead_subjectEmpty() { - gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) - - val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka").blockingGet() - assertEquals(null, stats) - } - - @Test - fun saveAndRead_allEmpty() { - gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) - - val stats = gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Wszystkie").blockingGet() - assertEquals(null, stats) - } - - private fun getSemester(): Semester { - return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1) - } - - private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics { - return GradeStatistics(studentId, semesterId, subject, 5, 5, false) - } - - private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics { - return GradePointsStatistics(studentId, semesterId, subject, 5.0, 5.0) - } -} diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt deleted file mode 100644 index efad0d4d5..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocalTest.kt +++ /dev/null @@ -1,48 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.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() { - luckyNumberLocal.saveLuckyNumber(LuckyNumber(1, LocalDate.of(2019, 1, 20), 14)) - - val luckyNumber = luckyNumberLocal.getLuckyNumber(Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", 1, false, now()), - LocalDate.of(2019, 1, 20) - ).blockingGet() - - 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 22578e41e..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocalTest.kt +++ /dev/null @@ -1,60 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.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() { - recipientLocal.saveRecipients(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") - )) - - val recipients = recipientLocal.getRecipients( - Student("fakelog.cf", "AUTO", "", "", "", "", false, "", "", "", 1, 0, "", "", "", "", "", 1, true, LocalDateTime.now()), - 2, - ReportingUnit(1, 4, "", 0, "", emptyList()) - ).blockingGet() - - 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 530bfb3f7..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/student/StudentLocalTest.kt +++ /dev/null @@ -1,44 +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.db.AppDatabase -import io.github.wulkanowy.data.repositories.getStudent -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, context) - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun saveAndReadTest() { - studentLocal.saveStudents(listOf(student)).blockingGet() - - val student = studentLocal.getCurrentStudent(true).blockingGet() - 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 aa35fe790..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TestTimetableEntityCreator.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import org.threeten.bp.LocalDateTime -import org.threeten.bp.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 a66e5843c..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocalTest.kt +++ /dev/null @@ -1,53 +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 org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.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() { - timetableDb.saveTimetable(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) - )) - - val exams = timetableDb.getTimetable( - Semester(1, 2, "", 1, 1, 2019, LocalDate.now(), LocalDate.now(), 1, 1), - LocalDate.of(2018, 9, 10), - LocalDate.of(2018, 9, 14) - ).blockingGet() - - 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 75f2f0b83..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepositoryTest.kt +++ /dev/null @@ -1,166 +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 com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.AppDatabase -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.TestInternetObservingStrategy -import io.github.wulkanowy.data.repositories.getStudent -import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper -import io.github.wulkanowy.sdk.Sdk -import io.mockk.MockKAnnotations -import io.mockk.every -import io.mockk.impl.annotations.MockK -import io.mockk.mockk -import io.reactivex.Single -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime.of -import kotlin.test.assertEquals - -@SdkSuppress(minSdkVersion = P) -@RunWith(AndroidJUnit4::class) -class TimetableRepositoryTest { - - @MockK - private lateinit var mockSdk: Sdk - - private val settings = InternetObservingSettings.builder() - .strategy(TestInternetObservingStrategy()) - .build() - - @MockK - private lateinit var studentMock: Student - - private val student = getStudent() - - @MockK - private lateinit var semesterMock: Semester - - @MockK - private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper - - private lateinit var timetableRemote: TimetableRemote - - private lateinit var timetableLocal: TimetableLocal - - private lateinit var testDb: AppDatabase - - @Before - fun initApi() { - MockKAnnotations.init(this) - testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build() - timetableLocal = TimetableLocal(testDb.timetableDao) - timetableRemote = TimetableRemote(mockSdk) - - every { timetableNotificationSchedulerHelper.scheduleNotifications(any(), any()) } returns mockk() - every { timetableNotificationSchedulerHelper.cancelScheduled(any(), any()) } returns mockk() - - every { studentMock.studentId } returns 1 - every { studentMock.studentName } returns "Jan Kowalski" - - every { semesterMock.studentId } returns 1 - every { semesterMock.diaryId } returns 2 - every { semesterMock.schoolYear } returns 2019 - every { semesterMock.semesterId } returns 1 - - every { mockSdk.switchDiary(any(), any()) } returns mockSdk - } - - @After - fun closeDb() { - testDb.close() - } - - @Test - fun copyRoomToCompletedFromPrevious() { - 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") - )) - - every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf( - createTimetableRemote(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"), - createTimetableRemote(of(2019, 3, 5, 8, 50), 2, "", "Religia"), - createTimetableRemote(of(2019, 3, 5, 9, 40), 3, "", "W-F"), - createTimetableRemote(of(2019, 3, 5, 10, 30), 4, "", "W-F") - )) - - val lessons = TimetableRepository(settings, timetableLocal, timetableRemote, timetableNotificationSchedulerHelper) - .getTimetable(student, semesterMock, LocalDate.of(2019, 3, 5), LocalDate.of(2019, 3, 5), true) - .blockingGet() - - assertEquals(4, lessons.size) - assertEquals("123", lessons[0].room) - assertEquals("321", lessons[1].room) - assertEquals("213", lessons[2].room) - } - - @Test - fun copyTeacherToCompletedFromPrevious() { - timetableLocal.saveTimetable(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) - )) - - every { mockSdk.getTimetable(any(), any()) } returns Single.just(listOf( - createTimetableRemote(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false), - createTimetableRemote(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true), - createTimetableRemote(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false), - createTimetableRemote(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true), - - createTimetableRemote(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false), - createTimetableRemote(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true), - createTimetableRemote(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false), - createTimetableRemote(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true), - - createTimetableRemote(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false), - createTimetableRemote(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true), - createTimetableRemote(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false), - createTimetableRemote(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true) - )) - - val lessons = TimetableRepository(settings, timetableLocal, timetableRemote, timetableNotificationSchedulerHelper) - .getTimetable(student, semesterMock, LocalDate.of(2019, 12, 23), LocalDate.of(2019, 12, 25), true) - .blockingGet() - - 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/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.java b/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.java new file mode 100644 index 000000000..2fd1904ba --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.java @@ -0,0 +1,25 @@ +package io.github.wulkanowy.utils.security; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SdkSuppress; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ScramblerTest { + + @Test + @SdkSuppress(minSdkVersion = 18) + public void encryptDecryptTest() throws Exception { + Context targetContext = InstrumentationRegistry.getTargetContext(); + + Assert.assertEquals("PASS", Scrambler.decrypt("TEST", + Scrambler.encrypt("TEST", "PASS", targetContext))); + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt b/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt deleted file mode 100644 index 0c47e6bb6..000000000 --- a/app/src/androidTest/java/io/github/wulkanowy/utils/security/ScramblerTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.utils.security - -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SdkSuppress -import androidx.test.filters.SmallTest -import org.junit.Test -import org.junit.runner.RunWith -import java.security.KeyStore -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -class ScramblerTest { - - @Test - fun encryptDecryptTest() { - assertEquals("TEST", decrypt(encrypt("TEST", - ApplicationProvider.getApplicationContext()))) - } - - @Test - fun emptyTextEncryptTest() { - assertFailsWith { - decrypt("") - } - - assertFailsWith { - encrypt("", ApplicationProvider.getApplicationContext()) - } - } - - @Test - @SdkSuppress(minSdkVersion = 18) - fun emptyKeyStoreTest() { - val text = encrypt("test", ApplicationProvider.getApplicationContext()) - - val keyStore = KeyStore.getInstance("AndroidKeyStore") - keyStore.load(null) - keyStore.deleteEntry("wulkanowy_password") - - assertFailsWith { - decrypt(text) - } - } -} diff --git a/app/src/debug/google-services.json b/app/src/debug/google-services.json deleted file mode 100644 index e9303986b..000000000 --- a/app/src/debug/google-services.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "project_info": { - "project_number": "", - "firebase_url": "", - "project_id": "", - "storage_bucket": "" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:1091101852179:android:b558a25f65d088b1", - "android_client_info": { - "package_name": "io.github.wulkanowy.dev" - } - }, - "oauth_client": [ - { - "client_id": "", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "" - } - ], - "services": { - "analytics_service": { - "status": 1 - }, - "appinvite_service": { - "status": 1, - "other_platform_oauth_client": [] - }, - "ads_service": { - "status": 2 - } - } - } - ], - "configuration_version": "1" -} diff --git a/app/src/debug/google-services.json.gpg b/app/src/debug/google-services.json.gpg deleted file mode 100644 index 736f7906d..000000000 Binary files a/app/src/debug/google-services.json.gpg and /dev/null differ diff --git a/app/src/debug/res/drawable-anydpi-v24/ic_stat_grade.xml b/app/src/debug/res/drawable-anydpi-v24/ic_stat_grade.xml deleted file mode 100644 index 832eba838..000000000 --- a/app/src/debug/res/drawable-anydpi-v24/ic_stat_grade.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/debug/res/drawable-anydpi-v24/ic_stat_luckynumber.xml b/app/src/debug/res/drawable-anydpi-v24/ic_stat_luckynumber.xml deleted file mode 100644 index 4f3eb98e1..000000000 --- a/app/src/debug/res/drawable-anydpi-v24/ic_stat_luckynumber.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/debug/res/drawable-anydpi-v24/ic_stat_message.xml b/app/src/debug/res/drawable-anydpi-v24/ic_stat_message.xml deleted file mode 100644 index 8fe12de45..000000000 --- a/app/src/debug/res/drawable-anydpi-v24/ic_stat_message.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/debug/res/drawable-anydpi-v24/ic_stat_note.xml b/app/src/debug/res/drawable-anydpi-v24/ic_stat_note.xml deleted file mode 100644 index d30f22336..000000000 --- a/app/src/debug/res/drawable-anydpi-v24/ic_stat_note.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/debug/res/drawable-hdpi/ic_stat_grade.png b/app/src/debug/res/drawable-hdpi/ic_stat_grade.png deleted file mode 100644 index 013b7ac49..000000000 Binary files a/app/src/debug/res/drawable-hdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/debug/res/drawable-hdpi/ic_stat_luckynumber.png b/app/src/debug/res/drawable-hdpi/ic_stat_luckynumber.png deleted file mode 100644 index 74a4d0c55..000000000 Binary files a/app/src/debug/res/drawable-hdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/debug/res/drawable-hdpi/ic_stat_message.png b/app/src/debug/res/drawable-hdpi/ic_stat_message.png deleted file mode 100644 index be41e3434..000000000 Binary files a/app/src/debug/res/drawable-hdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/debug/res/drawable-hdpi/ic_stat_note.png b/app/src/debug/res/drawable-hdpi/ic_stat_note.png deleted file mode 100644 index 1992edf25..000000000 Binary files a/app/src/debug/res/drawable-hdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/debug/res/drawable-mdpi/ic_stat_grade.png b/app/src/debug/res/drawable-mdpi/ic_stat_grade.png deleted file mode 100644 index a5df2a359..000000000 Binary files a/app/src/debug/res/drawable-mdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/debug/res/drawable-mdpi/ic_stat_luckynumber.png b/app/src/debug/res/drawable-mdpi/ic_stat_luckynumber.png deleted file mode 100644 index 278ed2c66..000000000 Binary files a/app/src/debug/res/drawable-mdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/debug/res/drawable-mdpi/ic_stat_message.png b/app/src/debug/res/drawable-mdpi/ic_stat_message.png deleted file mode 100644 index 7327a02f3..000000000 Binary files a/app/src/debug/res/drawable-mdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/debug/res/drawable-mdpi/ic_stat_note.png b/app/src/debug/res/drawable-mdpi/ic_stat_note.png deleted file mode 100644 index 2fb020982..000000000 Binary files a/app/src/debug/res/drawable-mdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xhdpi/ic_stat_grade.png b/app/src/debug/res/drawable-xhdpi/ic_stat_grade.png deleted file mode 100644 index c63f810fb..000000000 Binary files a/app/src/debug/res/drawable-xhdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xhdpi/ic_stat_luckynumber.png b/app/src/debug/res/drawable-xhdpi/ic_stat_luckynumber.png deleted file mode 100644 index 4035ceba8..000000000 Binary files a/app/src/debug/res/drawable-xhdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xhdpi/ic_stat_message.png b/app/src/debug/res/drawable-xhdpi/ic_stat_message.png deleted file mode 100644 index c4140be89..000000000 Binary files a/app/src/debug/res/drawable-xhdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xhdpi/ic_stat_note.png b/app/src/debug/res/drawable-xhdpi/ic_stat_note.png deleted file mode 100644 index 6b533c8ee..000000000 Binary files a/app/src/debug/res/drawable-xhdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xxhdpi/ic_stat_grade.png b/app/src/debug/res/drawable-xxhdpi/ic_stat_grade.png deleted file mode 100644 index 13c26b772..000000000 Binary files a/app/src/debug/res/drawable-xxhdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xxhdpi/ic_stat_luckynumber.png b/app/src/debug/res/drawable-xxhdpi/ic_stat_luckynumber.png deleted file mode 100644 index da4357456..000000000 Binary files a/app/src/debug/res/drawable-xxhdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xxhdpi/ic_stat_message.png b/app/src/debug/res/drawable-xxhdpi/ic_stat_message.png deleted file mode 100644 index 9d0fa781c..000000000 Binary files a/app/src/debug/res/drawable-xxhdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/debug/res/drawable-xxhdpi/ic_stat_note.png b/app/src/debug/res/drawable-xxhdpi/ic_stat_note.png deleted file mode 100644 index 64da443fd..000000000 Binary files a/app/src/debug/res/drawable-xxhdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/debug/res/drawable/ic_launcher_foreground_dev.xml b/app/src/debug/res/drawable/ic_launcher_foreground_dev.xml deleted file mode 100644 index 799ea0374..000000000 --- a/app/src/debug/res/drawable/ic_launcher_foreground_dev.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 7dbec2cb9..000000000 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7dbec2cb9..000000000 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher.png b/app/src/debug/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 5b688d7cb..000000000 Binary files a/app/src/debug/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 81e723ecc..000000000 Binary files a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher.png b/app/src/debug/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 48b13240c..000000000 Binary files a/app/src/debug/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 394b57076..000000000 Binary files a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index ff8bfa3e9..000000000 Binary files a/app/src/debug/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 365b4d663..000000000 Binary files a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 96be1ed4f..000000000 Binary files a/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 463c089b3..000000000 Binary files a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 57c7416f1..000000000 Binary files a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 53d6f5bbd..000000000 Binary files a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/values/preferences_defaults.xml b/app/src/debug/res/values/preferences_defaults.xml deleted file mode 100644 index f5a12464f..000000000 --- a/app/src/debug/res/values/preferences_defaults.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - true - diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt deleted file mode 100644 index d03a319a2..000000000 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/CrashlyticsUtils.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("UNUSED_PARAMETER") - -package io.github.wulkanowy.utils - -import timber.log.Timber - -open class TimberTreeNoOp : Timber.Tree() { - override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {} -} - -class CrashlyticsTree : TimberTreeNoOp() - -class CrashlyticsExceptionTree : TimberTreeNoOp() diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt deleted file mode 100644 index f23645bc3..000000000 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/FirebaseAnalyticsHelper.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.utils - -import android.app.Activity -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -@Suppress("UNUSED_PARAMETER") -class FirebaseAnalyticsHelper @Inject constructor() { - - fun logEvent(name: String, vararg params: Pair) { - // do nothing - } - - fun setCurrentScreen(activity: Activity, name: String?) { - // do nothing - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 802cf1ad2..f1733681e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,150 +1,54 @@ - + android:supportsRtl="true" + android:theme="@style/WulkanowyTheme"> + android:name=".ui.splash.SplashActivity" + android:configChanges="orientation|screenSize" + android:noHistory="true" + android:theme="@style/WulkanowyTheme.SplashTheme"> + - - - - - - - - - - - + android:label="@string/activity_dashboard_text" /> - - + android:name=".services.SyncJob" + android:exported="false"> - + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + android:name="io.fabric.ApiKey" + android:value="${fabricApiKey}" /> + diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json deleted file mode 100644 index 40aff4c48..000000000 --- a/app/src/main/assets/contributors.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "displayName": "Mikołaj Pich", - "githubUsername": "mklkj" - }, - { - "displayName": "Rafał Borcz", - "githubUsername": "Faierbel" - }, - { - "displayName": "Dominik Korsa", - "githubUsername": "dominik-korsa" - }, - { - "displayName": "Kacper Ziubryniewicz", - "githubUsername": "kapi2289" - }, - { - "displayName": "doteq", - "githubUsername": "doteq" - }, - { - "displayName": "Paweł Krzyś", - "githubUsername": "pavuloff" - }, - { - "displayName": "Piotr Romanowski", - "githubUsername": "v0idzz" - }, - { - "displayName": "Dinolek", - "githubUsername": "Dinolek" - }, - { - "displayName": "Mateusz Idziejczak", - "githubUsername": "PanTajemnic" - } -] diff --git a/app/src/main/assets/message-print-page.html b/app/src/main/assets/message-print-page.html deleted file mode 100644 index 8da7dec6e..000000000 --- a/app/src/main/assets/message-print-page.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - %SUBJECT% | Wulkanowy - - - -

%SUBJECT%

-
-
- %INFO% -
- -
-
-

Treść wiadomości

- %CONTENT% -
- - diff --git a/app/src/main/assets/wulkanowy-logo-black.svg b/app/src/main/assets/wulkanowy-logo-black.svg deleted file mode 100644 index 9bfbe2c02..000000000 --- a/app/src/main/assets/wulkanowy-logo-black.svg +++ /dev/null @@ -1,74 +0,0 @@ - -image/svg+xml \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 000000000..7cad5c2f4 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.java b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.java new file mode 100644 index 000000000..4b8866ce2 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy; + +import android.app.Application; + +import com.crashlytics.android.Crashlytics; +import com.crashlytics.android.core.CrashlyticsCore; + +import org.greenrobot.greendao.query.QueryBuilder; + +import javax.inject.Inject; + +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.utils.Log; +import io.fabric.sdk.android.Fabric; +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.di.component.ApplicationComponent; +import io.github.wulkanowy.di.component.DaggerApplicationComponent; +import io.github.wulkanowy.di.modules.ApplicationModule; + +public class WulkanowyApp extends Application { + + protected ApplicationComponent applicationComponent; + + @Inject + RepositoryContract repository; + + @Override + public void onCreate() { + super.onCreate(); + applicationComponent = DaggerApplicationComponent + .builder() + .applicationModule(new ApplicationModule(this)) + .build(); + applicationComponent.inject(this); + + if (BuildConfig.DEBUG) { + enableDebugLog(); + } + initializeFabric(); + } + + private void enableDebugLog() { + QueryBuilder.LOG_VALUES = true; + FlexibleAdapter.enableLogs(Log.Level.DEBUG); + } + + private void initializeFabric() { + Fabric.with(new Fabric.Builder(this) + .kits(new Crashlytics.Builder() + .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()) + .build()) + .debuggable(BuildConfig.DEBUG) + .build()); + } + + public ApplicationComponent getApplicationComponent() { + return applicationComponent; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt deleted file mode 100644 index 0e094f699..000000000 --- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.wulkanowy - -import android.content.Context -import android.util.Log.DEBUG -import android.util.Log.INFO -import android.util.Log.VERBOSE -import androidx.multidex.MultiDex -import androidx.work.Configuration -import com.jakewharton.threetenabp.AndroidThreeTen -import com.yariksoffice.lingver.Lingver -import dagger.android.AndroidInjector -import dagger.android.support.DaggerApplication -import fr.bipi.tressence.file.FileLoggerTree -import io.github.wulkanowy.di.DaggerAppComponent -import io.github.wulkanowy.services.sync.SyncWorkerFactory -import io.github.wulkanowy.ui.base.ThemeManager -import io.github.wulkanowy.utils.ActivityLifecycleLogger -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.CrashlyticsExceptionTree -import io.github.wulkanowy.utils.CrashlyticsTree -import io.github.wulkanowy.utils.DebugLogTree -import io.reactivex.exceptions.UndeliverableException -import io.reactivex.plugins.RxJavaPlugins -import timber.log.Timber -import java.io.IOException -import javax.inject.Inject - -class WulkanowyApp : DaggerApplication(), Configuration.Provider { - - @Inject - lateinit var workerFactory: SyncWorkerFactory - - @Inject - lateinit var themeManager: ThemeManager - - @Inject - lateinit var appInfo: AppInfo - - override fun attachBaseContext(base: Context?) { - super.attachBaseContext(base) - MultiDex.install(this) - } - - override fun onCreate() { - super.onCreate() - AndroidThreeTen.init(this) - RxJavaPlugins.setErrorHandler(::onError) - Lingver.init(this) - themeManager.applyDefaultTheme() - - initLogging() - } - - private fun initLogging() { - if (appInfo.isDebug) { - Timber.plant(DebugLogTree()) - Timber.plant(FileLoggerTree.Builder() - .withFileName("wulkanowy.%g.log") - .withDirName(applicationContext.filesDir.absolutePath) - .withFileLimit(10) - .withMinPriority(DEBUG) - .build() - ) - } else { - Timber.plant(CrashlyticsExceptionTree()) - Timber.plant(CrashlyticsTree()) - } - registerActivityLifecycleCallbacks(ActivityLifecycleLogger()) - } - - private fun onError(error: Throwable) { - //RxJava's too deep stack traces may cause SOE on older android devices - val cause = error.cause - if (error is UndeliverableException && cause is IOException || cause is InterruptedException || cause is StackOverflowError) { - Timber.e(cause, "An undeliverable error occurred") - } else throw error - } - - override fun applicationInjector(): AndroidInjector { - return DaggerAppComponent.factory().create(this) - } - - override fun getWorkManagerConfiguration() = Configuration.Builder() - .setWorkerFactory(workerFactory) - .setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO) - .build() -} diff --git a/app/src/main/java/io/github/wulkanowy/data/Repository.java b/app/src/main/java/io/github/wulkanowy/data/Repository.java new file mode 100644 index 000000000..04460a07e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/Repository.java @@ -0,0 +1,143 @@ +package io.github.wulkanowy.data; + + +import java.io.IOException; +import java.text.ParseException; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.api.login.AccountPermissionException; +import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.api.login.VulcanOfflineException; +import io.github.wulkanowy.data.db.dao.entities.Account; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.GradeDao; +import io.github.wulkanowy.data.db.dao.entities.Week; +import io.github.wulkanowy.data.db.dao.entities.WeekDao; +import io.github.wulkanowy.data.db.resources.ResourcesContract; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.data.sync.SyncContract; +import io.github.wulkanowy.data.sync.login.LoginSyncContract; +import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract; +import io.github.wulkanowy.di.annotations.SyncGrades; +import io.github.wulkanowy.di.annotations.SyncSubjects; +import io.github.wulkanowy.utils.security.CryptoException; + +@Singleton +public class Repository implements RepositoryContract { + + private final SharedPrefContract sharedPref; + + private final ResourcesContract resources; + + private final DaoSession daoSession; + + private final LoginSyncContract loginSync; + + private final TimetableSyncContract timetableSync; + + private final SyncContract gradeSync; + + private final SyncContract subjectSync; + + @Inject + Repository(SharedPrefContract sharedPref, + ResourcesContract resources, + DaoSession daoSession, + LoginSyncContract loginSync, + TimetableSyncContract timetableSync, + @SyncGrades SyncContract gradeSync, + @SyncSubjects SyncContract subjectSync) { + this.sharedPref = sharedPref; + this.resources = resources; + this.daoSession = daoSession; + this.loginSync = loginSync; + this.timetableSync = timetableSync; + this.gradeSync = gradeSync; + this.subjectSync = subjectSync; + } + + @Override + public long getCurrentUserId() { + return sharedPref.getCurrentUserId(); + } + + @Override + public String[] getSymbolsKeysArray() { + return resources.getSymbolsKeysArray(); + } + + @Override + public String[] getSymbolsValuesArray() { + return resources.getSymbolsValuesArray(); + } + + @Override + public String getErrorLoginMessage(Exception e) { + return resources.getErrorLoginMessage(e); + } + + @Override + public void loginUser(String email, String password, String symbol) + throws NotLoggedInErrorException, AccountPermissionException, IOException, + CryptoException, VulcanOfflineException, BadCredentialsException { + loginSync.loginUser(email, password, symbol); + } + + @Override + public void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException, + IOException, CryptoException, VulcanOfflineException, BadCredentialsException { + loginSync.loginCurrentUser(); + } + + @Override + public void syncGrades() throws NotLoggedInErrorException, IOException, ParseException { + gradeSync.sync(); + } + + @Override + public void syncSubjects() throws NotLoggedInErrorException, IOException, ParseException { + subjectSync.sync(); + } + + @Override + public void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException { + timetableSync.syncTimetable(); + } + + @Override + public void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException { + timetableSync.syncTimetable(date); + } + + @Override + public void syncAll() throws NotLoggedInErrorException, IOException, ParseException { + syncSubjects(); + syncGrades(); + syncTimetable(); + } + + @Override + public Account getCurrentUser() { + return daoSession.getAccountDao().load(sharedPref.getCurrentUserId()); + } + + @Override + public Week getWeek(String date) { + return daoSession.getWeekDao().queryBuilder() + .where(WeekDao.Properties.StartDayDate.eq(date), + WeekDao.Properties.UserId.eq(getCurrentUserId())) + .unique(); + } + + @Override + public List getNewGrades() { + return daoSession.getGradeDao().queryBuilder() + .where(GradeDao.Properties.IsNew.eq(1)) + .list(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryContract.java b/app/src/main/java/io/github/wulkanowy/data/RepositoryContract.java new file mode 100644 index 000000000..fcdf29ed8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryContract.java @@ -0,0 +1,34 @@ +package io.github.wulkanowy.data; + +import java.io.IOException; +import java.text.ParseException; +import java.util.List; + +import javax.inject.Singleton; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.data.db.dao.entities.Account; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.Week; +import io.github.wulkanowy.data.db.resources.ResourcesContract; +import io.github.wulkanowy.data.sync.login.LoginSyncContract; +import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract; + +@Singleton +public interface RepositoryContract extends ResourcesContract, LoginSyncContract, + TimetableSyncContract { + + long getCurrentUserId(); + + void syncGrades() throws NotLoggedInErrorException, IOException, ParseException; + + void syncSubjects() throws NotLoggedInErrorException, IOException, ParseException; + + void syncAll() throws NotLoggedInErrorException, IOException, ParseException; + + Account getCurrentUser(); + + Week getWeek(String date); + + List getNewGrades(); +} diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt deleted file mode 100644 index 19af1b2f8..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ /dev/null @@ -1,159 +0,0 @@ -package io.github.wulkanowy.data - -import android.content.Context -import android.content.SharedPreferences -import android.content.res.AssetManager -import android.content.res.Resources -import androidx.preference.PreferenceManager -import com.chuckerteam.chucker.api.ChuckerCollector -import com.chuckerteam.chucker.api.ChuckerInterceptor -import com.chuckerteam.chucker.api.RetentionManager -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy -import dagger.Module -import dagger.Provides -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.sdk.Sdk -import timber.log.Timber -import javax.inject.Singleton - -@Module -internal class RepositoryModule { - - @Singleton - @Provides - fun provideInternetObservingSettings(): InternetObservingSettings { - return InternetObservingSettings.builder() - .strategy(WalledGardenInternetObservingStrategy()) - .build() - } - - @Singleton - @Provides - fun provideSdk(chuckerCollector: ChuckerCollector, context: Context): Sdk { - return Sdk().apply { - androidVersion = android.os.Build.VERSION.RELEASE - buildTag = android.os.Build.MODEL - setSimpleHttpLogger { Timber.d(it) } - - // for debug only - addInterceptor(ChuckerInterceptor(context, chuckerCollector), true) - } - } - - @Singleton - @Provides - fun provideChuckerCollector(context: Context, prefRepository: PreferencesRepository): ChuckerCollector { - return ChuckerCollector( - context = context, - showNotification = prefRepository.isDebugNotificationEnable, - retentionPeriod = RetentionManager.Period.ONE_HOUR - ) - } - - @Singleton - @Provides - fun provideDatabase(context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider) - - @Singleton - @Provides - fun provideResources(context: Context): Resources = context.resources - - @Singleton - @Provides - fun provideAssets(context: Context): AssetManager = context.assets - - @Singleton - @Provides - fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - - @Singleton - @Provides - fun provideStudentDao(database: AppDatabase) = database.studentDao - - @Singleton - @Provides - fun provideSemesterDao(database: AppDatabase) = database.semesterDao - - @Singleton - @Provides - fun provideGradeDao(database: AppDatabase) = database.gradeDao - - @Singleton - @Provides - fun provideGradeSummaryDao(database: AppDatabase) = database.gradeSummaryDao - - @Singleton - @Provides - fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics - - @Singleton - @Provides - fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics - - @Singleton - @Provides - fun provideMessagesDao(database: AppDatabase) = database.messagesDao - - @Singleton - @Provides - fun provideMessageAttachmentsDao(database: AppDatabase) = database.messageAttachmentDao - - @Singleton - @Provides - fun provideExamDao(database: AppDatabase) = database.examsDao - - @Singleton - @Provides - fun provideAttendanceDao(database: AppDatabase) = database.attendanceDao - - @Singleton - @Provides - fun provideAttendanceSummaryDao(database: AppDatabase) = database.attendanceSummaryDao - - @Singleton - @Provides - fun provideTimetableDao(database: AppDatabase) = database.timetableDao - - @Singleton - @Provides - fun provideNoteDao(database: AppDatabase) = database.noteDao - - @Singleton - @Provides - fun provideHomeworkDao(database: AppDatabase) = database.homeworkDao - - @Singleton - @Provides - fun provideSubjectDao(database: AppDatabase) = database.subjectDao - - @Singleton - @Provides - fun provideLuckyNumberDao(database: AppDatabase) = database.luckyNumberDao - - @Singleton - @Provides - fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao - - @Singleton - @Provides - fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao - - @Singleton - @Provides - fun provideRecipientDao(database: AppDatabase) = database.recipientDao - - @Singleton - @Provides - fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao - - @Singleton - @Provides - fun provideTeacherDao(database: AppDatabase) = database.teacherDao - - @Singleton - @Provides - fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao -} 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 deleted file mode 100644 index a31b68c0d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ /dev/null @@ -1,199 +0,0 @@ -package io.github.wulkanowy.data.db - -import android.content.Context -import androidx.room.Database -import androidx.room.Room -import androidx.room.RoomDatabase -import androidx.room.RoomDatabase.JournalMode.TRUNCATE -import androidx.room.TypeConverters -import androidx.room.migration.Migration -import io.github.wulkanowy.data.db.dao.AttendanceDao -import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao -import io.github.wulkanowy.data.db.dao.CompletedLessonsDao -import io.github.wulkanowy.data.db.dao.ExamDao -import io.github.wulkanowy.data.db.dao.GradeDao -import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeSummaryDao -import io.github.wulkanowy.data.db.dao.HomeworkDao -import io.github.wulkanowy.data.db.dao.LuckyNumberDao -import io.github.wulkanowy.data.db.dao.MessageAttachmentDao -import io.github.wulkanowy.data.db.dao.MessagesDao -import io.github.wulkanowy.data.db.dao.MobileDeviceDao -import io.github.wulkanowy.data.db.dao.NoteDao -import io.github.wulkanowy.data.db.dao.RecipientDao -import io.github.wulkanowy.data.db.dao.ReportingUnitDao -import io.github.wulkanowy.data.db.dao.SchoolDao -import io.github.wulkanowy.data.db.dao.SemesterDao -import io.github.wulkanowy.data.db.dao.StudentDao -import io.github.wulkanowy.data.db.dao.SubjectDao -import io.github.wulkanowy.data.db.dao.TeacherDao -import io.github.wulkanowy.data.db.dao.TimetableDao -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.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.migrations.Migration10 -import io.github.wulkanowy.data.db.migrations.Migration11 -import io.github.wulkanowy.data.db.migrations.Migration12 -import io.github.wulkanowy.data.db.migrations.Migration13 -import io.github.wulkanowy.data.db.migrations.Migration14 -import io.github.wulkanowy.data.db.migrations.Migration15 -import io.github.wulkanowy.data.db.migrations.Migration16 -import io.github.wulkanowy.data.db.migrations.Migration17 -import io.github.wulkanowy.data.db.migrations.Migration18 -import io.github.wulkanowy.data.db.migrations.Migration19 -import io.github.wulkanowy.data.db.migrations.Migration2 -import io.github.wulkanowy.data.db.migrations.Migration20 -import io.github.wulkanowy.data.db.migrations.Migration21 -import io.github.wulkanowy.data.db.migrations.Migration22 -import io.github.wulkanowy.data.db.migrations.Migration23 -import io.github.wulkanowy.data.db.migrations.Migration24 -import io.github.wulkanowy.data.db.migrations.Migration25 -import io.github.wulkanowy.data.db.migrations.Migration26 -import io.github.wulkanowy.data.db.migrations.Migration3 -import io.github.wulkanowy.data.db.migrations.Migration4 -import io.github.wulkanowy.data.db.migrations.Migration5 -import io.github.wulkanowy.data.db.migrations.Migration6 -import io.github.wulkanowy.data.db.migrations.Migration7 -import io.github.wulkanowy.data.db.migrations.Migration8 -import io.github.wulkanowy.data.db.migrations.Migration9 -import javax.inject.Singleton - -@Singleton -@Database( - entities = [ - Student::class, - Semester::class, - Exam::class, - Timetable::class, - Attendance::class, - AttendanceSummary::class, - Grade::class, - GradeSummary::class, - GradeStatistics::class, - GradePointsStatistics::class, - Message::class, - MessageAttachment::class, - Note::class, - Homework::class, - Subject::class, - LuckyNumber::class, - CompletedLesson::class, - ReportingUnit::class, - Recipient::class, - MobileDevice::class, - Teacher::class, - School::class - ], - version = AppDatabase.VERSION_SCHEMA, - exportSchema = true -) -@TypeConverters(Converters::class) -abstract class AppDatabase : RoomDatabase() { - - companion object { - const val VERSION_SCHEMA = 26 - - fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array { - return arrayOf( - Migration2(), - Migration3(), - Migration4(), - Migration5(), - Migration6(), - Migration7(), - Migration8(), - Migration9(), - Migration10(), - Migration11(), - Migration12(), - Migration13(), - Migration14(), - Migration15(), - Migration16(), - Migration17(), - Migration18(), - Migration19(sharedPrefProvider), - Migration20(), - Migration21(), - Migration22(), - Migration23(), - Migration24(), - Migration25(), - Migration26() - ) - } - - fun newInstance(context: Context, sharedPrefProvider: SharedPrefProvider): AppDatabase { - return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") - .setJournalMode(TRUNCATE) - .fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1) - .fallbackToDestructiveMigrationOnDowngrade() - .addMigrations(*getMigrations(sharedPrefProvider)) - .build() - } - } - - abstract val studentDao: StudentDao - - abstract val semesterDao: SemesterDao - - abstract val examsDao: ExamDao - - abstract val timetableDao: TimetableDao - - abstract val attendanceDao: AttendanceDao - - abstract val attendanceSummaryDao: AttendanceSummaryDao - - abstract val gradeDao: GradeDao - - abstract val gradeSummaryDao: GradeSummaryDao - - abstract val gradeStatistics: GradeStatisticsDao - - abstract val gradePointsStatistics: GradePointsStatisticsDao - - abstract val messagesDao: MessagesDao - - abstract val messageAttachmentDao: MessageAttachmentDao - - abstract val noteDao: NoteDao - - abstract val homeworkDao: HomeworkDao - - abstract val subjectDao: SubjectDao - - abstract val luckyNumberDao: LuckyNumberDao - - abstract val completedLessonsDao: CompletedLessonsDao - - abstract val reportingUnitDao: ReportingUnitDao - - abstract val recipientDao: RecipientDao - - abstract val mobileDeviceDao: MobileDeviceDao - - abstract val teacherDao: TeacherDao - - abstract val schoolDao: SchoolDao -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt deleted file mode 100644 index 294f73d3d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.wulkanowy.data.db - -import androidx.room.TypeConverter -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken -import org.threeten.bp.DateTimeUtils -import org.threeten.bp.Instant -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime -import org.threeten.bp.Month -import org.threeten.bp.ZoneOffset -import java.util.Date - -class Converters { - - @TypeConverter - fun timestampToDate(value: Long?): LocalDate? = value?.run { - DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate() - } - - @TypeConverter - fun dateToTimestamp(date: LocalDate?): Long? { - return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli() - } - - @TypeConverter - fun timestampToTime(value: Long?): LocalDateTime? = value?.let { - LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC) - } - - @TypeConverter - fun timeToTimestamp(date: LocalDateTime?): Long? { - return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli() - } - - @TypeConverter - fun monthToInt(month: Month?) = month?.value - - @TypeConverter - fun intToMonth(value: Int?) = value?.let { Month.of(it) } - - @TypeConverter - fun intListToGson(list: List): String { - return Gson().toJson(list) - } - - @TypeConverter - fun gsonToIntList(value: String): List { - return Gson().fromJson(value, object : TypeToken>() {}.type) - } - - @TypeConverter - fun stringPairListToGson(list: List>): String { - return Gson().toJson(list) - } - - @TypeConverter - fun gsonToStringPairList(value: String): List> { - return Gson().fromJson(value, object : TypeToken>>() {}.type) - } -} 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 deleted file mode 100644 index 4a4aaf74f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.data.db - -import android.content.SharedPreferences -import androidx.core.content.edit -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) { - - companion object { - const val APP_VERSION_CODE_KEY = "app_version_code" - } - - fun putLong(key: String, value: Long, sync: Boolean = false) { - sharedPref.edit(sync) { putLong(key, value) } - } - - fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue) - - fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue - - fun putString(key: String, value: String, sync: Boolean = false) { - sharedPref.edit(sync) { putString(key, value) } - } - - fun delete(key: String) { - sharedPref.edit().remove(key).apply() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt deleted file mode 100644 index 3eb57473d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Attendance -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -interface AttendanceDao : BaseDao { - - @Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") - fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt deleted file mode 100644 index fd58533f1..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.reactivex.Maybe - -@Dao -interface AttendanceSummaryDao : BaseDao { - - @Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId") - fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt deleted file mode 100644 index 32dbadb86..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.Update - -interface BaseDao { - - @Insert - fun insertAll(items: List): List - - @Update - fun updateAll(items: List) - - @Delete - fun deleteAll(items: List) -} 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 deleted file mode 100644 index e13e569b6..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -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): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java new file mode 100644 index 000000000..199a6c8b1 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.db.dao; + +import android.content.Context; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.data.db.dao.entities.DaoMaster; +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.di.annotations.DatabaseInfo; + +@Singleton +public class DbHelper extends DaoMaster.DevOpenHelper { + + @Inject + DbHelper(@ApplicationContext Context context, @DatabaseInfo String dbName) { + super(context, dbName); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt deleted file mode 100644 index ca6b32dfc..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Exam -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -interface ExamDao : BaseDao { - - @Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") - fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt deleted file mode 100644 index c74d1937f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Grade -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface GradeDao : BaseDao { - - @Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId") - fun loadAll(semesterId: Int, studentId: Int): Maybe> - -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt deleted file mode 100644 index da1828666..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface GradePointsStatisticsDao : BaseDao { - - @Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName") - fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe> - - @Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId") - fun loadAll(semesterId: Int, studentId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt deleted file mode 100644 index 6faa35d0b..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface GradeStatisticsDao : BaseDao { - - @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester") - fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe> - - @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester") - fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt deleted file mode 100644 index 1165ef07f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface GradeSummaryDao : BaseDao { - - @Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId") - fun loadAll(semesterId: Int, studentId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt deleted file mode 100644 index 1947a0dfe..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Homework -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -interface HomeworkDao : BaseDao { - - @Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end") - fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt deleted file mode 100644 index f16c28d9e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -interface LuckyNumberDao : BaseDao { - - @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date") - fun load(studentId: Int, date: LocalDate): Maybe -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt deleted file mode 100644 index 3c511a277..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import io.github.wulkanowy.data.db.entities.MessageAttachment - -@Dao -interface MessageAttachmentDao : BaseDao { - - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertAttachments(items: List): List -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt deleted file mode 100644 index 7a69e2707..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import androidx.room.Transaction -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.reactivex.Maybe -import io.reactivex.Single - -@Dao -interface MessagesDao : BaseDao { - - @Transaction - @Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId") - fun loadMessageWithAttachment(studentId: Int, messageId: Int): Single - - @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC") - fun loadAll(studentId: Int, folder: Int): Maybe> - - @Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC") - fun loadDeleted(studentId: Int): Maybe> -} 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 deleted file mode 100644 index b05b2d9cc..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.reactivex.Maybe - -@Dao -interface MobileDeviceDao : BaseDao { - - @Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC") - fun loadAll(studentId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt deleted file mode 100644 index ea2fc6eb2..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Note -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface NoteDao : BaseDao { - - @Query("SELECT * FROM Notes WHERE student_id = :studentId") - fun loadAll(studentId: Int): Maybe> -} 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 deleted file mode 100644 index afb941b1a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Recipient -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface RecipientDao : BaseDao { - - @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId") - fun load(studentId: Int, role: Int, unitId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt deleted file mode 100644 index 6ddfd4941..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface ReportingUnitDao : BaseDao { - - @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId") - fun load(studentId: Int): Maybe> - - @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId") - fun loadOne(studentId: Int, unitId: Int): Maybe -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt deleted file mode 100644 index e9bd67557..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.School -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface SchoolDao : BaseDao { - - @Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId") - fun load(studentId: Int, classId: Int): Maybe -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt deleted file mode 100644 index 654b80f38..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface SemesterDao : BaseDao { - - @Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId") - fun loadAll(studentId: Int, classId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt deleted file mode 100644 index 901ddc73f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.OnConflictStrategy.ABORT -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface StudentDao { - - @Insert(onConflict = ABORT) - fun insertAll(student: List): List - - @Delete - fun delete(student: Student) - - @Query("SELECT * FROM Students WHERE is_current = 1") - fun loadCurrent(): Maybe - - @Query("SELECT * FROM Students WHERE id = :id") - fun loadById(id: Int): Maybe - - @Query("SELECT * FROM Students") - fun loadAll(): Maybe> - - @Query("UPDATE Students SET is_current = 1 WHERE id = :id") - fun updateCurrent(id: Long) - - @Query("UPDATE Students SET is_current = 0") - fun resetCurrent() -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt deleted file mode 100644 index 525a7129a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Subject -import io.reactivex.Maybe - -@Dao -interface SubjectDao : BaseDao { - - @Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId") - fun loadAll(diaryId: Int, studentId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt deleted file mode 100644 index 5ea237a84..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Teacher -import io.reactivex.Maybe -import javax.inject.Singleton - -@Singleton -@Dao -interface TeacherDao : BaseDao { - - @Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId") - fun loadAll(studentId: Int, classId: Int): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt deleted file mode 100644 index 6b62cc82a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.Timetable -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Singleton - -@Singleton -@Dao -interface TimetableDao : BaseDao { - - @Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end") - fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Account.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Account.java new file mode 100644 index 000000000..20a47ac26 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Account.java @@ -0,0 +1,258 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Property; +import org.greenrobot.greendao.annotation.ToMany; + +import java.util.List; + +@Entity( + nameInDb = "Accounts", + active = true +) +public class Account { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "NAME") + private String name; + + @Property(nameInDb = "E-MAIL") + private String email; + + @Property(nameInDb = "PASSWORD") + private String password; + + @Property(nameInDb = "SYMBOL") + private String symbol; + + @Property(nameInDb = "SNPID") + private String snpId; + + @ToMany(referencedJoinProperty = "userId") + private List subjectList; + + @ToMany(referencedJoinProperty = "userId") + private List gradeList; + + @ToMany(referencedJoinProperty = "userId") + private List dayList; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 335469827) + private transient AccountDao myDao; + + @Generated(hash = 735765217) + public Account(Long id, String name, String email, String password, String symbol, + String snpId) { + this.id = id; + this.name = name; + this.email = email; + this.password = password; + this.symbol = symbol; + this.snpId = snpId; + } + + @Generated(hash = 882125521) + public Account() { + } + + public Long getId() { + return id; + } + + public Account setId(Long id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public Account setName(String name) { + this.name = name; + return this; + } + + public String getEmail() { + return email; + } + + public Account setEmail(String email) { + this.email = email; + return this; + } + + public String getPassword() { + return password; + } + + public Account setPassword(String password) { + this.password = password; + return this; + } + + public String getSymbol() { + return symbol; + } + + public Account setSymbol(String symbol) { + this.symbol = symbol; + return this; + } + + public String getSnpId() { + return this.snpId; + } + + public Account setSnpId(String snpId) { + this.snpId = snpId; + return this; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1800750450) + public List getSubjectList() { + if (subjectList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + SubjectDao targetDao = daoSession.getSubjectDao(); + List subjectListNew = targetDao._queryAccount_SubjectList(id); + synchronized (this) { + if (subjectList == null) { + subjectList = subjectListNew; + } + } + } + return subjectList; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 594294258) + public synchronized void resetSubjectList() { + subjectList = null; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1040074549) + public List getGradeList() { + if (gradeList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + GradeDao targetDao = daoSession.getGradeDao(); + List gradeListNew = targetDao._queryAccount_GradeList(id); + synchronized (this) { + if (gradeList == null) { + gradeList = gradeListNew; + } + } + } + return gradeList; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 1939990047) + public synchronized void resetGradeList() { + gradeList = null; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 300459794) + public List getDayList() { + if (dayList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + DayDao targetDao = daoSession.getDayDao(); + List dayListNew = targetDao._queryAccount_DayList(id); + synchronized (this) { + if (dayList == null) { + dayList = dayListNew; + } + } + } + return dayList; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 1010399236) + public synchronized void resetDayList() { + dayList = null; + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 1812283172) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getAccountDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java new file mode 100644 index 000000000..15a063091 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java @@ -0,0 +1,214 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Index; +import org.greenrobot.greendao.annotation.Property; +import org.greenrobot.greendao.annotation.ToMany; + +import java.util.List; + +@Entity( + nameInDb = "Days", + active = true, + indexes ={@Index(value = "userId,weekId,date", unique = true)} +) +public class Day { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "USER_ID") + private Long userId; + + @Property(nameInDb = "WEEK_ID") + private Long weekId; + + @Property(nameInDb = "DATE") + private String date = ""; + + @Property(nameInDb = "DAY_NAME") + private String dayName = ""; + + @Property(nameInDb = "IS_FREE_DAY") + private boolean isFreeDay = false; + + @Property(nameInDb = "FREE_DAY_NAME") + private String freeDayName = ""; + + @ToMany(referencedJoinProperty = "dayId") + private List lessons; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 312167767) + private transient DayDao myDao; + + @Generated(hash = 723729681) + public Day(Long id, Long userId, Long weekId, String date, String dayName, + boolean isFreeDay, String freeDayName) { + this.id = id; + this.userId = userId; + this.weekId = weekId; + this.date = date; + this.dayName = dayName; + this.isFreeDay = isFreeDay; + this.freeDayName = freeDayName; + } + + @Generated(hash = 866989762) + public Day() { + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public Long getWeekId() { + return weekId; + } + + public Day setWeekId(Long weekId) { + this.weekId = weekId; + return this; + } + + public Day setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getDate() { + return date; + } + + public Day setDate(String date) { + this.date = date; + return this; + } + + public String getDayName() { + return dayName; + } + + public Day setDayName(String dayName) { + this.dayName = dayName; + return this; + } + + public boolean isFreeDay() { + return isFreeDay; + } + + public Day setFreeDay(boolean freeDay) { + isFreeDay = freeDay; + return this; + } + + public String getFreeDayName() { + return freeDayName; + } + + public Day setFreeDayName(String freeDayName) { + this.freeDayName = freeDayName; + return this; + } + + public boolean getIsFreeDay() { + return this.isFreeDay; + } + + public void setIsFreeDay(boolean isFreeDay) { + this.isFreeDay = isFreeDay; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1552857303) + public List getLessons() { + if (lessons == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + LessonDao targetDao = daoSession.getLessonDao(); + List lessonsNew = targetDao._queryDay_Lessons(id); + synchronized (this) { + if (lessons == null) { + lessons = lessonsNew; + } + } + } + return lessons; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 1769801440) + public synchronized void resetLessons() { + lessons = null; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 1409317752) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getDayDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Grade.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Grade.java new file mode 100644 index 000000000..632f9bcc7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Grade.java @@ -0,0 +1,331 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Property; + +import java.io.Serializable; + +import io.github.wulkanowy.R; + +@Entity( + nameInDb = "Grades", + active = true +) +public class Grade implements Serializable { + + @Id(autoincrement = true) + protected Long id; + + @Property(nameInDb = "SUBJECT_ID") + private Long subjectId; + + @Property(nameInDb = "USER_ID") + private Long userId; + + @Property(nameInDb = "SUBJECT") + private String subject = ""; + + @Property(nameInDb = "VALUE") + protected String value = ""; + + @Property(nameInDb = "COLOR") + private String color = ""; + + @Property(nameInDb = "SYMBOL") + private String symbol = ""; + + @Property(nameInDb = "DESCRIPTION") + private String description = ""; + + @Property(nameInDb = "WEIGHT") + private String weight = ""; + + @Property(nameInDb = "DATE") + private String date = ""; + + @Property(nameInDb = "TEACHER") + private String teacher = ""; + + @Property(nameInDb = "SEMESTER") + private String semester = ""; + + @Property(nameInDb = "IS_NEW") + private boolean isNew = false; + + @Property(nameInDb = "READ") + private boolean read = true; + + private static final long serialVersionUID = 42L; + + @Generated(hash = 568899968) + public Grade(Long id, Long subjectId, Long userId, String subject, String value, + String color, String symbol, String description, String weight, + String date, String teacher, String semester, boolean isNew, + boolean read) { + this.id = id; + this.subjectId = subjectId; + this.userId = userId; + this.subject = subject; + this.value = value; + this.color = color; + this.symbol = symbol; + this.description = description; + this.weight = weight; + this.date = date; + this.teacher = teacher; + this.semester = semester; + this.isNew = isNew; + this.read = read; + } + + @Generated(hash = 2042976393) + public Grade() { + } + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 681281562) + private transient GradeDao myDao; + + public int getValueColor() { + + String replacedString = value.replaceAll("[^0-9]", ""); + + if (!"".equals(replacedString)) { + switch (Integer.parseInt(replacedString)) { + case 6: + return R.color.six_grade; + case 5: + return R.color.five_grade; + case 4: + return R.color.four_grade; + case 3: + return R.color.three_grade; + case 2: + return R.color.two_grade; + case 1: + return R.color.one_grade; + default: + return R.color.default_grade; + } + } + return R.color.default_grade; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + Grade grade = (Grade) o; + + return new EqualsBuilder() + .append(subject, grade.subject) + .append(value, grade.value) + .append(color, grade.color) + .append(symbol, grade.symbol) + .append(description, grade.description) + .append(weight, grade.weight) + .append(date, grade.date) + .append(teacher, grade.teacher) + .append(semester, grade.semester) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(subject) + .append(value) + .append(color) + .append(symbol) + .append(description) + .append(weight) + .append(date) + .append(teacher) + .append(semester) + .toHashCode(); + } + + public Long getId() { + return id; + } + + public Grade setId(Long id) { + this.id = id; + return this; + } + + public Long getSubjectId() { + return subjectId; + } + + public Grade setSubjectId(Long subjectId) { + this.subjectId = subjectId; + return this; + } + + public Long getUserId() { + return userId; + } + + public Grade setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getSubject() { + return subject; + } + + public Grade setSubject(String subject) { + this.subject = subject; + return this; + } + + public String getValue() { + return value; + } + + public Grade setValue(String value) { + this.value = value; + return this; + } + + public String getColor() { + return color; + } + + public Grade setColor(String color) { + this.color = color; + return this; + } + + public String getSymbol() { + return symbol; + } + + public Grade setSymbol(String symbol) { + this.symbol = symbol; + return this; + } + + public String getDescription() { + return description; + } + + public Grade setDescription(String description) { + this.description = description; + return this; + } + + public String getWeight() { + return weight; + } + + public Grade setWeight(String weight) { + this.weight = weight; + return this; + } + + public String getDate() { + return date; + } + + public Grade setDate(String date) { + this.date = date; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Grade setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getSemester() { + return semester; + } + + public Grade setSemester(String semester) { + this.semester = semester; + return this; + } + + public boolean getIsNew() { + return this.isNew; + } + + public Grade setIsNew(boolean isNew) { + this.isNew = isNew; + return this; + } + + public boolean getRead() { + return this.read; + } + + public Grade setRead(boolean read) { + this.read = read; + return this; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 1187286414) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getGradeDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Lesson.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Lesson.java new file mode 100644 index 000000000..db9be9445 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Lesson.java @@ -0,0 +1,353 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Index; +import org.greenrobot.greendao.annotation.Property; + +import java.io.Serializable; + +@Entity( + nameInDb = "Lessons", + active = true, + indexes = {@Index(value = "dayId,date,startTime,endTime", unique = true)} +) +public class Lesson implements Serializable { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "DAY_ID") + private Long dayId; + + @Property(nameInDb = "NUMBER_OF_LESSON") + private String number; + + @Property(nameInDb = "SUBJECT_NAME") + private String subject = ""; + + @Property(nameInDb = "TEACHER") + private String teacher = ""; + + @Property(nameInDb = "ROOM") + private String room = ""; + + @Property(nameInDb = "DESCRIPTION") + private String description = ""; + + @Property(nameInDb = "GROUP_NAME") + private String groupName = ""; + + @Property(nameInDb = "START_TIME") + private String startTime = ""; + + @Property(nameInDb = "END_TIME") + private String endTime = ""; + + @Property(nameInDb = "DATE") + private String date = ""; + + @Property(nameInDb = "IS_EMPTY") + private boolean isEmpty = false; + + @Property(nameInDb = "IS_DIVISION_INTO_GROUP") + private boolean isDivisionIntoGroups = false; + + @Property(nameInDb = "IS_PLANNING") + private boolean isPlanning = false; + + @Property(nameInDb = "IS_REALIZED") + private boolean isRealized = false; + + @Property(nameInDb = "IS_MOVED_CANCELED") + private boolean isMovedOrCanceled = false; + + @Property(nameInDb = "IS_NEW_MOVED_IN_CANCELED") + private boolean isNewMovedInOrChanged = false; + + private static final long serialVersionUID = 42L; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 610143130) + private transient LessonDao myDao; + + @Generated(hash = 140778287) + public Lesson(Long id, Long dayId, String number, String subject, String teacher, String room, + String description, String groupName, String startTime, String endTime, String date, + boolean isEmpty, boolean isDivisionIntoGroups, boolean isPlanning, boolean isRealized, + boolean isMovedOrCanceled, boolean isNewMovedInOrChanged) { + this.id = id; + this.dayId = dayId; + this.number = number; + this.subject = subject; + this.teacher = teacher; + this.room = room; + this.description = description; + this.groupName = groupName; + this.startTime = startTime; + this.endTime = endTime; + this.date = date; + this.isEmpty = isEmpty; + this.isDivisionIntoGroups = isDivisionIntoGroups; + this.isPlanning = isPlanning; + this.isRealized = isRealized; + this.isMovedOrCanceled = isMovedOrCanceled; + this.isNewMovedInOrChanged = isNewMovedInOrChanged; + } + + @Generated(hash = 1669664117) + public Lesson() { + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getDayId() { + return this.dayId; + } + + public void setDayId(Long dayId) { + this.dayId = dayId; + } + + public String getNumber() { + return number; + } + + public Lesson setNumber(String number) { + this.number = number; + return this; + } + + public String getSubject() { + return subject; + } + + public Lesson setSubject(String subject) { + this.subject = subject; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Lesson setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getRoom() { + return room; + } + + public Lesson setRoom(String room) { + this.room = room; + return this; + } + + public String getDescription() { + return description; + } + + public Lesson setDescription(String description) { + this.description = description; + return this; + } + + public String getGroupName() { + return groupName; + } + + public Lesson setGroupName(String groupName) { + this.groupName = groupName; + return this; + } + + public String getStartTime() { + return startTime; + } + + public Lesson setStartTime(String startTime) { + this.startTime = startTime; + return this; + } + + public String getEndTime() { + return endTime; + } + + public Lesson setEndTime(String endTime) { + this.endTime = endTime; + return this; + } + + public String getDate() { + return date; + } + + public Lesson setDate(String date) { + this.date = date; + return this; + } + + public boolean isEmpty() { + return isEmpty; + } + + public Lesson setEmpty(boolean empty) { + isEmpty = empty; + return this; + } + + public boolean isDivisionIntoGroups() { + return isDivisionIntoGroups; + } + + public Lesson setDivisionIntoGroups(boolean divisionIntoGroups) { + isDivisionIntoGroups = divisionIntoGroups; + return this; + } + + public boolean isPlanning() { + return isPlanning; + } + + public Lesson setPlanning(boolean planning) { + isPlanning = planning; + return this; + } + + public boolean isRealized() { + return isRealized; + } + + public Lesson setRealized(boolean realized) { + isRealized = realized; + return this; + } + + public boolean isMovedOrCanceled() { + return isMovedOrCanceled; + } + + public Lesson setMovedOrCanceled(boolean movedOrCanceled) { + isMovedOrCanceled = movedOrCanceled; + return this; + } + + public boolean isNewMovedInOrChanged() { + return isNewMovedInOrChanged; + } + + public Lesson setNewMovedInOrChanged(boolean newMovedInOrChanged) { + isNewMovedInOrChanged = newMovedInOrChanged; + return this; + } + + public boolean getIsEmpty() { + return this.isEmpty; + } + + public void setIsEmpty(boolean isEmpty) { + this.isEmpty = isEmpty; + } + + public boolean getIsDivisionIntoGroups() { + return this.isDivisionIntoGroups; + } + + public void setIsDivisionIntoGroups(boolean isDivisionIntoGroups) { + this.isDivisionIntoGroups = isDivisionIntoGroups; + } + + public boolean getIsPlanning() { + return this.isPlanning; + } + + public void setIsPlanning(boolean isPlanning) { + this.isPlanning = isPlanning; + } + + public boolean getIsRealized() { + return this.isRealized; + } + + public void setIsRealized(boolean isRealized) { + this.isRealized = isRealized; + } + + public boolean getIsMovedOrCanceled() { + return this.isMovedOrCanceled; + } + + public void setIsMovedOrCanceled(boolean isMovedOrCanceled) { + this.isMovedOrCanceled = isMovedOrCanceled; + } + + public boolean getIsNewMovedInOrChanged() { + return this.isNewMovedInOrChanged; + } + + public void setIsNewMovedInOrChanged(boolean isNewMovedInOrChanged) { + this.isNewMovedInOrChanged = isNewMovedInOrChanged; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 2078826279) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getLessonDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Subject.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Subject.java new file mode 100644 index 000000000..6bcce6229 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Subject.java @@ -0,0 +1,192 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Property; +import org.greenrobot.greendao.annotation.ToMany; + +import java.util.List; + +@Entity( + nameInDb = "Subjects", + active = true +) +public class Subject { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "USER_ID") + private Long userId; + + @Property(nameInDb = "NAME") + private String name; + + @Property(nameInDb = "PREDICTED_RATING") + private String predictedRating; + + @Property(nameInDb = "FINAL_RATING") + private String finalRating; + + @Property(nameInDb = "SEMESTER") + private String semester; + + @ToMany(referencedJoinProperty = "subjectId") + private List gradeList; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 1644932788) + private transient SubjectDao myDao; + + @Generated(hash = 396325764) + public Subject(Long id, Long userId, String name, String predictedRating, + String finalRating, String semester) { + this.id = id; + this.userId = userId; + this.name = name; + this.predictedRating = predictedRating; + this.finalRating = finalRating; + this.semester = semester; + } + + @Generated(hash = 1617906264) + public Subject() { + } + + public Long getId() { + return id; + } + + public Subject setId(Long id) { + this.id = id; + return this; + } + + public Long getUserId() { + return userId; + } + + public Subject setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getName() { + return name; + } + + public Subject setName(String name) { + this.name = name; + return this; + } + + public String getPredictedRating() { + return predictedRating; + } + + public Subject setPredictedRating(String predictedRating) { + this.predictedRating = predictedRating; + return this; + } + + public String getFinalRating() { + return finalRating; + } + + public Subject setFinalRating(String finalRating) { + this.finalRating = finalRating; + return this; + } + + public String getSemester() { + return semester; + } + + public Subject setSemester(String semester) { + this.semester = semester; + return this; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1358847893) + public List getGradeList() { + if (gradeList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + GradeDao targetDao = daoSession.getGradeDao(); + List gradeListNew = targetDao._querySubject_GradeList(id); + synchronized (this) { + if (gradeList == null) { + gradeList = gradeListNew; + } + } + } + return gradeList; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 1939990047) + public synchronized void resetGradeList() { + gradeList = null; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 937984622) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getSubjectDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java new file mode 100644 index 000000000..c82f3277b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java @@ -0,0 +1,148 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Index; +import org.greenrobot.greendao.annotation.Property; +import org.greenrobot.greendao.annotation.ToMany; + +import java.util.List; + +@Entity( + nameInDb = "Weeks", + active = true, + indexes ={@Index(value = "userId,startDayDate", unique = true)} +) +public class Week { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "USER_ID") + private Long userId; + + @Property(nameInDb = "START_DATE") + private String startDayDate = ""; + + @ToMany(referencedJoinProperty = "weekId") + private List dayList; + + /** Used to resolve relations */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** Used for active entity operations. */ + @Generated(hash = 1019310398) + private transient WeekDao myDao; + + @Generated(hash = 36829814) + public Week(Long id, Long userId, String startDayDate) { + this.id = id; + this.userId = userId; + this.startDayDate = startDayDate; + } + + @Generated(hash = 2135529658) + public Week() { + } + + public Long getId() { + return id; + } + + public Week setId(Long id) { + this.id = id; + return this; + } + + public Long getUserId() { + return userId; + } + + public Week setUserId(Long userId) { + this.userId = userId; + return this; + } + + public String getStartDayDate() { + return startDayDate; + } + + public Week setStartDayDate(String startDayDate) { + this.startDayDate = startDayDate; + return this; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1562119145) + public List getDayList() { + if (dayList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + DayDao targetDao = daoSession.getDayDao(); + List dayListNew = targetDao._queryWeek_DayList(id); + synchronized (this) { + if (dayList == null) { + dayList = dayListNew; + } + } + } + return dayList; + } + + /** Resets a to-many relationship, making the next get call to query for a fresh result. */ + @Generated(hash = 1010399236) + public synchronized void resetDayList() { + dayList = null; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 665278367) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getWeekDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt deleted file mode 100644 index aa8da8db7..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "Attendance") -data class Attendance( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - @ColumnInfo(name = "time_id") - val timeId: Int, - - val date: LocalDate, - - val number: Int, - - val subject: String, - - val name: String, - - val presence: Boolean, - - val absence: Boolean, - - val exemption: Boolean, - - val lateness: Boolean, - - val excused: Boolean, - - val deleted: Boolean, - - val excusable: Boolean, - - @ColumnInfo(name = "excuse_status") - val excuseStatus: String? - -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt deleted file mode 100644 index d2e1f174e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt +++ /dev/null @@ -1,43 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.Month -import java.io.Serializable - -@Entity(tableName = "AttendanceSummary") -data class AttendanceSummary( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - @ColumnInfo(name = "subject_id") - val subjectId: Int, - - val month: Month, - - val presence: Int, - - val absence: Int, - - @ColumnInfo(name = "absence_excused") - val absenceExcused: Int, - - @ColumnInfo(name = "absence_for_school_reasons") - val absenceForSchoolReasons: Int, - - val lateness: Int, - - @ColumnInfo(name = "lateness_excused") - val latenessExcused: Int, - - val exemption: Int -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt deleted file mode 100644 index 775f3f558..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "CompletedLesson") -data class CompletedLesson( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - val date: LocalDate, - - val number: Int, - - val subject: String, - - val topic: String, - - val teacher: String, - - @ColumnInfo(name = "teacher_symbol") - val teacherSymbol: String, - - val substitution: String, - - val absence: String, - - val resources: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt deleted file mode 100644 index 9ae795e71..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "Exams") -data class Exam( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - val date: LocalDate, - - @ColumnInfo(name = "entry_date") - val entryDate: LocalDate, - - val subject: String, - - val group: String, - - val type: String, - - val description: String, - - val teacher: String, - - @ColumnInfo(name = "teacher_symbol") - val teacherSymbol: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt deleted file mode 100644 index 3f69c61b1..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "Grades") -data class Grade( - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val subject: String, - - val entry: String, - - val value: Double, - - val modifier: Double, - - val comment: String, - - val color: String, - - @ColumnInfo(name = "grade_symbol") - val gradeSymbol: String, - - val description: String, - - val weight: String, - - val weightValue: Double, - - val date: LocalDate, - - val teacher: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_read") - var isRead: Boolean = true - - @ColumnInfo(name = "is_notified") - var isNotified: Boolean = true -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePointsStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePointsStatistics.kt deleted file mode 100644 index 407f18bd6..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePointsStatistics.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity(tableName = "GradesPointsStatistics") -data class GradePointsStatistics( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - val subject: String, - - val others: Double, - - val student: Double -) { - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt deleted file mode 100644 index 8ad8b8b8d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity(tableName = "GradesStatistics") -data class GradeStatistics( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - val subject: String, - - val grade: Int, - - val amount: Int, - - @ColumnInfo(name = "is_semester") - val semester: Boolean -) { - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt deleted file mode 100644 index dd3126d4d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDateTime - -@Entity(tableName = "GradesSummary") -data class GradeSummary( - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val position: Int, - - val subject: String, - - @ColumnInfo(name = "predicted_grade") - val predictedGrade: String, - - @ColumnInfo(name = "final_grade") - val finalGrade: String, - - @ColumnInfo(name = "proposed_points") - val proposedPoints: String, - - @ColumnInfo(name = "final_points") - val finalPoints: String, - - @ColumnInfo(name = "points_sum") - val pointsSum: String, - - val average: Double -) { - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_predicted_grade_notified") - var isPredictedGradeNotified: Boolean = true - - @ColumnInfo(name = "is_final_grade_notified") - var isFinalGradeNotified: Boolean = true - - @ColumnInfo(name = "predicted_grade_last_change") - var predictedGradeLastChange: LocalDateTime = LocalDateTime.now() - - @ColumnInfo(name = "final_grade_last_change") - var finalGradeLastChange: LocalDateTime = LocalDateTime.now() -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt deleted file mode 100644 index cd7d153e9..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "Homework") -data class Homework( - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val date: LocalDate, - - @ColumnInfo(name = "entry_date") - val entryDate: LocalDate, - - val subject: String, - - val content: String, - - val teacher: String, - - @ColumnInfo(name = "teacher_symbol") - val teacherSymbol: String, - - val attachments: List> -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_done") - var isDone: Boolean = false -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt deleted file mode 100644 index 5b9130f5d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "LuckyNumbers") -data class LuckyNumber ( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val date: LocalDate, - - @ColumnInfo(name = "lucky_number") - val luckyNumber: Int - -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_notified") - var isNotified: Boolean = true -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt deleted file mode 100644 index 058298415..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDateTime -import java.io.Serializable - -@Entity(tableName = "Messages") -data class Message( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "real_id") - val realId: Int, - - @ColumnInfo(name = "message_id") - val messageId: Int, - - @ColumnInfo(name = "sender_name") - val sender: String, - - @ColumnInfo(name = "sender_id") - val senderId: Int, - - @ColumnInfo(name = "recipient_name") - val recipient: String, - - val subject: String, - - var content: String, - - val date: LocalDateTime, - - @ColumnInfo(name = "folder_id") - val folderId: Int, - - var unread: Boolean, - - @ColumnInfo(name = "unread_by") - val unreadBy: Int, - - @ColumnInfo(name = "read_by") - val readBy: Int, - - val removed: Boolean, - - @ColumnInfo(name = "has_attachments") - val hasAttachments: Boolean -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_notified") - var isNotified: Boolean = true -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt deleted file mode 100644 index d1886e910..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "MessageAttachments") -data class MessageAttachment( - - @PrimaryKey - @ColumnInfo(name = "real_id") - val realId: Int, - - @ColumnInfo(name = "message_id") - val messageId: Int, - - @ColumnInfo(name = "one_drive_id") - val oneDriveId: String, - - @ColumnInfo(name = "url") - val url: String, - - @ColumnInfo(name = "filename") - val filename: String -) : Serializable diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt deleted file mode 100644 index 2e7af0f40..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.Embedded -import androidx.room.Relation - -data class MessageWithAttachment( - @Embedded - val message: Message, - - @Relation(parentColumn = "message_id", entityColumn = "message_id") - val attachments: List -) 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 deleted file mode 100644 index f67ed599f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDateTime -import java.io.Serializable - -@Entity(tableName = "MobileDevices") -data class MobileDevice( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "device_id") - val deviceId: Int, - - val name: String, - - val date: LocalDateTime -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt deleted file mode 100644 index 6f707a66a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt +++ /dev/null @@ -1,43 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import java.io.Serializable - -@Entity(tableName = "Notes") -data class Note( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - val date: LocalDate, - - val teacher: String, - - @ColumnInfo(name = "teacher_symbol") - val teacherSymbol: String, - - val category: String, - - @ColumnInfo(name = "category_type") - val categoryType: Int, - - @ColumnInfo(name = "is_points_show") - val isPointsShow: Boolean, - - val points: Int, - - val content: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - @ColumnInfo(name = "is_read") - var isRead: Boolean = true - - @ColumnInfo(name = "is_notified") - var isNotified: Boolean = true -} 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 deleted file mode 100644 index 3021da72d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "Recipients") -data class Recipient( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "real_id") - val realId: String, - - val name: String, - - @ColumnInfo(name = "real_name") - val realName: String, - - @ColumnInfo(name = "login_id") - val loginId: Int, - - @ColumnInfo(name = "unit_id") - val unitId: Int, - - val role: Int, - - val hash: String - -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - override fun toString() = name -} 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 deleted file mode 100644 index 601d8aac7..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "ReportingUnits") -data class ReportingUnit( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "real_id") - val realId: Int, - - @ColumnInfo(name = "short") - val shortName: String, - - @ColumnInfo(name = "sender_id") - val senderId: Int, - - @ColumnInfo(name = "sender_name") - val senderName: String, - - val roles: List - -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt deleted file mode 100644 index 20fae4508..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/School.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "School") -data class School( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "class_id") - val classId: Int, - - val name: String, - - val address: String, - - val contact: String, - - val headmaster: String, - - val pedagogue: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt deleted file mode 100644 index 0641e0b6d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.Index -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate - -@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)]) -data class Semester( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - @ColumnInfo(name = "diary_name") - val diaryName: String, - - @ColumnInfo(name = "school_year") - val schoolYear: Int, - - @ColumnInfo(name = "semester_id") - val semesterId: Int, - - @ColumnInfo(name = "semester_name") - val semesterName: Int, - - val start: LocalDate, - - val end: LocalDate, - - @ColumnInfo(name = "class_id") - val classId: Int, - - @ColumnInfo(name = "unit_id") - val unitId: Int -) { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - - @ColumnInfo(name = "is_current") - var current: Boolean = false -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt deleted file mode 100644 index 905979f99..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.Index -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDateTime -import java.io.Serializable - -@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)]) -data class Student( - - @ColumnInfo(name = "scrapper_base_url") - val scrapperBaseUrl: String, - - @ColumnInfo(name = "mobile_base_url") - val mobileBaseUrl: String, - - @ColumnInfo(name = "login_type") - val loginType: String, - - @ColumnInfo(name = "login_mode") - val loginMode: String, - - @ColumnInfo(name = "certificate_key") - val certificateKey: String, - - @ColumnInfo(name = "private_key") - val privateKey: String, - - @ColumnInfo(name = "is_parent") - val isParent: Boolean, - - val email: String, - - var password: String, - - val symbol: String, - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "user_login_id") - val userLoginId: Int, - - @ColumnInfo(name = "student_name") - val studentName: String, - - @ColumnInfo(name = "school_id") - val schoolSymbol: String, - - @ColumnInfo(name ="school_short") - val schoolShortName: String, - - @ColumnInfo(name = "school_name") - val schoolName: String, - - @ColumnInfo(name = "class_name") - val className: String, - - @ColumnInfo(name = "class_id") - val classId: Int, - - @ColumnInfo(name = "is_current") - val isCurrent: Boolean, - - @ColumnInfo(name = "registration_date") - val registrationDate: LocalDateTime -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Subject.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Subject.kt deleted file mode 100644 index dbaa6f4ed..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Subject.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "Subjects") -data class Subject( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - @ColumnInfo(name = "real_id") - val realId: Int, - - val name: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Teacher.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Teacher.kt deleted file mode 100644 index 52c96f8a3..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Teacher.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import java.io.Serializable - -@Entity(tableName = "Teachers") -data class Teacher( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "class_id") - val classId: Int, - - val subject: String, - - val name: String, - - @ColumnInfo(name = "short_name") - val shortName: String -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt deleted file mode 100644 index cad3b7c69..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.data.db.entities - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime -import java.io.Serializable - -@Entity(tableName = "Timetable") -data class Timetable( - - @ColumnInfo(name = "student_id") - val studentId: Int, - - @ColumnInfo(name = "diary_id") - val diaryId: Int, - - val number: Int, - - val start: LocalDateTime, - - val end: LocalDateTime, - - val date: LocalDate, - - val subject: String, - - val subjectOld: String, - - val group: String, - - val room: String, - - val roomOld: String, - - val teacher: String, - - val teacherOld: String, - - val info: String, - - @ColumnInfo(name = "student_plan") - val isStudentPlan: Boolean, - - val changes: Boolean, - - val canceled: Boolean -) : Serializable { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt deleted file mode 100644 index c26a02d1f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration10 : Migration(9, 10) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt deleted file mode 100644 index 6d129bca0..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration11 : Migration(10, 11) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Grades_temp ( - id INTEGER PRIMARY KEY NOT NULL, - is_read INTEGER NOT NULL, - is_notified INTEGER NOT NULL, - semester_id INTEGER NOT NULL, - student_id INTEGER NOT NULL, - subject TEXT NOT NULL, - entry TEXT NOT NULL, - value INTEGER 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 - ) - """) - database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades") - database.execSQL("DROP TABLE Grades") - database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt deleted file mode 100644 index 1dc38e14c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt +++ /dev/null @@ -1,69 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration12 : Migration(11, 12) { - - override fun migrate(database: SupportSQLiteDatabase) { - createTempStudentsTable(database) - replaceStudentTable(database) - updateStudentsWithClassId(database, getStudentsIds(database)) - removeStudentsWithNoClassId(database) - ensureThereIsOnlyOneCurrentStudent(database) - } - - private fun createTempStudentsTable(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Students_tmp ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - endpoint TEXT NOT NULL, - loginType TEXT NOT NULL, - email TEXT NOT NULL, - password TEXT NOT NULL, - symbol TEXT NOT NULL, - student_id INTEGER NOT NULL, - student_name TEXT NOT NULL, - school_id TEXT NOT NULL, - school_name TEXT NOT NULL, - is_current INTEGER NOT NULL, - registration_date INTEGER NOT NULL, - class_id INTEGER NOT NULL - ) - """) - database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)") - } - - private fun replaceStudentTable(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") - database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students") - database.execSQL("DROP TABLE Students") - database.execSQL("ALTER TABLE Students_tmp RENAME TO Students") - } - - private fun getStudentsIds(database: SupportSQLiteDatabase): List { - val students = mutableListOf() - val studentsCursor = database.query("SELECT student_id FROM Students") - if (studentsCursor.moveToFirst()) { - do { - students.add(studentsCursor.getInt(0)) - } while (studentsCursor.moveToNext()) - } - return students - } - - private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List) { - students.forEach { - database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it") - } - } - - private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) { - database.execSQL("DELETE FROM Students WHERE class_id = 0") - } - - private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) { - database.execSQL("UPDATE Students SET is_current = 0") - database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt deleted file mode 100644 index 0cf8cd9b0..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration13 : Migration(12, 13) { - - override fun migrate(database: SupportSQLiteDatabase) { - addClassNameToStudents(database, getStudentsIds(database)) - updateSemestersTable(database) - markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database)) - clearMessagesTable(database) - } - - private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List>) { - database.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL") - - students.forEach { (id, name) -> - val schoolName = name.substringAfter(" - ") - val className = name.substringBefore(" - ", "").replace("Klasa ", "") - database.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'") - database.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'") - } - } - - private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList> { - val students = mutableListOf>() - val studentsCursor = database.query("SELECT id, school_name FROM Students") - if (studentsCursor.moveToFirst()) { - do { - students.add(studentsCursor.getInt(0) to studentsCursor.getString(1)) - } while (studentsCursor.moveToNext()) - } - return students - } - - private fun updateSemestersTable(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL") - database.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL") - database.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL") - } - - private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List> { - val students = mutableListOf>() - val studentsCursor = database.query("SELECT student_id, class_id FROM Students") - if (studentsCursor.moveToFirst()) { - do { - students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1)) - } while (studentsCursor.moveToNext()) - } - return students - } - - private fun markAtLeastAndOnlyOneSemesterAtCurrent(database: SupportSQLiteDatabase, students: List>) { - students.forEach { (studentId, classId) -> - database.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'") - database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)") - } - } - - private fun clearMessagesTable(database: SupportSQLiteDatabase) { - database.execSQL("DELETE FROM Messages") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt deleted file mode 100644 index 4dac0d306..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration14 : Migration(13, 14) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE IF EXISTS GradesSummary") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS GradesSummary ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - semester_id INTEGER NOT NULL, - 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 - ) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt deleted file mode 100644 index 5be49a95b..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration15 : Migration(14, 15) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS MobileDevices ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - student_id INTEGER NOT NULL, - device_id INTEGER NOT NULL, - name TEXT NOT NULL, - date INTEGER NOT NULL - ) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt deleted file mode 100644 index 7f40c0f8d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration16 : Migration(15, 16) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Teachers ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - student_id INTEGER NOT NULL, - class_id INTEGER NOT NULL, - subject TEXT NOT NULL, - name TEXT NOT NULL, - short_name TEXT NOT NULL - ) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt deleted file mode 100644 index e2a2574db..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration17 : Migration(16, 17) { - - override fun migrate(database: SupportSQLiteDatabase) { - createGradesPointsStatisticsTable(database) - truncateSemestersTable(database) - } - - private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS GradesPointsStatistics( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - student_id INTEGER NOT NULL, - semester_id INTEGER NOT NULL, - subject TEXT NOT NULL, - others REAL NOT NULL, - student REAL NOT NULL - ) - """) - } - - private fun truncateSemestersTable(database: SupportSQLiteDatabase) { - database.execSQL("DELETE FROM Semesters") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt deleted file mode 100644 index 6c5e56c6a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration18 : Migration(17, 18) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS School ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - student_id INTEGER NOT NULL, - class_id INTEGER NOT NULL, - name TEXT NOT NULL, - address TEXT NOT NULL, - contact TEXT NOT NULL, - headmaster TEXT NOT NULL, - pedagogue TEXT NOT NULL - ) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt deleted file mode 100644 index d38f1245a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt +++ /dev/null @@ -1,119 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase -import io.github.wulkanowy.data.db.SharedPrefProvider - -class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migration(18, 19) { - - override fun migrate(database: SupportSQLiteDatabase) { - migrateMessages(database) - migrateGrades(database) - migrateStudents(database) - migrateSharedPreferences() - } - - private fun migrateMessages(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE Messages") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Messages ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - is_notified INTEGER NOT NULL, - 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, - content TEXT NOT NULL, - date INTEGER NOT NULL, - folder_id INTEGER NOT NULL, - unread INTEGER NOT NULL, - unread_by INTEGER NOT NULL, - read_by INTEGER NOT NULL, - removed INTEGER NOT NULL - ) - """) - } - - private fun migrateGrades(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE Grades") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Grades ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - is_read INTEGER NOT NULL, - 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 - ) - """) - } - - private fun migrateStudents(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Students_tmp ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - scrapper_base_url TEXT NOT NULL, - mobile_base_url TEXT NOT NULL, - is_parent INTEGER NOT NULL, - login_type TEXT NOT NULL, - login_mode TEXT NOT NULL, - certificate_key TEXT NOT NULL, - private_key TEXT 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, - student_name TEXT NOT NULL, - school_id 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 - ) - """) - - database.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";") - database.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";") - database.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;") - database.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";") - database.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";") - database.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";") - database.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;") - - database.execSQL(""" - INSERT INTO Students_tmp( - id, scrapper_base_url, mobile_base_url, is_parent, login_type, login_mode, certificate_key, private_key, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date) - SELECT - id, endpoint, apiBaseUrl, is_parent, loginType, "SCRAPPER", certificateKey, privateKey, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date - FROM Students - """) - database.execSQL("DROP TABLE Students") - database.execSQL("ALTER TABLE Students_tmp RENAME TO Students") - database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)") - } - - private fun migrateSharedPreferences() { - if (sharedPrefProvider.getString("grade_modifier_plus", "0.0") == "0.0") { - sharedPrefProvider.putString("grade_modifier_plus", "0.33") - } - if (sharedPrefProvider.getString("grade_modifier_minus", "0.0") == "0.0") { - sharedPrefProvider.putString("grade_modifier_minus", "0.33") - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt deleted file mode 100644 index c5a30991a..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration2 : Migration(1, 2) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS LuckyNumbers ( - id INTEGER PRIMARY KEY NOT NULL, - is_notified INTEGER NOT NULL, - student_id INTEGER NOT NULL, - date INTEGER NOT NULL, - lucky_number INTEGER NOT NULL) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt deleted file mode 100644 index 2fcfc183d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration20 : Migration(19, 20) { - - override fun migrate(database: SupportSQLiteDatabase) { - migrateTimetable(database) - truncateSubjects(database) - } - - private fun migrateTimetable(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE Timetable") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS `Timetable` ( - `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - `student_id` INTEGER NOT NULL, - `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 - ) - """) - } - - private fun truncateSubjects(database: SupportSQLiteDatabase) { - database.execSQL("DELETE FROM Subjects") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt deleted file mode 100644 index bc0ff900c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration21 : Migration(20, 21) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL") - - database.execSQL("DELETE FROM Semesters") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt deleted file mode 100644 index cf50a6c3e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration22 : Migration(21, 22) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt deleted file mode 100644 index 22de94c3f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration23 : Migration(22, 23) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''") - database.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt deleted file mode 100644 index 604ed4875..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration24 : Migration(23, 24) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS MessageAttachments ( - 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) - ) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt deleted file mode 100644 index 4749bac73..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration25 : Migration(24, 25) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt deleted file mode 100644 index 7130d86d8..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration26 : Migration(25, 26) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1") - database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1") - database.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0") - database.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt deleted file mode 100644 index d9699c0f4..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration3 : Migration(2, 3) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS CompletedLesson ( - id INTEGER PRIMARY KEY 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) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt deleted file mode 100644 index 0ae89bdd6..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration4 : Migration(3, 4) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE IF EXISTS Messages") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Messages ( - id INTEGER PRIMARY KEY NOT NULL, - is_notified INTEGER NOT NULL, - content TEXT, - 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_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, - unreadBy INTEGER NOT NULL, - readBy INTEGER NOT NULL, - removed INTEGER NOT NULL) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt deleted file mode 100644 index fe0dec48f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase -import org.threeten.bp.LocalDateTime.now -import org.threeten.bp.ZoneOffset - -class Migration5 : Migration(4, 5) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL") - database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'") - database.execSQL("DROP TABLE IF EXISTS Notes") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Notes ( - id INTEGER PRIMARY KEY 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, - category TEXT NOT NULL, - content TEXT NOT NULL) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt deleted file mode 100644 index fa9436187..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration6 : Migration(5, 6) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS ReportingUnits ( - id INTEGER PRIMARY KEY 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) - """) - - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Recipients ( - id INTEGER PRIMARY KEY 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) - """) - - database.execSQL("DELETE FROM Semesters WHERE 1") - database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL") - database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt deleted file mode 100644 index 120716c81..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration7 : Migration(6, 7) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL(""" - CREATE TABLE IF NOT EXISTS GradesStatistics ( - id INTEGER PRIMARY KEY NOT NULL, - student_id INTEGER NOT NULL, - semester_id INTEGER NOT NULL, - subject TEXT NOT NULL, - grade INTEGER NOT NULL, - amount INTEGER NOT NULL, - is_semester INTEGER NOT NULL) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt deleted file mode 100644 index 7009ee129..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration8 : Migration(7, 8) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL") - database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL") - database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt deleted file mode 100644 index d79a57062..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase - -class Migration9 : Migration(8, 9) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE IF EXISTS Messages") - database.execSQL(""" - CREATE TABLE IF NOT EXISTS Messages ( - id INTEGER PRIMARY KEY NOT NULL, - student_id INTEGER NOT NULL, - 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, - unread_by INTEGER NOT NULL, - read_by INTEGER NOT NULL, - removed INTEGER NOT NULL, - is_notified INTEGER NOT NULL, - content TEXT) - """) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/resources/AppResources.java b/app/src/main/java/io/github/wulkanowy/data/db/resources/AppResources.java new file mode 100644 index 000000000..8e7227d36 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/resources/AppResources.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.data.db.resources; + +import android.content.Context; +import android.content.res.Resources; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.R; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.api.login.VulcanOfflineException; +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.utils.AppConstant; +import io.github.wulkanowy.utils.LogUtils; +import io.github.wulkanowy.utils.security.CryptoException; + +@Singleton +public class AppResources implements ResourcesContract { + + private Resources resources; + + @Inject + AppResources(@ApplicationContext Context context) { + resources = context.getResources(); + } + + @Override + public String[] getSymbolsKeysArray() { + return resources.getStringArray(R.array.symbols); + } + + @Override + public String[] getSymbolsValuesArray() { + return resources.getStringArray(R.array.symbols_values); + } + + @Override + public String getErrorLoginMessage(Exception exception) { + LogUtils.error(AppConstant.APP_NAME + " encountered a error", exception); + + if (exception instanceof CryptoException) { + return resources.getString(R.string.encrypt_failed_text); + } else if (exception instanceof UnknownHostException) { + return resources.getString(R.string.noInternet_text); + } else if (exception instanceof SocketTimeoutException) { + return resources.getString(R.string.generic_timeout_error); + } else if (exception instanceof NotLoggedInErrorException || exception instanceof IOException) { + return resources.getString(R.string.login_denied_text); + } else if (exception instanceof VulcanOfflineException) { + return resources.getString(R.string.error_host_offline); + } else { + return exception.getMessage(); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/resources/ResourcesContract.java b/app/src/main/java/io/github/wulkanowy/data/db/resources/ResourcesContract.java new file mode 100644 index 000000000..3768ad2c6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/resources/ResourcesContract.java @@ -0,0 +1,10 @@ +package io.github.wulkanowy.data.db.resources; + +public interface ResourcesContract { + + String[] getSymbolsKeysArray(); + + String[] getSymbolsValuesArray(); + + String getErrorLoginMessage(Exception e); +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPref.java b/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPref.java new file mode 100644 index 000000000..ba437f882 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPref.java @@ -0,0 +1,33 @@ +package io.github.wulkanowy.data.db.shared; + +import android.content.Context; +import android.content.SharedPreferences; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.di.annotations.SharedPreferencesInfo; + +@Singleton +public class SharedPref implements SharedPrefContract { + + private static final String SHARED_KEY_USER_ID = "USER_ID"; + + private final SharedPreferences sharedPreferences; + + @Inject + SharedPref(@ApplicationContext Context context, @SharedPreferencesInfo String sharedName) { + sharedPreferences = context.getSharedPreferences(sharedName, Context.MODE_PRIVATE); + } + + @Override + public long getCurrentUserId() { + return sharedPreferences.getLong(SHARED_KEY_USER_ID, 0); + } + + @Override + public void setCurrentUserId(long userId) { + sharedPreferences.edit().putLong(SHARED_KEY_USER_ID, userId).apply(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPrefContract.java b/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPrefContract.java new file mode 100644 index 000000000..7f540acfd --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/shared/SharedPrefContract.java @@ -0,0 +1,8 @@ +package io.github.wulkanowy.data.db.shared; + +public interface SharedPrefContract { + + long getCurrentUserId(); + + void setCurrentUserId(long userId); +} diff --git a/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt b/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt deleted file mode 100644 index 58a2396e2..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/exceptions/NoCurrentStudent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.wulkanowy.data.exceptions - -class NoCurrentStudentException : Exception("There no set current student in database") diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt deleted file mode 100644 index e792bde46..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/Contributor.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.wulkanowy.data.pojos - -class Contributor(val displayName: String, val githubUsername: String) diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt deleted file mode 100644 index 34b62abdb..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.data.pojos - -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.ui.modules.grade.statistics.ViewType - -data class GradeStatisticsItem( - - val type: ViewType, - - val partial: List, - - val points: GradePointsStatistics? -) diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/MobileDeviceToken.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/MobileDeviceToken.kt deleted file mode 100644 index 401018211..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/MobileDeviceToken.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.data.pojos - -data class MobileDeviceToken( - - val token: String, - - val symbol: String, - - val pin: String, - - val qr: String -) 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/appcreator/AppCreatorRepository.kt deleted file mode 100644 index 76cf698c9..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/appcreator/AppCreatorRepository.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.data.repositories.appcreator - -import android.content.res.AssetManager -import com.google.gson.Gson -import io.github.wulkanowy.data.pojos.Contributor -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AppCreatorRepository @Inject constructor(private val assets: AssetManager) { - fun getAppCreators(): Single> { - return Single.fromCallable { - Gson().fromJson( - assets.open("contributors.json").bufferedReader().use { it.readText() }, - Array::class.java - ).toList() - } - } -} 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 0f5873766..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import io.github.wulkanowy.data.db.dao.AttendanceDao -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) { - - fun saveAttendance(attendance: List) { - attendanceDb.insertAll(attendance) - } - - fun deleteAttendance(attendance: List) { - attendanceDb.deleteAll(attendance) - } - - fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe> { - return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate).filter { it.isNotEmpty() } - } -} 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 f64d920db..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRemote.kt +++ /dev/null @@ -1,53 +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 io.reactivex.Single -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime -import org.threeten.bp.LocalTime -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceRemote @Inject constructor(private val sdk: Sdk) { - - fun getAttendance(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getAttendance(startDate, endDate, semester.semesterId) - .map { attendance -> - attendance.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 excuseAbsence(student: Student, semester: Semester, absenceList: List, reason: String?): Single { - 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 68e7c5f12..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/AttendanceRepository.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: AttendanceLocal, - private val remote: AttendanceRemote -) { - - fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean): Single> { - return local.getAttendance(semester, start.monday, end.sunday).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getAttendance(student, semester, start.monday, end.sunday) - else Single.error(UnknownHostException()) - }.flatMap { newAttendance -> - local.getAttendance(semester, start.monday, end.sunday) - .toSingle(emptyList()) - .doOnSuccess { oldAttendance -> - local.deleteAttendance(oldAttendance.uniqueSubtract(newAttendance)) - local.saveAttendance(newAttendance.uniqueSubtract(oldAttendance)) - } - }.flatMap { - local.getAttendance(semester, start.monday, end.sunday) - .toSingle(emptyList()) - }).map { list -> list.filter { it.date in start..end } } - } - - fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List, reason: String? = null): Single { - return remote.excuseAbsence(student, semester, attendanceList, reason) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt deleted file mode 100644 index 50d6b8ed5..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendance - -enum class SentExcuseStatus(val id: Int = 0) { - WAITING, - ACCEPTED, - DENIED -} 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 2e9a10067..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendancesummary - -import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: AttendanceSummaryDao) { - - fun saveAttendanceSummary(attendance: List) { - attendanceDb.insertAll(attendance) - } - - fun deleteAttendanceSummary(attendance: List) { - attendanceDb.deleteAll(attendance) - } - - fun getAttendanceSummary(semester: Semester, subjectId: Int): Maybe> { - return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId).filter { it.isNotEmpty() } - } -} 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 8fef5c391..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRemote.kt +++ /dev/null @@ -1,36 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryRemote @Inject constructor(private val sdk: Sdk) { - - fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getAttendanceSummary(subjectId) - .map { attendance -> - attendance.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 5f0b2b346..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendancesummary/AttendanceSummaryRepository.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.data.repositories.attendancesummary - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AttendanceSummaryRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: AttendanceSummaryLocal, - private val remote: AttendanceSummaryRemote -) { - - fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean = false): Single> { - return local.getAttendanceSummary(semester, subjectId).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getAttendanceSummary(student, semester, subjectId) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteAttendanceSummary(old.uniqueSubtract(new)) - local.saveAttendanceSummary(new.uniqueSubtract(old)) - } - }.flatMap { local.getAttendanceSummary(semester, subjectId).toSingle(emptyList()) }) - } -} 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 9b275908e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import io.github.wulkanowy.data.db.dao.CompletedLessonsDao -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb: CompletedLessonsDao) { - - fun saveCompletedLessons(completedLessons: List) { - completedLessonsDb.insertAll(completedLessons) - } - - fun deleteCompleteLessons(completedLessons: List) { - completedLessonsDb.deleteAll(completedLessons) - } - - fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Maybe> { - return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end).filter { it.isNotEmpty() } - } -} 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 bb115111e..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRemote.kt +++ /dev/null @@ -1,38 +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 io.reactivex.Single -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsRemote @Inject constructor(private val sdk: Sdk) { - - fun getCompletedLessons(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getCompletedLessons(startDate, endDate) - .map { lessons -> - lessons.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 72cc93eb4..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/completedlessons/CompletedLessonsRepository.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.data.repositories.completedlessons - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompletedLessonsRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: CompletedLessonsLocal, - private val remote: CompletedLessonsRemote -) { - - fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single> { - return local.getCompletedLessons(semester, start.monday, end.sunday).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getCompletedLessons(student, semester, start.monday, end.sunday) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getCompletedLessons(semester, start.monday, end.sunday) - .toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteCompleteLessons(old.uniqueSubtract(new)) - local.saveCompletedLessons(new.uniqueSubtract(old)) - } - }.flatMap { - local.getCompletedLessons(semester, start.monday, end.sunday) - .toSingle(emptyList()) - }).map { list -> list.filter { it.date in start..end } } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt deleted file mode 100644 index 389eb5835..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamLocal.kt +++ /dev/null @@ -1,26 +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 io.reactivex.Maybe -import org.threeten.bp.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): Maybe> { - return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate) - .filter { it.isNotEmpty() } - } - - fun saveExams(exams: List) { - examDb.insertAll(exams) - } - - 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 fb105ceee..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRemote.kt +++ /dev/null @@ -1,36 +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 io.reactivex.Single -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExamRemote @Inject constructor(private val sdk: Sdk) { - - fun getExams(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getExams(startDate, endDate, semester.semesterId) - .map { exams -> - exams.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 f29e4fdf8..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/exam/ExamRepository.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.data.repositories.exam - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExamRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: ExamLocal, - private val remote: ExamRemote -) { - - fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single> { - return local.getExams(semester, start.monday, end.sunday).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getExams(student, semester, start.monday, end.sunday) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getExams(semester, start.monday, end.sunday) - .toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteExams(old.uniqueSubtract(new)) - local.saveExams(new.uniqueSubtract(old)) - } - }.flatMap { - local.getExams(semester, start.monday, end.sunday) - .toSingle(emptyList()) - }).map { list -> list.filter { it.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 52ab60178..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeLocal.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import io.github.wulkanowy.data.db.dao.GradeDao -import io.github.wulkanowy.data.db.dao.GradeSummaryDao -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeLocal @Inject constructor( - private val gradeDb: GradeDao, - private val gradeSummaryDb: GradeSummaryDao -) { - - fun saveGrades(grades: List) { - gradeDb.insertAll(grades) - } - - fun deleteGrades(grades: List) { - gradeDb.deleteAll(grades) - } - - fun updateGrades(grades: List) { - gradeDb.updateAll(grades) - } - - fun updateGradesSummary(gradesSummary: List) { - gradeSummaryDb.updateAll(gradesSummary) - } - - fun getGradesDetails(semester: Semester): Maybe> { - return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() } - } - - fun saveGradesSummary(gradesSummary: List) { - gradeSummaryDb.insertAll(gradesSummary) - } - - fun deleteGradesSummary(gradesSummary: List) { - gradeSummaryDb.deleteAll(gradesSummary) - } - - fun getGradesSummary(semester: Semester): Maybe> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() } - } -} 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 abb2f98c9..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRemote.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeRemote @Inject constructor(private val sdk: Sdk) { - - fun getGrades(student: Student, semester: Semester): Single, List>> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getGrades(semester.semesterId) - .map { (details, summary) -> - 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/grade/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt deleted file mode 100644 index 2ba68b967..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/grade/GradeRepository.kt +++ /dev/null @@ -1,110 +0,0 @@ -package io.github.wulkanowy.data.repositories.grade - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.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.utils.uniqueSubtract -import io.reactivex.Completable -import io.reactivex.Single -import org.threeten.bp.LocalDateTime -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: GradeLocal, - private val remote: GradeRemote -) { - - fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Single, List>> { - return local.getGradesDetails(semester).flatMap { details -> - local.getGradesSummary(semester).map { summary -> details to summary } - }.filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getGrades(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { (newDetails, newSummary) -> - local.getGradesDetails(semester).toSingle(emptyList()) - .doOnSuccess { old -> - val notifyBreakDate = old.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate() - local.deleteGrades(old.uniqueSubtract(newDetails)) - local.saveGrades(newDetails.uniqueSubtract(old) - .onEach { - if (it.date >= notifyBreakDate) it.apply { - isRead = false - if (notify) isNotified = false - } - }) - }.flatMap { - local.getGradesSummary(semester).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteGradesSummary(old.uniqueSubtract(newSummary)) - local.saveGradesSummary(newSummary.uniqueSubtract(old) - .onEach { summary -> - val oldSummary = old.find { oldSummary -> oldSummary.subject == summary.subject } - summary.isPredictedGradeNotified = when { - summary.predictedGrade.isEmpty() -> true - notify && oldSummary?.predictedGrade != summary.predictedGrade -> false - else -> true - } - summary.isFinalGradeNotified = when { - summary.finalGrade.isEmpty() -> true - notify && oldSummary?.finalGrade != summary.finalGrade -> false - else -> true - } - - summary.predictedGradeLastChange = when { - oldSummary == null -> LocalDateTime.now() - summary.predictedGrade != oldSummary.predictedGrade -> LocalDateTime.now() - else -> oldSummary.predictedGradeLastChange - } - summary.finalGradeLastChange = when { - oldSummary == null -> LocalDateTime.now() - summary.finalGrade != oldSummary.finalGrade -> LocalDateTime.now() - else -> oldSummary.finalGradeLastChange - } - }) - } - } - }.flatMap { - local.getGradesDetails(semester).toSingle(emptyList()).flatMap { details -> - local.getGradesSummary(semester).toSingle(emptyList()).map { summary -> - details to summary - } - } - }) - } - - fun getUnreadGrades(semester: Semester): Single> { - return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isRead } }.toSingle(emptyList()) - } - - fun getNotNotifiedGrades(semester: Semester): Single> { - return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList()) - } - - fun getNotNotifiedPredictedGrades(semester: Semester): Single> { - return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }.toSingle(emptyList()) - } - - fun getNotNotifiedFinalGrades(semester: Semester): Single> { - return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }.toSingle(emptyList()) - } - - fun updateGrade(grade: Grade): Completable { - return Completable.fromCallable { local.updateGrades(listOf(grade)) } - } - - fun updateGrades(grades: List): Completable { - return Completable.fromCallable { local.updateGrades(grades) } - } - - fun updateGradesSummary(gradesSummary: List): Completable { - return Completable.fromCallable { local.updateGradesSummary(gradesSummary) } - } -} 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 7994bd758..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeStatisticsDao -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeStatisticsLocal @Inject constructor( - private val gradeStatisticsDb: GradeStatisticsDao, - private val gradePointsStatisticsDb: GradePointsStatisticsDao -) { - - fun getGradesStatistics(semester: Semester, isSemester: Boolean): Maybe> { - return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).filter { it.isNotEmpty() } - } - - fun getGradesPointsStatistics(semester: Semester): Maybe> { - return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() } - } - - fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): Maybe> { - return when (subjectName) { - "Wszystkie" -> gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester).map { list -> - list.groupBy { it.grade }.map { - GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, - it.value.fold(0) { acc, e -> acc + e.amount }, false) - } + list - } - else -> gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester) - }.filter { it.isNotEmpty() } - } - - fun getGradesPointsStatistics(semester: Semester, subjectName: String): Maybe> { - return when (subjectName) { - "Wszystkie" -> gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) - else -> gradePointsStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName) - }.filter { it.isNotEmpty() } - } - - fun saveGradesStatistics(gradesStatistics: List) { - gradeStatisticsDb.insertAll(gradesStatistics) - } - - fun saveGradesPointsStatistics(gradePointsStatistics: List) { - gradePointsStatisticsDb.insertAll(gradePointsStatistics) - } - - fun deleteGradesStatistics(gradesStatistics: List) { - gradeStatisticsDb.deleteAll(gradesStatistics) - } - - fun deleteGradesPointsStatistics(gradesPointsStatistics: List) { - gradePointsStatisticsDb.deleteAll(gradesPointsStatistics) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt deleted file mode 100644 index 99e0cb987..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.init -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) { - - fun getGradeStatistics(student: Student, semester: Semester, isSemester: Boolean): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).let { - if (isSemester) it.getGradesAnnualStatistics(semester.semesterId) - else it.getGradesPartialStatistics(semester.semesterId) - }.map { gradeStatistics -> - gradeStatistics.map { - GradeStatistics( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - grade = it.gradeValue, - amount = it.amount, - semester = isSemester - ) - } - } - } - - fun getGradePointsStatistics(student: Student, semester: Semester): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getGradesPointsStatistics(semester.semesterId) - .map { gradePointsStatistics -> - gradePointsStatistics.map { - GradePointsStatistics( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - others = it.others, - student = it.student - ) - } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt deleted file mode 100644 index 8d96d2f57..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt +++ /dev/null @@ -1,75 +0,0 @@ -package io.github.wulkanowy.data.repositories.gradestatistics - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.ui.modules.grade.statistics.ViewType -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GradeStatisticsRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: GradeStatisticsLocal, - private val remote: GradeStatisticsRemote -) { - - fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false): Single> { - return local.getGradesStatistics(semester, isSemester, subjectName).map { it.mapToStatisticItems() }.filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getGradeStatistics(student, semester, isSemester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getGradesStatistics(semester, isSemester).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteGradesStatistics(old.uniqueSubtract(new)) - local.saveGradesStatistics(new.uniqueSubtract(old)) - } - }.flatMap { local.getGradesStatistics(semester, isSemester, subjectName).map { it.mapToStatisticItems() }.toSingle(emptyList()) }) - } - - fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean): Single> { - return local.getGradesPointsStatistics(semester, subjectName).map { it.mapToStatisticsItem() }.filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getGradePointsStatistics(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getGradesPointsStatistics(semester).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteGradesPointsStatistics(old.uniqueSubtract(new)) - local.saveGradesPointsStatistics(new.uniqueSubtract(old)) - } - }.flatMap { local.getGradesPointsStatistics(semester, subjectName).map { it.mapToStatisticsItem() }.toSingle(emptyList()) }) - } - - private fun List.mapToStatisticItems(): List { - return groupBy { it.subject }.map { - GradeStatisticsItem( - type = ViewType.PARTIAL, - partial = it.value - .sortedByDescending { item -> item.grade } - .filter { item -> item.amount != 0 }, - points = null - ) - } - } - - private fun List.mapToStatisticsItem(): List { - return map { - GradeStatisticsItem( - type = ViewType.POINTS, - partial = emptyList(), - points = it - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt deleted file mode 100644 index fdae45182..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkLocal.kt +++ /dev/null @@ -1,30 +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 io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) { - - fun saveHomework(homework: List) { - homeworkDb.insertAll(homework) - } - - fun deleteHomework(homework: List) { - homeworkDb.deleteAll(homework) - } - - fun updateHomework(homework: List) { - homeworkDb.updateAll(homework) - } - - fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe> { - return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate) - .filter { it.isNotEmpty() } - } -} 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 20ffee99c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRemote.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.sdk.Sdk -import io.github.wulkanowy.utils.init -import io.reactivex.Single -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkRemote @Inject constructor(private val sdk: Sdk) { - - fun getHomework(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getHomework(startDate, endDate) - .map { homework -> - homework.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 7e8fd5c30..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/homework/HomeworkRepository.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.data.repositories.homework - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Completable -import io.reactivex.Single -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HomeworkRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: HomeworkLocal, - private val remote: HomeworkRemote -) { - - fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single> { - return Single.fromCallable { start.monday to end.sunday }.flatMap { (monday, friday) -> - local.getHomework(semester, monday, friday).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getHomework(student, semester, monday, friday) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getHomework(semester, monday, friday).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteHomework(old.uniqueSubtract(new)) - local.saveHomework(new.uniqueSubtract(old)) - } - }.flatMap { local.getHomework(semester, monday, friday).toSingle(emptyList()) }) - } - } - - fun toggleDone(homework: Homework): Completable { - return Completable.fromCallable { - local.updateHomework(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/logger/LoggerRepository.kt deleted file mode 100644 index be6ad2f48..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/logger/LoggerRepository.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.data.repositories.logger - -import android.content.Context -import io.reactivex.Single -import java.io.File -import java.io.FileNotFoundException -import javax.inject.Inject - -class LoggerRepository @Inject constructor(private val context: Context) { - - fun getLastLogLines(): Single> { - return getLastModified() - .map { it.readText() } - .map { it.split("\n") } - } - - fun getLogFiles(): Single> { - return Single.fromCallable { - File(context.filesDir.absolutePath).listFiles(File::isFile)?.filter { - it.name.endsWith(".log") - } - } - } - - private fun getLastModified(): Single { - return Single.fromCallable { - var lastModifiedTime = Long.MIN_VALUE - var chosenFile: File? = null - File(context.filesDir.absolutePath).listFiles(File::isFile)?.forEach { file -> - if (file.lastModified() > lastModifiedTime) { - lastModifiedTime = file.lastModified() - chosenFile = file - } - } - if (chosenFile == null) throw FileNotFoundException("Log file not found") - chosenFile - } - } -} 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 0f4f79c84..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberLocal.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import io.github.wulkanowy.data.db.dao.LuckyNumberDao -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumberDao) { - - fun saveLuckyNumber(luckyNumber: LuckyNumber) { - luckyNumberDb.insertAll(listOf(luckyNumber)) - } - - fun updateLuckyNumber(luckyNumber: LuckyNumber) { - luckyNumberDb.updateAll(listOf(luckyNumber)) - } - - fun deleteLuckyNumber(luckyNumber: LuckyNumber) { - luckyNumberDb.deleteAll(listOf(luckyNumber)) - } - - fun getLuckyNumber(student: Student, date: LocalDate): Maybe { - 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 0c71897a6..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRemote.kt +++ /dev/null @@ -1,24 +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 io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberRemote @Inject constructor(private val sdk: Sdk) { - - fun getLuckyNumber(student: Student): Maybe { - return sdk.init(student).getLuckyNumber(student.schoolShortName).map { - 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 374b9a294..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/luckynumber/LuckyNumberRepository.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.data.repositories.luckynumber - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Completable -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LuckyNumberRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: LuckyNumberLocal, - private val remote: LuckyNumberRemote -) { - - fun getLuckyNumber(student: Student, forceRefresh: Boolean = false, notify: Boolean = false): Maybe { - return local.getLuckyNumber(student, LocalDate.now()).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMapMaybe { - if (it) remote.getLuckyNumber(student) - else Maybe.error(UnknownHostException()) - }.flatMap { new -> - local.getLuckyNumber(student, LocalDate.now()) - .doOnSuccess { old -> - if (new != old) { - local.deleteLuckyNumber(old) - local.saveLuckyNumber(new.apply { - if (notify) isNotified = false - }) - } - } - .doOnComplete { - local.saveLuckyNumber(new.apply { - if (notify) isNotified = false - }) - } - }.flatMap({ local.getLuckyNumber(student, LocalDate.now()) }, { Maybe.error(it) }, - { local.getLuckyNumber(student, LocalDate.now()) }) - ) - } - - fun getNotNotifiedLuckyNumber(student: Student): Maybe { - return local.getLuckyNumber(student, LocalDate.now()).filter { !it.isNotified } - } - - fun updateLuckyNumber(luckyNumber: LuckyNumber): Completable { - return Completable.fromCallable { local.updateLuckyNumber(luckyNumber) } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt deleted file mode 100644 index 06f5a1e05..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageFolder.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.data.repositories.message - -enum class MessageFolder(val id: Int = 1) { - RECEIVED(1), - SENT(2), - TRASHED(3) -} 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 53cf0a983..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageLocal.kt +++ /dev/null @@ -1,47 +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 io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED -import io.reactivex.Maybe -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageLocal @Inject constructor( - private val messagesDb: MessagesDao, - private val messageAttachmentDao: MessageAttachmentDao -) { - - fun saveMessages(messages: List) { - messagesDb.insertAll(messages) - } - - fun updateMessages(messages: List) { - messagesDb.updateAll(messages) - } - - fun deleteMessages(messages: List) { - messagesDb.deleteAll(messages) - } - - fun getMessageWithAttachment(student: Student, message: Message): Single { - return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) - } - - fun saveMessageAttachments(attachments: List) { - messageAttachmentDao.insertAttachments(attachments) - } - - fun getMessages(student: Student, folder: MessageFolder): Maybe> { - return when (folder) { - TRASHED -> messagesDb.loadDeleted(student.id.toInt()) - else -> messagesDb.loadAll(student.id.toInt(), folder.id) - }.filter { it.isNotEmpty() } - } -} 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 2df2e20a3..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRemote.kt +++ /dev/null @@ -1,80 +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 io.reactivex.Single -import org.threeten.bp.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) { - - fun getMessages(student: Student, semester: Semester, folder: MessageFolder): Single> { - return sdk.init(student).getMessages(Folder.valueOf(folder.name), semester.start.atStartOfDay(), semester.end.atStartOfDay()).map { messages -> - messages.map { - Message( - studentId = student.id.toInt(), - realId = it.id ?: 0, - messageId = it.messageId ?: 0, - sender = it.sender.orEmpty(), - senderId = it.senderId ?: 0, - recipient = it.recipient.orEmpty(), - subject = it.subject.trim(), - date = it.date ?: now(), - content = it.content.orEmpty(), - folderId = it.folderId, - unread = it.unread ?: false, - unreadBy = it.unreadBy ?: 0, - readBy = it.readBy ?: 0, - removed = it.removed, - hasAttachments = it.hasAttachments - ) - } - } - } - - fun getMessagesContentDetails(student: Student, message: Message, markAsRead: Boolean = false): Single>> { - return sdk.init(student).getMessageDetails(message.messageId, message.folderId, markAsRead, message.realId).map { details -> - details.content to details.attachments.map { - MessageAttachment( - realId = it.id, - messageId = it.messageId, - oneDriveId = it.oneDriveId, - url = it.url, - filename = it.filename - ) - } - } - } - - fun sendMessage(student: Student, subject: String, content: String, recipients: List): Single { - 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 - ) - } - ) - } - - fun deleteMessage(student: Student, message: Message): Single { - return sdk.init(student).deleteMessages(listOf(message.messageId to 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 2d2c0430c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/message/MessageRepository.kt +++ /dev/null @@ -1,105 +0,0 @@ -package io.github.wulkanowy.data.repositories.message - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -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.uniqueSubtract -import io.reactivex.Completable -import io.reactivex.Single -import timber.log.Timber -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: MessageLocal, - private val remote: MessageRemote -) { - - fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): Single> { - return local.getMessages(student, folder).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getMessages(student, semester, folder) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getMessages(student, folder).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteMessages(old.uniqueSubtract(new)) - local.saveMessages(new.uniqueSubtract(old) - .onEach { - it.isNotified = !notify - }) - } - }.flatMap { local.getMessages(student, folder).toSingle(emptyList()) } - ) - } - - fun getMessage(student: Student, message: Message, markAsRead: Boolean = false): Single { - return local.getMessageWithAttachment(student, message) - .filter { - it.message.content.isNotEmpty().also { status -> - Timber.d("Message content in db empty: ${!status}") - } && !it.message.unread - } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) local.getMessageWithAttachment(student, message) - else Single.error(UnknownHostException()) - } - .flatMap { dbMessage -> - remote.getMessagesContentDetails(student, dbMessage.message, markAsRead).doOnSuccess { (downloadedMessage, attachments) -> - local.updateMessages(listOf(dbMessage.message.copy(unread = !markAsRead).apply { - id = dbMessage.message.id - content = content.ifBlank { downloadedMessage } - })) - local.saveMessageAttachments(attachments) - Timber.d("Message ${message.messageId} with blank content: ${dbMessage.message.content.isBlank()}, marked as read") - } - }.flatMap { - local.getMessageWithAttachment(student, message) - } - ) - } - - fun getNotNotifiedMessages(student: Student): Single> { - return local.getMessages(student, RECEIVED) - .map { it.filter { message -> !message.isNotified && message.unread } } - .toSingle(emptyList()) - } - - fun updateMessages(messages: List): Completable { - return Completable.fromCallable { local.updateMessages(messages) } - } - - fun sendMessage(student: Student, subject: String, content: String, recipients: List): Single { - return ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.sendMessage(student, subject, content, recipients) - else Single.error(UnknownHostException()) - } - } - - fun deleteMessage(student: Student, message: Message): Single { - return ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.deleteMessage(student, message) - else Single.error(UnknownHostException()) - } - .doOnSuccess { - if (!message.removed) local.updateMessages(listOf(message.copy(removed = true).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 473ffa7fe..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceLocal.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.repositories.mobiledevice - -import io.github.wulkanowy.data.db.dao.MobileDeviceDao -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDao) { - - fun saveDevices(devices: List) { - mobileDb.insertAll(devices) - } - - fun deleteDevices(devices: List) { - mobileDb.deleteAll(devices) - } - - fun getDevices(semester: Semester): Maybe> { - return mobileDb.loadAll(semester.studentId).filter { it.isNotEmpty() } - } -} 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 800f95971..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRemote.kt +++ /dev/null @@ -1,48 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceRemote @Inject constructor(private val sdk: Sdk) { - - fun getDevices(student: Student, semester: Semester): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getRegisteredDevices() - .map { devices -> - devices.map { - MobileDevice( - studentId = semester.studentId, - date = it.createDate, - deviceId = it.id, - name = it.name - ) - } - } - } - - fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Single { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .unregisterDevice(device.deviceId) - } - - fun getToken(student: Student, semester: Semester): Single { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getToken() - .map { - 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 545846e85..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/mobiledevice/MobileDeviceRepository.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.data.repositories.mobiledevice - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.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.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MobileDeviceRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: MobileDeviceLocal, - private val remote: MobileDeviceRemote -) { - - fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean = false): Single> { - return local.getDevices(semester).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getDevices(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getDevices(semester).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteDevices(old uniqueSubtract new) - local.saveDevices(new uniqueSubtract old) - } - } - ).flatMap { local.getDevices(semester).toSingle(emptyList()) } - } - - fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Single { - return ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.unregisterDevice(student, semester, device) - else Single.error(UnknownHostException()) - } - } - - fun getToken(student: Student, semester: Semester): Single { - return ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getToken(student, semester) - else Single.error(UnknownHostException()) - } - } -} 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 784e61f0f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteLocal.kt +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.wulkanowy.data.repositories.note - -import io.github.wulkanowy.data.db.dao.NoteDao -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteLocal @Inject constructor(private val noteDb: NoteDao) { - - fun saveNotes(notes: List) { - noteDb.insertAll(notes) - } - - fun updateNotes(notes: List) { - noteDb.updateAll(notes) - } - - fun deleteNotes(notes: List) { - noteDb.deleteAll(notes) - } - - fun getNotes(student: Student): Maybe> { - return noteDb.loadAll(student.studentId).filter { it.isNotEmpty() } - } -} 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 2c62b608d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRemote.kt +++ /dev/null @@ -1,34 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteRemote @Inject constructor(private val sdk: Sdk) { - - fun getNotes(student: Student, semester: Semester): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getNotes(semester.semesterId) - .map { notes -> - notes.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 e155e2bad..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/note/NoteRepository.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.data.repositories.note - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Completable -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NoteRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: NoteLocal, - private val remote: NoteRemote -) { - - fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Single> { - return local.getNotes(student).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getNotes(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getNotes(student).toSingle(emptyList()) - .doOnSuccess { old -> - 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 - } - }) - } - }.flatMap { local.getNotes(student).toSingle(emptyList()) }) - } - - fun getNotNotifiedNotes(student: Student): Single> { - return local.getNotes(student).map { it.filter { note -> !note.isNotified } }.toSingle(emptyList()) - } - - fun updateNote(note: Note): Completable { - return Completable.fromCallable { local.updateNotes(listOf(note)) } - } - - fun updateNotes(notes: List): Completable { - return Completable.fromCallable { local.updateNotes(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/preferences/PreferencesRepository.kt deleted file mode 100644 index 7715cde0d..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/preferences/PreferencesRepository.kt +++ /dev/null @@ -1,89 +0,0 @@ -package io.github.wulkanowy.data.repositories.preferences - -import android.content.Context -import android.content.SharedPreferences -import io.github.wulkanowy.R -import io.github.wulkanowy.ui.modules.grade.GradeAverageMode -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PreferencesRepository @Inject constructor( - private val sharedPref: SharedPreferences, - val context: Context -) { - val startMenuIndex: Int - get() = getString(R.string.pref_key_start_menu, R.string.pref_default_startup).toInt() - - val isShowPresent: Boolean - get() = getBoolean(R.string.pref_key_attendance_present, R.bool.pref_default_attendance_present) - - val gradeAverageMode: GradeAverageMode - get() = GradeAverageMode.getByValue(getString(R.string.pref_key_grade_average_mode, R.string.pref_default_grade_average_mode)) - - val gradeAverageForceCalc: Boolean - get() = getBoolean(R.string.pref_key_grade_average_force_calc, R.bool.pref_default_grade_average_force_calc) - - val isGradeExpandable: Boolean - get() = !getBoolean(R.string.pref_key_expand_grade, R.bool.pref_default_expand_grade) - - val showAllSubjectsOnStatisticsList: Boolean - get() = getBoolean(R.string.pref_key_grade_statistics_list, R.bool.pref_default_grade_statistics_list) - - val appThemeKey = context.getString(R.string.pref_key_app_theme) - val appTheme: String - get() = getString(appThemeKey, R.string.pref_default_app_theme) - - val gradeColorTheme: String - get() = getString(R.string.pref_key_grade_color_scheme, R.string.pref_default_grade_color_scheme) - - val appLanguageKey = context.getString(R.string.pref_key_app_language) - val appLanguage - get() = getString(appLanguageKey, R.string.pref_default_app_language) - - val serviceEnableKey = context.getString(R.string.pref_key_services_enable) - val isServiceEnabled: Boolean - get() = getBoolean(serviceEnableKey, R.bool.pref_default_services_enable) - - val servicesIntervalKey = context.getString(R.string.pref_key_services_interval) - val servicesInterval: Long - get() = getString(servicesIntervalKey, R.string.pref_default_services_interval).toLong() - - val servicesOnlyWifiKey = context.getString(R.string.pref_key_services_wifi_only) - val isServicesOnlyWifi: Boolean - get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only) - - val isNotificationsEnable: Boolean - get() = getBoolean(R.string.pref_key_notifications_enable, R.bool.pref_default_notifications_enable) - - val isUpcomingLessonsNotificationsEnableKey = context.getString(R.string.pref_key_notifications_upcoming_lessons_enable) - val isUpcomingLessonsNotificationsEnable: Boolean - get() = getBoolean(isUpcomingLessonsNotificationsEnableKey, R.bool.pref_default_notification_upcoming_lessons_enable) - - val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug) - val isDebugNotificationEnable: Boolean - get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug) - - val gradePlusModifier: Double - get() = getString(R.string.pref_key_grade_modifier_plus, R.string.pref_default_grade_modifier_plus).toDouble() - - val gradeMinusModifier: Double - get() = getString(R.string.pref_key_grade_modifier_minus, R.string.pref_default_grade_modifier_minus).toDouble() - - val fillMessageContent: Boolean - get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content) - - val showWholeClassPlan: String - get() = getString(R.string.pref_key_timetable_show_whole_class, R.string.pref_default_timetable_show_whole_class) - - val showTimetableTimers: Boolean - get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers) - - private fun getString(id: Int, default: Int) = getString(context.getString(id), default) - - private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default) - - private fun getBoolean(id: Int, default: Int) = getBoolean(context.getString(id), default) - - private fun getBoolean(id: String, default: Int) = sharedPref.getBoolean(id, context.resources.getBoolean(default)) -} 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 ff8175440..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientLocal.kt +++ /dev/null @@ -1,25 +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 io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecipientLocal @Inject constructor(private val recipientDb: RecipientDao) { - - fun getRecipients(student: Student, role: Int, unit: ReportingUnit): Maybe> { - return recipientDb.load(student.studentId, role, unit.realId).filter { it.isNotEmpty() } - } - - fun saveRecipients(recipients: List): List { - return recipientDb.insertAll(recipients) - } - - 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 e5b16a156..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRemote.kt +++ /dev/null @@ -1,43 +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 io.reactivex.Single -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) { - - fun getRecipients(student: Student, role: Int, unit: ReportingUnit): Single> { - return sdk.init(student).getRecipients(unit.realId, role) - .map { recipients -> - recipients.map { it.toRecipient() } - } - } - - fun getMessageRecipients(student: Student, message: Message): Single> { - return sdk.init(student).getMessageRecipients(message.messageId, message.senderId) - .map { recipients -> - recipients.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 6f8a72af2..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recipient/RecipientRepository.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.data.repositories.recipient - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.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 io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecipientRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: RecipientLocal, - private val remote: RecipientRemote -) { - - fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): Single> { - return local.getRecipients(student, role, unit).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getRecipients(student, role, unit) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getRecipients(student, role, unit).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteRecipients(old.uniqueSubtract(new)) - local.saveRecipients(new.uniqueSubtract(old)) - } - }.flatMap { - local.getRecipients(student, role, unit).toSingle(emptyList()) - } - ) - } - - fun getMessageRecipients(student: Student, message: Message): Single> { - return ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getMessageRecipients(student, message) - else Single.error(UnknownHostException()) - } - } -} 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/recover/RecoverRemote.kt deleted file mode 100644 index f27891250..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRemote.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.data.repositories.recover - -import io.github.wulkanowy.sdk.Sdk -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecoverRemote @Inject constructor(private val sdk: Sdk) { - - fun getReCaptchaSiteKey(host: String, symbol: String): Single> { - return sdk.getPasswordResetCaptchaCode(host, symbol) - } - - fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): Single { - return sdk.sendPasswordResetRequest(url, symbol, email, reCaptchaResponse) - } -} - 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 86d4ba1b3..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/recover/RecoverRepository.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.data.repositories.recover - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecoverRepository @Inject constructor(private val settings: InternetObservingSettings, private val remote: RecoverRemote) { - - fun getReCaptchaSiteKey(host: String, symbol: String): Single> { - return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getReCaptchaSiteKey(host, symbol) - else Single.error(UnknownHostException()) - } - } - - fun sendRecoverRequest(url: String, symbol: String, email: String, reCaptchaResponse: String): Single { - return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.sendRecoverRequest(url, symbol, email, reCaptchaResponse) - else Single.error(UnknownHostException()) - } - } -} 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 0631c668c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitLocal.kt +++ /dev/null @@ -1,28 +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 io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitLocal @Inject constructor(private val reportingUnitDb: ReportingUnitDao) { - - fun getReportingUnits(student: Student): Maybe> { - return reportingUnitDb.load(student.studentId).filter { it.isNotEmpty() } - } - - fun getReportingUnit(student: Student, unitId: Int): Maybe { - return reportingUnitDb.loadOne(student.studentId, unitId) - } - - fun saveReportingUnits(reportingUnits: List): List { - return reportingUnitDb.insertAll(reportingUnits) - } - - 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 1fd8b08e3..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRemote.kt +++ /dev/null @@ -1,28 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitRemote @Inject constructor(private val sdk: Sdk) { - - fun getReportingUnits(student: Student): Single> { - return sdk.init(student).getReportingUnits().map { - it.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 ee5440984..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/reportingunit/ReportingUnitRepository.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.data.repositories.reportingunit - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Maybe -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReportingUnitRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: ReportingUnitLocal, - private val remote: ReportingUnitRemote -) { - - fun getReportingUnits(student: Student, forceRefresh: Boolean = false): Single> { - return local.getReportingUnits(student).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getReportingUnits(student) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getReportingUnits(student).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteReportingUnits(old.uniqueSubtract(new)) - local.saveReportingUnits(new.uniqueSubtract(old)) - } - }.flatMap { local.getReportingUnits(student).toSingle(emptyList()) } - ) - } - - fun getReportingUnit(student: Student, unitId: Int): Maybe { - return local.getReportingUnit(student, unitId) - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) getReportingUnits(student, true) - else Single.error(UnknownHostException()) - }.flatMapMaybe { - 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 d87272875..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolLocal.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.data.repositories.school - -import io.github.wulkanowy.data.db.dao.SchoolDao -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.Semester -import io.reactivex.Maybe -import javax.inject.Inject - -class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) { - - fun saveSchool(school: School) { - schoolDb.insertAll(listOf(school)) - } - - fun deleteSchool(school: School) { - schoolDb.deleteAll(listOf(school)) - } - - fun getSchool(semester: Semester): Maybe { - 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 6a95a446b..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRemote.kt +++ /dev/null @@ -1,28 +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 io.reactivex.Single -import javax.inject.Inject - -class SchoolRemote @Inject constructor(private val sdk: Sdk) { - - fun getSchoolInfo(student: Student, semester: Semester): Single { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getSchool() - .map { - 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 1715a28d5..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/school/SchoolRepository.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.data.repositories.school - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Maybe -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SchoolRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: SchoolLocal, - private val remote: SchoolRemote -) { - - fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean = false): Maybe { - return local.getSchool(semester).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getSchoolInfo(student, semester) - else Single.error(UnknownHostException()) - }.flatMapMaybe { new -> - local.getSchool(semester) - .doOnSuccess { old -> - if (new != old) { - local.deleteSchool(old) - local.saveSchool(new) - } - } - .doOnComplete { - local.saveSchool(new) - } - }.flatMap({ local.getSchool(semester) }, { Maybe.error(it) }, - { local.getSchool(semester) }) - ) - } -} 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 3d98785cd..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterLocal.kt +++ /dev/null @@ -1,24 +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 io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SemesterLocal @Inject constructor(private val semesterDb: SemesterDao) { - - fun saveSemesters(semesters: List) { - semesterDb.insertAll(semesters) - } - - fun deleteSemesters(semesters: List) { - semesterDb.deleteAll(semesters) - } - - fun getSemesters(student: Student): Maybe> { - return semesterDb.loadAll(student.studentId, student.classId).filter { it.isNotEmpty() } - } -} 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 90f0e1d71..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRemote.kt +++ /dev/null @@ -1,32 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SemesterRemote @Inject constructor(private val sdk: Sdk) { - - fun getSemesters(student: Student): Single> { - return sdk.init(student).getSemesters().map { semesters -> - semesters.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/semester/SemesterRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt deleted file mode 100644 index 68946beef..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/semester/SemesterRepository.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.data.repositories.semester - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.getCurrentOrLast -import io.github.wulkanowy.utils.isCurrent -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SemesterRepository @Inject constructor( - private val remote: SemesterRemote, - private val local: SemesterLocal, - private val settings: InternetObservingSettings -) { - - fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false): Single> { - return local.getSemesters(student).filter { !forceRefresh }.filter { semesters -> - when { - Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> semesters.firstOrNull { it.isCurrent }?.diaryId != 0 - refreshOnNoCurrent -> semesters.any { semester -> semester.isCurrent } - else -> true - } - }.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getSemesters(student) - else Single.error(UnknownHostException()) - }.flatMap { new -> - if (new.isEmpty()) throw IllegalArgumentException("Empty semester list!") - - local.getSemesters(student).toSingle(emptyList()).doOnSuccess { old -> - local.deleteSemesters(old.uniqueSubtract(new)) - local.saveSemesters(new.uniqueSubtract(old)) - } - }.flatMap { local.getSemesters(student).toSingle(emptyList()) }) - } - - fun getCurrentSemester(student: Student, forceRefresh: Boolean = false): Single { - return getSemesters(student, forceRefresh).map { it.getCurrentOrLast() } - } -} 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 06b9bb4ac..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentLocal.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import android.content.Context -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.security.decrypt -import io.github.wulkanowy.utils.security.encrypt -import io.reactivex.Completable -import io.reactivex.Maybe -import io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StudentLocal @Inject constructor( - private val studentDb: StudentDao, - private val context: Context -) { - - fun saveStudents(students: List): Single> { - return Single.fromCallable { - studentDb.insertAll(students.map { - if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context)) - else it - }) - } - } - - fun getStudents(decryptPass: Boolean): Maybe> { - return studentDb.loadAll() - .map { list -> list.map { it.apply { if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) } } } - .filter { it.isNotEmpty() } - } - - fun getStudentById(id: Int): Maybe { - return studentDb.loadById(id).map { - it.apply { - if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) - } - } - } - - fun getCurrentStudent(decryptPass: Boolean): Maybe { - return studentDb.loadCurrent().map { - it.apply { - if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password) - } - } - } - - fun setCurrentStudent(student: Student): Completable { - return Completable.fromCallable { - studentDb.run { - resetCurrent() - updateCurrent(student.id) - } - } - } - - fun logoutStudent(student: Student): Completable { - return Completable.fromCallable { 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 4c0ffd820..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRemote.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import io.reactivex.Single -import org.threeten.bp.LocalDateTime.now -import javax.inject.Inject -import javax.inject.Singleton -import io.github.wulkanowy.sdk.pojo.Student as SdkStudent - -@Singleton -class StudentRemote @Inject constructor(private val sdk: Sdk) { - - private fun mapStudents(students: List, email: String, password: String): List { - return students.map { student -> - Student( - email = email.ifBlank { student.email }, - password = password, - isParent = student.isParent, - symbol = student.symbol, - studentId = student.studentId, - userLoginId = student.userLoginId, - studentName = student.studentName, - schoolSymbol = student.schoolSymbol, - schoolShortName = student.schoolShortName, - schoolName = student.schoolName, - className = student.className, - classId = student.classId, - scrapperBaseUrl = student.scrapperBaseUrl, - loginType = student.loginType.name, - isCurrent = false, - registrationDate = now(), - mobileBaseUrl = student.mobileBaseUrl, - privateKey = student.privateKey, - certificateKey = student.certificateKey, - loginMode = student.loginMode.name - ) - } - } - - fun getStudentsMobileApi(token: String, pin: String, symbol: String): Single> { - return sdk.getStudentsFromMobileApi(token, pin, symbol, "").map { mapStudents(it, "", "") } - } - - fun getStudentsScrapper(email: String, password: String, scrapperBaseUrl: String, symbol: String): Single> { - return sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol).map { mapStudents(it, email, password) } - } - - fun getStudentsHybrid(email: String, password: String, scrapperBaseUrl: String, symbol: String): Single> { - return sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).map { mapStudents(it, email, 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 bebd1eb9c..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/student/StudentRepository.kt +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.wulkanowy.data.repositories.student - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.reactivex.Completable -import io.reactivex.Maybe -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StudentRepository @Inject constructor( - private val local: StudentLocal, - private val remote: StudentRemote, - private val settings: InternetObservingSettings -) { - - fun isStudentSaved(): Single = local.getStudents(false).isEmpty.map { !it } - - fun isCurrentStudentSet(): Single = local.getCurrentStudent(false).isEmpty.map { !it } - - fun getStudentsApi(pin: String, symbol: String, token: String): Single> { - return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getStudentsMobileApi(token, pin, symbol) - else Single.error(UnknownHostException("No internet connection")) - } - } - - fun getStudentsScrapper(email: String, password: String, endpoint: String, symbol: String): Single> { - return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getStudentsScrapper(email, password, endpoint, symbol) - else Single.error(UnknownHostException("No internet connection")) - } - } - - fun getStudentsHybrid(email: String, password: String, endpoint: String, symbol: String): Single> { - return ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getStudentsHybrid(email, password, endpoint, symbol) - else Single.error(UnknownHostException("No internet connection")) - } - } - - fun getSavedStudents(decryptPass: Boolean = true): Single> { - return local.getStudents(decryptPass).toSingle(emptyList()) - } - - fun getStudentById(id: Int): Single { - return local.getStudentById(id) - .switchIfEmpty(Maybe.error(NoCurrentStudentException())) - .toSingle() - } - - fun getCurrentStudent(decryptPass: Boolean = true): Single { - return local.getCurrentStudent(decryptPass) - .switchIfEmpty(Maybe.error(NoCurrentStudentException())) - .toSingle() - } - - fun saveStudents(students: List): Single> { - return local.saveStudents(students) - } - - fun switchStudent(student: Student): Completable { - return local.setCurrentStudent(student) - } - - fun logoutStudent(student: Student): Completable { - 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 f8c13e6c2..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectLocal.kt +++ /dev/null @@ -1,25 +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 io.reactivex.Maybe -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectLocal @Inject constructor(private val subjectDao: SubjectDao) { - - fun getSubjects(semester: Semester): Maybe> { - return subjectDao.loadAll(semester.diaryId, semester.studentId) - .filter { it.isNotEmpty() } - } - - fun saveSubjects(subjects: List) { - subjectDao.insertAll(subjects) - } - - 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 d30232f82..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRemote.kt +++ /dev/null @@ -1,29 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectRemote @Inject constructor(private val sdk: Sdk) { - - fun getSubjects(student: Student, semester: Semester): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getSubjects() - .map { subjects -> - subjects.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 649904da1..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/subject/SubjectRepository.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.data.repositories.subject - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Subject -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SubjectRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: SubjectLocal, - private val remote: SubjectRemote -) { - - fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false): Single> { - return local.getSubjects(semester).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getSubjects(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getSubjects(semester) - .toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteSubjects(old.uniqueSubtract(new)) - local.saveSubjects(new.uniqueSubtract(old)) - } - }.flatMap { - local.getSubjects(semester).toSingle(emptyList()) - }) - } -} 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 dd2be5e58..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherLocal.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.data.repositories.teacher - -import io.github.wulkanowy.data.db.dao.TeacherDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Teacher -import io.reactivex.Maybe -import javax.inject.Inject - -class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) { - - fun saveTeachers(teachers: List) { - teacherDb.insertAll(teachers) - } - - fun deleteTeachers(teachers: List) { - teacherDb.deleteAll(teachers) - } - - fun getTeachers(semester: Semester): Maybe> { - return teacherDb.loadAll(semester.studentId, semester.classId).filter { it.isNotEmpty() } - } -} 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 01552f748..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRemote.kt +++ /dev/null @@ -1,30 +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 io.reactivex.Single -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TeacherRemote @Inject constructor(private val sdk: Sdk) { - - fun getTeachers(student: Student, semester: Semester): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getTeachers(semester.semesterId) - .map { teachers -> - teachers.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 3c10be73f..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/teacher/TeacherRepository.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.data.repositories.teacher - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TeacherRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: TeacherLocal, - private val remote: TeacherRemote -) { - - fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean = false): Single> { - return local.getTeachers(semester).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings) - .flatMap { - if (it) remote.getTeachers(student, semester) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getTeachers(semester).toSingle(emptyList()) - .doOnSuccess { old -> - local.deleteTeachers(old.uniqueSubtract(new)) - local.saveTeachers(new.uniqueSubtract(old)) - } - }.flatMap { local.getTeachers(semester).toSingle(emptyList()) }) - } -} 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 e074ce2a1..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableLocal.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import io.github.wulkanowy.data.db.dao.TimetableDao -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Timetable -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao) { - - fun saveTimetable(timetables: List) { - timetableDb.insertAll(timetables) - } - - fun deleteTimetable(timetables: List) { - timetableDb.deleteAll(timetables) - } - - fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe> { - return timetableDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate).filter { it.isNotEmpty() } - } -} 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 22cb947db..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt +++ /dev/null @@ -1,43 +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 io.reactivex.Single -import org.threeten.bp.LocalDate -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableRemote @Inject constructor(private val sdk: Sdk) { - - fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): Single> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getTimetable(startDate, endDate) - .map { lessons -> - lessons.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 4a7a0eb24..000000000 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRepository.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.wulkanowy.data.repositories.timetable - -import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.uniqueSubtract -import io.reactivex.Single -import org.threeten.bp.LocalDate -import java.net.UnknownHostException -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimetableRepository @Inject constructor( - private val settings: InternetObservingSettings, - private val local: TimetableLocal, - private val remote: TimetableRemote, - private val schedulerHelper: TimetableNotificationSchedulerHelper -) { - - fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): Single> { - return Single.fromCallable { start.monday to end.sunday }.flatMap { (monday, sunday) -> - local.getTimetable(semester, monday, sunday).filter { !forceRefresh } - .switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap { - if (it) remote.getTimetable(student, semester, monday, sunday) - else Single.error(UnknownHostException()) - }.flatMap { new -> - local.getTimetable(semester, monday, sunday) - .toSingle(emptyList()) - .doOnSuccess { old -> - 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 - ) - } - } - }) - } - }.flatMap { - local.getTimetable(semester, monday, sunday).toSingle(emptyList()) - }).map { list -> list.filter { it.date in start..end }.also { schedulerHelper.scheduleNotifications(it, student) } } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java b/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java new file mode 100644 index 000000000..43b37b7e1 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.data.sync; + +import java.io.IOException; +import java.text.ParseException; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public interface SyncContract { + + void sync() throws NotLoggedInErrorException, IOException, ParseException; +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/grades/GradeSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/grades/GradeSync.java new file mode 100644 index 000000000..e0b388849 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/grades/GradeSync.java @@ -0,0 +1,72 @@ +package io.github.wulkanowy.data.sync.grades; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.data.db.dao.entities.Account; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.SubjectDao; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.data.sync.SyncContract; +import io.github.wulkanowy.utils.DataObjectConverter; +import io.github.wulkanowy.utils.EntitiesCompare; +import io.github.wulkanowy.utils.LogUtils; + +@Singleton +public class GradeSync implements SyncContract { + + private final DaoSession daoSession; + + private final Vulcan vulcan; + + private final SharedPrefContract sharedPref; + + @Inject + GradeSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) { + this.daoSession = daoSession; + this.sharedPref = sharedPref; + this.vulcan = vulcan; + } + + @Override + public void sync() throws IOException, NotLoggedInErrorException, ParseException { + + long userId = sharedPref.getCurrentUserId(); + + Account account = daoSession.getAccountDao().load(userId); + account.resetGradeList(); + account.resetSubjectList(); + + List gradesFromNet = DataObjectConverter + .gradesToGradeEntities(vulcan.getGradesList().getAll()); + List gradesFromDb = account.getGradeList(); + + List updatedGrades = EntitiesCompare.compareGradeList(gradesFromNet, gradesFromDb); + + daoSession.getGradeDao().deleteInTx(gradesFromDb); + + List lastList = new ArrayList<>(); + + for (Grade grade : updatedGrades) { + grade.setUserId(userId); + grade.setSubjectId(daoSession.getSubjectDao().queryBuilder() + .where(SubjectDao.Properties.Name.eq(grade.getSubject()), + SubjectDao.Properties.UserId.eq(userId)) + .build() + .uniqueOrThrow().getId()); + lastList.add(grade); + } + + daoSession.getGradeDao().insertInTx(lastList); + + LogUtils.debug("Synchronization grades (amount = " + lastList.size() + ")"); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSync.java new file mode 100644 index 000000000..71838ff54 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSync.java @@ -0,0 +1,81 @@ +package io.github.wulkanowy.data.sync.login; + +import android.content.Context; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.api.login.AccountPermissionException; +import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.api.login.VulcanOfflineException; +import io.github.wulkanowy.data.db.dao.entities.Account; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.utils.LogUtils; +import io.github.wulkanowy.utils.security.CryptoException; +import io.github.wulkanowy.utils.security.Scrambler; + +@Singleton +public class LoginSync implements LoginSyncContract { + + private final DaoSession daoSession; + + private final SharedPrefContract sharedPref; + + private final Vulcan vulcan; + + private final Context context; + + @Inject + LoginSync(DaoSession daoSession, SharedPrefContract sharedPref, + Vulcan vulcan, @ApplicationContext Context context) { + this.daoSession = daoSession; + this.sharedPref = sharedPref; + this.vulcan = vulcan; + this.context = context; + } + + @Override + public void loginUser(String email, String password, String symbol) + throws NotLoggedInErrorException, AccountPermissionException, IOException, + CryptoException, VulcanOfflineException, BadCredentialsException { + + LogUtils.debug("Login new user email=" + email); + + vulcan.login(email, password, symbol); + + Account account = new Account() + .setName(vulcan.getBasicInformation().getPersonalData().getFirstAndLastName()) + .setEmail(email) + .setPassword(Scrambler.encrypt(email, password, context)) + .setSymbol(vulcan.getSymbol()) + .setSnpId(vulcan.getStudentAndParent().getId()); + + sharedPref.setCurrentUserId(daoSession.getAccountDao().insert(account)); + } + + @Override + public void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException, + IOException, CryptoException, VulcanOfflineException, BadCredentialsException { + + long userId = sharedPref.getCurrentUserId(); + + if (userId == 0) { + throw new IOException("Can't find logged user"); + } + + LogUtils.debug("Login current user id=" + userId); + + Account account = daoSession.getAccountDao().load(userId); + + vulcan.login(account.getEmail(), + Scrambler.decrypt(account.getEmail(), account.getPassword()), + account.getSymbol(), + account.getSnpId()); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSyncContract.java b/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSyncContract.java new file mode 100644 index 000000000..1aed8b1bc --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/login/LoginSyncContract.java @@ -0,0 +1,19 @@ +package io.github.wulkanowy.data.sync.login; + +import java.io.IOException; + +import io.github.wulkanowy.api.login.AccountPermissionException; +import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.api.login.VulcanOfflineException; +import io.github.wulkanowy.utils.security.CryptoException; + +public interface LoginSyncContract { + + void loginUser(String email, String password, String symbol) + throws NotLoggedInErrorException, AccountPermissionException, IOException, + CryptoException, VulcanOfflineException, BadCredentialsException; + + void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException, IOException, + CryptoException, VulcanOfflineException, BadCredentialsException; +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/subjects/SubjectSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/subjects/SubjectSync.java new file mode 100644 index 000000000..d888090bf --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/subjects/SubjectSync.java @@ -0,0 +1,61 @@ +package io.github.wulkanowy.data.sync.subjects; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.dao.entities.Subject; +import io.github.wulkanowy.data.db.dao.entities.SubjectDao; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.data.sync.SyncContract; +import io.github.wulkanowy.utils.DataObjectConverter; +import io.github.wulkanowy.utils.LogUtils; + +@Singleton +public class SubjectSync implements SyncContract { + + private final SubjectDao subjectDao; + + private final Vulcan vulcan; + + private final SharedPrefContract sharedPref; + + @Inject + SubjectSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) { + this.subjectDao = daoSession.getSubjectDao(); + this.sharedPref = sharedPref; + this.vulcan = vulcan; + } + + @Override + public void sync() throws NotLoggedInErrorException, IOException, ParseException { + + long userId = sharedPref.getCurrentUserId(); + + List subjectsFromNet = DataObjectConverter + .subjectsToSubjectEntities(vulcan.getSubjectsList().getAll()); + + subjectDao.deleteInTx(subjectDao.queryBuilder() + .where(SubjectDao.Properties.UserId.eq(userId)) + .build() + .list()); + + List lastList = new ArrayList<>(); + + for (Subject subject : subjectsFromNet) { + subject.setUserId(userId); + lastList.add(subject); + } + + subjectDao.insertInTx(lastList); + + LogUtils.debug("Synchronization subjects (amount = " + lastList.size() + ")"); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSync.java new file mode 100644 index 000000000..dcb048f1a --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSync.java @@ -0,0 +1,120 @@ +package io.github.wulkanowy.data.sync.timetable; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.api.login.NotLoggedInErrorException; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.dao.entities.Day; +import io.github.wulkanowy.data.db.dao.entities.DayDao; +import io.github.wulkanowy.data.db.dao.entities.Lesson; +import io.github.wulkanowy.data.db.dao.entities.LessonDao; +import io.github.wulkanowy.data.db.dao.entities.Week; +import io.github.wulkanowy.data.db.dao.entities.WeekDao; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.utils.DataObjectConverter; +import io.github.wulkanowy.utils.LogUtils; +import io.github.wulkanowy.utils.TimeUtils; + +@Singleton +public class TimetableSync implements TimetableSyncContract { + + private final DaoSession daoSession; + + private final Vulcan vulcan; + + private final SharedPrefContract sharedPref; + + @Inject + TimetableSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) { + this.daoSession = daoSession; + this.sharedPref = sharedPref; + this.vulcan = vulcan; + } + + @Override + public void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException { + long userId = sharedPref.getCurrentUserId(); + + io.github.wulkanowy.api.generic.Week weekFromNet = + date == null ? vulcan.getTimetable().getWeekTable() + : vulcan.getTimetable().getWeekTable(String.valueOf(TimeUtils.getNetTicks(date))); + + Week weekFromDb = daoSession.getWeekDao().queryBuilder() + .where(WeekDao.Properties.UserId.eq(userId), + WeekDao.Properties.StartDayDate.eq(weekFromNet.getStartDayDate())) + .unique(); + + Long weekId; + + if (weekFromDb == null) { + Week weekFromNetEntity = DataObjectConverter.weekToWeekEntity(weekFromNet).setUserId(userId); + weekId = daoSession.getWeekDao().insert(weekFromNetEntity); + } else { + weekId = weekFromDb.getId(); + } + + List dayListFromNet = weekFromNet.getDays(); + + List updatedLessonList = new ArrayList<>(); + + for (io.github.wulkanowy.api.generic.Day dayFromNet : dayListFromNet) { + Day dayFromNetEntity = DataObjectConverter.dayToDayEntity(dayFromNet); + + Day dayFromDb = daoSession.getDayDao().queryBuilder() + .where(DayDao.Properties.UserId.eq(userId), + DayDao.Properties.WeekId.eq(weekId), + DayDao.Properties.Date.eq(dayFromNetEntity.getDate())) + .unique(); + + dayFromNetEntity.setUserId(userId); + dayFromNetEntity.setWeekId(weekId); + + Long dayId; + + if (dayFromDb != null) { + dayFromNetEntity.setId(dayFromDb.getId()); + daoSession.getDayDao().save(dayFromNetEntity); + dayId = dayFromNetEntity.getId(); + } else { + dayId = daoSession.getDayDao().insert(dayFromNetEntity); + } + + List lessonListFromNetEntities = DataObjectConverter + .lessonsToLessonsEntities(dayFromNet.getLessons()); + + for (Lesson lessonFromNetEntity : lessonListFromNetEntities) { + Lesson lessonFromDb = daoSession.getLessonDao().queryBuilder() + .where(LessonDao.Properties.DayId.eq(dayId), + LessonDao.Properties.Date.eq(lessonFromNetEntity.getDate()), + LessonDao.Properties.StartTime.eq(lessonFromNetEntity.getStartTime()), + LessonDao.Properties.EndTime.eq(lessonFromNetEntity.getEndTime())) + .unique(); + + if (lessonFromDb != null) { + lessonFromNetEntity.setId(lessonFromDb.getId()); + } + + lessonFromNetEntity.setDayId(dayFromNetEntity.getId()); + + if (!"".equals(lessonFromNetEntity.getSubject())) { + updatedLessonList.add(lessonFromNetEntity); + } + } + } + daoSession.getLessonDao().saveInTx(updatedLessonList); + + LogUtils.debug("Synchronization lessons (amount = " + updatedLessonList.size() + ")"); + } + + @Override + public void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException { + syncTimetable(null); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSyncContract.java b/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSyncContract.java new file mode 100644 index 000000000..4c37d2ec8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/timetable/TimetableSyncContract.java @@ -0,0 +1,13 @@ +package io.github.wulkanowy.data.sync.timetable; + +import java.io.IOException; +import java.text.ParseException; + +import io.github.wulkanowy.api.login.NotLoggedInErrorException; + +public interface TimetableSyncContract { + + void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException; + + void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException; +} diff --git a/app/src/main/java/io/github/wulkanowy/di/AppComponent.kt b/app/src/main/java/io/github/wulkanowy/di/AppComponent.kt deleted file mode 100644 index c0329f7d7..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/AppComponent.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.di - -import dagger.Component -import dagger.android.AndroidInjector -import dagger.android.support.AndroidSupportInjectionModule -import io.github.wulkanowy.WulkanowyApp -import io.github.wulkanowy.data.RepositoryModule -import io.github.wulkanowy.services.ServicesModule -import javax.inject.Singleton - -@Singleton -@Component(modules = [ - AndroidSupportInjectionModule::class, - AppModule::class, - RepositoryModule::class, - ServicesModule::class, - BindingModule::class]) -interface AppComponent : AndroidInjector { - - @Component.Factory - interface Factory : AndroidInjector.Factory -} diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt deleted file mode 100644 index db5ff59b3..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.di - -import android.appwidget.AppWidgetManager -import android.content.Context -import com.yariksoffice.lingver.Lingver -import dagger.Module -import dagger.Provides -import io.github.wulkanowy.WulkanowyApp -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Singleton - -@Module -internal class AppModule { - - @Singleton - @Provides - fun provideContext(app: WulkanowyApp): Context = app - - @Singleton - @Provides - fun provideSchedulersProvider() = SchedulersProvider() - - @Singleton - @Provides - fun provideAppWidgetManager(context: Context): AppWidgetManager = AppWidgetManager.getInstance(context) - - @Singleton - @Provides - fun provideAppInfo() = AppInfo() - - @Singleton - @Provides - fun provideLingver() = Lingver.getInstance() -} diff --git a/app/src/main/java/io/github/wulkanowy/di/BindingModule.kt b/app/src/main/java/io/github/wulkanowy/di/BindingModule.kt deleted file mode 100644 index 1b462964d..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/BindingModule.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.wulkanowy.di - -import dagger.Module -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.di.scopes.PerActivity -import io.github.wulkanowy.ui.base.ErrorDialog -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.login.LoginModule -import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetConfigureActivity -import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainModule -import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity -import io.github.wulkanowy.ui.modules.splash.SplashActivity -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider - -@Suppress("unused") -@Module -internal abstract class BindingModule { - - @ContributesAndroidInjector - abstract fun bindErrorDialog(): ErrorDialog - - @PerActivity - @ContributesAndroidInjector - abstract fun bindSplashActivity(): SplashActivity - - @PerActivity - @ContributesAndroidInjector(modules = [LoginModule::class]) - abstract fun bindLoginActivity(): LoginActivity - - @PerActivity - @ContributesAndroidInjector(modules = [MainModule::class]) - abstract fun bindMainActivity(): MainActivity - - @ContributesAndroidInjector - abstract fun bindMessageSendActivity(): SendMessageActivity - - @ContributesAndroidInjector - abstract fun bindTimetableWidgetAccountActivity(): TimetableWidgetConfigureActivity - - @ContributesAndroidInjector - abstract fun bindTimetableWidgetProvider(): TimetableWidgetProvider - - @ContributesAndroidInjector - abstract fun bindLuckyNumberWidgetAccountActivity(): LuckyNumberWidgetConfigureActivity - - @ContributesAndroidInjector - abstract fun bindLuckyNumberWidgetProvider(): LuckyNumberWidgetProvider - - @ContributesAndroidInjector - abstract fun bindTimetableNotificationReceiver(): TimetableNotificationReceiver -} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/ActivityContext.java b/app/src/main/java/io/github/wulkanowy/di/annotations/ActivityContext.java new file mode 100644 index 000000000..2a74c32d3 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/ActivityContext.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface ActivityContext { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/ApplicationContext.java b/app/src/main/java/io/github/wulkanowy/di/annotations/ApplicationContext.java new file mode 100644 index 000000000..04139d998 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/ApplicationContext.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface ApplicationContext { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/DatabaseInfo.java b/app/src/main/java/io/github/wulkanowy/di/annotations/DatabaseInfo.java new file mode 100644 index 000000000..fabcefbaa --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/DatabaseInfo.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface DatabaseInfo { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/PerActivity.java b/app/src/main/java/io/github/wulkanowy/di/annotations/PerActivity.java new file mode 100644 index 000000000..f103994a5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/PerActivity.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface PerActivity { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/PerFragment.java b/app/src/main/java/io/github/wulkanowy/di/annotations/PerFragment.java new file mode 100644 index 000000000..98f364f76 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/PerFragment.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface PerFragment { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/SharedPreferencesInfo.java b/app/src/main/java/io/github/wulkanowy/di/annotations/SharedPreferencesInfo.java new file mode 100644 index 000000000..919c77a0b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/SharedPreferencesInfo.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface SharedPreferencesInfo { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/SyncGrades.java b/app/src/main/java/io/github/wulkanowy/di/annotations/SyncGrades.java new file mode 100644 index 000000000..90e6c02f6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/SyncGrades.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface SyncGrades { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/annotations/SyncSubjects.java b/app/src/main/java/io/github/wulkanowy/di/annotations/SyncSubjects.java new file mode 100644 index 000000000..81d351bea --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/annotations/SyncSubjects.java @@ -0,0 +1,11 @@ +package io.github.wulkanowy.di.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface SyncSubjects { +} diff --git a/app/src/main/java/io/github/wulkanowy/di/component/ActivityComponent.java b/app/src/main/java/io/github/wulkanowy/di/component/ActivityComponent.java new file mode 100644 index 000000000..3365a317e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/component/ActivityComponent.java @@ -0,0 +1,19 @@ +package io.github.wulkanowy.di.component; + +import dagger.Component; +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.di.modules.ActivityModule; +import io.github.wulkanowy.ui.login.LoginActivity; +import io.github.wulkanowy.ui.main.MainActivity; +import io.github.wulkanowy.ui.splash.SplashActivity; + +@PerActivity +@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) +public interface ActivityComponent { + + void inject(SplashActivity splashActivity); + + void inject(LoginActivity loginActivity); + + void inject(MainActivity mainActivity); +} diff --git a/app/src/main/java/io/github/wulkanowy/di/component/ApplicationComponent.java b/app/src/main/java/io/github/wulkanowy/di/component/ApplicationComponent.java new file mode 100644 index 000000000..3439a9496 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/component/ApplicationComponent.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.di.component; + +import android.content.Context; + +import javax.inject.Singleton; + +import dagger.Component; +import io.github.wulkanowy.WulkanowyApp; +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.di.modules.ApplicationModule; +import io.github.wulkanowy.services.SyncJob; + +@Singleton +@Component(modules = ApplicationModule.class) +public interface ApplicationComponent { + + @ApplicationContext + Context getContext(); + + RepositoryContract getRepository(); + + void inject(WulkanowyApp wulkanowyApp); + + void inject(SyncJob syncJob); +} diff --git a/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java b/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java new file mode 100644 index 000000000..01a0fc02f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java @@ -0,0 +1,25 @@ +package io.github.wulkanowy.di.component; + +import dagger.Component; +import io.github.wulkanowy.di.annotations.PerFragment; +import io.github.wulkanowy.di.modules.FragmentModule; +import io.github.wulkanowy.ui.main.attendance.AttendanceFragment; +import io.github.wulkanowy.ui.main.dashboard.DashboardFragment; +import io.github.wulkanowy.ui.main.grades.GradesFragment; +import io.github.wulkanowy.ui.main.timetable.TimetableFragment; +import io.github.wulkanowy.ui.main.timetable.TimetableTabFragment; + +@PerFragment +@Component(dependencies = ApplicationComponent.class, modules = FragmentModule.class) +public interface FragmentComponent { + + void inject(GradesFragment gradesFragment); + + void inject(AttendanceFragment attendanceFragment); + + void inject(DashboardFragment dashboardFragment); + + void inject(TimetableFragment timetableFragment); + + void inject(TimetableTabFragment timetableTabFragment); +} diff --git a/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java b/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java new file mode 100644 index 000000000..53dc10864 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java @@ -0,0 +1,64 @@ +package io.github.wulkanowy.di.modules; + + +import android.content.Context; +import android.support.v7.app.AppCompatActivity; + +import dagger.Module; +import dagger.Provides; +import io.github.wulkanowy.di.annotations.ActivityContext; +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.login.LoginContract; +import io.github.wulkanowy.ui.login.LoginPresenter; +import io.github.wulkanowy.ui.main.MainContract; +import io.github.wulkanowy.ui.main.MainPagerAdapter; +import io.github.wulkanowy.ui.main.MainPresenter; +import io.github.wulkanowy.ui.splash.SplashContract; +import io.github.wulkanowy.ui.splash.SplashPresenter; + +@Module +public class ActivityModule { + + private AppCompatActivity activity; + + public ActivityModule(AppCompatActivity activity) { + this.activity = activity; + } + + @ActivityContext + @Provides + Context provideContext() { + return activity; + } + + @Provides + AppCompatActivity provideActivity() { + return activity; + } + + @PerActivity + @Provides + SplashContract.Presenter provideSplashPresenter + (SplashPresenter splashPresenter) { + return splashPresenter; + } + + @PerActivity + @Provides + LoginContract.Presenter provideLoginPresenter + (LoginPresenter loginPresenter) { + return loginPresenter; + } + + @PerActivity + @Provides + MainContract.Presenter provideMainPresenter + (MainPresenter mainPresenter) { + return mainPresenter; + } + + @Provides + MainPagerAdapter provideMainPagerAdapter() { + return new MainPagerAdapter(activity.getSupportFragmentManager()); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/di/modules/ApplicationModule.java b/app/src/main/java/io/github/wulkanowy/di/modules/ApplicationModule.java new file mode 100644 index 000000000..58e9909b4 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/modules/ApplicationModule.java @@ -0,0 +1,129 @@ +package io.github.wulkanowy.di.modules; + +import android.app.Application; +import android.content.Context; + +import com.firebase.jobdispatcher.FirebaseJobDispatcher; +import com.firebase.jobdispatcher.GooglePlayDriver; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.data.Repository; +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.data.db.dao.DbHelper; +import io.github.wulkanowy.data.db.dao.entities.DaoMaster; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.resources.AppResources; +import io.github.wulkanowy.data.db.resources.ResourcesContract; +import io.github.wulkanowy.data.db.shared.SharedPref; +import io.github.wulkanowy.data.db.shared.SharedPrefContract; +import io.github.wulkanowy.data.sync.SyncContract; +import io.github.wulkanowy.data.sync.grades.GradeSync; +import io.github.wulkanowy.data.sync.login.LoginSync; +import io.github.wulkanowy.data.sync.login.LoginSyncContract; +import io.github.wulkanowy.data.sync.subjects.SubjectSync; +import io.github.wulkanowy.data.sync.timetable.TimetableSync; +import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract; +import io.github.wulkanowy.di.annotations.ApplicationContext; +import io.github.wulkanowy.di.annotations.DatabaseInfo; +import io.github.wulkanowy.di.annotations.SharedPreferencesInfo; +import io.github.wulkanowy.di.annotations.SyncGrades; +import io.github.wulkanowy.di.annotations.SyncSubjects; +import io.github.wulkanowy.utils.AppConstant; + +@Module +public class ApplicationModule { + + private final Application application; + + public ApplicationModule(Application application) { + this.application = application; + } + + @Provides + Application provideApplication() { + return application; + } + + @ApplicationContext + @Provides + Context provideAppContext() { + return application; + } + + @DatabaseInfo + @Provides + String provideDatabaseName() { + return AppConstant.DATABASE_NAME; + } + + @SharedPreferencesInfo + @Provides + String provideSharedPreferencesName() { + return AppConstant.SHARED_PREFERENCES_NAME; + } + + @Singleton + @Provides + DaoSession provideDaoSession(DbHelper dbHelper) { + return new DaoMaster(dbHelper.getWritableDb()).newSession(); + } + + @Singleton + @Provides + Vulcan provideVulcan() { + return new Vulcan(); + } + + @Singleton + @Provides + RepositoryContract provideRepository(Repository repository) { + return repository; + } + + @Singleton + @Provides + SharedPrefContract provideSharedPref(SharedPref sharedPref) { + return sharedPref; + } + + @Singleton + @Provides + ResourcesContract provideAppResources(AppResources appResources) { + return appResources; + } + + @Singleton + @Provides + LoginSyncContract provideLoginSync(LoginSync loginSync) { + return loginSync; + } + + @SyncGrades + @Singleton + @Provides + SyncContract provideGradesSync(GradeSync gradeSync) { + return gradeSync; + } + + @SyncSubjects + @Singleton + @Provides + SyncContract provideSubjectSync(SubjectSync subjectSync) { + return subjectSync; + } + + @Singleton + @Provides + TimetableSyncContract provideTimetableSync(TimetableSync timetableSync) { + return timetableSync; + } + + @Provides + FirebaseJobDispatcher provideDispatcher() { + return new FirebaseJobDispatcher(new GooglePlayDriver(application)); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java b/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java new file mode 100644 index 000000000..8999bca86 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java @@ -0,0 +1,76 @@ +package io.github.wulkanowy.di.modules; + +import android.support.v4.app.Fragment; + +import dagger.Module; +import dagger.Provides; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import io.github.wulkanowy.di.annotations.PerFragment; +import io.github.wulkanowy.ui.main.attendance.AttendanceContract; +import io.github.wulkanowy.ui.main.attendance.AttendancePresenter; +import io.github.wulkanowy.ui.main.dashboard.DashboardContract; +import io.github.wulkanowy.ui.main.dashboard.DashboardPresenter; +import io.github.wulkanowy.ui.main.grades.GradeHeaderItem; +import io.github.wulkanowy.ui.main.grades.GradesContract; +import io.github.wulkanowy.ui.main.grades.GradesPresenter; +import io.github.wulkanowy.ui.main.timetable.TimetableContract; +import io.github.wulkanowy.ui.main.timetable.TimetableHeaderItem; +import io.github.wulkanowy.ui.main.timetable.TimetablePagerAdapter; +import io.github.wulkanowy.ui.main.timetable.TimetablePresenter; +import io.github.wulkanowy.ui.main.timetable.TimetableTabContract; +import io.github.wulkanowy.ui.main.timetable.TimetableTabPresenter; + +@Module +public class FragmentModule { + + private final Fragment fragment; + + public FragmentModule(Fragment fragment) { + this.fragment = fragment; + } + + @PerFragment + @Provides + GradesContract.Presenter provideGradesPresenter(GradesPresenter gradesPresenter) { + return gradesPresenter; + } + + @PerFragment + @Provides + AttendanceContract.Presenter provideAttendancePresenter(AttendancePresenter attendancePresenter) { + return attendancePresenter; + } + + @PerFragment + @Provides + DashboardContract.Presenter provideDashboardPresenter(DashboardPresenter dashboardPresenter) { + return dashboardPresenter; + } + + @PerFragment + @Provides + TimetableContract.Presenter provideTimetablePresenter(TimetablePresenter timetablePresenter) { + return timetablePresenter; + } + + @PerFragment + @Provides + TimetableTabContract.Presenter provideTimetableTabPresenter(TimetableTabPresenter timetableTabPresenter) { + return timetableTabPresenter; + } + + @Provides + TimetablePagerAdapter provideTimetablePagerAdapter() { + return new TimetablePagerAdapter(fragment.getChildFragmentManager()); + } + + @Provides + FlexibleAdapter provideGradesAdapter() { + return new FlexibleAdapter<>(null); + } + + @Provides + FlexibleAdapter provideTimetableTabAdapter() { + return new FlexibleAdapter<>(null); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/di/scopes/PerActivity.kt b/app/src/main/java/io/github/wulkanowy/di/scopes/PerActivity.kt deleted file mode 100644 index c1b4352a4..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/scopes/PerActivity.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.di.scopes - -import javax.inject.Scope - -@Scope -@Retention(AnnotationRetention.RUNTIME) -annotation class PerActivity diff --git a/app/src/main/java/io/github/wulkanowy/di/scopes/PerChildFragment.kt b/app/src/main/java/io/github/wulkanowy/di/scopes/PerChildFragment.kt deleted file mode 100644 index 08884dac5..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/scopes/PerChildFragment.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.di.scopes - -import javax.inject.Scope - -@Scope -@Retention(AnnotationRetention.RUNTIME) -annotation class PerChildFragment diff --git a/app/src/main/java/io/github/wulkanowy/di/scopes/PerFragment.kt b/app/src/main/java/io/github/wulkanowy/di/scopes/PerFragment.kt deleted file mode 100644 index 1203d7d88..000000000 --- a/app/src/main/java/io/github/wulkanowy/di/scopes/PerFragment.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.di.scopes - -import javax.inject.Scope - -@Scope -@Retention(AnnotationRetention.RUNTIME) -annotation class PerFragment diff --git a/app/src/main/java/io/github/wulkanowy/services/NotificationService.java b/app/src/main/java/io/github/wulkanowy/services/NotificationService.java new file mode 100644 index 000000000..ab721f46c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/services/NotificationService.java @@ -0,0 +1,55 @@ +package io.github.wulkanowy.services; + + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Build; +import android.support.v4.app.NotificationCompat; + +import java.util.Random; + +class NotificationService { + + private static final String CHANNEL_ID = "Wulkanowy_New_Grade_Channel"; + + private static final String CHANNEL_NAME = "New Grade Channel"; + + private NotificationManager manager; + + private Context context; + + NotificationService(Context context) { + this.context = context; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + createChannel(); + } + } + + void notify(Notification notification) { + getManager().notify(new Random().nextInt(1000), notification); + } + + NotificationCompat.Builder notificationBuilder() { + return new NotificationCompat.Builder(context, CHANNEL_ID); + } + + @TargetApi(26) + private void createChannel() { + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, + NotificationManager.IMPORTANCE_HIGH); + notificationChannel.enableLights(true); + notificationChannel.enableVibration(true); + notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); + getManager().createNotificationChannel(notificationChannel); + } + + private NotificationManager getManager() { + if (manager == null) { + manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + } + return manager; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt deleted file mode 100644 index b87f0e683..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt +++ /dev/null @@ -1,140 +0,0 @@ -package io.github.wulkanowy.services - -import android.app.AlarmManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.getSystemService -import androidx.work.WorkManager -import com.squareup.inject.assisted.dagger2.AssistedModule -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import dagger.multibindings.IntoSet -import io.github.wulkanowy.services.sync.channels.Channel -import io.github.wulkanowy.services.sync.channels.DebugChannel -import io.github.wulkanowy.services.sync.channels.LuckyNumberChannel -import io.github.wulkanowy.services.sync.channels.NewGradesChannel -import io.github.wulkanowy.services.sync.channels.NewMessagesChannel -import io.github.wulkanowy.services.sync.channels.NewNotesChannel -import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel -import io.github.wulkanowy.services.sync.channels.PushChannel -import io.github.wulkanowy.services.sync.works.AttendanceSummaryWork -import io.github.wulkanowy.services.sync.works.AttendanceWork -import io.github.wulkanowy.services.sync.works.CompletedLessonWork -import io.github.wulkanowy.services.sync.works.ExamWork -import io.github.wulkanowy.services.sync.works.GradeStatisticsWork -import io.github.wulkanowy.services.sync.works.GradeWork -import io.github.wulkanowy.services.sync.works.HomeworkWork -import io.github.wulkanowy.services.sync.works.LuckyNumberWork -import io.github.wulkanowy.services.sync.works.MessageWork -import io.github.wulkanowy.services.sync.works.NoteWork -import io.github.wulkanowy.services.sync.works.RecipientWork -import io.github.wulkanowy.services.sync.works.TeacherWork -import io.github.wulkanowy.services.sync.works.TimetableWork -import io.github.wulkanowy.services.sync.works.Work -import io.github.wulkanowy.services.widgets.TimetableWidgetService -import javax.inject.Singleton - -@Suppress("unused") -@AssistedModule -@Module(includes = [AssistedInject_ServicesModule::class]) -abstract class ServicesModule { - - companion object { - - @Provides - fun provideWorkManager(context: Context) = WorkManager.getInstance(context) - - @Singleton - @Provides - fun provideNotificationManager(context: Context) = NotificationManagerCompat.from(context) - - @Singleton - @Provides - fun provideAlarmManager(context: Context): AlarmManager = context.getSystemService()!! - } - - @ContributesAndroidInjector - abstract fun bindTimetableWidgetService(): TimetableWidgetService - - @Binds - @IntoSet - abstract fun provideGradeWork(work: GradeWork): Work - - @Binds - @IntoSet - abstract fun provideNoteWork(work: NoteWork): Work - - @Binds - @IntoSet - abstract fun provideAttendanceWork(work: AttendanceWork): Work - - @Binds - @IntoSet - abstract fun provideExamWork(work: ExamWork): Work - - @Binds - @IntoSet - abstract fun provideAttendanceSummaryWork(work: AttendanceSummaryWork): Work - - @Binds - @IntoSet - abstract fun provideTimetableWork(work: TimetableWork): Work - - @Binds - @IntoSet - abstract fun provideTeacherWork(work: TeacherWork): Work - - @Binds - @IntoSet - abstract fun provideLuckyNumberWork(work: LuckyNumberWork): Work - - @Binds - @IntoSet - abstract fun provideCompletedLessonWork(work: CompletedLessonWork): Work - - @Binds - @IntoSet - abstract fun provideHomeworkWork(work: HomeworkWork): Work - - @Binds - @IntoSet - abstract fun provideMessageWork(work: MessageWork): Work - - @Binds - @IntoSet - abstract fun provideRecipientWork(work: RecipientWork): Work - - @Binds - @IntoSet - abstract fun provideGradeStatistics(work: GradeStatisticsWork): Work - - @Binds - @IntoSet - abstract fun provideDebugChannel(channel: DebugChannel): Channel - - @Binds - @IntoSet - abstract fun provideLuckyNumberChannel(channel: LuckyNumberChannel): Channel - - @Binds - @IntoSet - abstract fun provideNewGradesChannel(channel: NewGradesChannel): Channel - - @Binds - @IntoSet - abstract fun provideNewMessageChannel(channel: NewMessagesChannel): Channel - - @Binds - @IntoSet - abstract fun provideNewNotesChannel(channel: NewNotesChannel): Channel - - @Binds - @IntoSet - abstract fun providePushChannel(channel: PushChannel): Channel - - @Binds - @IntoSet - abstract fun provideUpcomingLessonsChannel(channel: UpcomingLessonsChannel): Channel -} diff --git a/app/src/main/java/io/github/wulkanowy/services/SyncJob.java b/app/src/main/java/io/github/wulkanowy/services/SyncJob.java new file mode 100644 index 000000000..ab26fceef --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/services/SyncJob.java @@ -0,0 +1,114 @@ +package io.github.wulkanowy.services; + +import android.app.PendingIntent; +import android.content.Context; +import android.support.v4.app.NotificationCompat; + +import com.firebase.jobdispatcher.Constraint; +import com.firebase.jobdispatcher.FirebaseJobDispatcher; +import com.firebase.jobdispatcher.GooglePlayDriver; +import com.firebase.jobdispatcher.JobParameters; +import com.firebase.jobdispatcher.JobService; +import com.firebase.jobdispatcher.Lifetime; +import com.firebase.jobdispatcher.RetryStrategy; +import com.firebase.jobdispatcher.SimpleJobService; +import com.firebase.jobdispatcher.Trigger; + +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.R; +import io.github.wulkanowy.WulkanowyApp; +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.ui.main.MainActivity; +import io.github.wulkanowy.utils.LogUtils; + +public class SyncJob extends SimpleJobService { + + private static final int DEFAULT_INTERVAL_START = 60 * 50; + + private static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 40); + + public static final String EXTRA_INTENT_KEY = "cardId"; + + private List gradeList; + + @Inject + RepositoryContract repository; + + public static void start(Context context) { + FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context)); + + dispatcher.mustSchedule(dispatcher.newJobBuilder() + .setLifetime(Lifetime.FOREVER) + .setService(SyncJob.class) + .setTag("SyncJob") + .setRecurring(true) + .setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END)) + .setConstraints(Constraint.ON_ANY_NETWORK) + .setReplaceCurrent(false) + .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL) + .build()); + } + + @Override + public void onCreate() { + super.onCreate(); + ((WulkanowyApp) getApplication()).getApplicationComponent().inject(this); + } + + @Override + public int onRunJob(JobParameters job) { + try { + repository.loginCurrentUser(); + repository.syncAll(); + + gradeList = repository.getNewGrades(); + + if (!gradeList.isEmpty()) { + showNotification(); + } + return JobService.RESULT_SUCCESS; + } catch (Exception e) { + LogUtils.error("During background synchronization an error occurred", e); + return JobService.RESULT_FAIL_RETRY; + } + } + + private void showNotification() { + NotificationService service = new NotificationService(getApplicationContext()); + + service.notify(service.notificationBuilder() + .setContentTitle(getStringTitle()) + .setContentText(getStringContent()) + .setSmallIcon(R.drawable.ic_stat_notify) + .setAutoCancel(true) + .setDefaults(NotificationCompat.DEFAULT_ALL) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setColor(getResources().getColor(R.color.colorPrimary)) + .setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, + MainActivity.getStartIntent(getApplicationContext()).putExtra(EXTRA_INTENT_KEY, 0) + , 0 + )) + .build()); + } + + private String getStringTitle() { + if (gradeList.size() == 1) { + return getResources().getQuantityString(R.plurals.newGradePlurals, 1); + } else { + return getResources().getQuantityString(R.plurals.newGradePlurals, 2); + } + } + + private String getStringContent() { + if (gradeList.size() == 1) { + return gradeList.get(0).getSubject(); + } else { + return getResources().getQuantityString(R.plurals.receivedNewGradePlurals, + gradeList.size(), gradeList.size()); + } + } +} 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 deleted file mode 100644 index 0130f4673..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationReceiver.kt +++ /dev/null @@ -1,117 +0,0 @@ -package io.github.wulkanowy.services.alarm - -import android.annotation.SuppressLint -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.os.Build -import android.os.Build.VERSION_CODES.N -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import dagger.android.AndroidInjection -import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.getCompatColor -import io.github.wulkanowy.utils.toLocalDateTime -import timber.log.Timber -import javax.inject.Inject - -class TimetableNotificationReceiver : BroadcastReceiver() { - - @Inject - lateinit var studentRepository: StudentRepository - - @Inject - lateinit var schedulers: SchedulersProvider - - companion object { - const val NOTIFICATION_TYPE_CURRENT = 1 - const val NOTIFICATION_TYPE_UPCOMING = 2 - const val NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION = 3 - - const val NOTIFICATION_ID = "id" - - const val STUDENT_NAME = "student_name" - const val STUDENT_ID = "student_id" - const val LESSON_TYPE = "type" - const val LESSON_TITLE = "title" - const val LESSON_ROOM = "room" - const val LESSON_NEXT_TITLE = "next_title" - const val LESSON_NEXT_ROOM = "next_room" - const val LESSON_START = "start_timestamp" - const val LESSON_END = "end_timestamp" - } - - @SuppressLint("CheckResult") - override fun onReceive(context: Context, intent: Intent) { - Timber.d("Receiving intent... ${intent.toUri(0)}") - AndroidInjection.inject(this, context) - - studentRepository.getCurrentStudent(false) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - val studentId = intent.getIntExtra(STUDENT_ID, 0) - if (it.studentId == studentId) prepareNotification(context, intent) - else Timber.d("Notification studentId($studentId) differs from current(${it.studentId})") - }, { Timber.e(it) }) - } - - private fun prepareNotification(context: Context, intent: Intent) { - val type = intent.getIntExtra(LESSON_TYPE, 0) - val notificationId = intent.getIntExtra(NOTIFICATION_ID, MainView.Section.TIMETABLE.id) - - if (type == NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION) { - return NotificationManagerCompat.from(context).cancel(notificationId) - } - - val studentId = intent.getIntExtra(STUDENT_ID, 0) - val studentName = intent.getStringExtra(STUDENT_NAME) - - val subject = intent.getStringExtra(LESSON_TITLE) - val room = intent.getStringExtra(LESSON_ROOM) - - val start = intent.getLongExtra(LESSON_START, 0) - val end = intent.getLongExtra(LESSON_END, 0) - - val nextSubject = intent.getStringExtra(LESSON_NEXT_TITLE) - val nextRoom = intent.getStringExtra(LESSON_NEXT_ROOM) - - Timber.d("TimetableNotification receive: type: $type, subject: $subject, start: ${start.toLocalDateTime()}, student: $studentId") - - showNotification(context, notificationId, studentName, - if (type == NOTIFICATION_TYPE_CURRENT) end else start, end - start, - context.getString(if (type == NOTIFICATION_TYPE_CURRENT) R.string.timetable_now else R.string.timetable_next, "($room) $subject".removePrefix("()")), - nextSubject?.let { context.getString(R.string.timetable_later, "($nextRoom) $nextSubject".removePrefix("()")) } - ) - } - - private fun showNotification(context: Context, notificationId: Int, studentName: String?, countDown: Long, timeout: Long, title: String, next: String?) { - NotificationManagerCompat.from(context).notify(notificationId, NotificationCompat.Builder(context, CHANNEL_ID) - .setContentTitle(title) - .setContentText(next) - .setAutoCancel(false) - .setOngoing(true) - .setWhen(countDown) - .apply { - if (Build.VERSION.SDK_INT >= N) setUsesChronometer(true) - } - .setTimeoutAfter(timeout) - .setSmallIcon(R.drawable.ic_stat_timetable) - .setColor(context.getCompatColor(R.color.colorPrimary)) - .setStyle(NotificationCompat.InboxStyle().also { - it.setSummaryText(studentName) - it.addLine(next) - }) - .setContentIntent(PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id, - MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT)) - .build() - ) - } -} 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 deleted file mode 100644 index 54b245ddb..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/alarm/TimetableNotificationSchedulerHelper.kt +++ /dev/null @@ -1,109 +0,0 @@ -package io.github.wulkanowy.services.alarm - -import android.app.AlarmManager -import android.app.AlarmManager.RTC_WAKEUP -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.Context -import android.content.Intent -import androidx.core.app.AlarmManagerCompat -import androidx.core.app.NotificationManagerCompat -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.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 -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_ROOM -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_START -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_TITLE -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.LESSON_TYPE -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.NOTIFICATION_ID -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.NOTIFICATION_TYPE_CURRENT -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.NOTIFICATION_TYPE_UPCOMING -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_ID -import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companion.STUDENT_NAME -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.toTimestamp -import org.threeten.bp.LocalDateTime -import org.threeten.bp.LocalDateTime.now -import timber.log.Timber -import javax.inject.Inject - -class TimetableNotificationSchedulerHelper @Inject constructor( - private val context: Context, - private val alarmManager: AlarmManager, - private val preferencesRepository: PreferencesRepository -) { - - private fun getRequestCode(time: LocalDateTime, studentId: Int) = (time.toTimestamp() * studentId).toInt() - - private fun getUpcomingLessonTime(index: Int, day: List, lesson: Timetable): LocalDateTime { - return day.getOrNull(index - 1)?.end ?: lesson.start.minusMinutes(30) - } - - fun cancelScheduled(lessons: List, studentId: Int = 1) { - lessons.sortedBy { it.start }.forEachIndexed { index, lesson -> - val upcomingTime = getUpcomingLessonTime(index, lessons, lesson) - cancelScheduledTo(upcomingTime..lesson.start, getRequestCode(upcomingTime, studentId)) - cancelScheduledTo(lesson.start..lesson.end, getRequestCode(lesson.start, studentId)) - - Timber.d("TimetableNotification canceled: type 1 & 2, subject: ${lesson.subject}, start: ${lesson.start}, student: $studentId") - } - } - - private fun cancelScheduledTo(range: ClosedRange, requestCode: Int) { - if (now() in range) cancelNotification() - alarmManager.cancel(PendingIntent.getBroadcast(context, requestCode, Intent(), FLAG_UPDATE_CURRENT)) - } - - fun cancelNotification() = NotificationManagerCompat.from(context).cancel(MainView.Section.TIMETABLE.id) - - fun scheduleNotifications(lessons: List, student: Student) { - if (!preferencesRepository.isUpcomingLessonsNotificationsEnable) return cancelScheduled(lessons, student.studentId) - - lessons.groupBy { it.date } - .map { it.value.sortedBy { lesson -> lesson.start } } - .map { it.filter { lesson -> !lesson.canceled && lesson.isStudentPlan } } - .map { day -> - day.forEachIndexed { index, lesson -> - val intent = createIntent(student, lesson, day.getOrNull(index + 1)) - - if (lesson.start > now()) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_UPCOMING, getUpcomingLessonTime(index, day, lesson)) - } - - if (lesson.end > now()) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_CURRENT, lesson.start) - if (day.lastIndex == index) { - scheduleBroadcast(intent, student.studentId, NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION, lesson.end) - } - } - } - } - } - - private fun createIntent(student: Student, lesson: Timetable, nextLesson: Timetable?): Intent { - return Intent(context, TimetableNotificationReceiver::class.java).apply { - putExtra(STUDENT_ID, student.studentId) - putExtra(STUDENT_NAME, student.studentName) - putExtra(LESSON_ROOM, lesson.room) - putExtra(LESSON_START, lesson.start.toTimestamp()) - putExtra(LESSON_END, lesson.end.toTimestamp()) - putExtra(LESSON_TITLE, lesson.subject) - putExtra(LESSON_NEXT_TITLE, nextLesson?.subject) - putExtra(LESSON_NEXT_ROOM, nextLesson?.room) - } - } - - private fun scheduleBroadcast(intent: Intent, studentId: Int, notificationType: Int, time: LocalDateTime) { - AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, RTC_WAKEUP, time.toTimestamp(), - PendingIntent.getBroadcast(context, getRequestCode(time, studentId), intent.also { - it.putExtra(NOTIFICATION_ID, MainView.Section.TIMETABLE.id) - it.putExtra(LESSON_TYPE, notificationType) - }, FLAG_UPDATE_CURRENT) - ) - Timber.d("TimetableNotification scheduled: type: $notificationType, subject: ${intent.getStringExtra(LESSON_TITLE)}, start: $time, student: $studentId") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt deleted file mode 100644 index 965ed0ad9..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt +++ /dev/null @@ -1,86 +0,0 @@ -package io.github.wulkanowy.services.sync - -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.O -import androidx.core.app.NotificationManagerCompat -import androidx.work.BackoffPolicy.EXPONENTIAL -import androidx.work.Constraints -import androidx.work.Data -import androidx.work.ExistingPeriodicWorkPolicy.KEEP -import androidx.work.ExistingPeriodicWorkPolicy.REPLACE -import androidx.work.ExistingWorkPolicy -import androidx.work.NetworkType.CONNECTED -import androidx.work.NetworkType.UNMETERED -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.PeriodicWorkRequestBuilder -import androidx.work.WorkInfo -import androidx.work.WorkManager -import com.paulinasadowska.rxworkmanagerobservers.extensions.getWorkInfoByIdObservable -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.services.sync.channels.Channel -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.isHolidays -import io.reactivex.Observable -import org.threeten.bp.LocalDate.now -import timber.log.Timber -import java.util.concurrent.TimeUnit.MINUTES -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SyncManager @Inject constructor( - private val workManager: WorkManager, - private val preferencesRepository: PreferencesRepository, - channels: Set<@JvmSuppressWildcards Channel>, - notificationManager: NotificationManagerCompat, - sharedPrefProvider: SharedPrefProvider, - appInfo: AppInfo -) { - - init { - if (now().isHolidays) stopSyncWorker() - - if (SDK_INT >= O) { - channels.forEach { it.create() } - notificationManager.deleteNotificationChannel("new_entries_channel") - } - - if (sharedPrefProvider.getLong(APP_VERSION_CODE_KEY, -1L) != appInfo.versionCode.toLong()) { - startPeriodicSyncWorker(true) - sharedPrefProvider.putLong(APP_VERSION_CODE_KEY, appInfo.versionCode.toLong(), true) - } - Timber.i("SyncManager was initialized") - } - - fun startPeriodicSyncWorker(restart: Boolean = false) { - if (preferencesRepository.isServiceEnabled && !now().isHolidays) { - workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP, - PeriodicWorkRequestBuilder(preferencesRepository.servicesInterval, MINUTES) - .setInitialDelay(10, MINUTES) - .setBackoffCriteria(EXPONENTIAL, 30, MINUTES) - .setConstraints(Constraints.Builder() - .setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED) - .build()) - .build()) - } - } - - fun startOneTimeSyncWorker(): Observable { - val work = OneTimeWorkRequestBuilder() - .setInputData( - Data.Builder() - .putBoolean("one_time", true) - .build() - ) - .build() - - workManager.enqueueUniqueWork("${SyncWorker::class.java.simpleName}_one_time", ExistingWorkPolicy.REPLACE, work) - return workManager.getWorkInfoByIdObservable(work.id) - } - - fun stopSyncWorker() { - workManager.cancelUniqueWork(SyncWorker::class.java.simpleName) - } -} 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 deleted file mode 100644 index 126d856aa..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorker.kt +++ /dev/null @@ -1,93 +0,0 @@ -package io.github.wulkanowy.services.sync - -import android.content.Context -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.BigTextStyle -import androidx.core.app.NotificationCompat.PRIORITY_DEFAULT -import androidx.core.app.NotificationManagerCompat -import androidx.work.Data -import androidx.work.ListenableWorker -import androidx.work.RxWorker -import androidx.work.WorkerParameters -import com.squareup.inject.assisted.Assisted -import com.squareup.inject.assisted.AssistedInject -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.sdk.exception.FeatureDisabledException -import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException -import io.github.wulkanowy.services.sync.channels.DebugChannel -import io.github.wulkanowy.services.sync.works.Work -import io.github.wulkanowy.utils.getCompatColor -import io.reactivex.Completable -import io.reactivex.Single -import timber.log.Timber -import kotlin.random.Random - -class SyncWorker @AssistedInject constructor( - @Assisted appContext: Context, - @Assisted workerParameters: WorkerParameters, - private val studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val works: Set<@JvmSuppressWildcards Work>, - private val preferencesRepository: PreferencesRepository, - private val notificationManager: NotificationManagerCompat -) : RxWorker(appContext, workerParameters) { - - override fun createWork(): Single { - Timber.i("SyncWorker is starting") - return studentRepository.isCurrentStudentSet() - .filter { true } - .flatMap { studentRepository.getCurrentStudent().toMaybe() } - .flatMapCompletable { student -> - semesterRepository.getCurrentSemester(student, true) - .flatMapCompletable { semester -> - Completable.mergeDelayError(works.map { work -> - work.create(student, semester) - .onErrorResumeNext { - if (it is FeatureDisabledException || it is FeatureNotAvailableException) Completable.complete() - else Completable.error(it) - } - .doOnSubscribe { Timber.i("${work::class.java.simpleName} is starting") } - .doOnError { Timber.i("${work::class.java.simpleName} result: An exception occurred") } - .doOnComplete { Timber.i("${work::class.java.simpleName} result: Success") } - }) - } - } - .toSingleDefault(Result.success()) - .onErrorReturn { - Timber.e(it, "There was an error during synchronization") - when { - inputData.getBoolean("one_time", false) -> { - Result.failure(Data.Builder() - .putString("error", it.toString()) - .build() - ) - } - else -> Result.retry() - } - } - .doOnSuccess { - if (preferencesRepository.isDebugNotificationEnable) notify(it) - Timber.i("SyncWorker result: $it") - } - } - - private fun notify(result: Result) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(applicationContext, DebugChannel.CHANNEL_ID) - .setContentTitle("Debug notification") - .setSmallIcon(R.drawable.ic_stat_push) - .setAutoCancel(true) - .setColor(applicationContext.getCompatColor(R.color.colorPrimary)) - .setStyle(BigTextStyle().bigText("${SyncWorker::class.java.simpleName} result: $result")) - .setPriority(PRIORITY_DEFAULT) - .build()) - } - - @AssistedInject.Factory - interface Factory { - - fun create(appContext: Context, workerParameters: WorkerParameters): ListenableWorker - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorkerFactory.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorkerFactory.kt deleted file mode 100644 index aadfc27f4..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncWorkerFactory.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.services.sync - -import android.content.Context -import androidx.work.ListenableWorker -import androidx.work.WorkerFactory -import androidx.work.WorkerParameters -import timber.log.Timber -import javax.inject.Inject - -class SyncWorkerFactory @Inject constructor(private val syncWorkerFactory: SyncWorker.Factory) : WorkerFactory() { - - override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): ListenableWorker? { - return if (workerClassName == SyncWorker::class.java.name) { - syncWorkerFactory.create(appContext, workerParameters) - } else { - Timber.e(IllegalArgumentException("Unknown worker class name: $workerClassName")) - null - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/Channel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/Channel.kt deleted file mode 100644 index f47c2220c..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/Channel.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -interface Channel { - - fun create() -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/DebugChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/DebugChannel.kt deleted file mode 100644 index a67350550..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/DebugChannel.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification.VISIBILITY_PUBLIC -import android.app.NotificationChannel -import android.app.NotificationManager.IMPORTANCE_DEFAULT -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import io.github.wulkanowy.utils.AppInfo -import javax.inject.Inject - -@TargetApi(26) -class DebugChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context, - private val appInfo: AppInfo -) : Channel { - - companion object { - const val CHANNEL_ID = "debug_channel" - } - - override fun create() { - if (!appInfo.isDebug) return - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_debug), IMPORTANCE_DEFAULT) - .apply { - lockscreenVisibility = VISIBILITY_PUBLIC - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/LuckyNumberChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/LuckyNumberChannel.kt deleted file mode 100644 index ae228edd7..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/LuckyNumberChannel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class LuckyNumberChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "lucky_number_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_lucky_number), NotificationManager.IMPORTANCE_HIGH) - .apply { - enableLights(true) - enableVibration(true) - lockscreenVisibility = Notification.VISIBILITY_PUBLIC - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewGradesChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewGradesChannel.kt deleted file mode 100644 index 7d6f275d9..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewGradesChannel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class NewGradesChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "new_grade_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_new_grades), NotificationManager.IMPORTANCE_HIGH) - .apply { - enableLights(true) - enableVibration(true) - lockscreenVisibility = Notification.VISIBILITY_PUBLIC - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewMessagesChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewMessagesChannel.kt deleted file mode 100644 index 49f39c6be..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewMessagesChannel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class NewMessagesChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "new_message_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_new_message), NotificationManager.IMPORTANCE_HIGH) - .apply { - enableLights(true) - enableVibration(true) - lockscreenVisibility = Notification.VISIBILITY_PUBLIC - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewNotesChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewNotesChannel.kt deleted file mode 100644 index d80d43dc5..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/NewNotesChannel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class NewNotesChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "new_notes_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_new_notes), NotificationManager.IMPORTANCE_HIGH) - .apply { - enableLights(true) - enableVibration(true) - lockscreenVisibility = Notification.VISIBILITY_PUBLIC - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/PushChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/PushChannel.kt deleted file mode 100644 index a0e24ab45..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/PushChannel.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class PushChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "push_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_push), NotificationManager.IMPORTANCE_HIGH) - .apply { - enableLights(true) - enableVibration(true) - lockscreenVisibility = Notification.VISIBILITY_PUBLIC - } - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt b/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt deleted file mode 100644 index a292c8b53..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/channels/UpcomingLessonsChannel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.services.sync.channels - -import android.annotation.TargetApi -import android.app.Notification.VISIBILITY_PUBLIC -import android.app.NotificationChannel -import android.app.NotificationManager.IMPORTANCE_DEFAULT -import android.content.Context -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -import javax.inject.Inject - -@TargetApi(26) -class UpcomingLessonsChannel @Inject constructor( - private val notificationManager: NotificationManagerCompat, - private val context: Context -) : Channel { - - companion object { - const val CHANNEL_ID = "lesson_channel" - } - - override fun create() { - notificationManager.createNotificationChannel( - NotificationChannel(CHANNEL_ID, context.getString(R.string.channel_upcoming_lessons), IMPORTANCE_DEFAULT).apply { - lockscreenVisibility = VISIBILITY_PUBLIC - setShowBadge(false) - enableVibration(false) - } - ) - } -} 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 deleted file mode 100644 index 5f7d7efa2..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceSummaryWork.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository -import io.reactivex.Completable -import javax.inject.Inject - -class AttendanceSummaryWork @Inject constructor( - private val attendanceSummaryRepository: AttendanceSummaryRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return attendanceSummaryRepository.getAttendanceSummary(student, semester, -1, true).ignoreElement() - } -} - 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 deleted file mode 100644 index 063b74825..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/AttendanceWork.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.reactivex.Completable -import org.threeten.bp.LocalDate.now -import javax.inject.Inject - -class AttendanceWork @Inject constructor(private val attendanceRepository: AttendanceRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return attendanceRepository.getAttendance(student, semester, now().monday, now().sunday, true) - .ignoreElement() - } -} 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 deleted file mode 100644 index 26f79a0d5..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/CompletedLessonWork.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.reactivex.Completable -import org.threeten.bp.LocalDate.now -import javax.inject.Inject - -class CompletedLessonWork @Inject constructor( - private val completedLessonsRepository: CompletedLessonsRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return completedLessonsRepository.getCompletedLessons(student, semester, now().monday, now().sunday, true) - .ignoreElement() - } -} - 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 deleted file mode 100644 index 1ef97f59c..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/ExamWork.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.exam.ExamRepository -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.reactivex.Completable -import org.threeten.bp.LocalDate.now -import javax.inject.Inject - -class ExamWork @Inject constructor(private val examRepository: ExamRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return examRepository.getExams(student, semester, now().monday, now().sunday, true).ignoreElement() - } -} 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 deleted file mode 100644 index c4681fb8f..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository -import io.reactivex.Completable -import javax.inject.Inject - -class GradeStatisticsWork @Inject constructor(private val gradeStatisticsRepository: GradeStatisticsRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return gradeStatisticsRepository.getGradesStatistics(student, semester, "Wszystkie", false, forceRefresh = true) - .ignoreElement() - } -} - 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 deleted file mode 100644 index fcdaad6e6..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeWork.kt +++ /dev/null @@ -1,97 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.Context -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.DEFAULT_ALL -import androidx.core.app.NotificationCompat.PRIORITY_HIGH -import androidx.core.app.NotificationManagerCompat -import io.github.wulkanowy.R -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.services.sync.channels.NewGradesChannel -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.getCompatColor -import io.reactivex.Completable -import javax.inject.Inject -import kotlin.random.Random - -class GradeWork @Inject constructor( - private val context: Context, - private val notificationManager: NotificationManagerCompat, - private val gradeRepository: GradeRepository, - private val preferencesRepository: PreferencesRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable) - .ignoreElement() - .concatWith(Completable.concatArray(gradeRepository.getNotNotifiedGrades(semester).flatMapCompletable { - if (it.isNotEmpty()) notifyDetails(it) - gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true }) - }, gradeRepository.getNotNotifiedPredictedGrades(semester).flatMapCompletable { - if (it.isNotEmpty()) notifyPredicted(it) - gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isPredictedGradeNotified = true }) - }, gradeRepository.getNotNotifiedFinalGrades(semester).flatMapCompletable { - if (it.isNotEmpty()) notifyFinal(it) - gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isFinalGradeNotified = true }) - })) - } - - private fun getNotificationBuilder(): NotificationCompat.Builder { - return NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID) - .setSmallIcon(R.drawable.ic_stat_grade) - .setAutoCancel(true) - .setPriority(PRIORITY_HIGH) - .setDefaults(DEFAULT_ALL) - .setColor(context.getCompatColor(R.color.colorPrimary)) - .setContentIntent( - PendingIntent.getActivity(context, MainView.Section.GRADE.id, - MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT)) - } - - private fun notifyDetails(grades: List) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder() - .setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size)) - .setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size)) - .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size)) - grades.forEach { addLine("${it.subject}: ${it.entry}") } - this - }) - .build() - ) - } - - private fun notifyPredicted(gradesSummary: List) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder() - .setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_predicted, gradesSummary.size, gradesSummary.size)) - .setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_predicted, gradesSummary.size, gradesSummary.size)) - .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size)) - gradesSummary.forEach { addLine("${it.subject}: ${it.predictedGrade}") } - this - }) - .build() - ) - } - - private fun notifyFinal(gradesSummary: List) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder() - .setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_final, gradesSummary.size, gradesSummary.size)) - .setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_final, gradesSummary.size, gradesSummary.size)) - .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size)) - gradesSummary.forEach { addLine("${it.subject}: ${it.finalGrade}") } - this - }) - .build() - ) - } -} 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 deleted file mode 100644 index 186d57b03..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/HomeworkWork.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.homework.HomeworkRepository -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.reactivex.Completable -import org.threeten.bp.LocalDate.now -import javax.inject.Inject - -class HomeworkWork @Inject constructor(private val homeworkRepository: HomeworkRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return homeworkRepository.getHomework(student, semester, now().monday, now().sunday, true).ignoreElement() - } -} 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 deleted file mode 100644 index f19af4df6..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/LuckyNumberWork.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.Context -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.DEFAULT_ALL -import androidx.core.app.NotificationCompat.PRIORITY_HIGH -import androidx.core.app.NotificationManagerCompat -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.services.sync.channels.LuckyNumberChannel -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.getCompatColor -import io.reactivex.Completable -import javax.inject.Inject -import kotlin.random.Random - -class LuckyNumberWork @Inject constructor( - private val context: Context, - private val notificationManager: NotificationManagerCompat, - private val luckyNumberRepository: LuckyNumberRepository, - private val preferencesRepository: PreferencesRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable) - .flatMap { luckyNumberRepository.getNotNotifiedLuckyNumber(student) } - .flatMapCompletable { - notify(it) - luckyNumberRepository.updateLuckyNumber(it.apply { isNotified = true }) - } - } - - private fun notify(luckyNumber: LuckyNumber) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, LuckyNumberChannel.CHANNEL_ID) - .setContentTitle(context.getString(R.string.lucky_number_notify_new_item_title)) - .setContentText(context.getString(R.string.lucky_number_notify_new_item, luckyNumber.luckyNumber)) - .setSmallIcon(R.drawable.ic_stat_luckynumber) - .setAutoCancel(true) - .setDefaults(DEFAULT_ALL) - .setPriority(PRIORITY_HIGH) - .setColor(context.getCompatColor(R.color.colorPrimary)) - .setContentIntent( - PendingIntent.getActivity(context, MainView.Section.MESSAGE.id, - MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT)) - .build()) - } -} 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 deleted file mode 100644 index b8773dbca..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.Context -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.DEFAULT_ALL -import androidx.core.app.NotificationCompat.PRIORITY_HIGH -import androidx.core.app.NotificationManagerCompat -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.services.sync.channels.NewMessagesChannel -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.getCompatColor -import io.reactivex.Completable -import javax.inject.Inject -import kotlin.random.Random - -class MessageWork @Inject constructor( - private val context: Context, - private val notificationManager: NotificationManagerCompat, - private val messageRepository: MessageRepository, - private val preferencesRepository: PreferencesRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return messageRepository.getMessages(student, semester, RECEIVED, true, preferencesRepository.isNotificationsEnable) - .flatMap { messageRepository.getNotNotifiedMessages(student) } - .flatMapCompletable { - if (it.isNotEmpty()) notify(it) - messageRepository.updateMessages(it.onEach { message -> message.isNotified = true }) - } - } - - private fun notify(messages: List) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewMessagesChannel.CHANNEL_ID) - .setContentTitle(context.resources.getQuantityString(R.plurals.message_new_items, messages.size, messages.size)) - .setContentText(context.resources.getQuantityString(R.plurals.message_notify_new_items, messages.size, messages.size)) - .setSmallIcon(R.drawable.ic_stat_message) - .setAutoCancel(true) - .setDefaults(DEFAULT_ALL) - .setPriority(PRIORITY_HIGH) - .setColor(context.getCompatColor(R.color.colorPrimary)) - .setContentIntent( - PendingIntent.getActivity(context, MainView.Section.MESSAGE.id, - MainActivity.getStartIntent(context, MainView.Section.MESSAGE, true), FLAG_UPDATE_CURRENT) - ) - .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.message_number_item, messages.size, messages.size)) - messages.forEach { addLine("${it.sender}: ${it.subject}") } - this - }) - .build()) - } -} 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 deleted file mode 100644 index 4fc92ffcc..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/NoteWork.kt +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.content.Context -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.DEFAULT_ALL -import androidx.core.app.NotificationCompat.PRIORITY_HIGH -import androidx.core.app.NotificationManagerCompat -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.services.sync.channels.NewNotesChannel -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.getCompatColor -import io.reactivex.Completable -import javax.inject.Inject -import kotlin.random.Random - -class NoteWork @Inject constructor( - private val context: Context, - private val notificationManager: NotificationManagerCompat, - private val noteRepository: NoteRepository, - private val preferencesRepository: PreferencesRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return noteRepository.getNotes(student, semester, true, preferencesRepository.isNotificationsEnable) - .flatMap { noteRepository.getNotNotifiedNotes(student) } - .flatMapCompletable { - if (it.isNotEmpty()) notify(it) - noteRepository.updateNotes(it.onEach { note -> note.isNotified = true }) - } - } - - private fun notify(notes: List) { - notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewNotesChannel.CHANNEL_ID) - .setContentTitle(context.resources.getQuantityString(R.plurals.note_new_items, notes.size, notes.size)) - .setContentText(context.resources.getQuantityString(R.plurals.note_notify_new_items, notes.size, notes.size)) - .setSmallIcon(R.drawable.ic_stat_note) - .setAutoCancel(true) - .setDefaults(DEFAULT_ALL) - .setPriority(PRIORITY_HIGH) - .setColor(context.getCompatColor(R.color.colorPrimary)) - .setContentIntent( - PendingIntent.getActivity(context, MainView.Section.NOTE.id, - MainActivity.getStartIntent(context, MainView.Section.NOTE, true), FLAG_UPDATE_CURRENT)) - .setStyle(NotificationCompat.InboxStyle().run { - setSummaryText(context.resources.getQuantityString(R.plurals.note_number_item, notes.size, notes.size)) - notes.forEach { addLine("${it.teacher}: ${it.category}") } - this - }) - .build()) - } -} - 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 deleted file mode 100644 index fa610dee4..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.recipient.RecipientRepository -import io.github.wulkanowy.data.repositories.reportingunit.ReportingUnitRepository -import io.reactivex.Completable -import javax.inject.Inject - -class RecipientWork @Inject constructor( - private val reportingUnitRepository: ReportingUnitRepository, - private val recipientRepository: RecipientRepository -) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return reportingUnitRepository.getReportingUnits(student, true) - .flatMapCompletable { units -> - Completable.mergeDelayError(units.map { - recipientRepository.getRecipients(student, 2, it, true).ignoreElement() - }) - } - } -} - 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 deleted file mode 100644 index 5a7a41d8d..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TeacherWork.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.teacher.TeacherRepository -import io.reactivex.Completable -import javax.inject.Inject - -class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return teacherRepository.getTeachers(student, semester, true).ignoreElement() - } -} 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 deleted file mode 100644 index d79d24033..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/TimetableWork.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.timetable.TimetableRepository -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.monday -import io.reactivex.Completable -import org.threeten.bp.LocalDate.now -import javax.inject.Inject - -class TimetableWork @Inject constructor(private val timetableRepository: TimetableRepository) : Work { - - override fun create(student: Student, semester: Semester): Completable { - return timetableRepository.getTimetable(student, semester, now().monday, now().sunday, true) - .ignoreElement() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/Work.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/Work.kt deleted file mode 100644 index 1601a103b..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/Work.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.services.sync.works - -import io.github.wulkanowy.data.db.entities.Semester -import io.github.wulkanowy.data.db.entities.Student -import io.reactivex.Completable - -interface Work { - - fun create(student: Student, semester: Semester): Completable -} - 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 deleted file mode 100644 index e5ccf963c..000000000 --- a/app/src/main/java/io/github/wulkanowy/services/widgets/TimetableWidgetService.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.services.widgets - -import android.content.Intent -import android.widget.RemoteViewsService -import dagger.android.AndroidInjection -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.ui.modules.timetablewidget.TimetableWidgetFactory -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Inject - -class TimetableWidgetService : RemoteViewsService() { - - @Inject - lateinit var timetableRepo: TimetableRepository - - @Inject - lateinit var studentRepo: StudentRepository - - @Inject - lateinit var semesterRepo: SemesterRepository - - @Inject - lateinit var prefRepository: PreferencesRepository - - @Inject - lateinit var sharedPref: SharedPrefProvider - - @Inject - lateinit var schedulers: SchedulersProvider - - override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory { - AndroidInjection.inject(this) - return TimetableWidgetFactory(timetableRepo, studentRepo, semesterRepo, prefRepository, sharedPref, schedulers, applicationContext, intent) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.java b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.java new file mode 100644 index 000000000..c5c66df0c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.java @@ -0,0 +1,70 @@ +package io.github.wulkanowy.ui.base; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.app.AppCompatDelegate; +import android.widget.Toast; + +import butterknife.Unbinder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.WulkanowyApp; +import io.github.wulkanowy.di.component.ActivityComponent; +import io.github.wulkanowy.di.component.DaggerActivityComponent; +import io.github.wulkanowy.di.modules.ActivityModule; +import io.github.wulkanowy.utils.NetworkUtils; + +public abstract class BaseActivity extends AppCompatActivity implements BaseContract.View { + + private ActivityComponent activityComponent; + + private Unbinder unbinder; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); + + activityComponent = DaggerActivityComponent.builder() + .activityModule(new ActivityModule(this)) + .applicationComponent(((WulkanowyApp) getApplication()).getApplicationComponent()) + .build(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (unbinder != null) { + unbinder.unbind(); + } + } + + @Override + public void onError(int resId) { + onError(getString(resId)); + } + + @Override + public void onError(String message) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onNoNetworkError() { + onError(R.string.noInternet_text); + } + + @Override + public boolean isNetworkConnected() { + return NetworkUtils.isOnline(getApplicationContext()); + } + + public ActivityComponent getActivityComponent() { + return activityComponent; + } + + public void setButterKnife(Unbinder unbinder) { + this.unbinder = unbinder; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt deleted file mode 100644 index f20fb22f3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt +++ /dev/null @@ -1,96 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.app.ActivityManager -import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.LOLLIPOP -import android.os.Bundle -import android.view.View -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate -import androidx.viewbinding.ViewBinding -import com.google.android.material.snackbar.Snackbar -import com.google.android.material.snackbar.Snackbar.LENGTH_LONG -import dagger.android.AndroidInjection -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import io.github.wulkanowy.R -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.utils.FragmentLifecycleLogger -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.lifecycleAwareVariable -import javax.inject.Inject - -abstract class BaseActivity, VB : ViewBinding> : - AppCompatActivity(), BaseView, HasAndroidInjector { - - protected var binding: VB by lifecycleAwareVariable() - - @Inject - lateinit var androidInjector: DispatchingAndroidInjector - - @Inject - lateinit var fragmentLifecycleLogger: FragmentLifecycleLogger - - @Inject - lateinit var themeManager: ThemeManager - - protected var messageContainer: View? = null - - abstract var presenter: T - - public override fun onCreate(savedInstanceState: Bundle?) { - AndroidInjection.inject(this) - themeManager.applyActivityTheme(this) - super.onCreate(savedInstanceState) - supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true) - AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - - if (SDK_INT >= LOLLIPOP) { - @Suppress("DEPRECATION") - setTaskDescription(ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface))) - } - } - - override fun showError(text: String, error: Throwable) { - if (messageContainer != null) { - Snackbar.make(messageContainer!!, text, LENGTH_LONG) - .setAction(R.string.all_details) { showErrorDetailsDialog(error) } - .show() - } else showMessage(text) - } - - override fun showErrorDetailsDialog(error: Throwable) { - ErrorDialog.newInstance(error).show(supportFragmentManager, error.toString()) - } - - override fun showMessage(text: String) { - if (messageContainer != null) Snackbar.make(messageContainer!!, text, LENGTH_LONG).show() - else Toast.makeText(this, text, Toast.LENGTH_LONG).show() - } - - override fun showExpiredDialog() { - AlertDialog.Builder(this) - .setTitle(R.string.main_session_expired) - .setMessage(R.string.main_session_relogin) - .setPositiveButton(R.string.main_log_in) { _, _ -> presenter.onExpiredLoginSelected() } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - - override fun openClearLoginView() { - startActivity(LoginActivity.getStartIntent(this) - .apply { addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK) }) - } - - override fun onDestroy() { - super.onDestroy() - invalidateOptionsMenu() - presenter.onDetachView() - } - - override fun androidInjector() = androidInjector -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseContract.java b/app/src/main/java/io/github/wulkanowy/ui/base/BaseContract.java new file mode 100644 index 000000000..2a4dc5696 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseContract.java @@ -0,0 +1,27 @@ +package io.github.wulkanowy.ui.base; + +import android.support.annotation.StringRes; + +import io.github.wulkanowy.di.annotations.PerActivity; + +public interface BaseContract { + + interface View { + + void onError(@StringRes int resId); + + void onError(String message); + + void onNoNetworkError(); + + boolean isNetworkConnected(); + } + + @PerActivity + interface Presenter { + + void onStart(V view); + + void onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt deleted file mode 100644 index 0279dccf4..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.widget.Toast -import androidx.viewbinding.ViewBinding -import dagger.android.support.DaggerAppCompatDialogFragment -import io.github.wulkanowy.utils.lifecycleAwareVariable - -abstract class BaseDialogFragment : DaggerAppCompatDialogFragment(), BaseView { - - protected var binding: VB by lifecycleAwareVariable() - - override fun showError(text: String, error: Throwable) { - showMessage(text) - } - - override fun showMessage(text: String) { - Toast.makeText(context, text, Toast.LENGTH_LONG).show() - } - - override fun showExpiredDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredDialog() - } - - override fun openClearLoginView() { - (activity as? BaseActivity<*, *>)?.openClearLoginView() - } - - override fun showErrorDetailsDialog(error: Throwable) { - ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseExpandableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseExpandableAdapter.kt deleted file mode 100644 index eee4625c9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseExpandableAdapter.kt +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.util.DisplayMetrics -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.LinearSmoothScroller -import androidx.recyclerview.widget.RecyclerView -import kotlin.math.max -import kotlin.math.min - -abstract class BaseExpandableAdapter : RecyclerView.Adapter() { - - companion object { - private const val MILLISECONDS_PER_INCH = 100f - private const val AUTO_SCROLL_DELAY = 150L - } - - private var recyclerView: RecyclerView? = null - - override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { - super.onAttachedToRecyclerView(recyclerView) - this.recyclerView = recyclerView - } - - override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { - super.onDetachedFromRecyclerView(recyclerView) - this.recyclerView = null - } - - // original: https://github.com/davideas/FlexibleAdapter/blob/5.1.0/flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java#L4984-L5011 - protected fun scrollToHeaderWithSubItems(position: Int, subItemsCount: Int) { - val layoutManager = recyclerView!!.layoutManager as LinearLayoutManager - val firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition() - val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition() - val itemsToShow = position + subItemsCount - lastVisibleItem - if (itemsToShow > 0) { - val scrollMax: Int = position - firstVisibleItem - val scrollMin = max(0, position + subItemsCount - lastVisibleItem) - val scrollBy = min(scrollMax, scrollMin) - val scrollTo = firstVisibleItem + scrollBy - scrollToPosition(scrollTo) - } else if (position < firstVisibleItem) { - scrollToPosition(position) - } - } - - private fun scrollToPosition(position: Int) { - recyclerView?.run { - postDelayed({ - layoutManager?.startSmoothScroll(object : LinearSmoothScroller(context) { - override fun getVerticalSnapPreference() = SNAP_TO_START - override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics) = MILLISECONDS_PER_INCH / displayMetrics.densityDpi - }.apply { - targetPosition = position - }) - }, AUTO_SCROLL_DELAY) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.java b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.java new file mode 100644 index 000000000..efb9d61a9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.java @@ -0,0 +1,104 @@ +package io.github.wulkanowy.ui.base; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.View; + +import butterknife.Unbinder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.WulkanowyApp; +import io.github.wulkanowy.di.component.DaggerFragmentComponent; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.di.modules.FragmentModule; + +public abstract class BaseFragment extends Fragment implements BaseContract.View { + + private BaseActivity activity; + + private Unbinder unbinder; + + private FragmentComponent fragmentComponent; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof BaseActivity) { + activity = (BaseActivity) context; + } + + fragmentComponent = DaggerFragmentComponent.builder() + .fragmentModule(new FragmentModule(this)) + .applicationComponent(((WulkanowyApp) activity.getApplication()).getApplicationComponent()) + .build(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setUpOnViewCreated(view); + } + + @Override + public void onDetach() { + activity = null; + super.onDetach(); + } + + @Override + public void onDestroyView() { + if (unbinder != null) { + unbinder.unbind(); + } + super.onDestroyView(); + } + + @Override + public void onError(int resId) { + onError(getString(resId)); + } + + @Override + public void onError(String message) { + if (activity != null) { + activity.onError(message); + } + } + + @Override + public void onNoNetworkError() { + onError(R.string.noInternet_text); + } + + @Override + public boolean isNetworkConnected() { + return activity != null && activity.isNetworkConnected(); + } + + public void setButterKnife(Unbinder unbinder) { + this.unbinder = unbinder; + } + + public void setTitle(String title) { + if (activity != null) { + activity.setTitle(title); + } + } + + public FragmentComponent getFragmentComponent() { + return fragmentComponent; + } + + + protected void setUpOnViewCreated(View fragmentView) { + // do something on view created + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt deleted file mode 100644 index 83f787654..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.view.View -import androidx.annotation.LayoutRes -import androidx.viewbinding.ViewBinding -import com.google.android.material.snackbar.Snackbar -import com.google.android.material.snackbar.Snackbar.LENGTH_LONG -import dagger.android.support.DaggerFragment -import io.github.wulkanowy.R -import io.github.wulkanowy.utils.lifecycleAwareVariable - -abstract class BaseFragment(@LayoutRes layoutId: Int) : DaggerFragment(layoutId), - BaseView { - - protected var binding: VB by lifecycleAwareVariable() - - protected var messageContainer: View? = null - - override fun showError(text: String, error: Throwable) { - if (messageContainer != null) { - Snackbar.make(messageContainer!!, text, LENGTH_LONG) - .setAction(R.string.all_details) { if (isAdded) showErrorDetailsDialog(error) } - .show() - } else { - (activity as? BaseActivity<*, *>)?.showError(text, error) - } - } - - override fun showErrorDetailsDialog(error: Throwable) { - ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) - } - - override fun showMessage(text: String) { - if (messageContainer != null) { - Snackbar.make(messageContainer!!, text, LENGTH_LONG).show() - } else { - (activity as? BaseActivity<*, *>)?.showMessage(text) - } - } - - override fun showExpiredDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredDialog() - } - - override fun openClearLoginView() { - (activity as? BaseActivity<*, *>)?.openClearLoginView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragmentPagerAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragmentPagerAdapter.kt deleted file mode 100644 index 5f8bf4178..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragmentPagerAdapter.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.ui.base - -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.FragmentPagerAdapter - -class BaseFragmentPagerAdapter(private val fragmentManager: FragmentManager) : - FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - - private val pages = mutableMapOf() - - var containerId = 0 - - fun getFragmentInstance(position: Int): Fragment? { - require(containerId != 0) { "Container id is 0" } - return fragmentManager.findFragmentByTag("android:switcher:$containerId:$position") - } - - fun addFragments(fragments: List) { - fragments.forEach { pages[it] = null } - } - - fun addFragmentsWithTitle(pages: Map) { - this.pages.putAll(pages) - } - - override fun getItem(position: Int) = pages.keys.elementAt(position) - - override fun getCount() = pages.size - - override fun getPageTitle(position: Int) = pages.values.elementAt(position) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.java new file mode 100644 index 000000000..dfb60b6fb --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.java @@ -0,0 +1,35 @@ +package io.github.wulkanowy.ui.base; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; + +public class BasePresenter implements BaseContract.Presenter { + + private final RepositoryContract repository; + + private V view; + + @Inject + public BasePresenter(RepositoryContract repository) { + this.repository = repository; + } + + @Override + public void onStart(V view) { + this.view = view; + } + + @Override + public void onDestroy() { + view = null; + } + + public final RepositoryContract getRepository() { + return repository; + } + + public V getView() { + return view; + } +} 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 deleted file mode 100644 index 9f0b4047c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BasePresenter.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.wulkanowy.ui.base - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Completable -import io.reactivex.disposables.CompositeDisposable -import timber.log.Timber - -open class BasePresenter( - protected val errorHandler: ErrorHandler, - protected val studentRepository: StudentRepository, - protected val schedulers: SchedulersProvider -) { - - val disposable = CompositeDisposable() - - var view: T? = null - - open fun onAttachView(view: T) { - this.view = view - errorHandler.apply { - showErrorMessage = view::showError - onSessionExpired = view::showExpiredDialog - onNoCurrentStudent = view::openClearLoginView - } - } - - fun onExpiredLoginSelected() { - Timber.i("Attempt to switch the student after the session expires") - disposable.add(studentRepository.getCurrentStudent(false) - .flatMapCompletable { studentRepository.logoutStudent(it) } - .andThen(studentRepository.getSavedStudents(false)) - .flatMapCompletable { - if (it.isNotEmpty()) { - Timber.i("Switching current student") - studentRepository.switchStudent(it[0]) - } else Completable.complete() - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Switch student result: Open login view") - view?.openClearLoginView() - }, { - Timber.i("Switch student result: An exception occurred") - errorHandler.dispatch(it) - })) - } - - open fun onDetachView() { - view = null - disposable.clear() - errorHandler.clear() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt deleted file mode 100644 index 0f4df92cd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseView.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.ui.base - -interface BaseView { - - fun showError(text: String, error: Throwable) - - fun showMessage(text: String) - - fun showExpiredDialog() - - fun openClearLoginView() - - fun showErrorDetailsDialog(error: Throwable) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt deleted file mode 100644 index 896e4ff1c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt +++ /dev/null @@ -1,119 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.content.ClipData -import android.content.ClipboardManager -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.HorizontalScrollView -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG -import androidx.appcompat.app.AlertDialog -import androidx.core.content.getSystemService -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.DialogErrorBinding -import io.github.wulkanowy.sdk.exception.FeatureDisabledException -import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException -import io.github.wulkanowy.sdk.exception.ServiceUnavailableException -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.getString -import io.github.wulkanowy.utils.openAppInMarket -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import java.io.InterruptedIOException -import java.io.PrintWriter -import java.io.StringWriter -import java.net.SocketTimeoutException -import java.net.UnknownHostException -import javax.inject.Inject - -class ErrorDialog : BaseDialogFragment() { - - private lateinit var error: Throwable - - @Inject - lateinit var appInfo: AppInfo - - companion object { - private const val ARGUMENT_KEY = "Data" - - fun newInstance(error: Throwable): ErrorDialog { - return ErrorDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, error) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - error = getSerializable(ARGUMENT_KEY) as Throwable - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogErrorBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - val stringWriter = StringWriter().apply { - error.printStackTrace(PrintWriter(this)) - } - - with(binding) { - errorDialogContent.text = stringWriter.toString() - with(errorDialogHorizontalScroll) { - post { fullScroll(HorizontalScrollView.FOCUS_LEFT) } - } - errorDialogCopy.setOnClickListener { - val clip = ClipData.newPlainText("wulkanowy", stringWriter.toString()) - activity?.getSystemService()?.setPrimaryClip(clip) - - Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show() - } - errorDialogCancel.setOnClickListener { dismiss() } - errorDialogReport.setOnClickListener { - openConfirmDialog { openEmailClient(stringWriter.toString()) } - } - errorDialogMessage.text = resources.getString(error) - errorDialogReport.isEnabled = when (error) { - is UnknownHostException, - is InterruptedIOException, - is SocketTimeoutException, - is ServiceUnavailableException, - is FeatureDisabledException, - is FeatureNotAvailableException -> false - else -> true - } - } - } - - private fun openConfirmDialog(callback: () -> Unit) { - AlertDialog.Builder(requireContext()) - .setTitle(R.string.dialog_error_check_update) - .setMessage(R.string.dialog_error_check_update_message) - .setNeutralButton(R.string.about_feedback) { _, _ -> callback() } - .setPositiveButton(R.string.dialog_error_check_update) { _, _ -> - requireContext().openAppInMarket(::showMessage) - } - .show() - } - - private fun openEmailClient(content: String) { - requireContext().openEmailClient( - chooserTitle = getString(R.string.about_feedback), - email = "wulkanowyinc@gmail.com", - subject = "Zgłoszenie błędu", - body = requireContext().getString(R.string.about_feedback_template, - "${appInfo.systemManufacturer} ${appInfo.systemModel}", appInfo.systemVersion.toString(), appInfo.versionName - ) + "\n" + content, - onActivityNotFound = { - requireContext().openInternetBrowser("https://github.com/wulkanowy/wulkanowy/issues", ::showMessage) - } - ) - } -} 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 deleted file mode 100644 index f746b36f8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorHandler.kt +++ /dev/null @@ -1,39 +0,0 @@ -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.exception.BadCredentialsException -import io.github.wulkanowy.utils.getString -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) { - - var showErrorMessage: (String, Throwable) -> Unit = { _, _ -> } - - var onSessionExpired: () -> Unit = {} - - 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) - } - - protected open fun proceed(error: Throwable) { - when (error) { - is ScramblerException, is BadCredentialsException -> onSessionExpired() - is NoCurrentStudentException -> onNoCurrentStudent() - else -> showErrorMessage(resources.getString(error), error) - } - } - - open fun clear() { - showErrorMessage = { _, _ -> } - onSessionExpired = {} - onNoCurrentStudent = {} - } -} 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 deleted file mode 100644 index 501348612..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.content.pm.PackageManager.GET_ACTIVITIES -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate -import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO -import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES -import io.github.wulkanowy.R -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ThemeManager @Inject constructor(private val preferencesRepository: PreferencesRepository) { - - fun applyActivityTheme(activity: AppCompatActivity) { - if (isThemeApplicable(activity)) { - applyDefaultTheme() - if (preferencesRepository.appTheme == "black") activity.setTheme(R.style.WulkanowyTheme_Black) - } - } - - fun applyDefaultTheme() { - AppCompatDelegate.setDefaultNightMode( - when (val theme = preferencesRepository.appTheme) { - "light" -> MODE_NIGHT_NO - "dark", "black" -> MODE_NIGHT_YES - "system" -> MODE_NIGHT_FOLLOW_SYSTEM - else -> throw IllegalArgumentException("Wrong theme: $theme") - } - ) - } - - private fun isThemeApplicable(activity: AppCompatActivity): Boolean { - return activity.packageManager.getPackageInfo(activity.packageName, GET_ACTIVITIES) - .activities.singleOrNull { it.name == activity::class.java.canonicalName }?.theme - .let { it == R.style.WulkanowyTheme_Black || it == R.style.WulkanowyTheme_NoActionBar } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt deleted file mode 100644 index cefe6ed75..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt +++ /dev/null @@ -1,46 +0,0 @@ -package io.github.wulkanowy.ui.base - -import android.annotation.SuppressLint -import android.graphics.PorterDuff -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.ItemAccountBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import javax.inject.Inject - -class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList>() - - var onClickListener: (Student) -> Unit = {} - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemAccountBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("SetTextI18n") - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val (student, isCurrent) = items[position] - - with(holder.binding) { - accountItemName.text = "${student.studentName} ${student.className}" - accountItemSchool.text = student.schoolName - - with(accountItemImage) { - val colorImage = if (isCurrent) context.getThemeAttrColor(R.attr.colorPrimary) - else context.getThemeAttrColor(R.attr.colorOnSurface, 153) - - setColorFilter(colorImage, PorterDuff.Mode.SRC_IN) - } - - root.setOnClickListener { onClickListener(student) } - } - } - - class ItemViewHolder(val binding: ItemAccountBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/login/LoginActivity.java b/app/src/main/java/io/github/wulkanowy/ui/login/LoginActivity.java new file mode 100644 index 000000000..95c5548b2 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/login/LoginActivity.java @@ -0,0 +1,221 @@ +package io.github.wulkanowy.ui.login; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.support.design.widget.TextInputLayout; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.TextView; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.OnEditorAction; +import io.github.wulkanowy.R; +import io.github.wulkanowy.ui.base.BaseActivity; +import io.github.wulkanowy.ui.main.MainActivity; +import io.github.wulkanowy.utils.AppConstant; +import io.github.wulkanowy.utils.CommonUtils; +import io.github.wulkanowy.utils.KeyboardUtils; + +public class LoginActivity extends BaseActivity implements LoginContract.View { + + @BindView(R.id.login_activity_email_edit) + EditText emailView; + + @BindView(R.id.login_activity_pass_edit) + EditText passwordView; + + @BindView(R.id.login_activity_symbol_edit) + AutoCompleteTextView symbolView; + + @BindView(R.id.login_activity_form_scroll) + View loginFormView; + + @BindView(R.id.login_activity_progress_container) + View loadingBarView; + + @BindView(R.id.login_activity_progress_text) + TextView loginProgressText; + + @BindView(R.id.login_activity_symbol_text_input) + TextInputLayout symbolLayout; + + @Inject + LoginContract.Presenter presenter; + + private EditText requestedView; + + public static Intent getStartIntent(Context context) { + return new Intent(context, LoginActivity.class); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + setButterKnife(ButterKnife.bind(this)); + getActivityComponent().inject(this); + + presenter.onStart(this); + + setUpOnCreate(); + + } + + protected void setUpOnCreate() { + symbolView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + getResources().getStringArray(R.array.symbols))); + } + + @OnClick(R.id.login_activity_sign_button) + void onLoginButtonClick() { + presenter.attemptLogin( + emailView.getText().toString(), + passwordView.getText().toString(), + symbolView.getText().toString()); + } + + @OnEditorAction(value = {R.id.login_activity_symbol_edit, R.id.login_activity_pass_edit}) + boolean onEditorAction(int id) { + if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) { + onLoginButtonClick(); + return true; + } + return false; + } + + @OnClick(R.id.login_activity_create_text) + void onCreateAccountButtonClick() { + CommonUtils.openInternalBrowserViewer(this, AppConstant.VULCAN_CREATE_ACCOUNT_URL); + } + + @OnClick(R.id.login_activity_forgot_text) + void onForgotPasswordButtonClick() { + CommonUtils.openInternalBrowserViewer(this, AppConstant.VULCAN_FORGOT_PASS_URL); + } + + @Override + public void setErrorEmailRequired() { + emailView.requestFocus(); + emailView.setError(getString(R.string.error_field_required)); + requestedView = emailView; + } + + @Override + public void setErrorEmailInvalid() { + emailView.requestFocus(); + emailView.setError(getString(R.string.error_invalid_email)); + requestedView = emailView; + } + + @Override + public void setErrorPassRequired() { + passwordView.requestFocus(); + passwordView.setError(getString(R.string.error_field_required)); + requestedView = passwordView; + } + + @Override + public void setErrorPassInvalid() { + passwordView.requestFocus(); + passwordView.setError(getString(R.string.error_invalid_password)); + requestedView = passwordView; + } + + @Override + public void setErrorPassIncorrect() { + passwordView.requestFocus(); + passwordView.setError(getString(R.string.error_incorrect_password)); + requestedView = passwordView; + } + + @Override + public void setErrorSymbolRequired() { + symbolLayout.setVisibility(View.VISIBLE); + symbolView.setError(getString(R.string.error_bad_account_permission)); + symbolView.requestFocus(); + requestedView = symbolView; + } + + @Override + public void resetViewErrors() { + emailView.setError(null); + passwordView.setError(null); + } + + @Override + public void showSoftInput() { + KeyboardUtils.showSoftInput(requestedView, this); + } + + @Override + public void hideSoftInput() { + KeyboardUtils.hideSoftInput(this); + } + + @Override + public void onError(String message) { + Snackbar.make(findViewById(R.id.login_activity_container), message, + Snackbar.LENGTH_LONG).show(); + } + + @Override + public void setStepOneLoginProgress() { + onLoginProgressUpdate("1", getString(R.string.step_login)); + } + + @Override + public void setStepTwoLoginProgress() { + onLoginProgressUpdate("2", getString(R.string.step_synchronization)); + } + + @Override + public void openMainActivity() { + startActivity(MainActivity.getStartIntent(this)); + finish(); + } + + @Override + public void showLoginProgress(final boolean show) { + int animTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + loginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + loginFormView.animate().setDuration(animTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + loginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE); + loadingBarView.animate().setDuration(animTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } + + @Override + public void onDestroy() { + super.onDestroy(); + presenter.onDestroy(); + } + + private void onLoginProgressUpdate(String step, String message) { + loginProgressText.setText(String.format("%1$s/2 - %2$s...", step, message)); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/login/LoginContract.java b/app/src/main/java/io/github/wulkanowy/ui/login/LoginContract.java new file mode 100644 index 000000000..fa074896c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/login/LoginContract.java @@ -0,0 +1,53 @@ +package io.github.wulkanowy.ui.login; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; + +public interface LoginContract { + interface View extends BaseContract.View { + + void setErrorEmailRequired(); + + void setErrorPassRequired(); + + void setErrorSymbolRequired(); + + void setErrorEmailInvalid(); + + void setErrorPassInvalid(); + + void setErrorPassIncorrect(); + + void resetViewErrors(); + + void setStepOneLoginProgress(); + + void setStepTwoLoginProgress(); + + void openMainActivity(); + + void showLoginProgress(boolean show); + + void showSoftInput(); + + void hideSoftInput(); + + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + + void attemptLogin(String email, String password, String symbol); + + void onStartAsync(); + + void onLoginProgress(int step); + + void onEndAsync(boolean success, Exception exception); + + void onCanceledAsync(); + + RepositoryContract getRepository(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/login/LoginPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/login/LoginPresenter.java new file mode 100644 index 000000000..c8e847258 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/login/LoginPresenter.java @@ -0,0 +1,143 @@ +package io.github.wulkanowy.ui.login; + +import android.text.TextUtils; + +import java.util.LinkedHashMap; + +import javax.inject.Inject; + +import io.github.wulkanowy.api.login.AccountPermissionException; +import io.github.wulkanowy.api.login.BadCredentialsException; +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.utils.AppConstant; + +public class LoginPresenter extends BasePresenter + implements LoginContract.Presenter { + + private LoginTask loginAsync; + + @Inject + LoginPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (loginAsync != null) { + loginAsync.cancel(true); + loginAsync = null; + } + } + + @Override + public void attemptLogin(String email, String password, String symbol) { + getView().resetViewErrors(); + + if (!isAllFieldCorrect(password, email)) { + getView().showSoftInput(); + return; + } + + if (getView().isNetworkConnected()) { + // Dopóki używamy AsyncTask presenter będzie musiał "wiedzieć" o AsyncTaskach + loginAsync = new LoginTask(this, + email, + password, + getNormalizedSymbol(symbol)); + loginAsync.execute(); + + } else { + getView().onNoNetworkError(); + } + + getView().hideSoftInput(); + } + + @Override + public void onStartAsync() { + getView().showLoginProgress(true); + } + + @Override + public void onLoginProgress(int step) { + if (step == 1) { + getView().setStepOneLoginProgress(); + } else if (step == 2) { + getView().setStepTwoLoginProgress(); + } + } + + @Override + public void onEndAsync(boolean success, Exception exception) { + if (success) { + getView().openMainActivity(); + } else if (exception instanceof BadCredentialsException) { + getView().setErrorPassIncorrect(); + getView().showSoftInput(); + getView().showLoginProgress(false); + } else if (exception instanceof AccountPermissionException) { + getView().setErrorSymbolRequired(); + getView().showSoftInput(); + getView().showLoginProgress(false); + } else { + getView().onError(getRepository().getErrorLoginMessage(exception)); + getView().showLoginProgress(false); + } + + } + + @Override + public void onCanceledAsync() { + getView().showLoginProgress(false); + } + + private boolean isEmailValid(String email) { + return email.contains("@") || email.contains("\\\\"); + } + + private boolean isPasswordValid(String password) { + return password.length() > 4; + } + + private String getNormalizedSymbol(String symbol) { + if (TextUtils.isEmpty(symbol)) { + return AppConstant.DEFAULT_SYMBOL; + } + + String[] keys = getRepository().getSymbolsKeysArray(); + String[] values = getRepository().getSymbolsValuesArray(); + LinkedHashMap map = new LinkedHashMap<>(); + + for (int i = 0; i < Math.min(keys.length, values.length); ++i) { + map.put(keys[i], values[i]); + } + + if (map.containsKey(symbol)) { + return map.get(symbol); + } + return AppConstant.DEFAULT_SYMBOL; + } + + private boolean isAllFieldCorrect(String password, String email) { + boolean correct = true; + + if (TextUtils.isEmpty(password)) { + getView().setErrorPassRequired(); + correct = false; + } else if (!isPasswordValid(password)) { + getView().setErrorPassInvalid(); + correct = false; + } + + if (TextUtils.isEmpty(email)) { + getView().setErrorEmailRequired(); + correct = false; + } else if (!isEmailValid(email)) { + getView().setErrorEmailInvalid(); + correct = false; + } + return correct; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/login/LoginTask.java b/app/src/main/java/io/github/wulkanowy/ui/login/LoginTask.java new file mode 100644 index 000000000..441b8d8d8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/login/LoginTask.java @@ -0,0 +1,58 @@ +package io.github.wulkanowy.ui.login; + +import android.os.AsyncTask; + +public class LoginTask extends AsyncTask { + + private String email; + + private String password; + + private String symbol; + + private LoginContract.Presenter presenter; + + private Exception exception; + + LoginTask(LoginContract.Presenter presenter, String email, String password, String symbol) { + this.presenter = presenter; + this.email = email; + this.password = password; + this.symbol = symbol; + } + + @Override + protected void onPreExecute() { + presenter.onStartAsync(); + } + + @Override + protected Boolean doInBackground(Void... params) { + try { + publishProgress(1); + presenter.getRepository().loginUser(email, password, symbol); + + publishProgress(2); + presenter.getRepository().syncAll(); + } catch (Exception e) { + exception = e; + return false; + } + return true; + } + + @Override + protected void onProgressUpdate(Integer... progress) { + presenter.onLoginProgress(progress[0]); + } + + @Override + protected void onPostExecute(Boolean success) { + presenter.onEndAsync(success, exception); + } + + @Override + protected void onCancelled() { + presenter.onCanceledAsync(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java new file mode 100644 index 000000000..d4c0b9dab --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java @@ -0,0 +1,153 @@ +package io.github.wulkanowy.ui.main; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.view.View; + +import com.aurelhubert.ahbottomnavigation.AHBottomNavigation; +import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem; +import com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.github.wulkanowy.R; +import io.github.wulkanowy.services.SyncJob; +import io.github.wulkanowy.ui.base.BaseActivity; +import io.github.wulkanowy.ui.main.dashboard.DashboardFragment; +import io.github.wulkanowy.ui.main.grades.GradesFragment; +import io.github.wulkanowy.ui.main.timetable.TimetableFragment; + +public class MainActivity extends BaseActivity implements MainContract.View, + AHBottomNavigation.OnTabSelectedListener, OnFragmentIsReadyListener { + + private int initTabPosition = 0; + + @BindView(R.id.main_activity_nav) + AHBottomNavigation bottomNavigation; + + @BindView(R.id.main_activity_view_pager) + AHBottomNavigationViewPager viewPager; + + @BindView(R.id.main_activity_progress_bar) + View progressBar; + + @Inject + MainPagerAdapter pagerAdapter; + + @Inject + MainContract.Presenter presenter; + + public static Intent getStartIntent(Context context) { + return new Intent(context, MainActivity.class); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + initTabPosition = getIntent().getIntExtra(SyncJob.EXTRA_INTENT_KEY, initTabPosition); + + getActivityComponent().inject(this); + setButterKnife(ButterKnife.bind(this)); + + presenter.onStart(this); + + initiationViewPager(); + initiationBottomNav(); + } + + @Override + public void showProgressBar(boolean show) { + progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + viewPager.setVisibility(show ? View.INVISIBLE : View.VISIBLE); + bottomNavigation.setVisibility(show ? View.INVISIBLE : View.VISIBLE); + } + + @Override + public void showActionBar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.show(); + } + } + + @Override + public void hideActionBar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.hide(); + } + } + + @Override + public boolean onTabSelected(int position, boolean wasSelected) { + presenter.onTabSelected(position, wasSelected); + return true; + } + + @Override + public void setCurrentPage(int position) { + viewPager.setCurrentItem(position, false); + } + + @Override + public void onFragmentIsReady() { + presenter.onFragmentIsReady(); + } + + private void initiationBottomNav() { + bottomNavigation.addItem(new AHBottomNavigationItem( + getString(R.string.grades_text), + getResources().getDrawable(R.drawable.ic_menu_grade_26dp) + )); + bottomNavigation.addItem(new AHBottomNavigationItem( + getString(R.string.attendance_text), + getResources().getDrawable(R.drawable.ic_menu_attendance_24dp) + )); + bottomNavigation.addItem(new AHBottomNavigationItem( + getString(R.string.dashboard_text), + getResources().getDrawable(R.drawable.ic_menu_dashboard_24dp) + )); + bottomNavigation.addItem(new AHBottomNavigationItem( + getString(R.string.lessonplan_text), + getResources().getDrawable(R.drawable.ic_menu_timetable_24dp) + )); + bottomNavigation.addItem(new AHBottomNavigationItem( + getString(R.string.settings_text), + getResources().getDrawable(R.drawable.ic_menu_other_24dp) + )); + + bottomNavigation.setAccentColor(getResources().getColor(R.color.colorPrimary)); + bottomNavigation.setInactiveColor(Color.BLACK); + bottomNavigation.setBackgroundColor(getResources().getColor(R.color.colorBackgroundBottomNav)); + bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW); + bottomNavigation.setOnTabSelectedListener(this); + bottomNavigation.setCurrentItem(initTabPosition); + bottomNavigation.setBehaviorTranslationEnabled(false); + } + + private void initiationViewPager() { + pagerAdapter.addFragment(new GradesFragment()); + pagerAdapter.addFragment(new DashboardFragment()); + pagerAdapter.addFragment(new DashboardFragment()); + pagerAdapter.addFragment(new TimetableFragment()); + pagerAdapter.addFragment(new DashboardFragment()); + + viewPager.setPagingEnabled(false); + viewPager.setAdapter(pagerAdapter); + viewPager.setOffscreenPageLimit(4); + viewPager.setCurrentItem(initTabPosition, false); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + presenter.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainContract.java new file mode 100644 index 000000000..cb1d5d7c7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainContract.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.ui.main; + +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; + +public interface MainContract { + + interface View extends BaseContract.View { + + void setCurrentPage(int position); + + void showProgressBar(boolean show); + + void showActionBar(); + + void hideActionBar(); + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + + void onTabSelected(int position, boolean wasSelected); + + void onFragmentIsReady(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java new file mode 100644 index 000000000..fcc51fb54 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java @@ -0,0 +1,31 @@ +package io.github.wulkanowy.ui.main; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; + +import java.util.ArrayList; +import java.util.List; + +public class MainPagerAdapter extends FragmentStatePagerAdapter { + + private List fragmentList = new ArrayList<>(); + + public MainPagerAdapter(FragmentManager fragmentManager) { + super(fragmentManager); + } + + void addFragment(Fragment fragment) { + fragmentList.add(fragment); + } + + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java new file mode 100644 index 000000000..149e49e2f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java @@ -0,0 +1,44 @@ +package io.github.wulkanowy.ui.main; + + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; + +public class MainPresenter extends BasePresenter + implements MainContract.Presenter { + + private int fragmentCount = 0; + + @Inject + MainPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(MainContract.View view) { + super.onStart(view); + getView().showProgressBar(true); + getView().hideActionBar(); + } + + @Override + public void onTabSelected(int position, boolean wasSelected) { + if (!wasSelected) { + getView().setCurrentPage(position); + } + } + + @Override + public void onFragmentIsReady() { + if (fragmentCount < 5) { + fragmentCount++; + } + + if (fragmentCount == 5) { + getView().showActionBar(); + getView().showProgressBar(false); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/OnFragmentIsReadyListener.java b/app/src/main/java/io/github/wulkanowy/ui/main/OnFragmentIsReadyListener.java new file mode 100644 index 000000000..21e3ba12f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/OnFragmentIsReadyListener.java @@ -0,0 +1,6 @@ +package io.github.wulkanowy.ui.main; + +public interface OnFragmentIsReadyListener { + + void onFragmentIsReady(); +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java new file mode 100644 index 000000000..fe4037171 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java @@ -0,0 +1,23 @@ +package io.github.wulkanowy.ui.main.attendance; + +import io.github.wulkanowy.di.annotations.PerFragment; +import io.github.wulkanowy.ui.base.BaseContract; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public interface AttendanceContract { + + interface View extends BaseContract.View { + + void setActivityTitle(); + + boolean isMenuVisible(); + } + + @PerFragment + interface Presenter extends BaseContract.Presenter { + + void onStart(View view, OnFragmentIsReadyListener listener); + + void onFragmentVisible(boolean isVisible); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java new file mode 100644 index 000000000..6010d1085 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java @@ -0,0 +1,59 @@ +package io.github.wulkanowy.ui.main.attendance; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import javax.inject.Inject; + +import butterknife.ButterKnife; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class AttendanceFragment extends BaseFragment implements AttendanceContract.View { + + @Inject + AttendanceContract.Presenter presenter; + + public AttendanceFragment() { + // empty constructor for fragment + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_attendance, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); + } + + return view; + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null) { + presenter.onFragmentVisible(menuVisible); + } + } + + @Override + public void setActivityTitle() { + setTitle(getString(R.string.dashboard_text)); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + presenter.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java new file mode 100644 index 000000000..da43e320f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java @@ -0,0 +1,37 @@ +package io.github.wulkanowy.ui.main.attendance; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class AttendancePresenter extends BasePresenter + implements AttendanceContract.Presenter { + + private OnFragmentIsReadyListener listener; + + @Inject + AttendancePresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(AttendanceContract.View view, OnFragmentIsReadyListener listener) { + super.onStart(view); + this.listener = listener; + + if (getView().isMenuVisible()) { + getView().setActivityTitle(); + } + + this.listener.onFragmentIsReady(); + } + + @Override + public void onFragmentVisible(boolean isVisible) { + if (isVisible) { + getView().setActivityTitle(); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java new file mode 100644 index 000000000..2488eb95c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java @@ -0,0 +1,23 @@ +package io.github.wulkanowy.ui.main.dashboard; + +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public interface DashboardContract { + + interface View extends BaseContract.View { + + void setActivityTitle(); + + boolean isMenuVisible(); + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + + void onStart(View view, OnFragmentIsReadyListener listener); + + void onFragmentVisible(boolean isVisible); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java new file mode 100644 index 000000000..0832b5fb7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java @@ -0,0 +1,48 @@ +package io.github.wulkanowy.ui.main.dashboard; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import javax.inject.Inject; + +import butterknife.ButterKnife; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class DashboardFragment extends BaseFragment implements DashboardContract.View { + + @Inject + DashboardContract.Presenter presenter; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_board, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); + } + return view; + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null) { + presenter.onFragmentVisible(menuVisible); + } + } + + @Override + public void setActivityTitle() { + setTitle(getString(R.string.dashboard_text)); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java new file mode 100644 index 000000000..58d89b399 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java @@ -0,0 +1,37 @@ +package io.github.wulkanowy.ui.main.dashboard; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class DashboardPresenter extends BasePresenter + implements DashboardContract.Presenter { + + private OnFragmentIsReadyListener listener; + + @Inject + DashboardPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(DashboardContract.View view, OnFragmentIsReadyListener listener) { + super.onStart(view); + this.listener = listener; + + if (getView().isMenuVisible()) { + getView().setActivityTitle(); + } + + this.listener.onFragmentIsReady(); + } + + @Override + public void onFragmentVisible(boolean isVisible) { + if (isVisible) { + getView().setActivityTitle(); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradeHeaderItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradeHeaderItem.java new file mode 100644 index 000000000..5edabb7b8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradeHeaderItem.java @@ -0,0 +1,117 @@ +package io.github.wulkanowy.ui.main.grades; + + +import android.content.res.Resources; +import android.view.View; +import android.widget.TextView; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem; +import eu.davidea.viewholders.ExpandableViewHolder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Subject; +import io.github.wulkanowy.utils.AverageCalculator; + +public class GradeHeaderItem + extends AbstractExpandableHeaderItem { + + private Subject subject; + + GradeHeaderItem(Subject subject) { + this.subject = subject; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + GradeHeaderItem that = (GradeHeaderItem) o; + + return new EqualsBuilder() + .append(subject, that.subject) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(subject) + .toHashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.grade_header; + } + + @Override + public HeaderViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new HeaderViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, HeaderViewHolder holder, int position, List payloads) { + holder.onBind(subject, getSubItems()); + } + + static class HeaderViewHolder extends ExpandableViewHolder { + + @BindView(R.id.grade_header_subject_text) + TextView subjectName; + + @BindView(R.id.grade_header_average_text) + TextView averageText; + + @BindView(R.id.grade_header_number_of_grade_text) + TextView numberText; + + @BindView(R.id.grade_header_alert_image) + View alertImage; + + Resources resources; + + HeaderViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + ButterKnife.bind(this, view); + resources = view.getResources(); + view.setOnClickListener(this); + } + + void onBind(Subject item, List subItems) { + subjectName.setText(item.getName()); + numberText.setText(resources.getQuantityString(R.plurals.numberOfGradesPlurals, + subItems.size(), subItems.size())); + averageText.setText(getGradesAverageString(item)); + alertImage.setVisibility(isSubItemsRead(subItems) ? View.INVISIBLE : View.VISIBLE); + alertImage.setTag(item.getName()); + } + + private boolean isSubItemsRead(List subItems) { + boolean isRead = true; + + for (GradesSubItem item : subItems) { + isRead = item.getGrade().getRead(); + } + return isRead; + } + + private String getGradesAverageString(Subject item) { + float average = AverageCalculator.calculate(item.getGradeList()); + + if (average < 0) { + return resources.getString(R.string.info_no_average); + } else { + return resources.getString(R.string.info_average_grades, average); + } + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesContract.java new file mode 100644 index 000000000..7deabb5e7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesContract.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.ui.main.grades; + +import android.support.v4.widget.SwipeRefreshLayout; + +import java.util.List; + +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public interface GradesContract { + + interface View extends BaseContract.View, SwipeRefreshLayout.OnRefreshListener { + + void updateAdapterList(List headerItems); + + void showNoItem(boolean show); + + void onRefreshSuccessNoGrade(); + + void onRefreshSuccess(int number); + + void hideRefreshingBar(); + + void setActivityTitle(); + + boolean isMenuVisible(); + + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + + void onFragmentVisible(boolean isVisible); + + void onRefresh(); + + void onStart(View view, OnFragmentIsReadyListener listener); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesDialogFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesDialogFragment.java new file mode 100644 index 000000000..0d9a699f5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesDialogFragment.java @@ -0,0 +1,116 @@ +package io.github.wulkanowy.ui.main.grades; + + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.utils.CommonUtils; + +public class GradesDialogFragment extends DialogFragment { + + private static final String ARGUMENT_KEY = "Item"; + + private Grade grade; + + @BindView(R.id.grade_dialog_value) + TextView value; + + @BindView(R.id.grade_dialog_subject) + TextView subject; + + @BindView(R.id.grade_dialog_description_value) + TextView description; + + @BindView(R.id.grade_dialog_weight_value) + TextView weight; + + @BindView(R.id.grade_dialog_teacher_value) + TextView teacher; + + @BindView(R.id.grade_dialog_color_value) + TextView color; + + @BindView(R.id.grade_dialog_date_value) + TextView date; + + public GradesDialogFragment() { + //empty constructor for fragment + } + + public static GradesDialogFragment newInstance(Grade item) { + GradesDialogFragment dialogFragment = new GradesDialogFragment(); + + Bundle bundle = new Bundle(); + bundle.putSerializable(ARGUMENT_KEY, item); + + dialogFragment.setArguments(bundle); + + return dialogFragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + grade = (Grade) getArguments().getSerializable(ARGUMENT_KEY); + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.grade_dialog, container, false); + + ButterKnife.bind(this, view); + + subject.setText(grade.getSubject()); + value.setText(grade.getValue()); + value.setBackgroundResource(grade.getValueColor()); + weight.setText(grade.getWeight()); + date.setText(grade.getDate()); + color.setText(CommonUtils.colorHexToColorName(grade.getColor())); + teacher.setText(getTeacherString()); + description.setText(getDescriptionString()); + + + return view; + } + + @OnClick(R.id.grade_dialog_close_button) + void onClickClose() { + dismiss(); + } + + private String getDescriptionString() { + if ("".equals(grade.getDescription())) { + if (!"".equals(grade.getSymbol())) { + return grade.getSymbol(); + } else { + return getString(R.string.noDescription_text); + } + } else if (!"".equals(grade.getSymbol())) { + return String.format("%1$s - %2$s", grade.getSymbol(), grade.getDescription()); + } else { + return grade.getDescription(); + } + } + + private String getTeacherString() { + if (grade.getTeacher() != null && !"".equals(grade.getTeacher())) { + return grade.getTeacher(); + } else { + return getString(R.string.generic_app_no_data); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesFragment.java new file mode 100644 index 000000000..bd44f2983 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesFragment.java @@ -0,0 +1,133 @@ +package io.github.wulkanowy.ui.main.grades; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.List; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class GradesFragment extends BaseFragment implements GradesContract.View { + + @BindView(R.id.grade_fragment_recycler) + RecyclerView recyclerView; + + @BindView(R.id.grade_fragment_no_item_container) + View noItemView; + + @BindView(R.id.grade_fragment_swipe_refresh) + SwipeRefreshLayout refreshLayout; + + @Inject + FlexibleAdapter adapter; + + @Inject + GradesContract.Presenter presenter; + + public GradesFragment() { + // empty constructor for fragment + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_grades, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); + } + + return view; + } + + @Override + protected void setUpOnViewCreated(View fragmentView) { + noItemView.setVisibility(View.GONE); + + adapter.setAutoCollapseOnExpand(true); + adapter.setAutoScrollOnExpand(true); + adapter.expandItemsAtStartUp(); + + recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext())); + recyclerView.setAdapter(adapter); + + refreshLayout.setColorSchemeResources(android.R.color.black); + refreshLayout.setOnRefreshListener(this); + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null) { + presenter.onFragmentVisible(menuVisible); + } + } + + @Override + public void setActivityTitle() { + setTitle(getString(R.string.grades_text)); + } + + @Override + public void onRefresh() { + presenter.onRefresh(); + } + + @Override + public void showNoItem(boolean show) { + noItemView.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public void hideRefreshingBar() { + refreshLayout.setRefreshing(false); + } + + @Override + public void updateAdapterList(List headerItems) { + adapter.updateDataSet(headerItems); + } + + @Override + public void onRefreshSuccessNoGrade() { + onError(R.string.snackbar_no_grades); + } + + @Override + public void onRefreshSuccess(int number) { + onError(getString(R.string.snackbar_new_grade, number)); + } + + @Override + public void onError(String message) { + if (getActivity() != null) { + Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager), + message, Snackbar.LENGTH_LONG).show(); + } + } + + @Override + public void onDestroyView() { + presenter.onDestroy(); + super.onDestroyView(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesPresenter.java new file mode 100644 index 000000000..cae2fbcb6 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesPresenter.java @@ -0,0 +1,157 @@ +package io.github.wulkanowy.ui.main.grades; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.Subject; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; +import io.github.wulkanowy.utils.async.AbstractTask; +import io.github.wulkanowy.utils.async.AsyncListeners; + +public class GradesPresenter extends BasePresenter + implements GradesContract.Presenter, AsyncListeners.OnRefreshListener, + AsyncListeners.OnFirstLoadingListener { + + private AbstractTask refreshTask; + + private AbstractTask loadingTask; + + private OnFragmentIsReadyListener listener; + + private List headerItems = new ArrayList<>(); + + private boolean isFirstSight = false; + + @Inject + GradesPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(GradesContract.View view, OnFragmentIsReadyListener listener) { + super.onStart(view); + this.listener = listener; + + if (getView().isMenuVisible()) { + getView().setActivityTitle(); + } + + if (!isFirstSight) { + isFirstSight = true; + + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + } + } + + @Override + public void onFragmentVisible(boolean isVisible) { + if (isVisible) { + getView().setActivityTitle(); + } + } + + @Override + public void onRefresh() { + if (getView().isNetworkConnected()) { + refreshTask = new AbstractTask(); + refreshTask.setOnRefreshListener(this); + refreshTask.execute(); + } else { + getView().onNoNetworkError(); + getView().hideRefreshingBar(); + } + } + + @Override + public void onDoInBackgroundRefresh() throws Exception { + getRepository().loginCurrentUser(); + getRepository().syncSubjects(); + getRepository().syncGrades(); + } + + @Override + public void onCanceledRefreshAsync() { + getView().hideRefreshingBar(); + } + + @Override + public void onEndRefreshAsync(boolean success, Exception exception) { + if (success) { + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + + int numberOfNewGrades = getRepository().getNewGrades().size(); + + if (numberOfNewGrades <= 0) { + getView().onRefreshSuccessNoGrade(); + } else { + getView().onRefreshSuccess(numberOfNewGrades); + } + } else { + getView().onError(getRepository().getErrorLoginMessage(exception)); + } + getView().hideRefreshingBar(); + } + + @Override + public void onDoInBackgroundLoading() throws Exception { + List subjectList = getRepository().getCurrentUser().getSubjectList(); + + headerItems = new ArrayList<>(); + + for (Subject subject : subjectList) { + List gradeList = subject.getGradeList(); + + if (!gradeList.isEmpty()) { + GradeHeaderItem headerItem = new GradeHeaderItem(subject); + + List subItems = new ArrayList<>(); + + for (Grade grade : gradeList) { + subItems.add(new GradesSubItem(headerItem, grade)); + } + + headerItem.setSubItems(subItems); + headerItem.setExpanded(false); + headerItems.add(headerItem); + } + } + } + + @Override + public void onCanceledLoadingAsync() { + // do nothing + } + + @Override + public void onEndLoadingAsync(boolean result, Exception exception) { + if (headerItems.isEmpty()) { + getView().showNoItem(true); + } else { + getView().updateAdapterList(headerItems); + getView().showNoItem(false); + listener.onFragmentIsReady(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (refreshTask != null) { + refreshTask.cancel(true); + refreshTask = null; + } + if (loadingTask != null) { + loadingTask.cancel(true); + loadingTask = null; + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java new file mode 100644 index 000000000..c252bb2ad --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java @@ -0,0 +1,150 @@ +package io.github.wulkanowy.ui.main.grades; + +import android.app.Activity; +import android.content.Context; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.View; +import android.widget.TextView; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractSectionableItem; +import eu.davidea.viewholders.FlexibleViewHolder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Grade; + +public class GradesSubItem + extends AbstractSectionableItem { + + private Grade grade; + + private static int numberOfNotReadGrade; + + GradesSubItem(GradeHeaderItem header, Grade grade) { + super(header); + this.grade = grade; + } + + public Grade getGrade() { + return grade; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + GradesSubItem that = (GradesSubItem) o; + + return new EqualsBuilder() + .append(grade, that.grade) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(grade) + .toHashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.grade_subitem; + } + + @Override + public SubItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new SubItemViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, SubItemViewHolder holder, int position, List payloads) { + holder.onBind(grade); + } + + static class SubItemViewHolder extends FlexibleViewHolder { + + @BindView(R.id.grade_subitem_value) + TextView value; + + @BindView(R.id.grade_subitem_description) + TextView description; + + @BindView(R.id.grade_subitem_date) + TextView date; + + @BindView(R.id.grade_subitem_alert_image) + View alert; + + private Context context; + + private Grade item; + + SubItemViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + ButterKnife.bind(this, view); + context = view.getContext(); + view.setOnClickListener(this); + } + + void onBind(Grade item) { + this.item = item; + + value.setText(item.getValue()); + value.setBackgroundResource(item.getValueColor()); + date.setText(item.getDate()); + description.setText(getDescriptionString()); + alert.setVisibility(item.getRead() ? View.INVISIBLE : View.VISIBLE); + + if (!item.getRead()) { + numberOfNotReadGrade++; + } + } + + @Override + public void onClick(View view) { + super.onClick(view); + showDialog(); + + if (!item.getRead()) { + numberOfNotReadGrade--; + + if (numberOfNotReadGrade == 0) { + ((Activity) context).findViewById(R.id.grade_fragment_container) + .findViewWithTag(item.getSubject()).setVisibility(View.INVISIBLE); + } + item.setIsNew(false); + item.setRead(true); + item.update(); + alert.setVisibility(View.INVISIBLE); + } + } + + private String getDescriptionString() { + if (item.getDescription() == null || "".equals(item.getDescription())) { + if (!"".equals(item.getSymbol())) { + return item.getSymbol(); + } else { + return context.getString(R.string.noDescription_text); + } + } else { + return item.getDescription(); + } + } + + private void showDialog() { + GradesDialogFragment dialogFragment = GradesDialogFragment.newInstance(item); + dialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0); + dialogFragment.show(((FragmentActivity) context).getSupportFragmentManager(), item.toString()); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TabsData.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TabsData.java new file mode 100644 index 000000000..156d1759b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TabsData.java @@ -0,0 +1,37 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.support.v4.app.Fragment; + +import java.util.ArrayList; +import java.util.List; + +class TabsData { + + private List fragments = new ArrayList<>(); + + private List titles = new ArrayList<>(); + + Fragment getFragment(int index) { + return fragments.get(index); + } + + void addFragment(Fragment fragment) { + if (fragment != null) { + fragments.add(fragment); + } + } + + int getFragmentsCount() { + return fragments.size(); + } + + String getTitle(int index) { + return titles.get(index); + } + + void addTitle(String title) { + if (title != null) { + titles.add(title); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java new file mode 100644 index 000000000..18fa33f96 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java @@ -0,0 +1,35 @@ +package io.github.wulkanowy.ui.main.timetable; + +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public interface TimetableContract { + + interface View extends BaseContract.View { + + void setActivityTitle(); + + void scrollViewPagerToPosition(int position); + + void setTabDataToAdapter(TabsData tabsData); + + void setAdapterWithTabLayout(); + + void setChildFragmentSelected(int position, boolean selected); + + boolean isMenuVisible(); + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + + void onFragmentVisible(boolean isVisible); + + void onTabSelected(int position); + + void onTabUnselected(int position); + + void onStart(View view, OnFragmentIsReadyListener listener); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableDialogFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableDialogFragment.java new file mode 100644 index 000000000..cfc1e0739 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableDialogFragment.java @@ -0,0 +1,127 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.apache.commons.lang3.StringUtils; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Lesson; + +public class TimetableDialogFragment extends DialogFragment { + + private static final String ARGUMENT_KEY = "Item"; + + private Lesson lesson; + + @BindView(R.id.timetable_dialog_lesson_value) + TextView lessonName; + + @BindView(R.id.timetable_dialog_teacher_value) + TextView teacher; + + @BindView(R.id.timetable_dialog_group_value) + TextView group; + + @BindView(R.id.timetable_dialog_room_value) + TextView room; + + @BindView(R.id.timetable_dialog_time_value) + TextView time; + + @BindView(R.id.timetable_dialog_description_value) + TextView description; + + @BindView(R.id.timetable_dialog_description) + View descriptionLabel; + + @BindView(R.id.timetable_dialog_teacher) + View teacherLabel; + + @BindView(R.id.timetable_dialog_group) + View groupLabel; + + public TimetableDialogFragment() { + //empty constructor for fragment + } + + public static TimetableDialogFragment newInstance(Lesson lesson) { + TimetableDialogFragment dialogFragment = new TimetableDialogFragment(); + + Bundle bundle = new Bundle(); + bundle.putSerializable(ARGUMENT_KEY, lesson); + + dialogFragment.setArguments(bundle); + + return dialogFragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + lesson = (Lesson) getArguments().getSerializable(ARGUMENT_KEY); + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.timetable_dialog, container, false); + + ButterKnife.bind(this, view); + + if (!lesson.getSubject().isEmpty()) { + lessonName.setText(lesson.getSubject()); + } + + if (!lesson.getTeacher().isEmpty()) { + teacher.setText(lesson.getTeacher()); + } else { + teacher.setVisibility(View.GONE); + teacherLabel.setVisibility(View.GONE); + } + + if (!lesson.getGroupName().isEmpty()) { + group.setText(lesson.getGroupName()); + } else { + group.setVisibility(View.GONE); + groupLabel.setVisibility(View.GONE); + } + + if (!lesson.getRoom().isEmpty()) { + room.setText(lesson.getRoom()); + } + + if (!lesson.getEndTime().isEmpty() && !lesson.getStartTime().isEmpty()) { + time.setText(getTimeString()); + } + + if (!lesson.getDescription().isEmpty()) { + description.setText(StringUtils.capitalize(lesson.getDescription())); + } else { + description.setVisibility(View.GONE); + descriptionLabel.setVisibility(View.GONE); + } + + return view; + } + + private String getTimeString() { + return String.format("%1$s - %2$s", lesson.getStartTime(), lesson.getEndTime()); + } + + @OnClick(R.id.timetable_dialog_close) + void onClickCloseButton() { + dismiss(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java new file mode 100644 index 000000000..a9a833917 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java @@ -0,0 +1,114 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class TimetableFragment extends BaseFragment implements TimetableContract.View, TabLayout.OnTabSelectedListener { + + @BindView(R.id.timetable_fragment_viewpager) + ViewPager viewPager; + + @BindView(R.id.timetable_fragment_tab_layout) + TabLayout tabLayout; + + @Inject + TimetablePagerAdapter pagerAdapter; + + @Inject + TimetableContract.Presenter presenter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_timetable, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); + } + return view; + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null) { + presenter.onFragmentVisible(menuVisible); + } + } + + @Override + public void onTabSelected(TabLayout.Tab tab) { + presenter.onTabSelected(tab.getPosition()); + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + presenter.onTabUnselected(tab.getPosition()); + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + //do nothing + } + + @Override + public void setTabDataToAdapter(TabsData tabsData) { + pagerAdapter.setTabsData(tabsData); + } + + @Override + public void setAdapterWithTabLayout() { + viewPager.setAdapter(pagerAdapter); + + tabLayout.setupWithViewPager(viewPager); + tabLayout.addOnTabSelectedListener(this); + } + + @Override + public void setChildFragmentSelected(int position, boolean selected) { + ((TimetableTabFragment) pagerAdapter.getItem(position)).setSelected(selected); + } + + @Override + public void scrollViewPagerToPosition(int position) { + viewPager.setCurrentItem(position, false); + } + + @Override + public void setActivityTitle() { + setTitle(getString(R.string.lessonplan_text)); + } + + @Override + public void onError(String message) { + if (getActivity() != null) { + Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager), + message, Snackbar.LENGTH_LONG).show(); + } + } + + @Override + public void onDestroyView() { + presenter.onDestroy(); + super.onDestroyView(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableHeaderItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableHeaderItem.java new file mode 100644 index 000000000..c418d9acd --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableHeaderItem.java @@ -0,0 +1,100 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem; +import eu.davidea.viewholders.ExpandableViewHolder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Day; + +public class TimetableHeaderItem + extends AbstractExpandableHeaderItem { + + private Day day; + + TimetableHeaderItem(Day day) { + this.day = day; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + TimetableHeaderItem that = (TimetableHeaderItem) o; + + return new EqualsBuilder() + .append(day, that.day) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(day) + .toHashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.timetable_header; + } + + @Override + public HeaderViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new HeaderViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, HeaderViewHolder holder, int position, List payloads) { + holder.onBind(day, getSubItems()); + } + + static class HeaderViewHolder extends ExpandableViewHolder { + + @BindView(R.id.timetable_header_day) + TextView dayName; + + @BindView(R.id.timetable_header_date) + TextView date; + + @BindView(R.id.timetable_header_alert_image) + ImageView alert; + + HeaderViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + view.setOnClickListener(this); + ButterKnife.bind(this, view); + } + + void onBind(Day item, List subItems) { + dayName.setText(StringUtils.capitalize(item.getDayName())); + date.setText(item.getDate()); + alert.setVisibility(isSubItemNewMovedInOrChanged(subItems) ? View.VISIBLE : View.INVISIBLE); + } + + private boolean isSubItemNewMovedInOrChanged(List subItems) { + boolean isAlertActive = false; + + for (TimetableSubItem subItem : subItems) { + if (subItem.getLesson().getIsMovedOrCanceled() || + subItem.getLesson().getIsNewMovedInOrChanged()) { + isAlertActive = true; + } + } + return isAlertActive; + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java new file mode 100644 index 000000000..24e7582d3 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java @@ -0,0 +1,36 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; + +public class TimetablePagerAdapter extends FragmentStatePagerAdapter { + + private TabsData tabsData; + + public TimetablePagerAdapter(FragmentManager fragmentManager) { + super(fragmentManager); + } + + void setTabsData(TabsData tabsData) { + this.tabsData = tabsData; + } + + @Override + public Fragment getItem(int position) { + return tabsData.getFragment(position); + } + + + @Override + public int getCount() { + return tabsData.getFragmentsCount(); + } + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return tabsData.getTitle(position); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java new file mode 100644 index 000000000..bee323ddb --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java @@ -0,0 +1,107 @@ +package io.github.wulkanowy.ui.main.timetable; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; +import io.github.wulkanowy.utils.TimeUtils; +import io.github.wulkanowy.utils.async.AbstractTask; +import io.github.wulkanowy.utils.async.AsyncListeners; + +public class TimetablePresenter extends BasePresenter + implements TimetableContract.Presenter, AsyncListeners.OnFirstLoadingListener { + + private AbstractTask loadingTask; + + private List dates = new ArrayList<>(); + + private TabsData tabsData = new TabsData(); + + private OnFragmentIsReadyListener listener; + + private int positionToScroll; + + private boolean isFirstSight = false; + + @Inject + TimetablePresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(TimetableContract.View view, OnFragmentIsReadyListener listener) { + super.onStart(view); + this.listener = listener; + + if (getView().isMenuVisible()) { + getView().setActivityTitle(); + } + + if (dates.isEmpty()) { + dates = TimeUtils.getMondaysFromCurrentSchoolYear(); + } + positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true)); + + if (!isFirstSight) { + isFirstSight = true; + + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + } + } + + @Override + public void onFragmentVisible(boolean isVisible) { + if (isVisible) { + getView().setActivityTitle(); + } + } + + @Override + public void onTabSelected(int position) { + getView().setChildFragmentSelected(position, true); + } + + @Override + public void onTabUnselected(int position) { + getView().setChildFragmentSelected(position, false); + } + + @Override + public void onDoInBackgroundLoading() throws Exception { + for (String date : dates) { + tabsData.addTitle(date); + tabsData.addFragment(TimetableTabFragment.newInstance(date)); + } + } + + @Override + public void onCanceledLoadingAsync() { + //do nothing + + } + + @Override + public void onEndLoadingAsync(boolean result, Exception exception) { + if (result) { + getView().setTabDataToAdapter(tabsData); + getView().setAdapterWithTabLayout(); + getView().scrollViewPagerToPosition(positionToScroll); + listener.onFragmentIsReady(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (loadingTask != null) { + loadingTask.cancel(true); + loadingTask = null; + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableSubItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableSubItem.java new file mode 100644 index 000000000..b4212940f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableSubItem.java @@ -0,0 +1,123 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.content.Context; +import android.graphics.Paint; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractSectionableItem; +import eu.davidea.viewholders.FlexibleViewHolder; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Lesson; + + +public class TimetableSubItem + extends AbstractSectionableItem { + + private Lesson lesson; + + public TimetableSubItem(TimetableHeaderItem header, Lesson lesson) { + super(header); + this.lesson = lesson; + } + + public Lesson getLesson() { + return lesson; + } + + @Override + public boolean equals(Object o) { + return this == o; + } + + @Override + public int getLayoutRes() { + return R.layout.timetable_subitem; + } + + @Override + public SubItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new SubItemViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, SubItemViewHolder holder, int position, List payloads) { + holder.onBind(lesson); + } + + static class SubItemViewHolder extends FlexibleViewHolder { + + @BindView(R.id.timetable_subItem_lesson) + TextView lessonName; + + @BindView(R.id.timetable_subItem_number_of_lesson) + TextView numberOfLesson; + + @BindView(R.id.timetable_subItem_time) + TextView lessonTime; + + @BindView(R.id.timetable_subItem_room) + TextView room; + + @BindView(R.id.timetable_subItem_alert_image) + ImageView alert; + + private Context context; + + private Lesson item; + + SubItemViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + ButterKnife.bind(this, view); + context = view.getContext(); + view.setOnClickListener(this); + } + + void onBind(Lesson lesson) { + item = lesson; + + lessonName.setText(lesson.getSubject()); + lessonTime.setText(getLessonTimeString()); + numberOfLesson.setText(lesson.getNumber()); + room.setText(getRoomString()); + alert.setVisibility(lesson.getIsMovedOrCanceled() || lesson.getIsNewMovedInOrChanged() + ? View.VISIBLE : View.INVISIBLE); + lessonName.setPaintFlags(lesson.getIsMovedOrCanceled() ? lessonName.getPaintFlags() + | Paint.STRIKE_THRU_TEXT_FLAG : + lessonName.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG)); + room.setText(getRoomString()); + } + + @Override + public void onClick(View view) { + super.onClick(view); + showDialog(); + } + + private String getLessonTimeString() { + return String.format("%1$s - %2$s", item.getStartTime(), item.getEndTime()); + } + + private String getRoomString() { + if (!item.getRoom().isEmpty()) { + return context.getString(R.string.timetable_subitem_room, item.getRoom()); + } else { + return item.getRoom(); + } + } + + private void showDialog() { + TimetableDialogFragment dialogFragment = TimetableDialogFragment.newInstance(item); + dialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0); + dialogFragment.show(((FragmentActivity) context).getSupportFragmentManager(), item.toString()); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabContract.java new file mode 100644 index 000000000..fbffdb12a --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabContract.java @@ -0,0 +1,30 @@ +package io.github.wulkanowy.ui.main.timetable; + +import java.util.List; + +import io.github.wulkanowy.ui.base.BaseContract; + +public interface TimetableTabContract { + + interface View extends BaseContract.View { + + void updateAdapterList(List headerItems); + + void onRefreshSuccess(); + + void hideRefreshingBar(); + + void showProgressBar(boolean show); + } + + interface Presenter extends BaseContract.Presenter { + + void onFragmentSelected(boolean isSelected); + + void setArgumentDate(String date); + + void onStart(View view, boolean isPrimary); + + void onRefresh(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabFragment.java new file mode 100644 index 000000000..10f3163af --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabFragment.java @@ -0,0 +1,145 @@ +package io.github.wulkanowy.ui.main.timetable; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.List; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; + +public class TimetableTabFragment extends BaseFragment implements TimetableTabContract.View, + SwipeRefreshLayout.OnRefreshListener { + + private static final String ARGUMENT_KEY = "Date"; + + private boolean isPrimary = false; + + private boolean isSelected = false; + + @BindView(R.id.timetable_tab_fragment_recycler) + RecyclerView recyclerView; + + @BindView(R.id.timetable_tab_fragment_swipe_refresh) + SwipeRefreshLayout refreshLayout; + + @BindView(R.id.timetable_tab_fragment_progress_bar) + View progressBar; + + @Inject + TimetableTabContract.Presenter presenter; + + @Inject + FlexibleAdapter adapter; + + public static TimetableTabFragment newInstance(String date) { + TimetableTabFragment fragmentTab = new TimetableTabFragment(); + + Bundle bundle = new Bundle(); + bundle.putString(ARGUMENT_KEY, date); + fragmentTab.setArguments(bundle); + + return fragmentTab; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_timetable_tab, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + + if (getArguments() != null) { + presenter.setArgumentDate(getArguments().getString(ARGUMENT_KEY)); + } + + presenter.onStart(this, isPrimary); + } + return view; + } + + @Override + protected void setUpOnViewCreated(View fragmentView) { + adapter.setAutoCollapseOnExpand(true); + adapter.setAutoScrollOnExpand(true); + adapter.expandItemsAtStartUp(); + + recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext())); + recyclerView.setAdapter(adapter); + + refreshLayout.setColorSchemeResources(android.R.color.black); + refreshLayout.setOnRefreshListener(this); + + } + + @Override + public void updateAdapterList(List headerItems) { + adapter.updateDataSet(headerItems); + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null && getView() != null) { + presenter.onFragmentSelected(isSelected); + } else if (isSelected) { + isPrimary = true; + } + } + + @Override + public void onRefresh() { + presenter.onRefresh(); + } + + @Override + public void onRefreshSuccess() { + onError(R.string.timetable_refresh_success); + } + + @Override + public void hideRefreshingBar() { + refreshLayout.setRefreshing(false); + } + + @Override + public void showProgressBar(boolean show) { + progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + + public void setSelected(boolean selected) { + isSelected = selected; + } + + @Override + public void onError(String message) { + if (getActivity() != null) { + Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager), + message, Snackbar.LENGTH_LONG).show(); + } + } + + @Override + public void onDestroyView() { + isPrimary = false; + presenter.onDestroy(); + super.onDestroyView(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java new file mode 100644 index 000000000..5872b4d05 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java @@ -0,0 +1,155 @@ +package io.github.wulkanowy.ui.main.timetable; + + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.data.db.dao.entities.Day; +import io.github.wulkanowy.data.db.dao.entities.Lesson; +import io.github.wulkanowy.data.db.dao.entities.Week; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.utils.async.AbstractTask; +import io.github.wulkanowy.utils.async.AsyncListeners; + +public class TimetableTabPresenter extends BasePresenter + implements TimetableTabContract.Presenter, AsyncListeners.OnRefreshListener, + AsyncListeners.OnFirstLoadingListener { + + private AbstractTask refreshTask; + + private AbstractTask loadingTask; + + private List headerItems = new ArrayList<>(); + + private String date; + + private boolean isFirstSight = false; + + @Inject + TimetableTabPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(TimetableTabContract.View view, boolean isPrimary) { + super.onStart(view); + getView().showProgressBar(true); + onFragmentSelected(isPrimary); + } + + @Override + public void onFragmentSelected(boolean isSelected) { + if (!isFirstSight && isSelected) { + isFirstSight = true; + + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + } + } + + @Override + public void onRefresh() { + if (getView().isNetworkConnected()) { + refreshTask = new AbstractTask(); + refreshTask.setOnRefreshListener(this); + refreshTask.execute(); + } else { + getView().onNoNetworkError(); + getView().hideRefreshingBar(); + } + } + + @Override + public void onDoInBackgroundRefresh() throws Exception { + syncData(); + } + + @Override + public void onCanceledRefreshAsync() { + // do nothing + } + + @Override + public void onEndRefreshAsync(boolean result, Exception exception) { + if (result) { + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + + getView().onRefreshSuccess(); + } else { + getView().onError(getRepository().getErrorLoginMessage(exception)); + } + getView().hideRefreshingBar(); + } + + @Override + public void onDoInBackgroundLoading() throws Exception { + Week week = getRepository().getWeek(date); + + if (week == null) { + syncData(); + week = getRepository().getWeek(date); + } + + List dayList = week.getDayList(); + + headerItems = new ArrayList<>(); + + for (Day day : dayList) { + TimetableHeaderItem headerItem = new TimetableHeaderItem(day); + + List lessonList = day.getLessons(); + + List subItems = new ArrayList<>(); + + for (Lesson lesson : lessonList) { + subItems.add(new TimetableSubItem(headerItem, lesson)); + } + + headerItem.setSubItems(subItems); + headerItem.setExpanded(false); + headerItems.add(headerItem); + } + } + + @Override + public void onCanceledLoadingAsync() { + // do nothing + } + + @Override + public void onEndLoadingAsync(boolean result, Exception exception) { + getView().updateAdapterList(headerItems); + getView().showProgressBar(false); + } + + @Override + public void setArgumentDate(String date) { + this.date = date; + } + + private void syncData() throws Exception { + getRepository().loginCurrentUser(); + getRepository().syncTimetable(date); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isFirstSight = false; + + if (refreshTask != null) { + refreshTask.cancel(true); + refreshTask = null; + } + if (loadingTask != null) { + loadingTask.cancel(true); + loadingTask = null; + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutAdapter.kt deleted file mode 100644 index 35dec3b4f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutAdapter.kt +++ /dev/null @@ -1,72 +0,0 @@ -package io.github.wulkanowy.ui.modules.about - -import android.graphics.drawable.Drawable -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.content.res.ResourcesCompat -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.databinding.ItemAboutBinding -import io.github.wulkanowy.databinding.ScrollableHeaderAboutBinding -import javax.inject.Inject - -class AboutAdapter @Inject constructor() : RecyclerView.Adapter() { - - private enum class ViewType(val id: Int) { - ITEM_HEADER(1), - ITEM_ELEMENT(2) - } - - var items = emptyList>() - - var onClickListener: (name: String) -> Unit = {} - - override fun getItemCount() = items.size + 1 - - override fun getItemViewType(position: Int) = when (position) { - 0 -> ViewType.ITEM_HEADER.id - else -> ViewType.ITEM_ELEMENT.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.ITEM_HEADER.id -> HeaderViewHolder(ScrollableHeaderAboutBinding.inflate(inflater, parent, false)) - ViewType.ITEM_ELEMENT.id -> ItemViewHolder(ItemAboutBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding) - is ItemViewHolder -> bindItemViewHolder(holder.binding, position - 1) - } - } - - private fun bindHeaderViewHolder(binding: ScrollableHeaderAboutBinding) { - with(binding.aboutScrollableHeaderIcon) { - setImageDrawable(ResourcesCompat.getDrawableForDensity( - context.resources, context.applicationInfo.icon, 640, null) - ) - } - } - - private fun bindItemViewHolder(binding: ItemAboutBinding, position: Int) { - val (title, summary, image) = items[position] - - with(binding) { - aboutItemImage.setImageDrawable(image) - aboutItemTitle.text = title - aboutItemSummary.text = summary - - root.setOnClickListener { onClickListener(title) } - } - } - - private class HeaderViewHolder(val binding: ScrollableHeaderAboutBinding) : - RecyclerView.ViewHolder(binding.root) - - private class ItemViewHolder(val binding: ItemAboutBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt deleted file mode 100644 index d85d01e9e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt +++ /dev/null @@ -1,152 +0,0 @@ -package io.github.wulkanowy.ui.modules.about - -import android.graphics.drawable.Drawable -import android.os.Bundle -import android.view.View -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentAboutBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.about.contributor.ContributorFragment -import io.github.wulkanowy.ui.modules.about.license.LicenseFragment -import io.github.wulkanowy.ui.modules.about.logviewer.LogViewerFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.getCompatDrawable -import io.github.wulkanowy.utils.openAppInMarket -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import javax.inject.Inject - -class AboutFragment : BaseFragment(R.layout.fragment_about), AboutView, - MainView.TitledView { - - @Inject - lateinit var presenter: AboutPresenter - - @Inject - lateinit var aboutAdapter: AboutAdapter - - @Inject - lateinit var appInfo: AppInfo - - override val versionRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_version), "${appInfo.versionName} (${appInfo.versionCode})", getCompatDrawable(R.drawable.ic_all_about)) - } - - override val creatorsRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_contributor), getString(R.string.about_contributor_summary), getCompatDrawable(R.drawable.ic_about_creator)) - } - - override val feedbackRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_feedback), getString(R.string.about_feedback_summary), getCompatDrawable(R.drawable.ic_about_feedback)) - } - - override val faqRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_faq), getString(R.string.about_faq_summary), getCompatDrawable(R.drawable.ic_about_faq)) - } - - override val discordRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord)) - } - - override val homepageRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage)) - } - - override val licensesRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_licenses), getString(R.string.about_licenses_summary), getCompatDrawable(R.drawable.ic_about_licenses)) - } - - override val privacyRes: Triple? - get() = context?.run { - Triple(getString(R.string.about_privacy), getString(R.string.about_privacy_summary), getCompatDrawable(R.drawable.ic_about_privacy)) - } - - override val titleStringId get() = R.string.about_title - - companion object { - fun newInstance() = AboutFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentAboutBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - aboutAdapter.onClickListener = presenter::onItemSelected - - with(binding.aboutRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = aboutAdapter - } - } - - override fun updateData(data: List>) { - with(aboutAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun openAppInMarket() { - context?.openAppInMarket(::showMessage) - } - - override fun openLogViewer() { - (activity as? MainActivity)?.pushView(LogViewerFragment.newInstance()) - } - - override fun openDiscordInvite() { - context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) - } - - override fun openHomepage() { - context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage) - } - - override fun openEmailClient() { - requireContext().openEmailClient( - chooserTitle = getString(R.string.about_feedback), - email = "wulkanowyinc@gmail.com", - subject = "Zgłoszenie błędu", - body = getString(R.string.about_feedback_template, - "${appInfo.systemManufacturer} ${appInfo.systemModel}", appInfo.systemVersion.toString(), appInfo.versionName - ), - onActivityNotFound = { - requireContext().openInternetBrowser("https://github.com/wulkanowy/wulkanowy/issues", ::showMessage) - } - ) - } - - override fun openFaqPage() { - context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania", ::showMessage) - } - - override fun openLicenses() { - (activity as? MainActivity)?.pushView(LicenseFragment.newInstance()) - } - - override fun openCreators() { - (activity as? MainActivity)?.pushView(ContributorFragment.newInstance()) - } - - override fun openPrivacyPolicy() { - context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index ee892adfc..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt +++ /dev/null @@ -1,89 +0,0 @@ -package io.github.wulkanowy.ui.modules.about - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class AboutPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val appInfo: AppInfo, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: AboutView) { - super.onAttachView(view) - view.initView() - Timber.i("About view was initialized") - loadData() - } - - fun onItemSelected(name: String) { - view?.run { - when (name) { - versionRes?.first -> { - Timber.i("Opening log viewer") - if (appInfo.isDebug) openLogViewer() - else openAppInMarket() - analytics.logEvent("about_open", "name" to "log_viewer") - } - feedbackRes?.first -> { - Timber.i("Opening email client") - openEmailClient() - analytics.logEvent("about_open", "name" to "feedback") - } - faqRes?.first -> { - Timber.i("Opening faq page") - openFaqPage() - analytics.logEvent("about_open", "name" to "faq") - } - discordRes?.first -> { - Timber.i("Opening discord") - openDiscordInvite() - analytics.logEvent("about_open", "name" to "discord") - } - homepageRes?.first -> { - Timber.i("Opening homepage") - openHomepage() - analytics.logEvent("about_open", "name" to "homepage") - } - licensesRes?.first -> { - Timber.i("Opening licenses view") - openLicenses() - analytics.logEvent("about_open", "name" to "licenses") - } - creatorsRes?.first -> { - Timber.i("Opening creators view") - openCreators() - analytics.logEvent("about_open", "name" to "creators") - } - privacyRes?.first -> { - Timber.i("Opening privacy page ") - openPrivacyPolicy() - analytics.logEvent("about_open", "name" to "privacy") - } - } - } - } - - private fun loadData() { - view?.run { - updateData(listOfNotNull( - versionRes, - creatorsRes, - feedbackRes, - faqRes, - discordRes, - homepageRes, - licensesRes, - privacyRes - )) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt deleted file mode 100644 index 4c4b002f9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.ui.modules.about - -import android.graphics.drawable.Drawable -import io.github.wulkanowy.ui.base.BaseView - -interface AboutView : BaseView { - - val versionRes: Triple? - - val creatorsRes: Triple? - - val feedbackRes: Triple? - - val faqRes: Triple? - - val discordRes: Triple? - - val homepageRes: Triple? - - val licensesRes: Triple? - - val privacyRes: Triple? - - fun initView() - - fun updateData(data: List>) - - fun openAppInMarket() - - fun openLogViewer() - - fun openDiscordInvite() - - fun openEmailClient() - - fun openFaqPage() - - fun openHomepage() - - fun openLicenses() - - fun openCreators() - - fun openPrivacyPolicy() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorAdapter.kt deleted file mode 100644 index 215cd27db..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorAdapter.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.contributor - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import coil.api.load -import coil.transform.RoundedCornersTransformation -import io.github.wulkanowy.data.pojos.Contributor -import io.github.wulkanowy.databinding.ItemContributorBinding -import javax.inject.Inject - -class ContributorAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = emptyList() - - var onClickListener: (Contributor) -> Unit = {} - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemContributorBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - creatorItemName.text = item.displayName - creatorItemAvatar.load("https://github.com/${item.githubUsername}.png") { - transformations(RoundedCornersTransformation(8f)) - crossfade(true) - } - - root.setOnClickListener { onClickListener(item) } - } - } - - class ItemViewHolder(val binding: ItemContributorBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorFragment.kt deleted file mode 100644 index 42eebd347..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorFragment.kt +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.contributor - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.Contributor -import io.github.wulkanowy.databinding.FragmentContributorBinding -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.openInternetBrowser -import javax.inject.Inject - -class ContributorFragment : BaseFragment(R.layout.fragment_contributor), - ContributorView, MainView.TitledView { - - @Inject - lateinit var presenter: ContributorPresenter - - @Inject - lateinit var creatorsAdapter: ContributorAdapter - - override val titleStringId get() = R.string.contributors_title - - companion object { - fun newInstance() = ContributorFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentContributorBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - with(binding.creatorRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = creatorsAdapter - addItemDecoration(DividerItemDecoration(context)) - } - creatorsAdapter.onClickListener = presenter::onItemSelected - binding.creatorSeeMore.setOnClickListener { presenter.onSeeMoreClick() } - } - - override fun updateData(data: List) { - with(creatorsAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun openUserGithubPage(username: String) { - context?.openInternetBrowser("https://github.com/${username}", ::showMessage) - } - - override fun openGithubContributorsPage() { - context?.openInternetBrowser("https://github.com/wulkanowy/wulkanowy/graphs/contributors", ::showMessage) - } - - override fun showProgress(show: Boolean) { - binding.creatorProgress.visibility = if (show) VISIBLE else GONE - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 416a59ce5..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorPresenter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.contributor - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Inject - -class ContributorPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val appCreatorRepository: AppCreatorRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: ContributorView) { - super.onAttachView(view) - view.initView() - loadData() - } - - fun onItemSelected(contributor: Contributor) { - view?.openUserGithubPage(contributor.githubUsername) - } - - fun onSeeMoreClick() { - view?.openGithubContributorsPage() - } - - private fun loadData() { - disposable.add(appCreatorRepository.getAppCreators() - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { view?.showProgress(false) } - .subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) })) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorView.kt deleted file mode 100644 index 8007e4e3f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/contributor/ContributorView.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.contributor - -import io.github.wulkanowy.data.pojos.Contributor -import io.github.wulkanowy.ui.base.BaseView - -interface ContributorView : BaseView { - - fun initView() - - fun updateData(data: List) - - fun openUserGithubPage(username: String) - - fun openGithubContributorsPage() - - fun showProgress(show: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseAdapter.kt deleted file mode 100644 index 07025c09f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseAdapter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.license - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import com.mikepenz.aboutlibraries.entity.Library -import io.github.wulkanowy.databinding.ItemLicenseBinding -import javax.inject.Inject - -class LicenseAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList() - - var onClickListener: (Library) -> Unit = {} - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemLicenseBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - licenseItemName.text = item.libraryName - licenseItemSummary.text = item.license?.licenseName?.takeIf { it.isNotBlank() } ?: item.libraryVersion - - root.setOnClickListener { onClickListener(item) } - } - } - - class ItemViewHolder(val binding: ItemLicenseBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseFragment.kt deleted file mode 100644 index f6c3b5698..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseFragment.kt +++ /dev/null @@ -1,83 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.license - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.appcompat.app.AlertDialog -import androidx.core.text.parseAsHtml -import androidx.recyclerview.widget.LinearLayoutManager -import com.mikepenz.aboutlibraries.Libs -import com.mikepenz.aboutlibraries.entity.Library -import dagger.Lazy -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentLicenseBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import javax.inject.Inject - -class LicenseFragment : BaseFragment(R.layout.fragment_license), - LicenseView, MainView.TitledView { - - @Inject - lateinit var presenter: LicensePresenter - - @Inject - lateinit var licenseAdapter: LicenseAdapter - - @Inject - lateinit var libs: Lazy - - override val titleStringId get() = R.string.license_title - - override val appLibraries: ArrayList? - get() = context?.let { - libs.get().prepareLibraries(it, emptyArray(), emptyArray(), autoDetect = true, checkCachedDetection = true, sort = true) - } - - companion object { - fun newInstance() = LicenseFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLicenseBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - licenseAdapter.onClickListener = presenter::onItemSelected - - with(binding.licenseRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = licenseAdapter - } - } - - override fun updateData(data: List) { - with(licenseAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun openLicense(licenseHtml: String) { - context?.let { - AlertDialog.Builder(it).apply { - setTitle(R.string.license_dialog_title) - setMessage(licenseHtml.parseAsHtml()) - setPositiveButton(android.R.string.ok) { _, _ -> } - show() - } - } - } - - override fun showProgress(show: Boolean) { - binding.licenseProgress.visibility = if (show) VISIBLE else GONE - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseModule.kt deleted file mode 100644 index 0ffc3d90e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseModule.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.license - -import android.content.Context -import com.mikepenz.aboutlibraries.Libs -import dagger.Module -import dagger.Provides -import io.github.wulkanowy.di.scopes.PerFragment - -@Module -class LicenseModule { - - @PerFragment - @Provides - fun provideLibs(context: Context) = Libs(context) -} 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 deleted file mode 100644 index d0f6d69e0..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicensePresenter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.license - -import com.mikepenz.aboutlibraries.entity.Library -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Single -import javax.inject.Inject - -class LicensePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: LicenseView) { - super.onAttachView(view) - view.initView() - loadData() - } - - fun onItemSelected(library: Library) { - view?.run { library.license?.licenseDescription?.let { openLicense(it) } } - } - - private fun loadData() { - disposable.add(Single.fromCallable { view?.appLibraries.orEmpty() } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnEvent { _, _ -> view?.showProgress(false) } - .subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) })) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseView.kt deleted file mode 100644 index 0680dbb73..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/license/LicenseView.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.license - -import com.mikepenz.aboutlibraries.entity.Library -import io.github.wulkanowy.ui.base.BaseView - -interface LicenseView : BaseView { - - val appLibraries: ArrayList? - - fun initView() - - fun updateData(data: List) - - fun openLicense(licenseHtml: String) - - fun showProgress(show: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerAdapter.kt deleted file mode 100644 index 45c304aae..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerAdapter.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.logviewer - -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView - -class LogViewerAdapter : RecyclerView.Adapter() { - - var lines = emptyList() - - class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - return ViewHolder(TextView(parent.context)) - } - - override fun getItemCount() = lines.size - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.textView.text = lines[position] - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerFragment.kt deleted file mode 100644 index 08f91aff1..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerFragment.kt +++ /dev/null @@ -1,94 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.logviewer - -import android.content.Intent -import android.content.Intent.EXTRA_EMAIL -import android.content.Intent.EXTRA_STREAM -import android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION -import android.net.Uri -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.LOLLIPOP -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import androidx.core.content.FileProvider -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.BuildConfig.APPLICATION_ID -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentLogviewerBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import java.io.File -import javax.inject.Inject - -class LogViewerFragment : BaseFragment(R.layout.fragment_logviewer), - LogViewerView, MainView.TitledView { - - @Inject - lateinit var presenter: LogViewerPresenter - - private val logAdapter = LogViewerAdapter() - - override val titleStringId: Int - get() = R.string.logviewer_title - - companion object { - fun newInstance() = LogViewerFragment() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLogviewerBinding.bind(view) - messageContainer = binding.logViewerRecycler - presenter.onAttachView(this) - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_logviewer, menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.logViewerMenuShare) presenter.onShareLogsSelected() - else false - } - - override fun initView() { - with(binding.logViewerRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = logAdapter - } - - binding.logViewRefreshButton.setOnClickListener { presenter.onRefreshClick() } - } - - override fun setLines(lines: List) { - logAdapter.lines = lines - logAdapter.notifyDataSetChanged() - binding.logViewerRecycler.scrollToPosition(lines.size - 1) - } - - override fun shareLogs(files: List) { - val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { - type = "text/plain" - putExtra(EXTRA_EMAIL, arrayOf("wulkanowyinc@gmail.com")) - addFlags(FLAG_GRANT_READ_URI_PERMISSION) - putParcelableArrayListExtra(EXTRA_STREAM, ArrayList(files.map { - if (SDK_INT < LOLLIPOP) Uri.fromFile(it) - else FileProvider.getUriForFile(requireContext(), "$APPLICATION_ID.fileprovider", it) - })) - } - - startActivity(Intent.createChooser(intent, getString(R.string.logviewer_share))) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 33eb1122d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerPresenter.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.logviewer - -import io.github.wulkanowy.data.repositories.logger.LoggerRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class LogViewerPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val loggerRepository: LoggerRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: LogViewerView) { - super.onAttachView(view) - view.initView() - loadLogFile() - } - - fun onShareLogsSelected(): Boolean { - disposable.add(loggerRepository.getLogFiles() - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ files -> - Timber.i("Loading logs files result: ${files.joinToString { it.name }}") - view?.shareLogs(files) - }, { - Timber.i("Loading logs files result: An exception occurred") - errorHandler.dispatch(it) - })) - return true - } - - fun onRefreshClick() { - loadLogFile() - } - - private fun loadLogFile() { - disposable.add(loggerRepository.getLastLogLines() - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Loading last log file result: load ${it.size} lines") - view?.setLines(it) - }, { - Timber.i("Loading last log file result: An exception occurred") - errorHandler.dispatch(it) - })) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerView.kt deleted file mode 100644 index bd98c24fd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/logviewer/LogViewerView.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.ui.modules.about.logviewer - -import io.github.wulkanowy.ui.base.BaseView -import java.io.File - -interface LogViewerView : BaseView { - - fun initView() - - fun setLines(lines: List) - - fun shareLogs(files: List) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/Account.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/Account.kt deleted file mode 100644 index dbcb499e8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/Account.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -data class Account(val email: String, val isParent: Boolean) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt deleted file mode 100644 index 27915a710..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountAdapter.kt +++ /dev/null @@ -1,88 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -import android.annotation.SuppressLint -import android.graphics.PorterDuff -import android.view.LayoutInflater -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.HeaderAccountBinding -import io.github.wulkanowy.databinding.ItemAccountBinding -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.getThemeAttrColor -import javax.inject.Inject - -class AccountAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList>() - - var onClickListener: (Student) -> Unit = {} - - override fun getItemCount() = items.size - - override fun getItemViewType(position: Int) = items[position].viewType.id - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - AccountItem.ViewType.HEADER.id -> HeaderViewHolder(HeaderAccountBinding.inflate(inflater, parent, false)) - AccountItem.ViewType.ITEM.id -> ItemViewHolder(ItemAccountBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding, items[position].value as Account) - is ItemViewHolder -> bindItemViewHolder(holder.binding, items[position].value as Student) - } - } - - private fun bindHeaderViewHolder(binding: HeaderAccountBinding, account: Account) { - with(binding) { - accountHeaderEmail.text = account.email - accountHeaderType.setText(if (account.isParent) R.string.account_type_parent else R.string.account_type_student) - } - } - - @SuppressLint("SetTextI18n") - private fun bindItemViewHolder(binding: ItemAccountBinding, student: Student) { - with(binding) { - accountItemName.text = "${student.studentName} ${student.className}" - accountItemSchool.text = student.schoolName - with(accountItemLoginMode) { - visibility = when (Sdk.Mode.valueOf(student.loginMode)) { - Sdk.Mode.API -> { - setText(R.string.account_login_mobile_api) - VISIBLE - } - Sdk.Mode.HYBRID -> { - setText(R.string.account_login_hybrid) - VISIBLE - } - Sdk.Mode.SCRAPPER -> { - GONE - } - } - } - - with(accountItemImage) { - val colorImage = if (student.isCurrent) context.getThemeAttrColor(R.attr.colorPrimary) - else context.getThemeAttrColor(R.attr.colorOnSurface, 153) - - setColorFilter(colorImage, PorterDuff.Mode.SRC_IN) - } - - root.setOnClickListener { onClickListener(student) } - } - } - - class HeaderViewHolder(val binding: HeaderAccountBinding) : - RecyclerView.ViewHolder(binding.root) - - class ItemViewHolder(val binding: ItemAccountBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt deleted file mode 100644 index 320613745..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountDialog.kt +++ /dev/null @@ -1,100 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG -import androidx.appcompat.app.AlertDialog -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.DialogAccountBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import javax.inject.Inject - -class AccountDialog : BaseDialogFragment(), AccountView { - - @Inject - lateinit var presenter: AccountPresenter - - @Inject - lateinit var accountAdapter: AccountAdapter - - companion object { - fun newInstance() = AccountDialog() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogAccountBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - presenter.onAttachView(this) - } - - override fun initView() { - accountAdapter.onClickListener = presenter::onItemSelected - - with(binding) { - accountDialogAdd.setOnClickListener { presenter.onAddSelected() } - accountDialogRemove.setOnClickListener { presenter.onRemoveSelected() } - accountDialogRecycler.apply { - layoutManager = LinearLayoutManager(context) - adapter = accountAdapter - } - } - } - - override fun updateData(data: List>) { - with(accountAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun showError(text: String, error: Throwable) { - showMessage(text) - } - - override fun showMessage(text: String) { - Toast.makeText(context, text, LENGTH_LONG).show() - } - - override fun dismissView() { - dismiss() - } - - override fun openLoginView() { - activity?.let { - startActivity(LoginActivity.getStartIntent(it)) - } - } - - override fun showConfirmDialog() { - context?.let { - AlertDialog.Builder(it) - .setTitle(R.string.account_logout_student) - .setMessage(R.string.account_confirm) - .setPositiveButton(R.string.account_logout) { _, _ -> presenter.onLogoutConfirm() } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - } - - override fun recreateMainView() { - activity?.recreate() - } - - override fun onDestroy() { - presenter.onDetachView() - super.onDestroy() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt deleted file mode 100644 index 05a4a69ce..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountItem.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -data class AccountItem(val value: T, val viewType: ViewType) { - - enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) - } -} 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 deleted file mode 100644 index b5fbcdb63..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt +++ /dev/null @@ -1,108 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.services.sync.SyncManager -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Single -import timber.log.Timber -import javax.inject.Inject - -class AccountPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val syncManager: SyncManager -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: AccountView) { - super.onAttachView(view) - view.initView() - Timber.i("Account dialog view was initialized") - loadData() - } - - fun onAddSelected() { - Timber.i("Select add account") - view?.openLoginView() - } - - fun onRemoveSelected() { - Timber.i("Select remove account") - view?.showConfirmDialog() - } - - fun onLogoutConfirm() { - Timber.i("Attempt to logout current user ") - disposable.add(studentRepository.getCurrentStudent() - .flatMapCompletable { studentRepository.logoutStudent(it) } - .andThen(studentRepository.getSavedStudents(false)) - .flatMap { - if (it.isNotEmpty()) studentRepository.switchStudent(it[0]).toSingle { it } - else Single.just(it) - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { view?.dismissView() } - .subscribe({ - view?.apply { - if (it.isEmpty()) { - Timber.i("Logout result: Open login view") - syncManager.stopSyncWorker() - openClearLoginView() - } else { - Timber.i("Logout result: Switch to another student") - recreateMainView() - } - } - }, { - Timber.i("Logout result: An exception occurred") - errorHandler.dispatch(it) - })) - } - - fun onItemSelected(student: Student) { - Timber.i("Select student item ${student.id}") - if (student.isCurrent) { - view?.dismissView() - } else { - Timber.i("Attempt to change a student") - disposable.add(studentRepository.switchStudent(student) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { view?.dismissView() } - .subscribe({ - Timber.i("Change a student result: Success") - view?.recreateMainView() - }, { - Timber.i("Change a student result: An exception occurred") - errorHandler.dispatch(it) - })) - } - } - - private fun createAccountItems(items: List): List> { - return items.groupBy { Account(it.email, it.isParent) }.map { (account, students) -> - listOf(AccountItem(account, AccountItem.ViewType.HEADER)) + students.map { student -> - AccountItem(student, AccountItem.ViewType.ITEM) - } - }.flatten() - } - - private fun loadData() { - Timber.i("Loading account data started") - disposable.add(studentRepository.getSavedStudents(false) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .map { createAccountItems(it) } - .subscribe({ - Timber.i("Loading account result: Success") - view?.updateData(it) - }, { - Timber.i("Loading account result: An exception occurred") - errorHandler.dispatch(it) - })) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountView.kt deleted file mode 100644 index a1f8086cd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountView.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.ui.modules.account - -import io.github.wulkanowy.ui.base.BaseView - -interface AccountView : BaseView { - - fun initView() - - fun updateData(data: List>) - - fun dismissView() - - fun showConfirmDialog() - - fun openLoginView() - - fun recreateMainView() -} - 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 deleted file mode 100644 index a63d5045a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceAdapter.kt +++ /dev/null @@ -1,80 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.data.repositories.attendance.SentExcuseStatus -import io.github.wulkanowy.databinding.ItemAttendanceBinding -import javax.inject.Inject - -class AttendanceAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = emptyList() - - var excuseActionMode: Boolean = false - - var onClickListener: (Attendance) -> Unit = {} - - var onExcuseCheckboxSelect: (attendanceItem: Attendance, checked: Boolean) -> Unit = { _, _ -> } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemAttendanceBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - attendanceItemNumber.text = item.number.toString() - attendanceItemSubject.text = item.subject - attendanceItemDescription.text = item.name - attendanceItemAlert.visibility = item.run { if (absence && !excused) View.VISIBLE else View.INVISIBLE } - attendanceItemNumber.visibility = View.GONE - attendanceItemExcuseInfo.visibility = View.GONE - attendanceItemExcuseCheckbox.visibility = View.GONE - attendanceItemExcuseCheckbox.isChecked = false - attendanceItemExcuseCheckbox.setOnCheckedChangeListener { _, checked -> - onExcuseCheckboxSelect(item, checked) - } - - when (if (item.excuseStatus != null) SentExcuseStatus.valueOf(item.excuseStatus) else null) { - SentExcuseStatus.WAITING -> { - attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_waiting) - attendanceItemExcuseInfo.visibility = View.VISIBLE - attendanceItemAlert.visibility = View.INVISIBLE - } - SentExcuseStatus.DENIED -> { - attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_denied) - attendanceItemExcuseInfo.visibility = View.VISIBLE - } - else -> { - if (item.excusable && excuseActionMode) { - attendanceItemNumber.visibility = View.GONE - attendanceItemExcuseCheckbox.visibility = View.VISIBLE - } else { - attendanceItemNumber.visibility = View.VISIBLE - attendanceItemExcuseCheckbox.visibility = View.GONE - } - } - } - root.setOnClickListener { - onClickListener(item) - - with(attendanceItemExcuseCheckbox) { - if (excuseActionMode && isVisible) { - isChecked = !isChecked - } - } - } - } - } - - class ItemViewHolder(val binding: ItemAttendanceBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt deleted file mode 100644 index 97b76e812..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.databinding.DialogAttendanceBinding -import io.github.wulkanowy.utils.lifecycleAwareVariable -import io.github.wulkanowy.utils.toFormattedString - -class AttendanceDialog : DialogFragment() { - - private var binding: DialogAttendanceBinding by lifecycleAwareVariable() - - private lateinit var attendance: Attendance - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(exam: Attendance): AttendanceDialog { - return AttendanceDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - attendance = getSerializable(ARGUMENT_KEY) as Attendance - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogAttendanceBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(binding) { - attendanceDialogSubject.text = attendance.subject - attendanceDialogDescription.text = attendance.name - attendanceDialogDate.text = attendance.date.toFormattedString() - attendanceDialogNumber.text = attendance.number.toString() - attendanceDialogClose.setOnClickListener { dismiss() } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt deleted file mode 100644 index 6599243dd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt +++ /dev/null @@ -1,269 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance - -import android.content.DialogInterface.BUTTON_POSITIVE -import android.os.Bundle -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.view.ActionMode -import androidx.recyclerview.widget.LinearLayoutManager -import com.wdullaer.materialdatetimepicker.date.DatePickerDialog -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.databinding.DialogExcuseBinding -import io.github.wulkanowy.databinding.FragmentAttendanceBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.SchooldaysRangeLimiter -import io.github.wulkanowy.utils.dpToPx -import org.threeten.bp.LocalDate -import javax.inject.Inject - -class AttendanceFragment : BaseFragment(R.layout.fragment_attendance), AttendanceView, MainView.MainChildView, - MainView.TitledView { - - @Inject - lateinit var presenter: AttendancePresenter - - @Inject - lateinit var attendanceAdapter: AttendanceAdapter - - override val excuseSuccessString: String - get() = getString(R.string.attendance_excuse_success) - - override val excuseNoSelectionString: String - get() = getString(R.string.attendance_excuse_no_selection) - - companion object { - private const val SAVED_DATE_KEY = "CURRENT_DATE" - - fun newInstance() = AttendanceFragment() - } - - override val titleStringId get() = R.string.attendance_title - - override val isViewEmpty get() = attendanceAdapter.items.isEmpty() - - override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize - - override val excuseActionMode: Boolean get() = attendanceAdapter.excuseActionMode - - private var actionMode: ActionMode? = null - private val actionModeCallback = object : ActionMode.Callback { - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { - val inflater = mode.menuInflater - inflater.inflate(R.menu.context_menu_excuse, menu) - return true - } - - override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { - mode.title = getString(R.string.attendance_excuse_title) - return presenter.onPrepareActionMode() - } - - override fun onDestroyActionMode(mode: ActionMode) { - presenter.onDestroyActionMode() - actionMode = null - } - - override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean { - return when (menu.itemId) { - R.id.excuseMenuSubmit -> presenter.onExcuseSubmitButtonClick() - else -> false - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentAttendanceBinding.bind(view) - messageContainer = binding.attendanceRecycler - presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) - } - - override fun initView() { - with(attendanceAdapter) { - onClickListener = presenter::onAttendanceItemSelected - onExcuseCheckboxSelect = presenter::onExcuseCheckboxSelect - } - - with(binding.attendanceRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = attendanceAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - attendanceErrorRetry.setOnClickListener { presenter.onRetry() } - attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - attendancePreviousButton.setOnClickListener { presenter.onPreviousDay() } - attendanceNavDate.setOnClickListener { presenter.onPickDate() } - attendanceNextButton.setOnClickListener { presenter.onNextDay() } - - attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() } - - attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_attendance, menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.attendanceMenuSummary) presenter.onSummarySwitchSelected() - else false - } - - override fun updateData(data: List) { - with(attendanceAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun updateNavigationDay(date: String) { - binding.attendanceNavDate.text = date - } - - override fun clearData() { - with(attendanceAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun resetView() { - binding.attendanceRecycler.smoothScrollToPosition(0) - } - - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun onFragmentChanged() { - if (::presenter.isInitialized) presenter.onMainViewChanged() - } - - override fun popView() { - (activity as? MainActivity)?.popView() - } - - override fun showEmpty(show: Boolean) { - binding.attendanceEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.attendanceError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.attendanceErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.attendanceProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.attendanceSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun hideRefresh() { - binding.attendanceSwipe.isRefreshing = false - } - - override fun showPreButton(show: Boolean) { - binding.attendancePreviousButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding. attendanceNextButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showExcuseButton(show: Boolean) { - binding.attendanceExcuseButton.visibility = if (show) VISIBLE else GONE - } - - override fun showAttendanceDialog(lesson: Attendance) { - (activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson)) - } - - 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@AttendanceFragment.parentFragmentManager, null) - } - } - - override fun showExcuseDialog() { - val dialogBinding = DialogExcuseBinding.inflate(LayoutInflater.from(context)) - AlertDialog.Builder(requireContext()) - .setTitle(R.string.attendance_excuse_title) - .setView(dialogBinding.root) - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .create() - .apply { - setButton(BUTTON_POSITIVE, getString(R.string.attendance_excuse_dialog_submit)) { _, _ -> - presenter.onExcuseDialogSubmit(dialogBinding.excuseReason.text?.toString().orEmpty()) - } - }.show() - } - - override fun openSummaryView() { - (activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance()) - } - - override fun startActionMode() { - actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback) - } - - override fun showExcuseCheckboxes(show: Boolean) { - attendanceAdapter.apply { - excuseActionMode = show - notifyDataSetChanged() - } - } - - override fun finishActionMode() { - actionMode?.finish() - } - - 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/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt deleted file mode 100644 index f58d0617f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt +++ /dev/null @@ -1,298 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance - -import android.annotation.SuppressLint -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday -import io.github.wulkanowy.utils.isHolidays -import io.github.wulkanowy.utils.nextSchoolDay -import io.github.wulkanowy.utils.previousOrSameSchoolDay -import io.github.wulkanowy.utils.previousSchoolDay -import io.github.wulkanowy.utils.toFormattedString -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.LocalDate.ofEpochDay -import timber.log.Timber -import javax.inject.Inject - -class AttendancePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val attendanceRepository: AttendanceRepository, - private val semesterRepository: SemesterRepository, - private val prefRepository: PreferencesRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var baseDate: LocalDate = now().previousOrSameSchoolDay - - lateinit var currentDate: LocalDate - private set - - private lateinit var lastError: Throwable - - private val attendanceToExcuseList = mutableListOf() - - fun onAttachView(view: AttendanceView, date: Long?) { - super.onAttachView(view) - view.initView() - Timber.i("Attendance view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) - if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() - } - - fun onPreviousDay() { - view?.finishActionMode() - attendanceToExcuseList.clear() - loadData(currentDate.previousSchoolDay) - reloadView() - } - - fun onNextDay() { - view?.finishActionMode() - attendanceToExcuseList.clear() - 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 attendance") - loadData(currentDate, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentDate, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onViewReselected() { - Timber.i("Attendance view is reselected") - view?.also { view -> - if (view.currentStackSize == 1) { - baseDate.also { - if (currentDate != it) { - loadData(it) - reloadView() - } else if (!view.isViewEmpty) view.resetView() - } - } else view.popView() - } - } - - fun onMainViewChanged() { - view?.finishActionMode() - } - - fun onAttendanceItemSelected(attendance: Attendance) { - view?.apply { - if (!excuseActionMode) { - Timber.i("Select attendance item ${attendance.id}") - showAttendanceDialog(attendance) - } - } - } - - fun onExcuseButtonClick() { - view?.startActionMode() - } - - fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) { - if (checked) attendanceToExcuseList.add(attendanceItem) - else attendanceToExcuseList.remove(attendanceItem) - } - - fun onExcuseSubmitButtonClick(): Boolean { - view?.apply { - return if (attendanceToExcuseList.isNotEmpty()) { - showExcuseDialog() - true - } else { - showMessage(excuseNoSelectionString) - false - } - } - return false - } - - fun onExcuseDialogSubmit(reason: String) { - view?.finishActionMode() - excuseAbsence(if (reason != "") reason else null, attendanceToExcuseList.toList()) - } - - fun onPrepareActionMode(): Boolean { - view?.apply { - showExcuseCheckboxes(true) - showExcuseButton(false) - } - attendanceToExcuseList.clear() - return true - } - - fun onDestroyActionMode() { - view?.apply { - showExcuseCheckboxes(false) - showExcuseButton(true) - } - } - - fun onSummarySwitchSelected(): Boolean { - view?.openSummaryView() - return true - } - - private fun setBaseDateOnHolidays() { - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) - currentDate = baseDate - reloadNavigation() - }) { - Timber.i("Loading semester result: An exception occurred") - }) - } - - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - Timber.i("Loading attendance data started") - currentDate = date - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - attendanceRepository.getAttendance(student, semester, date, date, forceRefresh) - } - } - .map { list -> - if (prefRepository.isShowPresent) list - else list.filter { !it.presence } - } - .map { items -> items.sortedBy { it.number } } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading attendance result: Success") - view?.apply { - updateData(it) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - showExcuseButton(it.any { item -> item.excusable }) - } - analytics.logEvent( - "load_data", - "type" to "attendance", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading attendance result: An exception occurred") - errorHandler.dispatch(it) - } - ) - } - } - - private fun excuseAbsence(reason: String?, toExcuseList: List) { - Timber.i("Excusing absence started") - disposable.apply { - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - attendanceRepository.excuseForAbsence(student, semester, toExcuseList, reason) - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.apply { - showProgress(true) - showContent(false) - showExcuseButton(false) - } - } - .subscribe({ - Timber.i("Excusing for absence result: Success") - analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size) - attendanceToExcuseList.clear() - view?.apply { - showExcuseButton(false) - showMessage(excuseSuccessString) - } - loadData(currentDate, true) - }) { - Timber.i("Excusing for absence result: An exception occurred") - view?.showProgress(false) - errorHandler.dispatch(it) - }) - } - } - - 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 attendance 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/attendance/AttendanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt deleted file mode 100644 index 484070a2e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceView.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance - -import io.github.wulkanowy.data.db.entities.Attendance -import io.github.wulkanowy.ui.base.BaseView -import org.threeten.bp.LocalDate - -interface AttendanceView : BaseView { - - val isViewEmpty: Boolean - - val currentStackSize: Int? - - val excuseSuccessString: String - - val excuseNoSelectionString: String - - val excuseActionMode: Boolean - - fun initView() - - fun updateData(data: List) - - fun updateNavigationDay(date: String) - - fun clearData() - - fun hideRefresh() - - fun resetView() - - 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 showExcuseButton(show: Boolean) - - fun showAttendanceDialog(lesson: Attendance) - - fun showDatePickerDialog(currentDate: LocalDate) - - fun showExcuseDialog() - - fun openSummaryView() - - fun startActionMode() - - fun showExcuseCheckboxes(show: Boolean) - - fun finishActionMode() - - fun popView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt deleted file mode 100644 index 236c3da16..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt +++ /dev/null @@ -1,101 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance.summary - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.databinding.ItemAttendanceSummaryBinding -import io.github.wulkanowy.databinding.ScrollableHeaderAttendanceSummaryBinding -import io.github.wulkanowy.utils.calculatePercentage -import io.github.wulkanowy.utils.getFormattedName -import org.threeten.bp.Month -import java.util.Locale -import javax.inject.Inject - -class AttendanceSummaryAdapter @Inject constructor() : - RecyclerView.Adapter() { - - private enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) - } - - var items = emptyList() - - override fun getItemCount() = if (items.isNotEmpty()) items.size + 2 else 0 - - override fun getItemViewType(position: Int) = when (position) { - 0 -> ViewType.HEADER.id - else -> ViewType.ITEM.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.HEADER.id -> HeaderViewHolder(ScrollableHeaderAttendanceSummaryBinding.inflate(inflater, parent, false)) - ViewType.ITEM.id -> ItemViewHolder(ItemAttendanceSummaryBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding) - is ItemViewHolder -> bindItemViewHolder(holder.binding, position - 2) - } - } - - private fun bindHeaderViewHolder(binding: ScrollableHeaderAttendanceSummaryBinding) { - binding.attendanceSummaryScrollableHeaderPercentage.text = formatPercentage(items.calculatePercentage()) - } - - private fun bindItemViewHolder(binding: ItemAttendanceSummaryBinding, position: Int) { - val item = if (position == -1) getTotalItem() else items[position] - - with(binding) { - attendanceSummaryMonth.text = when (position) { - -1 -> root.context.getString(R.string.attendance_summary_total) - else -> item.month.getFormattedName() - } - attendanceSummaryPercentage.text = when (position) { - -1 -> formatPercentage(items.calculatePercentage()) - else -> formatPercentage(item.calculatePercentage()) - } - - attendanceSummaryPresent.text = item.presence.toString() - attendanceSummaryAbsenceUnexcused.text = item.absence.toString() - attendanceSummaryAbsenceExcused.text = item.absenceExcused.toString() - attendanceSummaryAbsenceSchool.text = item.absenceForSchoolReasons.toString() - attendanceSummaryExemption.text = item.exemption.toString() - attendanceSummaryLatenessUnexcused.text = item.lateness.toString() - attendanceSummaryLatenessExcused.text = item.latenessExcused.toString() - } - } - - private fun getTotalItem() = AttendanceSummary( - month = Month.APRIL, - presence = items.sumBy { it.presence }, - absence = items.sumBy { it.absence }, - absenceExcused = items.sumBy { it.absenceExcused }, - absenceForSchoolReasons = items.sumBy { it.absenceForSchoolReasons }, - exemption = items.sumBy { it.exemption }, - lateness = items.sumBy { it.lateness }, - latenessExcused = items.sumBy { it.latenessExcused }, - diaryId = -1, - studentId = -1, - subjectId = -1 - ) - - private fun formatPercentage(percentage: Double): String { - return if (percentage == 0.0) "0%" - else "${String.format(Locale.FRANCE, "%.2f", percentage)}%" - } - - class HeaderViewHolder(val binding: ScrollableHeaderAttendanceSummaryBinding) : - RecyclerView.ViewHolder(binding.root) - - class ItemViewHolder(val binding: ItemAttendanceSummaryBinding) : - RecyclerView.ViewHolder(binding.root) -} 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 deleted file mode 100644 index 1b9fe08ef..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryFragment.kt +++ /dev/null @@ -1,135 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance.summary - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import android.widget.ArrayAdapter -import android.widget.TextView -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.databinding.FragmentAttendanceSummaryBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.setOnItemSelectedListener -import javax.inject.Inject - -class AttendanceSummaryFragment : - BaseFragment(R.layout.fragment_attendance_summary), - AttendanceSummaryView, MainView.TitledView { - - @Inject - lateinit var presenter: AttendanceSummaryPresenter - - @Inject - lateinit var attendanceSummaryAdapter: AttendanceSummaryAdapter - - private lateinit var subjectsAdapter: ArrayAdapter - - companion object { - private const val SAVED_SUBJECT_KEY = "CURRENT_SUBJECT" - - fun newInstance() = AttendanceSummaryFragment() - } - - override val titleStringId get() = R.string.attendance_title - - override val isViewEmpty get() = attendanceSummaryAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentAttendanceSummaryBinding.bind(view) - messageContainer = binding.attendanceSummaryRecycler - presenter.onAttachView(this, savedInstanceState?.getInt(SAVED_SUBJECT_KEY)) - } - - override fun initView() { - with(binding.attendanceSummaryRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = attendanceSummaryAdapter - } - - with(binding) { - attendanceSummarySwipe.setOnRefreshListener(presenter::onSwipeRefresh) - attendanceSummaryErrorRetry.setOnClickListener { presenter.onRetry() } - attendanceSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - - subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf()) - subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject) - - with(binding.attendanceSummarySubjects) { - adapter = subjectsAdapter - setOnItemSelectedListener { presenter.onSubjectSelected(it?.text?.toString()) } - } - - binding.attendanceSummarySubjectsContainer.setElevationCompat(requireContext().dpToPx(1f)) - } - - override fun updateSubjects(data: ArrayList) { - with(subjectsAdapter) { - clear() - addAll(data) - notifyDataSetChanged() - } - } - - override fun updateDataSet(data: List) { - with(attendanceSummaryAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun clearView() { - with(attendanceSummaryAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun showEmpty(show: Boolean) { - binding.attendanceSummaryEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.attendanceSummaryError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.attendanceSummaryErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.attendanceSummaryProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.attendanceSummarySwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.attendanceSummaryRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showSubjects(show: Boolean) { - binding.attendanceSummarySubjectsContainer.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun hideRefresh() { - binding.attendanceSummarySwipe.isRefreshing = false - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putInt(SAVED_SUBJECT_KEY, presenter.currentSubjectId) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 33e18c2e7..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryPresenter.kt +++ /dev/null @@ -1,152 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance.summary - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import org.threeten.bp.Month -import timber.log.Timber -import javax.inject.Inject - -class AttendanceSummaryPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val attendanceSummaryRepository: AttendanceSummaryRepository, - private val subjectRepository: SubjectRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var subjects = emptyList() - - var currentSubjectId = -1 - private set - - private lateinit var lastError: Throwable - - fun onAttachView(view: AttendanceSummaryView, subjectId: Int?) { - super.onAttachView(view) - view.initView() - Timber.i("Attendance summary view was initialized with subject id ${subjectId ?: -1}") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(subjectId ?: -1) - loadSubjects() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the attendance summary") - loadData(currentSubjectId, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentSubjectId, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onSubjectSelected(name: String?) { - Timber.i("Select attendance summary subject $name") - view?.run { - showContent(false) - showProgress(true) - enableSwipe(false) - showEmpty(false) - showErrorView(false) - clearView() - } - (subjects.singleOrNull { it.name == name }?.realId ?: -1).let { - if (it != currentSubjectId) loadData(it) - } - } - - private fun loadData(subjectId: Int, forceRefresh: Boolean = false) { - Timber.i("Loading attendance summary data started") - currentSubjectId = subjectId - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { - attendanceSummaryRepository.getAttendanceSummary(student, it, subjectId, forceRefresh) - } - } - .map { items -> items.sortedByDescending { if (it.month.value <= Month.JUNE.value) it.month.value + 12 else it.month.value } } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading attendance summary result: Success") - view?.apply { - showEmpty(it.isEmpty()) - showContent(it.isNotEmpty()) - updateDataSet(it) - } - analytics.logEvent( - "load_data", - "type" to "attendance_summary", - "items" to it.size, - "force_refresh" to forceRefresh, - "item_id" to subjectId - ) - }) { - Timber.i("Loading attendance summary result: An exception occurred") - errorHandler.dispatch(it) - } - ) - } - } - - 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 loadSubjects() { - Timber.i("Loading attendance summary subjects started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - subjectRepository.getSubjects(student, semester) - } - } - .doOnSuccess { subjects = it } - .map { ArrayList(it.map { subject -> subject.name }) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Loading attendance summary subjects result: Success") - view?.run { - view?.updateSubjects(it) - showSubjects(true) - } - }, { - Timber.i("Loading attendance summary subjects result: An exception occurred") - errorHandler.dispatch(it) - }) - ) - } -} 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 deleted file mode 100644 index dd4053c72..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryView.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.wulkanowy.ui.modules.attendance.summary - -import io.github.wulkanowy.data.db.entities.AttendanceSummary -import io.github.wulkanowy.ui.base.BaseView - -interface AttendanceSummaryView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun hideRefresh() - - fun showContent(show: Boolean) - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun updateDataSet(data: List) - - fun updateSubjects(data: ArrayList) - - fun showSubjects(show: Boolean) - - fun clearView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamAdapter.kt deleted file mode 100644 index 85061997c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamAdapter.kt +++ /dev/null @@ -1,65 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.databinding.HeaderExamBinding -import io.github.wulkanowy.databinding.ItemExamBinding -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.utils.weekDayName -import org.threeten.bp.LocalDate -import javax.inject.Inject - -class ExamAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList>() - - var onClickListener: (Exam) -> Unit = {} - - override fun getItemCount() = items.size - - override fun getItemViewType(position: Int) = items[position].viewType.id - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ExamItem.ViewType.HEADER.id -> HeaderViewHolder(HeaderExamBinding.inflate(inflater, parent, false)) - ExamItem.ViewType.ITEM.id -> ItemViewHolder(ItemExamBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding, items[position].value as LocalDate) - is ItemViewHolder -> bindItemViewHolder(holder.binding, items[position].value as Exam) - } - } - - @SuppressLint("DefaultLocale") - private fun bindHeaderViewHolder(binding: HeaderExamBinding, date: LocalDate) { - with(binding) { - examHeaderDay.text = date.weekDayName.capitalize() - examHeaderDate.text = date.toFormattedString() - } - } - - private fun bindItemViewHolder(binding: ItemExamBinding, exam: Exam) { - with(binding) { - examItemSubject.text = exam.subject - examItemTeacher.text = exam.teacher - examItemType.text = exam.type - - root.setOnClickListener { onClickListener(exam) } - } - } - - private class HeaderViewHolder(val binding: HeaderExamBinding) : - RecyclerView.ViewHolder(binding.root) - - private class ItemViewHolder(val binding: ItemExamBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt deleted file mode 100644 index c1a6f1f0d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.databinding.DialogExamBinding -import io.github.wulkanowy.utils.lifecycleAwareVariable -import io.github.wulkanowy.utils.toFormattedString - -class ExamDialog : DialogFragment() { - - private var binding: DialogExamBinding by lifecycleAwareVariable() - - private lateinit var exam: Exam - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(exam: Exam): ExamDialog { - return ExamDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - exam = getSerializable(ARGUMENT_KEY) as Exam - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogExamBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(binding) { - examDialogSubjectValue.text = exam.subject - examDialogTypeValue.text = exam.type - examDialogTeacherValue.text = exam.teacher - examDialogDateValue.text = exam.entryDate.toFormattedString() - examDialogDescriptionValue.text = exam.description - - examDialogClose.setOnClickListener { dismiss() } - } - } -} 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 deleted file mode 100644 index eeab30c15..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamFragment.kt +++ /dev/null @@ -1,141 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.databinding.FragmentExamBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.dpToPx -import javax.inject.Inject - -class ExamFragment : BaseFragment(R.layout.fragment_exam), ExamView, - MainView.MainChildView, MainView.TitledView { - - @Inject - lateinit var presenter: ExamPresenter - - @Inject - lateinit var examAdapter: ExamAdapter - - companion object { - private const val SAVED_DATE_KEY = "CURRENT_DATE" - - fun newInstance() = ExamFragment() - } - - override val titleStringId get() = R.string.exam_title - - override val isViewEmpty get() = examAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentExamBinding.bind(view) - messageContainer = binding.examRecycler - presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) - } - - override fun initView() { - examAdapter.onClickListener = presenter::onExamItemSelected - - with(binding.examRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = examAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - examSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - examErrorRetry.setOnClickListener { presenter.onRetry() } - examErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - examPreviousButton.setOnClickListener { presenter.onPreviousWeek() } - examNextButton.setOnClickListener { presenter.onNextWeek() } - - examNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun hideRefresh() { - binding.examSwipe.isRefreshing = false - } - - override fun updateData(data: List>) { - with(examAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun updateNavigationWeek(date: String) { - binding.examNavDate.text = date - } - - override fun clearData() { - with(examAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun resetView() { - binding.examRecycler.scrollToPosition(0) - } - - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun showEmpty(show: Boolean) { - binding.examEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.examError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.examErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.examProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.examSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.examRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showPreButton(show: Boolean) { - binding.examPreviousButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding.examNextButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showExamDialog(exam: Exam) { - (activity as? MainActivity)?.showDialogFragment(ExamDialog.newInstance(exam)) - } - - 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/exam/ExamItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt deleted file mode 100644 index 579e37203..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamItem.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -data class ExamItem(val value: T, val viewType: ViewType) { - - enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) - } -} 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 deleted file mode 100644 index 1140cb020..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamPresenter.kt +++ /dev/null @@ -1,187 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday -import io.github.wulkanowy.utils.isHolidays -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.toFormattedString -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.LocalDate.ofEpochDay -import timber.log.Timber -import javax.inject.Inject - -class ExamPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val examRepository: ExamRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var baseDate: LocalDate = now().nextOrSameSchoolDay - - lateinit var currentDate: LocalDate - private set - - private lateinit var lastError: Throwable - - fun onAttachView(view: ExamView, date: Long?) { - super.onAttachView(view) - view.initView() - Timber.i("Exam view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) - if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() - } - - fun onPreviousWeek() { - loadData(currentDate.minusDays(7)) - reloadView() - } - - fun onNextWeek() { - loadData(currentDate.plusDays(7)) - reloadView() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the exam") - loadData(currentDate, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentDate, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onExamItemSelected(exam: Exam) { - Timber.i("Select exam item ${exam.id}") - view?.showExamDialog(exam) - } - - fun onViewReselected() { - Timber.i("Exam view is reselected") - baseDate.also { - if (currentDate != it) { - loadData(it) - reloadView() - } else if (view?.isViewEmpty == false) view?.resetView() - } - } - - private fun setBaseDateOnHolidays() { - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) - currentDate = baseDate - reloadNavigation() - }) { - Timber.i("Loading semester result: An exception occurred") - }) - } - - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - Timber.i("Loading exam data started") - currentDate = date - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh) - } - } - .map { createExamItems(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading exam result: Success") - view?.apply { - updateData(it) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - } - analytics.logEvent( - "load_data", - "type" to "exam", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading exam result: An exception occurred") - errorHandler.dispatch(it) - }) - } - } - - 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 createExamItems(items: List): List> { - return items.groupBy { it.date }.toSortedMap().map { (date, exams) -> - listOf(ExamItem(date, ExamItem.ViewType.HEADER)) + exams.reversed().map { exam -> - ExamItem(exam, ExamItem.ViewType.ITEM) - } - }.flatten() - } - - private fun reloadView() { - Timber.i("Reload exam view with the date ${currentDate.toFormattedString()}") - view?.apply { - showProgress(true) - enableSwipe(false) - showContent(false) - showEmpty(false) - showErrorView(false) - clearData() - reloadNavigation() - } - } - - private fun reloadNavigation() { - view?.apply { - showPreButton(!currentDate.minusDays(7).isHolidays) - showNextButton(!currentDate.plusDays(7).isHolidays) - updateNavigationWeek("${currentDate.monday.toFormattedString("dd.MM")} - " + - currentDate.sunday.toFormattedString("dd.MM")) - } - } -} 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 deleted file mode 100644 index 00429bae6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamView.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.ui.modules.exam - -import io.github.wulkanowy.data.db.entities.Exam -import io.github.wulkanowy.ui.base.BaseView - -interface ExamView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List>) - - fun updateNavigationWeek(date: String) - - fun clearData() - - fun hideRefresh() - - fun resetView() - - 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 showNextButton(show: Boolean) - - fun showPreButton(show: Boolean) - - fun showExamDialog(exam: Exam) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageMode.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageMode.kt deleted file mode 100644 index 1960c3df7..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageMode.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -enum class GradeAverageMode(val value: String) { - ALL_YEAR("all_year"), - ONE_SEMESTER("only_one_semester"), - BOTH_SEMESTERS("both_semesters"); - - companion object { - fun getByValue(value: String) = values().firstOrNull { it.value == value } ?: ONE_SEMESTER - } -} 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 deleted file mode 100644 index af1699323..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt +++ /dev/null @@ -1,125 +0,0 @@ -package io.github.wulkanowy.ui.modules.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.data.repositories.grade.GradeRepository -import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ALL_YEAR -import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.BOTH_SEMESTERS -import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ONE_SEMESTER -import io.github.wulkanowy.utils.calcAverage -import io.github.wulkanowy.utils.changeModifier -import io.reactivex.Single -import javax.inject.Inject - -class GradeAverageProvider @Inject constructor( - private val semesterRepository: SemesterRepository, - private val gradeRepository: GradeRepository, - private val preferencesRepository: PreferencesRepository -) { - - private val plusModifier get() = preferencesRepository.gradePlusModifier - - private val minusModifier get() = preferencesRepository.gradeMinusModifier - - fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean = false): Single> { - return semesterRepository.getSemesters(student).flatMap { semesters -> - when (preferencesRepository.gradeAverageMode) { - ONE_SEMESTER -> getSemesterDetailsWithAverage(student, semesters.single { it.semesterId == semesterId }, forceRefresh) - BOTH_SEMESTERS -> calculateBothSemestersAverage(student, semesters, semesterId, forceRefresh) - ALL_YEAR -> calculateAllYearAverage(student, semesters, semesterId, forceRefresh) - } - } - } - - private fun calculateBothSemestersAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single> { - val selectedSemester = semesters.single { it.semesterId == semesterId } - val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } - - return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMap { selectedDetails -> - val isAnyAverage = selectedDetails.any { it.average != .0 } - - if (selectedSemester != firstSemester) { - getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails -> - selectedDetails.map { selected -> - val second = secondDetails.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) - } - } - } else Single.just(selectedDetails) - } - } - - private fun calculateAllYearAverage(student: Student, semesters: List, semesterId: Int, forceRefresh: Boolean): Single> { - val selectedSemester = semesters.single { it.semesterId == semesterId } - val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 } - - return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMap { selectedDetails -> - val isAnyAverage = selectedDetails.any { it.average != .0 } - - if (selectedSemester != firstSemester) { - getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails -> - selectedDetails.map { selected -> - val second = secondDetails.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) - } - } - } else Single.just(selectedDetails) - } - } - - private fun getSemesterDetailsWithAverage(student: Student, semester: Semester, forceRefresh: Boolean): Single> { - return gradeRepository.getGrades(student, semester, forceRefresh).map { (details, summaries) -> - val isAnyAverage = summaries.any { it.average != .0 } - val allGrades = details.groupBy { it.subject } - - summaries.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage).map { summary -> - val grades = allGrades[summary.subject].orEmpty() - GradeDetailsWithAverage( - subject = summary.subject, - average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) { - grades.updateModifiers(student).calcAverage() - } else summary.average, - points = summary.pointsSum, - summary = summary, - grades = grades - ) - } - } - } - - private fun List.emulateEmptySummaries(student: Student, semester: Semester, grades: List>>, calcAverage: Boolean): List { - if (isNotEmpty() && size > grades.size) return this - - return grades.mapIndexed { i, (subject, details) -> - singleOrNull { it.subject == subject }?.let { return@mapIndexed it } - GradeSummary( - studentId = student.studentId, - semesterId = semester.semesterId, - position = i, - subject = subject, - predictedGrade = "", - finalGrade = "", - proposedPoints = "", - finalPoints = "", - pointsSum = "", - average = if (calcAverage) details.updateModifiers(student).calcAverage() else .0 - ) - } - } - - private fun List.updateModifiers(student: Student): List { - return if (student.loginMode == Sdk.Mode.SCRAPPER.name) { - map { it.changeModifier(plusModifier, minusModifier) } - } else this - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeDetailsWithAverage.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeDetailsWithAverage.kt deleted file mode 100644 index 3f5d706b3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeDetailsWithAverage.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary - -data class GradeDetailsWithAverage( - val subject: String, - val average: Double, - val points: String, - val summary: GradeSummary, - val grades: List -) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt deleted file mode 100644 index 59b83c4b0..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt +++ /dev/null @@ -1,171 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.appcompat.app.AlertDialog -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentGradeBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment -import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment -import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.setOnSelectPageListener -import javax.inject.Inject - -class GradeFragment : BaseFragment(R.layout.fragment_grade), GradeView, MainView.MainChildView, MainView.TitledView { - - @Inject - lateinit var presenter: GradePresenter - - @Inject - lateinit var pagerAdapter: BaseFragmentPagerAdapter - - private var semesterSwitchMenu: MenuItem? = null - - companion object { - private const val SAVED_SEMESTER_KEY = "CURRENT_SEMESTER" - - fun newInstance() = GradeFragment() - } - - override val titleStringId get() = R.string.grade_title - - override var subtitleString = "" - - override val currentPageIndex get() = binding.gradeViewPager.currentItem - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentGradeBinding.bind(view) - presenter.onAttachView(this, savedInstanceState?.getInt(SAVED_SEMESTER_KEY)) - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_grade, menu) - semesterSwitchMenu = menu.findItem(R.id.gradeMenuSemester) - presenter.onCreateMenu() - } - - override fun initView() { - with(pagerAdapter) { - containerId = binding.gradeViewPager.id - addFragmentsWithTitle(mapOf( - GradeDetailsFragment.newInstance() to getString(R.string.all_details), - GradeSummaryFragment.newInstance() to getString(R.string.grade_menu_summary), - GradeStatisticsFragment.newInstance() to getString(R.string.grade_menu_statistics) - )) - } - - with(binding.gradeViewPager) { - adapter = pagerAdapter - offscreenPageLimit = 3 - setOnSelectPageListener(presenter::onPageSelected) - } - - with(binding.gradeTabLayout) { - setupWithViewPager(binding.gradeViewPager) - setElevationCompat(context.dpToPx(4f)) - } - - with(binding) { - gradeErrorRetry.setOnClickListener { presenter.onRetry() } - gradeErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.gradeMenuSemester) presenter.onSemesterSwitch() - else false - } - - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun showContent(show: Boolean) { - with(binding) { - gradeViewPager.visibility = if (show) VISIBLE else INVISIBLE - gradeTabLayout.visibility = if (show) VISIBLE else INVISIBLE - } - } - - override fun showProgress(show: Boolean) { - binding.gradeProgress.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showErrorView(show: Boolean) { - binding.gradeError.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun setErrorDetails(message: String) { - binding.gradeErrorMessage.text = message - } - - override fun showSemesterSwitch(show: Boolean) { - semesterSwitchMenu?.isVisible = show - } - - override fun showSemesterDialog(selectedIndex: Int) { - val choices = arrayOf( - getString(R.string.grade_semester, 1), - getString(R.string.grade_semester, 2) - ) - - AlertDialog.Builder(requireContext()) - .setSingleChoiceItems(choices, selectedIndex) { dialog, which -> - presenter.onSemesterSelected(which) - dialog.dismiss() - } - .setTitle(R.string.grade_switch_semester) - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - - override fun setCurrentSemesterName(semester: Int, schoolYear: Int) { - subtitleString = getString(R.string.grade_subtitle, semester, schoolYear, schoolYear + 1) - (activity as MainView).setViewSubTitle(subtitleString) - } - - fun onChildRefresh() { - presenter.onChildViewRefresh() - } - - fun onChildFragmentLoaded(semesterId: Int) { - presenter.onChildViewLoaded(semesterId) - } - - override fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean) { - (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentLoadData(semesterId, forceRefresh) - } - - override fun notifyChildParentReselected(index: Int) { - (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentReselected() - } - - override fun notifyChildSemesterChange(index: Int) { - (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentChangeSemester() - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putInt(SAVED_SEMESTER_KEY, presenter.selectedIndex) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt deleted file mode 100644 index 342f356cb..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeModule.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.di.scopes.PerChildFragment -import io.github.wulkanowy.di.scopes.PerFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.grade.details.GradeDetailsFragment -import io.github.wulkanowy.ui.modules.grade.statistics.GradeStatisticsFragment -import io.github.wulkanowy.ui.modules.grade.summary.GradeSummaryFragment - -@Suppress("unused") -@Module -abstract class GradeModule { - - companion object { - - @PerFragment - @Provides - fun provideGradeAdapter(fragment: GradeFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) - } - - @PerChildFragment - @ContributesAndroidInjector - abstract fun bindGradeDetailsFragment(): GradeDetailsFragment - - @PerChildFragment - @ContributesAndroidInjector - abstract fun binGradeSummaryFragment(): GradeSummaryFragment - - @PerChildFragment - @ContributesAndroidInjector - abstract fun binGradeStatisticsFragment(): GradeStatisticsFragment -} 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 deleted file mode 100644 index ec66e2bd9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ /dev/null @@ -1,148 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.getCurrentOrLast -import timber.log.Timber -import java.util.concurrent.TimeUnit.MILLISECONDS -import javax.inject.Inject - -class GradePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - var selectedIndex = 0 - private set - - private var schoolYear = 0 - - private var semesters = emptyList() - - private val loadedSemesterId = mutableMapOf() - - private lateinit var lastError: Throwable - - fun onAttachView(view: GradeView, savedIndex: Int?) { - super.onAttachView(view) - selectedIndex = savedIndex ?: 0 - view.initView() - Timber.i("Grade view was initialized with $selectedIndex index") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - fun onCreateMenu() { - if (semesters.isEmpty()) view?.showSemesterSwitch(false) - } - - fun onViewReselected() { - Timber.i("Grade view is reselected") - view?.run { notifyChildParentReselected(currentPageIndex) } - } - - fun onSemesterSwitch(): Boolean { - if (semesters.isNotEmpty()) view?.showSemesterDialog(selectedIndex - 1) - return true - } - - fun onSemesterSelected(index: Int) { - if (selectedIndex != index - 1) { - Timber.i("Change semester in grade view to ${index + 1}") - selectedIndex = index + 1 - loadedSemesterId.clear() - view?.let { - it.setCurrentSemesterName(index + 1, schoolYear) - notifyChildrenSemesterChange() - loadChild(it.currentPageIndex) - } - analytics.logEvent("changed_semester", "number" to index + 1) - } - } - - fun onChildViewRefresh() { - view?.let { loadChild(it.currentPageIndex, true) } - } - - fun onChildViewLoaded(semesterId: Int) { - view?.apply { - showContent(true) - showProgress(false) - showErrorView(false) - loadedSemesterId[currentPageIndex] = semesterId - } - } - - fun onPageSelected(index: Int) { - if (semesters.isNotEmpty()) loadChild(index) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData() - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - private fun loadData() { - Timber.i("Loading grade data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getSemesters(it, refreshOnNoCurrent = true) } - .delay(200, MILLISECONDS) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - val current = it.getCurrentOrLast() - selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex - schoolYear = current.schoolYear - semesters = it.filter { semester -> semester.diaryId == current.diaryId } - view?.setCurrentSemesterName(current.semesterName, schoolYear) - - view?.run { - Timber.i("Loading grade result: Attempt load index $currentPageIndex") - loadChild(currentPageIndex) - showErrorView(false) - showSemesterSwitch(true) - } - }) { - Timber.i("Loading grade result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - lastError = error - view?.run { - showProgress(false) - showErrorView(true) - setErrorDetails(message) - } - } - - private fun loadChild(index: Int, forceRefresh: Boolean = false) { - Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${semesters.joinToString { it.semesterName.toString() }}") - semesters.first { it.semesterName == selectedIndex }.semesterId.also { - if (forceRefresh || loadedSemesterId[index] != it) { - Timber.i("Load grade child view index: $index") - view?.notifyChildLoadData(index, it, forceRefresh) - } - } - } - - private fun notifyChildrenSemesterChange() { - for (i in 0..2) view?.notifyChildSemesterChange(i) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt deleted file mode 100644 index 7b52daa88..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade - -import io.github.wulkanowy.ui.base.BaseView - -interface GradeView : BaseView { - - val currentPageIndex: Int - - fun initView() - - fun showContent(show: Boolean) - - fun showProgress(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showSemesterSwitch(show: Boolean) - - fun showSemesterDialog(selectedIndex: Int) - - fun setCurrentSemesterName(semester: Int, schoolYear: Int) - - fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean) - - fun notifyChildParentReselected(index: Int) - - fun notifyChildSemesterChange(index: Int) - - interface GradeChildView { - - fun onParentChangeSemester() - - fun onParentLoadData(semesterId: Int, forceRefresh: Boolean) - - fun onParentReselected() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt deleted file mode 100644 index c129d9485..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsAdapter.kt +++ /dev/null @@ -1,198 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -import android.annotation.SuppressLint -import android.content.res.Resources -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerView.NO_POSITION -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.databinding.HeaderGradeDetailsBinding -import io.github.wulkanowy.databinding.ItemGradeDetailsBinding -import io.github.wulkanowy.ui.base.BaseExpandableAdapter -import io.github.wulkanowy.utils.getBackgroundColor -import io.github.wulkanowy.utils.toFormattedString -import timber.log.Timber -import javax.inject.Inject - -class GradeDetailsAdapter @Inject constructor() : BaseExpandableAdapter() { - - private var headers = mutableListOf() - - private var items = mutableListOf() - - private var expandedPosition = NO_POSITION - - private var isExpandable = false - - var onClickListener: (Grade, position: Int) -> Unit = { _, _ -> } - - var colorTheme = "" - - fun setDataItems(data: List, isExpanded: Boolean = isExpandable) { - headers = data.filter { it.viewType == ViewType.HEADER }.toMutableList() - items = if (isExpanded) headers else data.toMutableList() - isExpandable = isExpanded - expandedPosition = NO_POSITION - } - - fun updateDetailsItem(position: Int, grade: Grade) { - if (items.getOrNull(position)?.viewType != ViewType.ITEM) { - Timber.e("Trying to update item $position on list ${items.size} size, expanded position: $expandedPosition") - return - } - items[position] = GradeDetailsItem(grade, ViewType.ITEM) - notifyItemChanged(position) - } - - fun getHeaderItem(subject: String): GradeDetailsItem { - val candidates = headers.filter { (it.value as GradeDetailsHeader).subject == subject } - - if (candidates.size > 1) { - Timber.e("Header with subject $subject found ${candidates.size} times! Expanded: $expandedPosition. Items: $candidates") - } - - return candidates.first() - } - - fun updateHeaderItem(item: GradeDetailsItem) { - val headerPosition = headers.indexOf(item) - val itemPosition = items.indexOf(item) - - if (headerPosition == NO_POSITION || itemPosition == NO_POSITION) { - Timber.e("Invalid update header positions! Header: $headerPosition, item: $itemPosition") - } - - headers[headerPosition] = item - items[itemPosition] = item - notifyItemChanged(itemPosition) - } - - fun collapseAll() { - if (expandedPosition != -1) { - refreshList(headers) - expandedPosition = NO_POSITION - } - } - - @Synchronized - private fun refreshList(newItems: MutableList) { - val diffCallback = GradeDetailsDiffUtil(items, newItems) - val diffResult = DiffUtil.calculateDiff(diffCallback) - items = newItems - diffResult.dispatchUpdatesTo(this) - } - - override fun getItemCount() = items.size - - override fun getItemViewType(position: Int) = items[position].viewType.id - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.HEADER.id -> HeaderViewHolder(HeaderGradeDetailsBinding.inflate(inflater, parent, false)) - ViewType.ITEM.id -> ItemViewHolder(ItemGradeDetailsBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder( - holder = holder, - header = items[position].value as GradeDetailsHeader, - position = position - ) - is ItemViewHolder -> bindItemViewHolder( - holder = holder, - grade = items[position].value as Grade - ) - } - } - - private fun bindHeaderViewHolder(holder: HeaderViewHolder, header: GradeDetailsHeader, position: Int) { - val headerPosition = headers.indexOf(items[position]) - val adapterPosition = holder.adapterPosition - - with(holder.binding) { - gradeHeaderDivider.visibility = if (adapterPosition == 0) View.GONE else View.VISIBLE - with(gradeHeaderSubject) { - text = header.subject - maxLines = if (headerPosition == expandedPosition) 2 else 1 - } - gradeHeaderAverage.text = formatAverage(header.average, root.context.resources) - gradeHeaderPointsSum.text = root.context.getString(R.string.grade_points_sum, header.pointsSum) - gradeHeaderPointsSum.visibility = if (!header.pointsSum.isNullOrEmpty()) View.VISIBLE else View.GONE - gradeHeaderNumber.text = root.context.resources.getQuantityString(R.plurals.grade_number_item, header.grades.size, header.grades.size) - gradeHeaderNote.visibility = if (header.newGrades > 0) View.VISIBLE else View.GONE - if (header.newGrades > 0) gradeHeaderNote.text = header.newGrades.toString(10) - - gradeHeaderContainer.isEnabled = isExpandable - gradeHeaderContainer.setOnClickListener { - expandedPosition = if (expandedPosition == adapterPosition) -1 else adapterPosition - - if (expandedPosition != NO_POSITION) { - refreshList(headers.toMutableList().apply { - addAll(headerPosition + 1, header.grades) - }) - scrollToHeaderWithSubItems(headerPosition, header.grades.size) - } else { - refreshList(headers) - } - } - } - } - - private fun formatAverage(average: Double?, resources: Resources): String { - return if (average == null || average == .0) resources.getString(R.string.grade_no_average) - else resources.getString(R.string.grade_average, average) - } - - @SuppressLint("SetTextI18n") - private fun bindItemViewHolder(holder: ItemViewHolder, grade: Grade) { - with(holder.binding) { - gradeItemValue.run { - text = grade.entry - setBackgroundResource(grade.getBackgroundColor(colorTheme)) - } - gradeItemDescription.text = when { - grade.description.isNotBlank() -> grade.description - grade.gradeSymbol.isNotBlank() -> grade.gradeSymbol - else -> root.context.getString(R.string.all_no_description) - } - gradeItemDate.text = grade.date.toFormattedString() - gradeItemWeight.text = "${root.context.getString(R.string.grade_weight)}: ${grade.weight}" - gradeItemNote.visibility = if (!grade.isRead) View.VISIBLE else View.GONE - - root.setOnClickListener { - holder.adapterPosition.let { if (it != NO_POSITION) onClickListener(grade, it) } - } - } - } - - private class HeaderViewHolder(val binding: HeaderGradeDetailsBinding) : - RecyclerView.ViewHolder(binding.root) - - private class ItemViewHolder(val binding: ItemGradeDetailsBinding) : - RecyclerView.ViewHolder(binding.root) - - class GradeDetailsDiffUtil(private val old: List, private val new: List) : - DiffUtil.Callback() { - - override fun getOldListSize() = old.size - - override fun getNewListSize() = new.size - - override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition] == new[newItemPosition] - } - - override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition] == new[newItemPosition] - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt deleted file mode 100644 index 698aff3ea..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt +++ /dev/null @@ -1,95 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.View.GONE -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.databinding.DialogGradeBinding -import io.github.wulkanowy.utils.colorStringId -import io.github.wulkanowy.utils.getBackgroundColor -import io.github.wulkanowy.utils.getGradeColor -import io.github.wulkanowy.utils.lifecycleAwareVariable -import io.github.wulkanowy.utils.toFormattedString - -class GradeDetailsDialog : DialogFragment() { - - private var binding: DialogGradeBinding by lifecycleAwareVariable() - - private lateinit var grade: Grade - - private lateinit var colorScheme: String - - companion object { - private const val ARGUMENT_KEY = "Item" - private const val COLOR_SCHEME_KEY = "Scheme" - - fun newInstance(grade: Grade, colorScheme: String): GradeDetailsDialog { - return GradeDetailsDialog().apply { - arguments = Bundle().apply { - putSerializable(ARGUMENT_KEY, grade) - putString(COLOR_SCHEME_KEY, colorScheme) - } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - grade = getSerializable(ARGUMENT_KEY) as Grade - colorScheme = getString(COLOR_SCHEME_KEY) ?: "default" - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogGradeBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(binding) { - gradeDialogSubject.text = grade.subject - - gradeDialogColorAndWeightValue.run { - text = context.getString(R.string.grade_weight_value, grade.weight) - setBackgroundResource(grade.getGradeColor()) - } - - gradeDialogDateValue.text = grade.date.toFormattedString() - gradeDialogColorValue.text = getString(grade.colorStringId) - - gradeDialogCommentValue.apply { - if (grade.comment.isBlank()) { - visibility = GONE - gradeDialogComment.visibility = GONE - } else text = grade.comment - } - - gradeDialogValue.run { - text = grade.entry - setBackgroundResource(grade.getBackgroundColor(colorScheme)) - } - - gradeDialogTeacherValue.text = if (grade.teacher.isBlank()) { - getString(R.string.all_no_data) - } else grade.teacher - - gradeDialogDescriptionValue.text = grade.run { - when { - description.isBlank() && gradeSymbol.isNotBlank() -> gradeSymbol - description.isBlank() && gradeSymbol.isBlank() -> getString(R.string.all_no_description) - gradeSymbol.isNotBlank() && description.isNotBlank() -> "$gradeSymbol - $description" - else -> description - } - } - - gradeDialogClose.setOnClickListener { dismiss() } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt deleted file mode 100644 index ac50b9f53..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsFragment.kt +++ /dev/null @@ -1,172 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.databinding.FragmentGradeDetailsBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.grade.GradeView -import io.github.wulkanowy.ui.modules.main.MainActivity -import javax.inject.Inject - -class GradeDetailsFragment : - BaseFragment(R.layout.fragment_grade_details), GradeDetailsView, - GradeView.GradeChildView { - - @Inject - lateinit var presenter: GradeDetailsPresenter - - @Inject - lateinit var gradeDetailsAdapter: GradeDetailsAdapter - - private var gradeDetailsMenu: Menu? = null - - companion object { - fun newInstance() = GradeDetailsFragment() - } - - override val isViewEmpty - get() = gradeDetailsAdapter.itemCount == 0 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentGradeDetailsBinding.bind(view) - messageContainer = binding.gradeDetailsRecycler - presenter.onAttachView(this) - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_grade_details, menu) - gradeDetailsMenu = menu - presenter.updateMarkAsDoneButton() - } - - override fun initView() { - gradeDetailsAdapter.onClickListener = presenter::onGradeItemSelected - - with(binding) { - with(gradeDetailsRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = gradeDetailsAdapter - } - gradeDetailsSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - gradeDetailsErrorRetry.setOnClickListener { presenter.onRetry() } - gradeDetailsErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.gradeDetailsMenuRead) presenter.onMarkAsReadSelected() - else false - } - - override fun updateData(data: List, isGradeExpandable: Boolean, gradeColorTheme: String) { - with(gradeDetailsAdapter) { - colorTheme = gradeColorTheme - setDataItems(data, isGradeExpandable) - notifyDataSetChanged() - } - } - - override fun updateItem(item: Grade, position: Int) { - gradeDetailsAdapter.updateDetailsItem(position, item) - } - - override fun clearView() { - with(gradeDetailsAdapter) { - setDataItems(mutableListOf()) - notifyDataSetChanged() - } - } - - override fun collapseAllItems() { - gradeDetailsAdapter.collapseAll() - } - - override fun scrollToStart() { - binding.gradeDetailsRecycler.smoothScrollToPosition(0) - } - - override fun getHeaderOfItem(subject: String): GradeDetailsItem { - return gradeDetailsAdapter.getHeaderItem(subject) - } - - override fun updateHeaderItem(item: GradeDetailsItem) { - gradeDetailsAdapter.updateHeaderItem(item) - } - - override fun showProgress(show: Boolean) { - binding.gradeDetailsProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.gradeDetailsSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.gradeDetailsRecycler.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showEmpty(show: Boolean) { - binding.gradeDetailsEmpty.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showErrorView(show: Boolean) { - binding.gradeDetailsError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.gradeDetailsErrorMessage.text = message - } - - override fun showRefresh(show: Boolean) { - binding.gradeDetailsSwipe.isRefreshing = show - } - - override fun showGradeDialog(grade: Grade, colorScheme: String) { - (activity as? MainActivity)?.showDialogFragment(GradeDetailsDialog.newInstance(grade, colorScheme)) - } - - override fun onParentLoadData(semesterId: Int, forceRefresh: Boolean) { - presenter.onParentViewLoadData(semesterId, forceRefresh) - } - - override fun onParentReselected() { - presenter.onParentViewReselected() - } - - override fun onParentChangeSemester() { - presenter.onParentViewChangeSemester() - } - - override fun notifyParentDataLoaded(semesterId: Int) { - (parentFragment as? GradeFragment)?.onChildFragmentLoaded(semesterId) - } - - override fun notifyParentRefresh() { - (parentFragment as? GradeFragment)?.onChildRefresh() - } - - override fun enableMarkAsDoneButton(enable: Boolean) { - gradeDetailsMenu?.findItem(R.id.gradeDetailsMenuRead)?.isEnabled = enable - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt deleted file mode 100644 index 281974969..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsItem.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) -} - -data class GradeDetailsItem( - val value: Any, - val viewType: ViewType -) - -data class GradeDetailsHeader( - val subject: String, - val average: Double?, - val pointsSum: String?, - var newGrades: Int, - val grades: List -) 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 deleted file mode 100644 index 37f2c935a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsPresenter.kt +++ /dev/null @@ -1,209 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider -import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class GradeDetailsPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val gradeRepository: GradeRepository, - private val semesterRepository: SemesterRepository, - private val preferencesRepository: PreferencesRepository, - private val averageProvider: GradeAverageProvider, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var newGradesAmount: Int = 0 - - private var currentSemesterId = 0 - - private lateinit var lastError: Throwable - - override fun onAttachView(view: GradeDetailsView) { - super.onAttachView(view) - view.initView() - errorHandler.showErrorMessage = ::showErrorViewOnError - } - - fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) { - currentSemesterId = semesterId - loadData(semesterId, forceRefresh) - } - - fun onGradeItemSelected(grade: Grade, position: Int) { - Timber.i("Select grade item ${grade.id}, position: $position") - view?.apply { - showGradeDialog(grade, preferencesRepository.gradeColorTheme) - if (!grade.isRead) { - grade.isRead = true - updateItem(grade, position) - getHeaderOfItem(grade.subject).let { header -> - (header.value as GradeDetailsHeader).newGrades-- - updateHeaderItem(header) - } - newGradesAmount-- - updateMarkAsDoneButton() - updateGrade(grade) - } - } - } - - fun onMarkAsReadSelected(): Boolean { - Timber.i("Select mark grades as read") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getSemesters(it) } - .flatMap { gradeRepository.getUnreadGrades(it.first { item -> item.semesterId == currentSemesterId }) } - .map { it.map { grade -> grade.apply { isRead = true } } } - .flatMapCompletable { - Timber.i("Mark as read ${it.size} grades") - gradeRepository.updateGrades(it) - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Mark as read result: Success") - loadData(currentSemesterId, false) - }, { - Timber.i("Mark as read result: An exception occurred") - errorHandler.dispatch(it) - })) - return true - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the grade details") - view?.notifyParentRefresh() - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - view?.notifyParentRefresh() - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onParentViewReselected() { - view?.run { - if (!isViewEmpty) { - if (preferencesRepository.isGradeExpandable) collapseAllItems() - scrollToStart() - } - } - } - - fun onParentViewChangeSemester() { - view?.run { - showProgress(true) - enableSwipe(false) - showRefresh(false) - showContent(false) - showEmpty(false) - clearView() - } - disposable.clear() - } - - fun updateMarkAsDoneButton() { - view?.enableMarkAsDoneButton(newGradesAmount > 0) - } - - private fun loadData(semesterId: Int, forceRefresh: Boolean) { - Timber.i("Loading grade details data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - showRefresh(false) - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded(semesterId) - } - } - .subscribe({ grades -> - Timber.i("Loading grade details result: Success") - newGradesAmount = grades.sumBy { it.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } } - updateMarkAsDoneButton() - view?.run { - showEmpty(grades.isEmpty()) - showErrorView(false) - showContent(grades.isNotEmpty()) - updateData( - data = createGradeItems(grades), - isGradeExpandable = preferencesRepository.isGradeExpandable, - gradeColorTheme = preferencesRepository.gradeColorTheme - ) - } - analytics.logEvent( - "load_data", - "type" to "grade_details", - "items" to grades.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading grade details result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - 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 createGradeItems(items: List): List { - return items - .filter { it.grades.isNotEmpty() } - .sortedBy { it.subject } - .map { (subject, average, points, _, grades) -> - val subItems = grades - .sortedByDescending { it.date } - .map { GradeDetailsItem(it, ViewType.ITEM) } - - listOf(GradeDetailsItem(GradeDetailsHeader( - subject = subject, - average = average, - pointsSum = points, - newGrades = grades.filter { grade -> !grade.isRead }.size, - grades = subItems - ), ViewType.HEADER)) + if (preferencesRepository.isGradeExpandable) emptyList() else subItems - }.flatten() - } - - private fun updateGrade(grade: Grade) { - Timber.i("Attempt to update grade ${grade.id}") - disposable.add(gradeRepository.updateGrade(grade) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Update grade result: Success") - }) { error -> - Timber.i("Update grade result: An exception occurred") - errorHandler.dispatch(error) - }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt deleted file mode 100644 index e71fcc3c8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsView.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.details - -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.ui.base.BaseView - -interface GradeDetailsView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List, isGradeExpandable: Boolean, gradeColorTheme: String) - - fun updateItem(item: Grade, position: Int) - - fun updateHeaderItem(item: GradeDetailsItem) - - fun clearView() - - fun scrollToStart() - - fun collapseAllItems() - - fun showGradeDialog(grade: Grade, colorScheme: String) - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showProgress(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun enableSwipe(enable: Boolean) - - fun showRefresh(show: Boolean) - - fun notifyParentDataLoaded(semesterId: Int) - - fun notifyParentRefresh() - - fun enableMarkAsDoneButton(enable: Boolean) - - fun getHeaderOfItem(subject: String): GradeDetailsItem -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt deleted file mode 100644 index dbb60910a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt +++ /dev/null @@ -1,208 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.statistics - -import android.graphics.Color -import android.view.LayoutInflater -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.RecyclerView -import com.github.mikephil.charting.components.Legend -import com.github.mikephil.charting.components.LegendEntry -import com.github.mikephil.charting.data.BarData -import com.github.mikephil.charting.data.BarDataSet -import com.github.mikephil.charting.data.BarEntry -import com.github.mikephil.charting.data.PieData -import com.github.mikephil.charting.data.PieDataSet -import com.github.mikephil.charting.data.PieEntry -import com.github.mikephil.charting.formatter.ValueFormatter -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics -import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding -import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import javax.inject.Inject - -class GradeStatisticsAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = emptyList() - - var theme: String = "vulcan" - - var showAllSubjectsOnList: Boolean = false - - private val vulcanGradeColors = listOf( - 6 to R.color.grade_vulcan_six, - 5 to R.color.grade_vulcan_five, - 4 to R.color.grade_vulcan_four, - 3 to R.color.grade_vulcan_three, - 2 to R.color.grade_vulcan_two, - 1 to R.color.grade_vulcan_one - ) - - private val materialGradeColors = listOf( - 6 to R.color.grade_material_six, - 5 to R.color.grade_material_five, - 4 to R.color.grade_material_four, - 3 to R.color.grade_material_three, - 2 to R.color.grade_material_two, - 1 to R.color.grade_material_one - ) - - private val gradePointsColors = listOf( - Color.parseColor("#37c69c"), - Color.parseColor("#d8b12a") - ) - - private val gradeLabels = listOf( - "6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+" - ) - - override fun getItemCount() = if (showAllSubjectsOnList) items.size else (if (items.isEmpty()) 0 else 1) - - override fun getItemViewType(position: Int) = items[position].type.id - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - return when (viewType) { - ViewType.PARTIAL.id, ViewType.SEMESTER.id -> PieViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) - ViewType.POINTS.id -> BarViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is PieViewHolder -> bindPieChart(holder, items[position].partial) - is BarViewHolder -> bindBarChart(holder, items[position].points!!) - } - } - - private fun bindPieChart(holder: PieViewHolder, partials: List) { - with(holder.binding.gradeStatisticsPieTitle) { - text = partials.firstOrNull()?.subject - visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE - } - - val gradeColors = when (theme) { - "vulcan" -> vulcanGradeColors - else -> materialGradeColors - } - - val dataset = PieDataSet(partials.map { - PieEntry(it.amount.toFloat(), it.grade.toString()) - }, "Legenda") - - with(dataset) { - valueTextSize = 12f - sliceSpace = 1f - valueTextColor = Color.WHITE - setColors(partials.map { - gradeColors.single { color -> color.first == it.grade }.second - }.toIntArray(), holder.binding.root.context) - } - - with(holder.binding.gradeStatisticsPie) { - setTouchEnabled(false) - if (partials.size == 1) animateXY(1000, 1000) - data = PieData(dataset).apply { - setValueFormatter(object : ValueFormatter() { - override fun getPieLabel(value: Float, pieEntry: PieEntry): String { - return resources.getQuantityString(R.plurals.grade_number_item, value.toInt(), value.toInt()) - } - }) - } - with(legend) { - textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary) - setCustom(gradeLabels.mapIndexed { i, it -> - LegendEntry().apply { - label = it - formColor = ContextCompat.getColor(context, gradeColors[i].second) - form = Legend.LegendForm.SQUARE - } - }) - } - - minAngleForSlices = 25f - description.isEnabled = false - centerText = partials.fold(0) { acc, it -> acc + it.amount } - .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } - - setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground)) - setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) - invalidate() - } - } - - private fun bindBarChart(holder: BarViewHolder, points: GradePointsStatistics) { - with(holder.binding.gradeStatisticsBarTitle) { - text = points.subject - visibility = if (items.size == 1) GONE else VISIBLE - } - - val dataset = BarDataSet(listOf( - BarEntry(1f, points.others.toFloat()), - BarEntry(2f, points.student.toFloat()) - ), "Legenda") - - with(dataset) { - valueTextSize = 12f - valueTextColor = holder.binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary) - valueFormatter = object : ValueFormatter() { - override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%" - } - colors = gradePointsColors - } - - with(holder.binding.gradeStatisticsBar) { - setTouchEnabled(false) - if (items.size == 1) animateXY(1000, 1000) - data = BarData(dataset).apply { - barWidth = 0.5f - setFitBars(true) - } - legend.setCustom(listOf( - LegendEntry().apply { - label = "Średnia klasy" - formColor = gradePointsColors[0] - form = Legend.LegendForm.SQUARE - }, - LegendEntry().apply { - label = "Uczeń" - formColor = gradePointsColors[1] - form = Legend.LegendForm.SQUARE - } - )) - legend.textColor = context.getThemeAttrColor(android.R.attr.textColorPrimary) - - description.isEnabled = false - - holder.binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary).let { - axisLeft.textColor = it - axisRight.textColor = it - } - xAxis.setDrawLabels(false) - xAxis.setDrawGridLines(false) - with(axisLeft) { - axisMinimum = 0f - axisMaximum = 100f - labelCount = 11 - } - with(axisRight) { - axisMinimum = 0f - axisMaximum = 100f - labelCount = 11 - } - invalidate() - } - } - - private class PieViewHolder(val binding: ItemGradeStatisticsPieBinding) : - RecyclerView.ViewHolder(binding.root) - - private class BarViewHolder(val binding: ItemGradeStatisticsBarBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt deleted file mode 100644 index 3a8f40073..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt +++ /dev/null @@ -1,166 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.statistics - -import android.os.Bundle -import android.view.View -import android.widget.ArrayAdapter -import android.widget.TextView -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.databinding.FragmentGradeStatisticsBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.grade.GradeView -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.setOnItemSelectedListener -import javax.inject.Inject - -class GradeStatisticsFragment : - BaseFragment(R.layout.fragment_grade_statistics), - GradeStatisticsView, GradeView.GradeChildView { - - @Inject - lateinit var presenter: GradeStatisticsPresenter - - @Inject - lateinit var statisticsAdapter: GradeStatisticsAdapter - - private lateinit var subjectsAdapter: ArrayAdapter - - companion object { - private const val SAVED_CHART_TYPE = "CURRENT_TYPE" - - fun newInstance() = GradeStatisticsFragment() - } - - override val isViewEmpty get() = statisticsAdapter.items.isEmpty() - - override val currentType - get() = when (binding.gradeStatisticsTypeSwitch.checkedRadioButtonId) { - R.id.gradeStatisticsTypeSemester -> ViewType.SEMESTER - R.id.gradeStatisticsTypePartial -> ViewType.PARTIAL - else -> ViewType.POINTS - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentGradeStatisticsBinding.bind(view) - messageContainer = binding.gradeStatisticsSwipe - presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? ViewType) - } - - override fun initView() { - with(binding.gradeStatisticsRecycler) { - layoutManager = LinearLayoutManager(requireContext()) - adapter = statisticsAdapter - } - - subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf()) - subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject) - - with(binding.gradeStatisticsSubjects) { - adapter = subjectsAdapter - setOnItemSelectedListener { presenter.onSubjectSelected(it?.text?.toString()) } - } - - with(binding) { - gradeStatisticsSubjectsContainer.setElevationCompat(requireContext().dpToPx(1f)) - - gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - gradeStatisticsErrorRetry.setOnClickListener { presenter.onRetry() } - gradeStatisticsErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun updateSubjects(data: ArrayList) { - with(subjectsAdapter) { - clear() - addAll(data) - notifyDataSetChanged() - } - } - - override fun updateData(items: List, theme: String, showAllSubjectsOnStatisticsList: Boolean) { - with(statisticsAdapter) { - this.showAllSubjectsOnList = showAllSubjectsOnStatisticsList - this.theme = theme - this.items = items - notifyDataSetChanged() - } - } - - override fun showSubjects(show: Boolean) { - binding.gradeStatisticsSubjectsContainer.visibility = if (show) View.VISIBLE else View.GONE - } - - override fun clearView() { - statisticsAdapter.items = emptyList() - } - - override fun resetView() { - binding.gradeStatisticsScroll.scrollTo(0, 0) - } - - override fun showContent(show: Boolean) { - binding.gradeStatisticsRecycler.visibility = if (show) View.VISIBLE else View.GONE - } - - override fun showEmpty(show: Boolean) { - binding.gradeStatisticsEmpty.visibility = if (show) View.VISIBLE else View.INVISIBLE - } - - override fun showErrorView(show: Boolean) { - binding.gradeStatisticsError.visibility = if (show) View.VISIBLE else View.GONE - } - - override fun setErrorDetails(message: String) { - binding.gradeStatisticsErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.gradeStatisticsProgress.visibility = if (show) View.VISIBLE else View.GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.gradeStatisticsSwipe.isEnabled = enable - } - - override fun showRefresh(show: Boolean) { - binding.gradeStatisticsSwipe.isRefreshing = show - } - - override fun onParentLoadData(semesterId: Int, forceRefresh: Boolean) { - presenter.onParentViewLoadData(semesterId, forceRefresh) - } - - override fun onParentReselected() { - presenter.onParentViewReselected() - } - - override fun onParentChangeSemester() { - presenter.onParentViewChangeSemester() - } - - override fun notifyParentDataLoaded(semesterId: Int) { - (parentFragment as? GradeFragment)?.onChildFragmentLoaded(semesterId) - } - - override fun notifyParentRefresh() { - (parentFragment as? GradeFragment)?.onChildRefresh() - } - - override fun onResume() { - super.onResume() - binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, _ -> presenter.onTypeChange() } - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 590e9ce12..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt +++ /dev/null @@ -1,199 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.statistics - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class GradeStatisticsPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val gradeStatisticsRepository: GradeStatisticsRepository, - private val subjectRepository: SubjectRepository, - private val semesterRepository: SemesterRepository, - private val preferencesRepository: PreferencesRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var subjects = emptyList() - - private var currentSemesterId = 0 - - private var currentSubjectName: String = "Wszystkie" - - private lateinit var lastError: Throwable - - var currentType: ViewType = ViewType.PARTIAL - private set - - fun onAttachView(view: GradeStatisticsView, type: ViewType?) { - super.onAttachView(view) - currentType = type ?: ViewType.PARTIAL - view.initView() - errorHandler.showErrorMessage = ::showErrorViewOnError - } - - fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) { - currentSemesterId = semesterId - loadSubjects() - loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh) - } - - fun onParentViewReselected() { - view?.run { - if (!isViewEmpty) resetView() - } - } - - fun onParentViewChangeSemester() { - view?.run { - showProgress(true) - enableSwipe(false) - showRefresh(false) - showContent(false) - showErrorView(false) - showEmpty(false) - clearView() - } - disposable.clear() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the grade stats") - view?.notifyParentRefresh() - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - view?.notifyParentRefresh() - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onSubjectSelected(name: String?) { - Timber.i("Select grade stats subject $name") - view?.run { - showContent(false) - showProgress(true) - enableSwipe(false) - showEmpty(false) - showErrorView(false) - clearView() - } - (subjects.singleOrNull { it.name == name }?.name)?.let { - if (it != currentSubjectName) loadDataByType(currentSemesterId, it, currentType) - } - } - - fun onTypeChange() { - val type = view?.currentType ?: ViewType.POINTS - Timber.i("Select grade stats semester: $type") - disposable.clear() - view?.run { - showContent(false) - showProgress(true) - enableSwipe(false) - showEmpty(false) - showErrorView(false) - clearView() - } - loadDataByType(currentSemesterId, currentSubjectName, type) - } - - private fun loadSubjects() { - Timber.i("Loading grade stats subjects started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - subjectRepository.getSubjects(student, semester) - } - } - .doOnSuccess { subjects = it } - .map { ArrayList(it.map { subject -> subject.name }) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Loading grade stats subjects result: Success") - view?.updateSubjects(it) - }, { - Timber.i("Loading grade stats subjects result: An exception occurred") - errorHandler.dispatch(it) - }) - ) - } - - private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) { - currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName - currentType = type - - Timber.i("Loading grade stats data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getSemesters(student).flatMap { semesters -> - val semester = semesters.first { item -> item.semesterId == semesterId } - - with(gradeStatisticsRepository) { - when (type) { - ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh) - ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, forceRefresh) - ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh) - } - } - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - showRefresh(false) - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded(semesterId) - } - } - .subscribe({ - Timber.i("Loading grade stats result: Success") - view?.run { - showEmpty(it.isEmpty()) - showContent(it.isNotEmpty()) - showErrorView(false) - updateData(it, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) - showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) - } - analytics.logEvent( - "load_data", - "type" to "grade_statistics", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading grade stats result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt deleted file mode 100644 index 26b4a119a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.statistics - -import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.ui.base.BaseView - -interface GradeStatisticsView : BaseView { - - val isViewEmpty: Boolean - - val currentType: ViewType - - fun initView() - - fun updateSubjects(data: ArrayList) - - fun updateData(items: List, theme: String, showAllSubjectsOnStatisticsList: Boolean) - - fun showSubjects(show: Boolean) - - fun notifyParentDataLoaded(semesterId: Int) - - fun notifyParentRefresh() - - fun clearView() - - fun resetView() - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showRefresh(show: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/ViewType.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/ViewType.kt deleted file mode 100644 index 02e95b0e5..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/ViewType.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.statistics - -enum class ViewType(val id: Int) { - SEMESTER(1), - PARTIAL(2), - POINTS(3) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt deleted file mode 100644 index 30c4ccc23..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryAdapter.kt +++ /dev/null @@ -1,85 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.summary - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.databinding.ItemGradeSummaryBinding -import io.github.wulkanowy.databinding.ScrollableHeaderGradeSummaryBinding -import io.github.wulkanowy.utils.calcAverage -import java.util.Locale -import javax.inject.Inject - -class GradeSummaryAdapter @Inject constructor() : RecyclerView.Adapter() { - - private enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) - } - - var items = emptyList() - - override fun getItemCount() = items.size + 1 - - override fun getItemViewType(position: Int) = when (position) { - 0 -> ViewType.HEADER.id - else -> ViewType.ITEM.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.HEADER.id -> HeaderViewHolder(ScrollableHeaderGradeSummaryBinding.inflate(inflater, parent, false)) - ViewType.ITEM.id -> ItemViewHolder(ItemGradeSummaryBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding) - is ItemViewHolder -> bindItemViewHolder(holder.binding, items[position - 1]) - } - } - - private fun bindHeaderViewHolder(binding: ScrollableHeaderGradeSummaryBinding) { - if (items.isEmpty()) return - - with(binding) { - gradeSummaryScrollableHeaderFinal.text = formatAverage(items.calcAverage()) - gradeSummaryScrollableHeaderCalculated.text = formatAverage(items - .filter { value -> value.average != 0.0 } - .map { values -> values.average } - .reversed() // fix average precision - .average() - ) - } - } - - @SuppressLint("SetTextI18n") - private fun bindItemViewHolder(binding: ItemGradeSummaryBinding, item: GradeSummary) { - with(binding) { - gradeSummaryItemTitle.text = item.subject - gradeSummaryItemPoints.text = item.pointsSum - gradeSummaryItemAverage.text = formatAverage(item.average, "") - gradeSummaryItemPredicted.text = "${item.predictedGrade} ${item.proposedPoints}".trim() - gradeSummaryItemFinal.text = "${item.finalGrade} ${item.finalPoints}".trim() - - gradeSummaryItemPointsContainer.visibility = if (item.pointsSum.isBlank()) View.GONE else View.VISIBLE - } - } - - private fun formatAverage(average: Double, defaultValue: String = "-- --"): String { - return if (average == 0.0) defaultValue - else String.format(Locale.FRANCE, "%.2f", average) - } - - private class HeaderViewHolder(val binding: ScrollableHeaderGradeSummaryBinding) : - RecyclerView.ViewHolder(binding.root) - - private class ItemViewHolder(val binding: ItemGradeSummaryBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt deleted file mode 100644 index d169f7c62..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryFragment.kt +++ /dev/null @@ -1,129 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.summary - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.databinding.FragmentGradeSummaryBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.grade.GradeView -import javax.inject.Inject - -class GradeSummaryFragment : - BaseFragment(R.layout.fragment_grade_summary), GradeSummaryView, - GradeView.GradeChildView { - - @Inject - lateinit var presenter: GradeSummaryPresenter - - @Inject - lateinit var gradeSummaryAdapter: GradeSummaryAdapter - - companion object { - fun newInstance() = GradeSummaryFragment() - } - - override val isViewEmpty - get() = gradeSummaryAdapter.items.isEmpty() - - override val predictedString - get() = getString(R.string.grade_summary_predicted_grade) - - override val finalString - get() = getString(R.string.grade_summary_final_grade) - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentGradeSummaryBinding.bind(view) - messageContainer = binding.gradeSummaryRecycler - presenter.onAttachView(this) - } - - override fun initView() { - with(binding.gradeSummaryRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = gradeSummaryAdapter - } - with(binding) { - gradeSummarySwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - gradeSummaryErrorRetry.setOnClickListener { presenter.onRetry() } - gradeSummaryErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun updateData(data: List) { - with(gradeSummaryAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun clearView() { - with(gradeSummaryAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun resetView() { - binding.gradeSummaryRecycler.scrollToPosition(0) - } - - override fun showContent(show: Boolean) { - binding.gradeSummaryRecycler.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showEmpty(show: Boolean) { - binding.gradeSummaryEmpty.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showErrorView(show: Boolean) { - binding.gradeSummaryError.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun setErrorDetails(message: String) { - binding.gradeSummaryErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.gradeSummaryProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.gradeSummarySwipe.isEnabled = enable - } - - override fun showRefresh(show: Boolean) { - binding.gradeSummarySwipe.isRefreshing = show - } - - override fun onParentLoadData(semesterId: Int, forceRefresh: Boolean) { - presenter.onParentViewLoadData(semesterId, forceRefresh) - } - - override fun onParentReselected() { - presenter.onParentViewReselected() - } - - override fun onParentChangeSemester() { - presenter.onParentViewChangeSemester() - } - - override fun notifyParentDataLoaded(semesterId: Int) { - (parentFragment as? GradeFragment)?.onChildFragmentLoaded(semesterId) - } - - override fun notifyParentRefresh() { - (parentFragment as? GradeFragment)?.onChildRefresh() - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 229a0107d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryPresenter.kt +++ /dev/null @@ -1,125 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.summary - -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider -import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class GradeSummaryPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val averageProvider: GradeAverageProvider, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: GradeSummaryView) { - super.onAttachView(view) - view.initView() - errorHandler.showErrorMessage = ::showErrorViewOnError - } - - fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) { - Timber.i("Loading grade summary data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } - .map { createGradeSummaryItems(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - showRefresh(false) - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded(semesterId) - } - }.subscribe({ - Timber.i("Loading grade summary result: Success") - view?.run { - showEmpty(it.isEmpty()) - showContent(it.isNotEmpty()) - showErrorView(false) - updateData(it) - } - analytics.logEvent( - "load_data", - "type" to "grade_summary", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading grade summary result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the grade summary") - view?.notifyParentRefresh() - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - view?.notifyParentRefresh() - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onParentViewReselected() { - view?.run { - if (!isViewEmpty) resetView() - } - } - - fun onParentViewChangeSemester() { - view?.run { - showProgress(true) - enableSwipe(false) - showRefresh(false) - showContent(false) - showEmpty(false) - clearView() - } - disposable.clear() - } - - private fun createGradeSummaryItems(items: List): List { - return items - .filter { !checkEmpty(it) } - .sortedBy { it.subject } - .map { it.summary.copy(average = it.average) } - } - - private fun checkEmpty(gradeSummary: GradeDetailsWithAverage): Boolean { - return gradeSummary.run { - summary.finalGrade.isBlank() - && summary.predictedGrade.isBlank() - && average == .0 - && points.isBlank() - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt deleted file mode 100644 index 974d91415..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/summary/GradeSummaryView.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.ui.modules.grade.summary - -import io.github.wulkanowy.data.db.entities.GradeSummary -import io.github.wulkanowy.ui.base.BaseView - -interface GradeSummaryView : BaseView { - - val isViewEmpty: Boolean - - val predictedString: String - - val finalString: String - - fun initView() - - fun updateData(data: List) - - fun resetView() - - fun clearView() - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showRefresh(show: Boolean) - - fun showContent(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showEmpty(show: Boolean) - - fun notifyParentDataLoaded(semesterId: Int) - - fun notifyParentRefresh() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkAdapter.kt deleted file mode 100644 index a87ad18e8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkAdapter.kt +++ /dev/null @@ -1,67 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.databinding.HeaderHomeworkBinding -import io.github.wulkanowy.databinding.ItemHomeworkBinding -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.utils.weekDayName -import org.threeten.bp.LocalDate -import javax.inject.Inject - -class HomeworkAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList>() - - var onClickListener: (Homework) -> Unit = {} - - override fun getItemCount() = items.size - - override fun getItemViewType(position: Int) = items[position].viewType.id - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - HomeworkItem.ViewType.HEADER.id -> HeaderViewHolder(HeaderHomeworkBinding.inflate(inflater, parent, false)) - HomeworkItem.ViewType.ITEM.id -> ItemViewHolder(ItemHomeworkBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> bindHeaderViewHolder(holder.binding, items[position].value as LocalDate) - is ItemViewHolder -> bindItemViewHolder(holder.binding, items[position].value as Homework) - } - } - - @SuppressLint("DefaultLocale") - private fun bindHeaderViewHolder(binding: HeaderHomeworkBinding, date: LocalDate) { - with(binding) { - homeworkHeaderDay.text = date.weekDayName.capitalize() - homeworkHeaderDate.text = date.toFormattedString() - } - } - - private fun bindItemViewHolder(binding: ItemHomeworkBinding, homework: Homework) { - with(binding) { - homeworkItemSubject.text = homework.subject - homeworkItemTeacher.text = homework.teacher - homeworkItemContent.text = homework.content - homeworkItemCheckImage.visibility = if (homework.isDone) View.VISIBLE else View.GONE - homeworkItemAttachmentImage.visibility = if (!homework.isDone && homework.attachments.isNotEmpty()) View.VISIBLE else View.GONE - - root.setOnClickListener { onClickListener(homework) } - } - } - - class HeaderViewHolder(val binding: HeaderHomeworkBinding) : - RecyclerView.ViewHolder(binding.root) - - class ItemViewHolder(val binding: ItemHomeworkBinding) : RecyclerView.ViewHolder(binding.root) -} 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 deleted file mode 100644 index f30529575..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkFragment.kt +++ /dev/null @@ -1,137 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.databinding.FragmentHomeworkBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.homework.details.HomeworkDetailsDialog -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.dpToPx -import javax.inject.Inject - -class HomeworkFragment : BaseFragment(R.layout.fragment_homework), - HomeworkView, MainView.TitledView { - - @Inject - lateinit var presenter: HomeworkPresenter - - @Inject - lateinit var homeworkAdapter: HomeworkAdapter - - companion object { - private const val SAVED_DATE_KEY = "CURRENT_DATE" - - fun newInstance() = HomeworkFragment() - } - - override val titleStringId get() = R.string.homework_title - - override val isViewEmpty get() = homeworkAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentHomeworkBinding.bind(view) - messageContainer = binding.homeworkRecycler - presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) - } - - override fun initView() { - homeworkAdapter.onClickListener = presenter::onHomeworkItemSelected - - with(binding.homeworkRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = homeworkAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - homeworkSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - homeworkErrorRetry.setOnClickListener { presenter.onRetry() } - homeworkErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - homeworkPreviousButton.setOnClickListener { presenter.onPreviousDay() } - homeworkNextButton.setOnClickListener { presenter.onNextDay() } - - homeworkNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun updateData(data: List>) { - with(homeworkAdapter) { - items = data - notifyDataSetChanged() - } - } - - fun onReloadList() { - presenter.reloadData() - } - - override fun clearData() { - with(homeworkAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun updateNavigationWeek(date: String) { - binding.homeworkNavDate.text = date - } - - override fun hideRefresh() { - binding.homeworkSwipe.isRefreshing = false - } - - override fun showEmpty(show: Boolean) { - binding.homeworkEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.homeworkError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.homeworkErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.homeworkProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.homeworkSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.homeworkRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showPreButton(show: Boolean) { - binding.homeworkPreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding.homeworkNextButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showTimetableDialog(homework: Homework) { - (activity as? MainActivity)?.showDialogFragment(HomeworkDetailsDialog.newInstance(homework)) - } - - 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/homework/HomeworkItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt deleted file mode 100644 index 7e0039583..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkItem.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework - -data class HomeworkItem(val value: T, val viewType: ViewType) { - - enum class ViewType(val id: Int) { - HEADER(1), - ITEM(2) - } -} 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 deleted file mode 100644 index 41735a23f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkPresenter.kt +++ /dev/null @@ -1,181 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday -import io.github.wulkanowy.utils.isHolidays -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.toFormattedString -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.ofEpochDay -import timber.log.Timber -import javax.inject.Inject - -class HomeworkPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val homeworkRepository: HomeworkRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay - - lateinit var currentDate: LocalDate - private set - - private lateinit var lastError: Throwable - - fun onAttachView(view: HomeworkView, date: Long?) { - super.onAttachView(view) - view.initView() - Timber.i("Homework view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(ofEpochDay(date ?: baseDate.toEpochDay())) - if (currentDate.isHolidays) setBaseDateOnHolidays() - reloadView() - } - - fun onPreviousDay() { - loadData(currentDate.minusDays(7)) - reloadView() - } - - fun onNextDay() { - loadData(currentDate.plusDays(7)) - reloadView() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the homework") - loadData(currentDate, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentDate, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onHomeworkItemSelected(homework: Homework) { - Timber.i("Select homework item ${homework.id}") - view?.showTimetableDialog(homework) - } - - private fun setBaseDateOnHolidays() { - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) - currentDate = baseDate - reloadNavigation() - }) { - Timber.i("Loading semester result: An exception occurred") - }) - } - - fun reloadData() { - loadData(currentDate, false) - } - - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - Timber.i("Loading homework data started") - currentDate = date - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh) - } - } - .map { createHomeworkItem(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading homework result: Success") - view?.apply { - updateData(it) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - } - analytics.logEvent( - "load_data", - "type" to "homework", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading homework result: An exception occurred") - - errorHandler.dispatch(it) - }) - } - } - - 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 createHomeworkItem(items: List): List> { - return items.groupBy { it.date }.toSortedMap().map { (date, exams) -> - listOf(HomeworkItem(date, HomeworkItem.ViewType.HEADER)) + exams.reversed().map { exam -> - HomeworkItem(exam, HomeworkItem.ViewType.ITEM) - } - }.flatten() - } - - private fun reloadView() { - Timber.i("Reload homework view with the date ${currentDate.toFormattedString()}") - view?.apply { - showProgress(true) - enableSwipe(false) - showContent(false) - showEmpty(false) - showErrorView(false) - clearData() - reloadNavigation() - } - } - - private fun reloadNavigation() { - view?.apply { - showPreButton(!currentDate.minusDays(7).isHolidays) - showNextButton(!currentDate.plusDays(7).isHolidays) - updateNavigationWeek("${currentDate.monday.toFormattedString("dd.MM")} - " + - currentDate.sunday.toFormattedString("dd.MM")) - } - } -} 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 deleted file mode 100644 index 2a678cd4c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/HomeworkView.kt +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework - -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.ui.base.BaseView - -interface HomeworkView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List>) - - fun clearData() - - fun updateNavigationWeek(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 showTimetableDialog(homework: Homework) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt deleted file mode 100644 index 5d6ee162a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsAdapter.kt +++ /dev/null @@ -1,102 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework.details - -import android.view.LayoutInflater -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.databinding.ItemHomeworkDialogAttachmentBinding -import io.github.wulkanowy.databinding.ItemHomeworkDialogAttachmentsHeaderBinding -import io.github.wulkanowy.databinding.ItemHomeworkDialogDetailsBinding -import io.github.wulkanowy.utils.toFormattedString -import javax.inject.Inject - -class HomeworkDetailsAdapter @Inject constructor() : - RecyclerView.Adapter() { - - private enum class ViewType(val id: Int) { - DETAILS(1), - ATTACHMENTS_HEADER(2), - ATTACHMENT(3) - } - - private var attachments = emptyList>() - - var homework: Homework? = null - set(value) { - field = value - attachments = value?.attachments.orEmpty() - } - - var onAttachmentClickListener: (url: String) -> Unit = {} - - var onFullScreenClickListener = {} - - var onFullScreenExitClickListener = {} - - override fun getItemCount() = 1 + if (attachments.isNotEmpty()) attachments.size + 1 else 0 - - override fun getItemViewType(position: Int) = when (position) { - 0 -> ViewType.DETAILS.id - 1 -> ViewType.ATTACHMENTS_HEADER.id - else -> ViewType.ATTACHMENT.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.ATTACHMENTS_HEADER.id -> AttachmentsHeaderViewHolder(ItemHomeworkDialogAttachmentsHeaderBinding.inflate(inflater, parent, false)) - ViewType.ATTACHMENT.id -> AttachmentViewHolder(ItemHomeworkDialogAttachmentBinding.inflate(inflater, parent, false)) - else -> DetailsViewHolder(ItemHomeworkDialogDetailsBinding.inflate(inflater, parent, false)) - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is DetailsViewHolder -> bindDetailsViewHolder(holder) - is AttachmentViewHolder -> bindAttachmentViewHolder(holder, position - 2) - } - } - - private fun bindDetailsViewHolder(holder: DetailsViewHolder) { - with(holder.binding) { - homeworkDialogDate.text = homework?.date?.toFormattedString() - homeworkDialogEntryDate.text = homework?.entryDate?.toFormattedString() - homeworkDialogSubject.text = homework?.subject - homeworkDialogTeacher.text = homework?.teacher - homeworkDialogContent.text = homework?.content - homeworkDialogFullScreen.setOnClickListener { - homeworkDialogFullScreen.visibility = GONE - homeworkDialogFullScreenExit.visibility = VISIBLE - onFullScreenClickListener() - } - homeworkDialogFullScreenExit.setOnClickListener { - homeworkDialogFullScreen.visibility = VISIBLE - homeworkDialogFullScreenExit.visibility = GONE - onFullScreenExitClickListener() - } - } - } - - private fun bindAttachmentViewHolder(holder: AttachmentViewHolder, position: Int) { - val item = attachments[position] - - with(holder.binding) { - homeworkDialogAttachment.text = item.second - root.setOnClickListener { - onAttachmentClickListener(item.first) - } - } - } - - class DetailsViewHolder(val binding: ItemHomeworkDialogDetailsBinding) : - RecyclerView.ViewHolder(binding.root) - - class AttachmentsHeaderViewHolder(val binding: ItemHomeworkDialogAttachmentsHeaderBinding) : - RecyclerView.ViewHolder(binding.root) - - class AttachmentViewHolder(val binding: ItemHomeworkDialogAttachmentBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt deleted file mode 100644 index 7b3b9821a..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt +++ /dev/null @@ -1,84 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework.details - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.databinding.DialogHomeworkBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import io.github.wulkanowy.ui.modules.homework.HomeworkFragment -import io.github.wulkanowy.utils.openInternetBrowser -import javax.inject.Inject - -class HomeworkDetailsDialog : BaseDialogFragment(), HomeworkDetailsView { - - @Inject - lateinit var presenter: HomeworkDetailsPresenter - - @Inject - lateinit var detailsAdapter: HomeworkDetailsAdapter - - private lateinit var homework: Homework - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(homework: Homework): HomeworkDetailsDialog { - return HomeworkDetailsDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - homework = getSerializable(ARGUMENT_KEY) as Homework - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogHomeworkBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - presenter.onAttachView(this) - } - - @SuppressLint("SetTextI18n") - override fun initView() { - with(binding) { - homeworkDialogRead.text = view?.context?.getString(if (homework.isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done) - homeworkDialogRead.setOnClickListener { presenter.toggleDone(homework) } - homeworkDialogClose.setOnClickListener { dismiss() } - } - - with(binding.homeworkDialogRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = detailsAdapter.apply { - onAttachmentClickListener = { context.openInternetBrowser(it, ::showMessage) } - onFullScreenClickListener = { dialog?.window?.setLayout(MATCH_PARENT, MATCH_PARENT) } - onFullScreenExitClickListener = { dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT) } - homework = this@HomeworkDetailsDialog.homework - } - } - } - - override fun updateMarkAsDoneLabel(isDone: Boolean) { - (parentFragment as? HomeworkFragment)?.onReloadList() - binding.homeworkDialogRead.text = view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 04a97b8cd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsPresenter.kt +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework.details - -import io.github.wulkanowy.data.db.entities.Homework -import io.github.wulkanowy.data.repositories.homework.HomeworkRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class HomeworkDetailsPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val homeworkRepository: HomeworkRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: HomeworkDetailsView) { - super.onAttachView(view) - view.initView() - Timber.i("Homework details view was initialized") - } - - fun toggleDone(homework: Homework) { - Timber.i("Homework details update start") - disposable.add(homeworkRepository.toggleDone(homework) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.i("Homework details update: Success") - view?.run { - updateMarkAsDoneLabel(homework.isDone) - } - analytics.logEvent("homework_mark_as_done") - }) { - Timber.i("Homework details update result: An exception occurred") - errorHandler.dispatch(it) - } - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsView.kt deleted file mode 100644 index 697f22335..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsView.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.wulkanowy.ui.modules.homework.details - -import io.github.wulkanowy.ui.base.BaseView - -interface HomeworkDetailsView : BaseView { - - fun initView() - - fun updateMarkAsDoneLabel(isDone: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt deleted file mode 100644 index ffb36fe6e..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt +++ /dev/null @@ -1,107 +0,0 @@ -package io.github.wulkanowy.ui.modules.login - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.view.MenuItem -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.ActivityLoginBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment -import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment -import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment -import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment -import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment -import io.github.wulkanowy.utils.setOnSelectPageListener -import javax.inject.Inject - -class LoginActivity : BaseActivity(), LoginView { - - @Inject - override lateinit var presenter: LoginPresenter - - @Inject - lateinit var loginAdapter: BaseFragmentPagerAdapter - - companion object { - - fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java) - } - - override val currentViewIndex get() = binding.loginViewpager.currentItem - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(ActivityLoginBinding.inflate(layoutInflater).apply { binding = this }.root) - setSupportActionBar(binding.loginToolbar) - messageContainer = binding.loginContainer - - presenter.onAttachView(this) - } - - override fun initView() { - with(requireNotNull(supportActionBar)) { - setDisplayHomeAsUpEnabled(true) - setDisplayShowTitleEnabled(false) - } - - with(loginAdapter) { - containerId = binding.loginViewpager.id - addFragments(listOf( - LoginFormFragment.newInstance(), - LoginSymbolFragment.newInstance(), - LoginStudentSelectFragment.newInstance(), - LoginAdvancedFragment.newInstance(), - LoginRecoverFragment.newInstance() - )) - } - - with(binding.loginViewpager) { - offscreenPageLimit = 2 - adapter = loginAdapter - setOnSelectPageListener(presenter::onViewSelected) - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) onBackPressed() - return true - } - - override fun switchView(index: Int) { - binding.loginViewpager.setCurrentItem(index, false) - } - - override fun showActionBar(show: Boolean) { - supportActionBar?.run { if (show) show() else hide() } - } - - override fun onBackPressed() { - presenter.onBackPressed { super.onBackPressed() } - } - - override fun notifyInitSymbolFragment(loginData: Triple) { - (loginAdapter.getFragmentInstance(1) as? LoginSymbolFragment)?.onParentInitSymbolFragment(loginData) - } - - override fun notifyInitStudentSelectFragment(students: List) { - (loginAdapter.getFragmentInstance(2) as? LoginStudentSelectFragment)?.onParentInitStudentSelectFragment(students) - } - - fun onFormFragmentAccountLogged(students: List, loginData: Triple) { - presenter.onFormViewAccountLogged(students, loginData) - } - - fun onSymbolFragmentAccountLogged(students: List) { - presenter.onSymbolViewAccountLogged(students) - } - - fun onAdvancedLoginClick() { - presenter.onAdvancedLoginClick() - } - - fun onRecoverClick() { - presenter.onRecoverClick() - } -} 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 deleted file mode 100644 index 5ed181bf1..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginErrorHandler.kt +++ /dev/null @@ -1,50 +0,0 @@ -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.exception.BadCredentialsException -import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException -import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException -import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException -import io.github.wulkanowy.sdk.mobile.exception.TokenDeadException -import io.github.wulkanowy.ui.base.ErrorHandler -import javax.inject.Inject - -class LoginErrorHandler @Inject constructor( - resources: Resources, - chuckerCollector: ChuckerCollector -) : ErrorHandler(resources, chuckerCollector) { - - var onBadCredentials: () -> Unit = {} - - var onInvalidToken: (String) -> Unit = {} - - var onInvalidPin: (String) -> Unit = {} - - var onInvalidSymbol: (String) -> Unit = {} - - var onStudentDuplicate: (String) -> Unit = {} - - override fun proceed(error: Throwable) { - when (error) { - is BadCredentialsException -> onBadCredentials() - is SQLiteConstraintException -> onStudentDuplicate(resources.getString(R.string.login_duplicate_student)) - is TokenDeadException -> onInvalidToken(resources.getString(R.string.login_expired_token)) - is InvalidTokenException -> onInvalidToken(resources.getString(R.string.login_invalid_token)) - is InvalidPinException -> onInvalidPin(resources.getString(R.string.login_invalid_pin)) - is InvalidSymbolException -> onInvalidSymbol(resources.getString(R.string.login_invalid_symbol)) - else -> super.proceed(error) - } - } - - override fun clear() { - super.clear() - onBadCredentials = {} - onStudentDuplicate = {} - onInvalidToken = {} - onInvalidPin = {} - onInvalidSymbol = {} - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt deleted file mode 100644 index 26a243dcd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginModule.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.ui.modules.login - -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.di.scopes.PerActivity -import io.github.wulkanowy.di.scopes.PerFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment -import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment -import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment -import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment -import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment - -@Suppress("unused") -@Module -internal abstract class LoginModule { - - companion object { - - @PerActivity - @Provides - fun provideLoginAdapter(activity: LoginActivity) = BaseFragmentPagerAdapter(activity.supportFragmentManager) - } - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLoginFormFragment(): LoginFormFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLoginAdvancedFragment(): LoginAdvancedFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLoginSymbolFragment(): LoginSymbolFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLoginSelectStudentFragment(): LoginStudentSelectFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLoginRecoverFragment(): LoginRecoverFragment -} 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 deleted file mode 100644 index 16342de4f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginPresenter.kt +++ /dev/null @@ -1,74 +0,0 @@ -package io.github.wulkanowy.ui.modules.login - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class LoginPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: LoginView) { - super.onAttachView(view) - with(view) { - initView() - showActionBar(false) - } - Timber.i("Login view was initialized") - } - - fun onFormViewAccountLogged(students: List, loginData: Triple) { - view?.apply { - if (students.isEmpty()) { - Timber.i("Switch to symbol form") - notifyInitSymbolFragment(loginData) - switchView(1) - } else { - Timber.i("Switch to student select") - notifyInitStudentSelectFragment(students) - switchView(2) - } - } - } - - fun onSymbolViewAccountLogged(students: List) { - view?.apply { - Timber.i("Switch to student select") - notifyInitStudentSelectFragment(students) - switchView(2) - } - } - - fun onAdvancedLoginClick() { - view?.switchView(3) - } - - fun onRecoverClick() { - view?.switchView(4) - } - - fun onViewSelected(index: Int) { - view?.apply { - when (index) { - 0 -> showActionBar(false) - 1, 2, 3, 4 -> showActionBar(true) - } - } - } - - fun onBackPressed(default: () -> Unit) { - Timber.i("Back pressed in login view") - view?.apply { - when (currentViewIndex) { - 1, 2, 3, 4 -> switchView(0) - else -> default() - } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginView.kt deleted file mode 100644 index 9c98a1d8d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginView.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.ui.modules.login - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LoginView : BaseView { - - val currentViewIndex: Int - - fun initView() - - fun switchView(index: Int) - - fun showActionBar(show: Boolean) - - fun notifyInitSymbolFragment(loginData: Triple) - - fun notifyInitStudentSelectFragment(students: List) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt deleted file mode 100644 index 3b6a985be..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedFragment.kt +++ /dev/null @@ -1,313 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.advanced - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.ArrayAdapter -import androidx.core.widget.doOnTextChanged -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.setOnEditorDoneSignIn -import io.github.wulkanowy.utils.showSoftInput -import javax.inject.Inject - -class LoginAdvancedFragment : - BaseFragment(R.layout.fragment_login_advanced), - LoginAdvancedView { - - @Inject - lateinit var presenter: LoginAdvancedPresenter - - companion object { - fun newInstance() = LoginAdvancedFragment() - } - - override val formLoginType: String - get() = when (binding.loginTypeSwitch.checkedRadioButtonId) { - R.id.loginTypeApi -> "API" - R.id.loginTypeScrapper -> "SCRAPPER" - else -> "HYBRID" - } - - override val formUsernameValue: String - get() = binding.loginFormUsername.text.toString().trim() - - override val formPassValue: String - get() = binding.loginFormPass.text.toString().trim() - - private lateinit var hostKeys: Array - - private lateinit var hostValues: Array - - private lateinit var hostSymbols: Array - - override val formHostValue: String - get() = hostValues.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())).orEmpty() - - override val formHostSymbol: String - get() = hostSymbols.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())).orEmpty() - - override val formPinValue: String - get() = binding.loginFormPin.text.toString().trim() - - override val formSymbolValue: String - get() = binding.loginFormSymbol.text.toString().trim() - - override val formTokenValue: String - get() = binding.loginFormToken.text.toString().trim() - - override val nicknameLabel: String - get() = getString(R.string.login_nickname_hint) - - override val emailLabel: String - get() = getString(R.string.login_email_hint) - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLoginAdvancedBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - hostKeys = resources.getStringArray(R.array.hosts_keys) - hostValues = resources.getStringArray(R.array.hosts_values) - hostSymbols = resources.getStringArray(R.array.hosts_symbols) - - with(binding) { - loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() } - loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } - loginFormPin.doOnTextChanged { _, _, _, _ -> presenter.onPinTextChanged() } - loginFormSymbol.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() } - loginFormToken.doOnTextChanged { _, _, _, _ -> presenter.onTokenTextChanged() } - loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } - loginFormSignIn.setOnClickListener { presenter.onSignInClick() } - - loginTypeSwitch.setOnCheckedChangeListener { _, checkedId -> - presenter.onLoginModeSelected(when (checkedId) { - R.id.loginTypeApi -> Sdk.Mode.API - R.id.loginTypeScrapper -> Sdk.Mode.SCRAPPER - else -> Sdk.Mode.HYBRID - }) - } - - loginFormPin.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() } - loginFormPass.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() } - - loginFormSymbol.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values))) - } - - with(binding.loginFormHost) { - setText(hostKeys.getOrNull(0).orEmpty()) - setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) - setOnClickListener { if (binding.loginFormContainer.visibility == GONE) dismissDropDown() } - } - } - - override fun showMobileApiWarningMessage() { - binding.loginFormAdvancedWarningInfo.text = getString(R.string.login_advanced_warning_mobile_api) - } - - override fun showScraperWarningMessage() { - binding.loginFormAdvancedWarningInfo.text = getString(R.string.login_advanced_warning_scraper) - } - - override fun showHybridWarningMessage() { - binding.loginFormAdvancedWarningInfo.text = getString(R.string.login_advanced_warning_hybrid) - } - - override fun setDefaultCredentials(username: String, pass: String, symbol: String, token: String, pin: String) { - with(binding) { - loginFormUsername.setText(username) - loginFormPass.setText(pass) - loginFormToken.setText(token) - loginFormSymbol.setText(symbol) - loginFormPin.setText(pin) - } - } - - override fun setUsernameLabel(label: String) { - binding.loginFormUsernameLayout.hint = label - } - - override fun setSymbol(symbol: String) { - binding.loginFormSymbol.setText(symbol) - } - - override fun setErrorUsernameRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorLoginRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_invalid_login) - } - } - - override fun setErrorEmailRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_invalid_email) - } - } - - override fun setErrorPassRequired(focus: Boolean) { - with(binding.loginFormPassLayout) { - if (focus) requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorPassInvalid(focus: Boolean) { - with(binding.loginFormPassLayout) { - if (focus) requestFocus() - error = getString(R.string.login_invalid_password) - } - } - - override fun setErrorPassIncorrect() { - with(binding.loginFormPassLayout) { - requestFocus() - error = getString(R.string.login_incorrect_password) - } - } - - override fun setErrorPinRequired() { - with(binding.loginFormPinLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorPinInvalid(message: String) { - with(binding.loginFormPinLayout) { - requestFocus() - error = message - } - } - - override fun setErrorSymbolRequired() { - with(binding.loginFormSymbolLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorSymbolInvalid(message: String) { - with(binding.loginFormSymbolLayout) { - requestFocus() - error = message - } - } - - override fun setErrorTokenRequired() { - with(binding.loginFormTokenLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorTokenInvalid(message: String) { - with(binding.loginFormTokenLayout) { - requestFocus() - error = message - } - } - - override fun clearUsernameError() { - binding.loginFormUsernameLayout.error = null - } - - override fun clearPassError() { - binding.loginFormPassLayout.error = null - } - - override fun clearPinKeyError() { - binding.loginFormPinLayout.error = null - } - - override fun clearSymbolError() { - binding.loginFormSymbolLayout.error = null - } - - override fun clearTokenError() { - binding.loginFormTokenLayout.error = null - } - - override fun showOnlyHybridModeInputs() { - with(binding) { - loginFormUsernameLayout.visibility = VISIBLE - loginFormPassLayout.visibility = VISIBLE - loginFormHostLayout.visibility = VISIBLE - loginFormPinLayout.visibility = GONE - loginFormSymbolLayout.visibility = VISIBLE - loginFormTokenLayout.visibility = GONE - } - } - - override fun showOnlyScrapperModeInputs() { - with(binding) { - loginFormUsernameLayout.visibility = VISIBLE - loginFormPassLayout.visibility = VISIBLE - loginFormHostLayout.visibility = VISIBLE - loginFormPinLayout.visibility = GONE - loginFormSymbolLayout.visibility = VISIBLE - loginFormTokenLayout.visibility = GONE - } - } - - override fun showOnlyMobileApiModeInputs() { - with(binding) { - loginFormUsernameLayout.visibility = GONE - loginFormPassLayout.visibility = GONE - loginFormHostLayout.visibility = GONE - loginFormPinLayout.visibility = VISIBLE - loginFormSymbolLayout.visibility = VISIBLE - loginFormTokenLayout.visibility = VISIBLE - } - } - - override fun showSoftKeyboard() { - activity?.showSoftInput() - } - - override fun hideSoftKeyboard() { - activity?.hideSoftInput() - } - - override fun showProgress(show: Boolean) { - binding.loginFormProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.loginFormContainer.visibility = if (show) VISIBLE else GONE - } - - override fun notifyParentAccountLogged(students: List) { - (activity as? LoginActivity)?.onFormFragmentAccountLogged(students, Triple( - binding.loginFormUsername.text.toString(), - binding.loginFormPass.text.toString(), - resources.getStringArray(R.array.hosts_values)[1] - )) - } - - override fun onResume() { - super.onResume() - presenter.updateUsernameLabel() - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 3a0d4a0d8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedPresenter.kt +++ /dev/null @@ -1,231 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.advanced - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.ifNullOrBlank -import io.reactivex.Single -import timber.log.Timber -import javax.inject.Inject - -class LoginAdvancedPresenter @Inject constructor( - schedulers: SchedulersProvider, - studentRepository: StudentRepository, - private val loginErrorHandler: LoginErrorHandler, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(loginErrorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: LoginAdvancedView) { - super.onAttachView(view) - view.run { - initView() - showOnlyScrapperModeInputs() - with(loginErrorHandler) { - onBadCredentials = ::onBadCredentials - onInvalidToken = ::onInvalidToken - onInvalidSymbol = ::onInvalidSymbol - onInvalidPin = ::onInvalidPin - } - } - } - - private fun onBadCredentials() { - view?.run { - setErrorPassIncorrect() - showSoftKeyboard() - Timber.i("Entered wrong username or password") - } - } - - private fun onInvalidToken(message: String) { - view?.run { - setErrorTokenInvalid(message) - showSoftKeyboard() - Timber.i("Entered invalid token") - } - } - - private fun onInvalidSymbol(message: String) { - view?.run { - setErrorSymbolInvalid(message) - showSoftKeyboard() - Timber.i("Entered invalid symbol") - } - } - - private fun onInvalidPin(message: String) { - view?.run { - setErrorPinInvalid(message) - showSoftKeyboard() - Timber.i("Entered invalid PIN") - } - } - - fun updateUsernameLabel() { - view?.apply { - setUsernameLabel(if ("vulcan" in formHostValue || "fakelog" in formHostValue) emailLabel else nicknameLabel) - } - } - - fun onHostSelected() { - view?.apply { - clearPassError() - clearUsernameError() - if (formHostValue.contains("fakelog")) { - setDefaultCredentials("jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999") - } - setSymbol(formHostSymbol) - updateUsernameLabel() - } - } - - fun onLoginModeSelected(type: Sdk.Mode) { - view?.run { - when (type) { - Sdk.Mode.API -> { - showOnlyMobileApiModeInputs() - showMobileApiWarningMessage() - } - Sdk.Mode.SCRAPPER -> { - showOnlyScrapperModeInputs() - showScraperWarningMessage() - } - Sdk.Mode.HYBRID -> { - showOnlyHybridModeInputs() - showHybridWarningMessage() - } - } - } - } - - fun onPassTextChanged() { - view?.clearPassError() - } - - fun onUsernameTextChanged() { - view?.clearUsernameError() - } - - fun onPinTextChanged() { - view?.clearPinKeyError() - } - - fun onSymbolTextChanged() { - view?.clearSymbolError() - } - - fun onTokenTextChanged() { - view?.clearTokenError() - } - - fun onSignInClick() { - if (!validateCredentials()) return - - disposable.add(getStudentsAppropriatesToLoginType() - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.apply { - hideSoftKeyboard() - showProgress(true) - showContent(false) - } - Timber.i("Login started") - } - .doFinally { - view?.apply { - showProgress(false) - showContent(true) - } - } - .subscribe({ - Timber.i("Login result: Success") - analytics.logEvent("registration_form", "success" to true, "students" to it.size, "error" to "No error") - view?.notifyParentAccountLogged(it) - }, { - Timber.i("Login result: An exception occurred") - analytics.logEvent("registration_form", "success" to false, "students" to -1, "error" to it.message.ifNullOrBlank { "No message" }) - loginErrorHandler.dispatch(it) - })) - } - - private fun getStudentsAppropriatesToLoginType(): Single> { - val email = view?.formUsernameValue.orEmpty() - val password = view?.formPassValue.orEmpty() - val endpoint = view?.formHostValue.orEmpty() - - val pin = view?.formPinValue.orEmpty() - val symbol = view?.formSymbolValue.orEmpty() - val token = view?.formTokenValue.orEmpty() - - return when (Sdk.Mode.valueOf(view?.formLoginType ?: "")) { - Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token) - Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(email, password, endpoint, symbol) - Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(email, password, endpoint, symbol) - } - } - - private fun validateCredentials(): Boolean { - val login = view?.formUsernameValue.orEmpty() - val password = view?.formPassValue.orEmpty() - - val host = view?.formHostValue.orEmpty() - - val pin = view?.formPinValue.orEmpty() - val symbol = view?.formSymbolValue.orEmpty() - val token = view?.formTokenValue.orEmpty() - - var isCorrect = true - - when (Sdk.Mode.valueOf(view?.formLoginType ?: "")) { - Sdk.Mode.API -> { - if (pin.isEmpty()) { - view?.setErrorPinRequired() - isCorrect = false - } - - if (symbol.isEmpty()) { - view?.setErrorSymbolRequired() - isCorrect = false - } - - if (token.isEmpty()) { - view?.setErrorTokenRequired() - isCorrect = false - } - } - Sdk.Mode.HYBRID, Sdk.Mode.SCRAPPER -> { - if (login.isEmpty()) { - view?.setErrorUsernameRequired() - isCorrect = false - } else { - if ("@" in login && "standard" !in host) { - view?.setErrorLoginRequired() - isCorrect = false - } - - if ("@" !in login && "standard" in host) { - view?.setErrorEmailRequired() - isCorrect = false - } - } - - if (password.isEmpty()) { - view?.setErrorPassRequired(focus = isCorrect) - isCorrect = false - } - - if (password.length < 6 && password.isNotEmpty()) { - view?.setErrorPassInvalid(focus = isCorrect) - isCorrect = false - } - } - } - - return isCorrect - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt deleted file mode 100644 index 36c9a93f8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/advanced/LoginAdvancedView.kt +++ /dev/null @@ -1,91 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.advanced - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LoginAdvancedView : BaseView { - - val formUsernameValue: String - - val formPassValue: String - - val formHostValue: String - - val formHostSymbol: String - - val formLoginType: String - - val formPinValue: String - - val formSymbolValue: String - - val formTokenValue: String - - val nicknameLabel: String - - val emailLabel: String - - fun initView() - - fun showMobileApiWarningMessage() - - fun showScraperWarningMessage() - - fun showHybridWarningMessage() - - fun setDefaultCredentials(username: String, pass: String, symbol: String, token: String, pin: String) - - fun setUsernameLabel(label: String) - - fun setSymbol(symbol: String) - - fun setErrorUsernameRequired() - - fun setErrorLoginRequired() - - fun setErrorEmailRequired() - - fun setErrorPassRequired(focus: Boolean) - - fun setErrorPassInvalid(focus: Boolean) - - fun setErrorPassIncorrect() - - fun clearUsernameError() - - fun clearPassError() - - fun clearPinKeyError() - - fun clearSymbolError() - - fun clearTokenError() - - fun showSoftKeyboard() - - fun hideSoftKeyboard() - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun notifyParentAccountLogged(students: List) - - fun setErrorPinRequired() - - fun setErrorPinInvalid(message: String) - - fun setErrorSymbolRequired() - - fun setErrorSymbolInvalid(message: String) - - fun setErrorTokenRequired() - - fun setErrorTokenInvalid(message: String) - - fun showOnlyHybridModeInputs() - - fun showOnlyScrapperModeInputs() - - fun showOnlyMobileApiModeInputs() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt deleted file mode 100644 index a2a083c00..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ /dev/null @@ -1,220 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.form - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.core.widget.doOnTextChanged -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.FragmentLoginFormBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.setOnEditorDoneSignIn -import io.github.wulkanowy.utils.showSoftInput -import javax.inject.Inject - -class LoginFormFragment : BaseFragment(R.layout.fragment_login_form), - LoginFormView { - - @Inject - lateinit var presenter: LoginFormPresenter - - @Inject - lateinit var appInfo: AppInfo - - companion object { - fun newInstance() = LoginFormFragment() - } - - override val formUsernameValue: String - get() = binding.loginFormUsername.text.toString() - - override val formPassValue: String - get() = binding.loginFormPass.text.toString() - - override val formHostValue: String - get() = hostValues.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())).orEmpty() - - override val formHostSymbol: String - get() = hostSymbols.getOrNull(hostKeys.indexOf(binding.loginFormHost.text.toString())).orEmpty() - - override val nicknameLabel: String - get() = getString(R.string.login_nickname_hint) - - override val emailLabel: String - get() = getString(R.string.login_email_hint) - - private lateinit var hostKeys: Array - - private lateinit var hostValues: Array - - private lateinit var hostSymbols: Array - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLoginFormBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - hostKeys = resources.getStringArray(R.array.hosts_keys) - hostValues = resources.getStringArray(R.array.hosts_values) - hostSymbols = resources.getStringArray(R.array.hosts_symbols) - - with(binding) { - loginFormUsername.doOnTextChanged { _, _, _, _ -> presenter.onUsernameTextChanged() } - loginFormPass.doOnTextChanged { _, _, _, _ -> presenter.onPassTextChanged() } - loginFormHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } - loginFormSignIn.setOnClickListener { presenter.onSignInClick() } - loginFormAdvancedButton.setOnClickListener { presenter.onAdvancedLoginClick() } - loginFormPrivacyLink.setOnClickListener { presenter.onPrivacyLinkClick() } - loginFormFaq.setOnClickListener { presenter.onFaqClick() } - loginFormContactEmail.setOnClickListener { presenter.onEmailClick() } - loginFormRecoverLink.setOnClickListener { presenter.onRecoverClick() } - loginFormPass.setOnEditorDoneSignIn { loginFormSignIn.callOnClick() } - } - - with(binding.loginFormHost) { - setText(hostKeys.getOrNull(0).orEmpty()) - setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) - setOnClickListener { if (binding.loginFormContainer.visibility == GONE) dismissDropDown() } - } - } - - override fun setCredentials(username: String, pass: String) { - with(binding) { - loginFormUsername.setText(username) - loginFormPass.setText(pass) - } - } - - override fun setUsernameLabel(label: String) { - binding.loginFormUsernameLayout.hint = label - } - - override fun setErrorUsernameRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorLoginRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_invalid_login) - } - } - - override fun setErrorEmailRequired() { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_invalid_email) - } - } - - override fun setErrorPassRequired(focus: Boolean) { - with(binding.loginFormPassLayout) { - if (focus) requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setErrorPassInvalid(focus: Boolean) { - with(binding.loginFormPassLayout) { - if (focus) requestFocus() - error = getString(R.string.login_invalid_password) - } - } - - override fun setErrorPassIncorrect() { - with(binding.loginFormPassLayout) { - requestFocus() - error = getString(R.string.login_incorrect_password) - } - } - - override fun clearUsernameError() { - binding.loginFormUsernameLayout.error = null - } - - override fun clearPassError() { - binding.loginFormPassLayout.error = null - } - - override fun showSoftKeyboard() { - activity?.showSoftInput() - } - - override fun hideSoftKeyboard() { - activity?.hideSoftInput() - } - - override fun showProgress(show: Boolean) { - binding.loginFormProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.loginFormContainer.visibility = if (show) VISIBLE else GONE - } - - @SuppressLint("SetTextI18n") - override fun showVersion() { - binding.loginFormVersion.text = "v${appInfo.versionName}" - } - - override fun notifyParentAccountLogged(students: List, loginData: Triple) { - (activity as? LoginActivity)?.onFormFragmentAccountLogged(students, loginData) - } - - override fun openPrivacyPolicyPage() { - context?.openInternetBrowser("https://wulkanowy.github.io/polityka-prywatnosci.html", ::showMessage) - } - - override fun showContact(show: Boolean) { - binding.loginFormContact.visibility = if (show) VISIBLE else GONE - } - - override fun openAdvancedLogin() { - (activity as? LoginActivity)?.onAdvancedLoginClick() - } - - override fun onRecoverClick() { - (activity as? LoginActivity)?.onRecoverClick() - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } - - override fun openFaqPage() { - context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania/dlaczego-nie-moge-sie-zalogowac", ::showMessage) - } - - override fun onResume() { - super.onResume() - presenter.updateUsernameLabel() - } - - override fun openEmail(lastError: String) { - context?.openEmailClient( - chooserTitle = requireContext().getString(R.string.login_email_intent_title), - email = "wulkanowyinc@gmail.com", - subject = requireContext().getString(R.string.login_email_subject), - body = requireContext().getString(R.string.login_email_text, - "${appInfo.systemManufacturer} ${appInfo.systemModel}", - appInfo.systemVersion.toString(), - appInfo.versionName, - "$formHostValue/$formHostSymbol", - lastError - ) - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt deleted file mode 100644 index 997e1e85f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt +++ /dev/null @@ -1,149 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.form - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.ifNullOrBlank -import timber.log.Timber -import javax.inject.Inject - -class LoginFormPresenter @Inject constructor( - schedulers: SchedulersProvider, - studentRepository: StudentRepository, - private val loginErrorHandler: LoginErrorHandler, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(loginErrorHandler, studentRepository, schedulers) { - - private var lastError: Throwable? = null - - override fun onAttachView(view: LoginFormView) { - super.onAttachView(view) - view.run { - initView() - showContact(false) - showVersion() - - loginErrorHandler.onBadCredentials = { - setErrorPassIncorrect() - showSoftKeyboard() - Timber.i("Entered wrong username or password") - } - } - } - - fun onPrivacyLinkClick() { - view?.openPrivacyPolicyPage() - } - - fun onAdvancedLoginClick() { - view?.openAdvancedLogin() - } - - fun onHostSelected() { - view?.apply { - clearPassError() - clearUsernameError() - if (formHostValue.contains("fakelog")) { - setCredentials("jan@fakelog.cf", "jan123") - } - updateUsernameLabel() - } - } - - fun updateUsernameLabel() { - view?.run { - setUsernameLabel(if ("standard" in formHostValue) emailLabel else nicknameLabel) - } - } - - fun onPassTextChanged() { - view?.clearPassError() - } - - fun onUsernameTextChanged() { - view?.clearUsernameError() - } - - fun onSignInClick() { - val email = view?.formUsernameValue.orEmpty().trim() - val password = view?.formPassValue.orEmpty().trim() - val host = view?.formHostValue.orEmpty().trim() - val symbol = view?.formHostSymbol.orEmpty().trim() - - if (!validateCredentials(email, password, host)) return - - disposable.add(studentRepository.getStudentsScrapper(email, password, host, symbol) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.apply { - hideSoftKeyboard() - showProgress(true) - showContent(false) - } - Timber.i("Login started") - } - .doFinally { - view?.apply { - showProgress(false) - showContent(true) - } - } - .subscribe({ - Timber.i("Login result: Success") - analytics.logEvent("registration_form", "success" to true, "students" to it.size, "scrapperBaseUrl" to host, "error" to "No error") - view?.notifyParentAccountLogged(it, Triple(email, password, host)) - }, { - Timber.i("Login result: An exception occurred") - analytics.logEvent("registration_form", "success" to false, "students" to -1, "scrapperBaseUrl" to host, "error" to it.message.ifNullOrBlank { "No message" }) - loginErrorHandler.dispatch(it) - lastError = it - view?.showContact(true) - })) - } - - fun onFaqClick() { - view?.openFaqPage() - } - - fun onEmailClick() { - view?.openEmail(lastError?.message.ifNullOrBlank { "none" }) - } - - fun onRecoverClick() { - view?.onRecoverClick() - } - - private fun validateCredentials(login: String, password: String, host: String): Boolean { - var isCorrect = true - - if (login.isEmpty()) { - view?.setErrorUsernameRequired() - isCorrect = false - } else { - if ("@" in login && "standard" !in host) { - view?.setErrorLoginRequired() - isCorrect = false - } - - if ("@" !in login && "standard" in host) { - view?.setErrorEmailRequired() - isCorrect = false - } - } - - if (password.isEmpty()) { - view?.setErrorPassRequired(focus = isCorrect) - isCorrect = false - } - - if (password.length < 6 && password.isNotEmpty()) { - view?.setErrorPassInvalid(focus = isCorrect) - isCorrect = false - } - - return isCorrect - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt deleted file mode 100644 index 6506fa88f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt +++ /dev/null @@ -1,65 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.form - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LoginFormView : BaseView { - - fun initView() - - val formUsernameValue: String - - val formPassValue: String - - val formHostValue: String - - val formHostSymbol: String - - val nicknameLabel: String - - val emailLabel: String - - fun setCredentials(username: String, pass: String) - - fun setUsernameLabel(label: String) - - fun setErrorUsernameRequired() - - fun setErrorLoginRequired() - - fun setErrorEmailRequired() - - fun setErrorPassRequired(focus: Boolean) - - fun setErrorPassInvalid(focus: Boolean) - - fun setErrorPassIncorrect() - - fun clearUsernameError() - - fun clearPassError() - - fun showSoftKeyboard() - - fun hideSoftKeyboard() - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun showVersion() - - fun notifyParentAccountLogged(students: List, loginData: Triple) - - fun openPrivacyPolicyPage() - - fun showContact(show: Boolean) - - fun openFaqPage() - - fun openEmail(lastError: String) - - fun openAdvancedLogin() - - fun onRecoverClick() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt deleted file mode 100644 index 87fa038ec..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginSymbolAdapter.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.form - -import android.content.Context -import android.widget.ArrayAdapter -import android.widget.Filter - -class LoginSymbolAdapter(context: Context, resource: Int, objects: Array) : - ArrayAdapter(context, resource, objects) { - - override fun getFilter() = object : Filter() { - - override fun performFiltering(constraint: CharSequence?) = null - - override fun publishResults(constraint: CharSequence?, results: FilterResults?) {} - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt deleted file mode 100644 index e27c845a6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt +++ /dev/null @@ -1,210 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.recover - -import android.annotation.SuppressLint -import android.graphics.Color -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.webkit.JavascriptInterface -import android.webkit.WebView -import android.webkit.WebViewClient -import androidx.core.widget.doOnTextChanged -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentLoginRecoverBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.showSoftInput -import javax.inject.Inject - -class LoginRecoverFragment : - BaseFragment(R.layout.fragment_login_recover), LoginRecoverView { - - private var _binding: FragmentLoginRecoverBinding? = null - - private val bindingLocal: FragmentLoginRecoverBinding get() = _binding!! - - @Inject - lateinit var presenter: LoginRecoverPresenter - - companion object { - fun newInstance() = LoginRecoverFragment() - } - - private lateinit var hostKeys: Array - - private lateinit var hostValues: Array - - private lateinit var hostSymbols: Array - - override val recoverHostValue: String - get() = hostValues.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() - - override val formHostSymbol: String - get() = hostSymbols.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() - - override val recoverNameValue: String - get() = bindingLocal.loginRecoverName.text.toString().trim() - - override val emailHintString: String - get() = getString(R.string.login_email_hint) - - override val loginPeselEmailHintString: String - get() = getString(R.string.login_login_pesel_email_hint) - - override val invalidEmailString: String - get() = getString(R.string.login_invalid_email) - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - _binding = FragmentLoginRecoverBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - hostKeys = resources.getStringArray(R.array.hosts_keys) - hostValues = resources.getStringArray(R.array.hosts_values) - hostSymbols = resources.getStringArray(R.array.hosts_symbols) - - with(bindingLocal) { - loginRecoverWebView.setBackgroundColor(Color.TRANSPARENT) - loginRecoverName.doOnTextChanged { _, _, _, _ -> presenter.onNameTextChanged() } - loginRecoverHost.setOnItemClickListener { _, _, _, _ -> presenter.onHostSelected() } - loginRecoverButton.setOnClickListener { presenter.onRecoverClick() } - loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() } - loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() } - loginRecoverLogin.setOnClickListener { (activity as LoginActivity).switchView(0) } - } - - with(bindingLocal.loginRecoverHost) { - setText(hostKeys.getOrNull(0).orEmpty()) - setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) - setOnClickListener { if (bindingLocal.loginRecoverFormContainer.visibility == GONE) dismissDropDown() } - } - } - - override fun setDefaultCredentials(username: String) { - bindingLocal.loginRecoverName.setText(username) - } - - override fun setErrorNameRequired() { - with(bindingLocal.loginRecoverNameLayout) { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun setUsernameHint(hint: String) { - bindingLocal.loginRecoverNameLayout.hint = hint - } - - override fun setUsernameError(message: String) { - with(bindingLocal.loginRecoverNameLayout) { - requestFocus() - error = message - } - } - - override fun clearUsernameError() { - bindingLocal.loginRecoverNameLayout.error = null - } - - override fun showProgress(show: Boolean) { - bindingLocal.loginRecoverProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showRecoverForm(show: Boolean) { - bindingLocal.loginRecoverFormContainer.visibility = if (show) VISIBLE else GONE - } - - override fun showCaptcha(show: Boolean) { - bindingLocal.loginRecoverCaptchaContainer.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - bindingLocal.loginRecoverError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - bindingLocal.loginRecoverErrorMessage.text = message - } - - override fun showSuccessView(show: Boolean) { - bindingLocal.loginRecoverSuccess.visibility = if (show) VISIBLE else GONE - } - - override fun setSuccessTitle(title: String) { - bindingLocal.loginRecoverSuccessTitle.text = title - } - - override fun setSuccessMessage(message: String) { - bindingLocal.loginRecoverSuccessMessage.text = message - } - - override fun showSoftKeyboard() { - activity?.showSoftInput() - } - - override fun hideSoftKeyboard() { - activity?.hideSoftInput() - } - - @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface") - override fun loadReCaptcha(siteKey: String, url: String) { - val html = """ -
- - - """.trimIndent() - - with(bindingLocal.loginRecoverWebView) { - settings.javaScriptEnabled = true - webViewClient = object : WebViewClient() { - private var recoverWebViewSuccess: Boolean = true - - override fun onPageFinished(view: WebView?, url: String?) { - if (recoverWebViewSuccess) { - showCaptcha(true) - showProgress(false) - } else { - showProgress(false) - showErrorView(true) - } - } - - override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) { - recoverWebViewSuccess = false - } - } - - loadDataWithBaseURL(url, html, "text/html", "UTF-8", null) - addJavascriptInterface(object { - - @Suppress("UNUSED") - @JavascriptInterface - fun captchaCallback(reCaptchaResponse: String) { - activity?.runOnUiThread { - presenter.onReCaptchaVerified(reCaptchaResponse) - } - } - }, "Android") - } - } - - override fun onResume() { - super.onResume() - presenter.updateFields() - } - - override fun onDestroyView() { - bindingLocal.loginRecoverWebView.destroy() - _binding = null - presenter.onDetachView() - - super.onDestroyView() - } -} 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 deleted file mode 100644 index 9a21fb910..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverPresenter.kt +++ /dev/null @@ -1,159 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.recover - -import io.github.wulkanowy.data.repositories.recover.RecoverRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.ifNullOrBlank -import timber.log.Timber -import javax.inject.Inject - -class LoginRecoverPresenter @Inject constructor( - schedulers: SchedulersProvider, - studentRepository: StudentRepository, - private val loginErrorHandler: RecoverErrorHandler, - private val analytics: FirebaseAnalyticsHelper, - private val recoverRepository: RecoverRepository -) : BasePresenter(loginErrorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: LoginRecoverView) { - super.onAttachView(view) - view.initView() - - with(loginErrorHandler) { - showErrorMessage = ::showErrorMessage - onInvalidUsername = ::onInvalidUsername - onInvalidCaptcha = ::onInvalidCaptcha - } - } - - fun onNameTextChanged() { - view?.clearUsernameError() - } - - fun onHostSelected() { - view?.run { - if ("fakelog" in recoverHostValue) setDefaultCredentials("jan@fakelog.cf") - clearUsernameError() - updateFields() - } - } - - fun updateFields() { - view?.run { - setUsernameHint(if ("standard" in recoverHostValue) emailHintString else loginPeselEmailHintString) - } - } - - fun onRecoverClick() { - val username = view?.recoverNameValue.orEmpty() - val host = view?.recoverHostValue.orEmpty() - val symbol = view?.formHostSymbol.orEmpty() - - if (!validateInput(username, host)) return - - disposable.add(recoverRepository.getReCaptchaSiteKey(host, symbol.ifBlank { "Default" }) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - hideSoftKeyboard() - showRecoverForm(false) - showProgress(true) - showErrorView(false) - showCaptcha(false) - } - } - .subscribe({ (resetUrl, siteKey) -> - view?.loadReCaptcha(siteKey, resetUrl) - }) { - Timber.i("Obtain captcha site key result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun validateInput(username: String, host: String): Boolean { - var isCorrect = true - - if (username.isEmpty()) { - view?.setErrorNameRequired() - isCorrect = false - } - - if ("standard" in host && "@" !in username) { - view?.setUsernameError(view?.invalidEmailString.orEmpty()) - isCorrect = false - } - - return isCorrect - } - - fun onReCaptchaVerified(reCaptchaResponse: String) { - val username = view?.recoverNameValue.orEmpty() - val host = view?.recoverHostValue.orEmpty() - val symbol = view?.formHostSymbol.ifNullOrBlank { "Default" } - - with(disposable) { - clear() - add(recoverRepository.sendRecoverRequest(host, symbol, username, reCaptchaResponse) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - showProgress(true) - showRecoverForm(false) - showCaptcha(false) - } - } - .doFinally { - view?.showProgress(false) - } - .subscribe({ - view?.run { - showSuccessView(true) - setSuccessTitle(it.substringBefore(". ")) - setSuccessMessage(it.substringAfter(". ")) - } - - analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to true) - }) { - Timber.i("Send recover request result: An exception occurred") - errorHandler.dispatch(it) - analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to false) - }) - } - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - private fun showErrorMessage(message: String, error: Throwable) { - view?.run { - lastError = error - showProgress(false) - setErrorDetails(message) - showErrorView(true) - } - } - - private fun onInvalidUsername(message: String) { - view?.run { - setUsernameError(message) - showRecoverForm(true) - } - } - - private fun onInvalidCaptcha(message: String, error: Throwable) { - view?.run { - lastError = error - setErrorDetails(message) - showCaptcha(false) - showRecoverForm(false) - showErrorView(true) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverView.kt deleted file mode 100644 index 2e21d3351..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverView.kt +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.recover - -import io.github.wulkanowy.ui.base.BaseView - -interface LoginRecoverView : BaseView { - - val recoverHostValue: String - - val formHostSymbol: String - - val recoverNameValue: String - - val emailHintString: String - - val loginPeselEmailHintString: String - - val invalidEmailString: String - - fun initView() - - fun setDefaultCredentials(username: String) - - fun clearUsernameError() - - fun setErrorNameRequired() - - fun setUsernameHint(hint: String) - - fun setUsernameError(message: String) - - fun showSoftKeyboard() - - fun hideSoftKeyboard() - - fun showProgress(show: Boolean) - - fun showRecoverForm(show: Boolean) - - fun showCaptcha(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showSuccessView(show: Boolean) - - fun setSuccessMessage(message: String) - - fun setSuccessTitle(title: String) - - fun loadReCaptcha(siteKey: String, url: String) -} 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 deleted file mode 100644 index 110dd82e5..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/RecoverErrorHandler.kt +++ /dev/null @@ -1,32 +0,0 @@ -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) { - - var onInvalidUsername: (String) -> Unit = {} - - var onInvalidCaptcha: (String, Throwable) -> Unit = { _, _ -> } - - override fun proceed(error: Throwable) { - when (error) { - is InvalidEmailException, is NoAccountFoundException -> onInvalidUsername(error.localizedMessage.orEmpty()) - is InvalidCaptchaException -> onInvalidCaptcha(error.localizedMessage.orEmpty(), error) - else -> super.proceed(error) - } - } - - override fun clear() { - super.clear() - onInvalidUsername = {} - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt deleted file mode 100644 index 3332f2be8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectAdapter.kt +++ /dev/null @@ -1,63 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.studentselect - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.ItemLoginStudentSelectBinding -import javax.inject.Inject - -class LoginStudentSelectAdapter @Inject constructor() : - RecyclerView.Adapter() { - - private val checkedList = mutableMapOf() - - var items = emptyList>() - set(value) { - field = value - checkedList.clear() - } - - var onClickListener: (Student, alreadySaved: Boolean) -> Unit = { _, _ -> } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemLoginStudentSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("SetTextI18n") - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val (student, alreadySaved) = items[position] - - with(holder.binding) { - loginItemName.text = "${student.studentName} ${student.className}" - loginItemSchool.text = student.schoolName - loginItemName.isEnabled = !alreadySaved - loginItemSchool.isEnabled = !alreadySaved - loginItemSignedIn.visibility = if (alreadySaved) View.VISIBLE else View.GONE - - with(loginItemCheck) { - isEnabled = !alreadySaved - keyListener = null - isChecked = checkedList[position] ?: false - } - - root.setOnClickListener { - onClickListener(student, alreadySaved) - - with(loginItemCheck) { - if (isEnabled) { - isChecked = !isChecked - checkedList[position] = isChecked - } - } - } - } - } - - class ItemViewHolder(val binding: ItemLoginStudentSelectBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt deleted file mode 100644 index b0df51991..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectFragment.kt +++ /dev/null @@ -1,117 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.studentselect - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import java.io.Serializable -import javax.inject.Inject - -class LoginStudentSelectFragment : - BaseFragment(R.layout.fragment_login_student_select), - LoginStudentSelectView { - - @Inject - lateinit var presenter: LoginStudentSelectPresenter - - @Inject - lateinit var loginAdapter: LoginStudentSelectAdapter - - @Inject - lateinit var appInfo: AppInfo - - companion object { - const val SAVED_STUDENTS = "STUDENTS" - - fun newInstance() = LoginStudentSelectFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLoginStudentSelectBinding.bind(view) - presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_STUDENTS)) - } - - override fun initView() { - loginAdapter.onClickListener = presenter::onItemSelected - - with(binding) { - loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() } - loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() } - loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() } - - with(loginStudentSelectRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = loginAdapter - } - } - } - - override fun updateData(data: List>) { - with(loginAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun openMainView() { - activity?.let { startActivity(MainActivity.getStartIntent(context = it, clear = true)) } - } - - override fun showProgress(show: Boolean) { - binding.loginStudentSelectProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.loginStudentSelectContent.visibility = if (show) VISIBLE else GONE - } - - override fun enableSignIn(enable: Boolean) { - binding.loginStudentSelectSignIn.isEnabled = enable - } - - fun onParentInitStudentSelectFragment(students: List) { - presenter.onParentInitStudentSelectView(students) - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putSerializable(SAVED_STUDENTS, presenter.students as Serializable) - } - - override fun showContact(show: Boolean) { - binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } - - override fun openDiscordInvite() { - context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) - } - - override fun openEmail(lastError: String) { - context?.openEmailClient( - chooserTitle = requireContext().getString(R.string.login_email_intent_title), - email = "wulkanowyinc@gmail.com", - subject = requireContext().getString(R.string.login_email_subject), - body = requireContext().getString(R.string.login_email_text, appInfo.systemModel, - appInfo.systemVersion.toString(), - appInfo.versionName, - "Select users to log in", - lastError - ) - ) - } -} 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 deleted file mode 100644 index db25c0da3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectPresenter.kt +++ /dev/null @@ -1,134 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.studentselect - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.ifNullOrBlank -import timber.log.Timber -import java.io.Serializable -import javax.inject.Inject - -class LoginStudentSelectPresenter @Inject constructor( - schedulers: SchedulersProvider, - studentRepository: StudentRepository, - private val loginErrorHandler: LoginErrorHandler, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(loginErrorHandler, studentRepository, schedulers) { - - private var lastError: Throwable? = null - - var students = emptyList() - - private val selectedStudents = mutableListOf() - - fun onAttachView(view: LoginStudentSelectView, students: Serializable?) { - super.onAttachView(view) - view.run { - initView() - showContact(false) - enableSignIn(false) - loginErrorHandler.onStudentDuplicate = { - showMessage(it) - Timber.i("The student already registered in the app was selected") - } - } - - if (students is List<*> && students.isNotEmpty()) { - loadData(students.filterIsInstance()) - } - } - - fun onSignIn() { - registerStudents(selectedStudents) - } - - fun onParentInitStudentSelectView(students: List) { - loadData(students) - if (students.size == 1) registerStudents(students) - } - - fun onItemSelected(student: Student, alreadySaved: Boolean) { - if (alreadySaved) return - - selectedStudents - .removeAll { it == student } - .let { if (!it) selectedStudents.add(student) } - - view?.enableSignIn(selectedStudents.isNotEmpty()) - } - - private fun compareStudents(a: Student, b: Student): Boolean { - return a.email == b.email - && a.symbol == b.symbol - && a.studentId == b.studentId - && a.schoolSymbol == b.schoolSymbol - && a.classId == b.classId - } - - private fun loadData(students: List) { - resetSelectedState() - this.students = students - disposable.add(studentRepository.getSavedStudents() - .map { savedStudents -> - students.map { student -> - student to savedStudents.any { compareStudents(student, it) } - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - view?.updateData(it) - }, { - errorHandler.dispatch(it) - lastError = it - view?.updateData(students.map { student -> student to false }) - }) - ) - } - - private fun resetSelectedState() { - selectedStudents.clear() - view?.enableSignIn(false) - } - - private fun registerStudents(students: List) { - disposable.add(studentRepository.saveStudents(students) - .map { students.first().apply { id = it.first() } } - .flatMapCompletable { studentRepository.switchStudent(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.apply { - showProgress(true) - showContent(false) - } - Timber.i("Registration started") - } - .subscribe({ - students.forEach { analytics.logEvent("registration_student_select", "success" to true, "scrapperBaseUrl" to it.scrapperBaseUrl, "symbol" to it.symbol, "error" to "No error") } - Timber.i("Registration result: Success") - view?.openMainView() - }, { error -> - students.forEach { analytics.logEvent("registration_student_select", "success" to false, "scrapperBaseUrl" to it.scrapperBaseUrl, "symbol" to it.symbol, "error" to error.message.ifNullOrBlank { "No message" }) } - Timber.i("Registration result: An exception occurred ") - loginErrorHandler.dispatch(error) - lastError = error - view?.apply { - showProgress(false) - showContent(true) - showContact(true) - } - })) - } - - fun onDiscordClick() { - view?.openDiscordInvite() - } - - fun onEmailClick() { - view?.openEmail(lastError?.message.ifNullOrBlank { "empty" }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt deleted file mode 100644 index 89431dfc6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/studentselect/LoginStudentSelectView.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.studentselect - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LoginStudentSelectView : BaseView { - - fun initView() - - fun updateData(data: List>) - - fun openMainView() - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun enableSignIn(enable: Boolean) - - fun showContact(show: Boolean) - - fun openDiscordInvite() - - fun openEmail(lastError: String) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt deleted file mode 100644 index befbffd50..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolFragment.kt +++ /dev/null @@ -1,145 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.symbol - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.inputmethod.EditorInfo.IME_ACTION_DONE -import android.view.inputmethod.EditorInfo.IME_NULL -import android.widget.ArrayAdapter -import androidx.core.widget.doOnTextChanged -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.openEmailClient -import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.showSoftInput -import javax.inject.Inject - -class LoginSymbolFragment : - BaseFragment(R.layout.fragment_login_symbol), LoginSymbolView { - - @Inject - lateinit var presenter: LoginSymbolPresenter - - @Inject - lateinit var appInfo: AppInfo - - companion object { - private const val SAVED_LOGIN_DATA = "LOGIN_DATA" - - fun newInstance() = LoginSymbolFragment() - } - - override val symbolNameError: CharSequence? - get() = binding.loginSymbolNameLayout.error - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLoginSymbolBinding.bind(view) - presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_LOGIN_DATA)) - } - - override fun initView() { - with(binding) { - loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) } - loginSymbolFaq.setOnClickListener { presenter.onFaqClick() } - loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() } - - loginSymbolName.doOnTextChanged { _, _, _, _ -> presenter.onSymbolTextChanged() } - - loginSymbolName.apply { - setOnEditorActionListener { _, id, _ -> - if (id == IME_ACTION_DONE || id == IME_NULL) loginSymbolSignIn.callOnClick() else false - } - setAdapter(ArrayAdapter(context, android.R.layout.simple_list_item_1, resources.getStringArray(R.array.symbols_values))) - } - } - } - - fun onParentInitSymbolFragment(loginData: Triple) { - presenter.onParentInitSymbolView(loginData) - } - - override fun setErrorSymbolIncorrect() { - binding.loginSymbolNameLayout.apply { - requestFocus() - error = getString(R.string.login_incorrect_symbol) - } - } - - override fun setErrorSymbolRequire() { - binding.loginSymbolNameLayout.apply { - requestFocus() - error = getString(R.string.login_field_required) - } - } - - override fun clearSymbolError() { - binding.loginSymbolNameLayout.error = null - } - - override fun clearAndFocusSymbol() { - binding.loginSymbolNameLayout.apply { - editText?.text = null - requestFocus() - } - } - - override fun showSoftKeyboard() { - activity?.showSoftInput() - } - - override fun hideSoftKeyboard() { - activity?.hideSoftInput() - } - - override fun showProgress(show: Boolean) { - binding.loginSymbolProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE - } - - override fun notifyParentAccountLogged(students: List) { - (activity as? LoginActivity)?.onSymbolFragmentAccountLogged(students) - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putSerializable(SAVED_LOGIN_DATA, presenter.loginData) - } - - override fun showContact(show: Boolean) { - binding.loginSymbolContact.visibility = if (show) VISIBLE else GONE - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } - - override fun openFaqPage() { - context?.openInternetBrowser("https://wulkanowy.github.io/czesto-zadawane-pytania/co-to-jest-symbol", ::showMessage) - } - - override fun openEmail(host: String, lastError: String) { - context?.openEmailClient( - chooserTitle = requireContext().getString(R.string.login_email_intent_title), - email = "wulkanowyinc@gmail.com", - subject = requireContext().getString(R.string.login_email_subject), - body = requireContext().getString(R.string.login_email_text, - "${appInfo.systemManufacturer} ${appInfo.systemModel}", - appInfo.systemVersion.toString(), - appInfo.versionName, - "$host/${binding.loginSymbolName.text}", - lastError - ) - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt deleted file mode 100644 index 1f9e66b70..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolPresenter.kt +++ /dev/null @@ -1,104 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.symbol - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.modules.login.LoginErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.ifNullOrBlank -import io.reactivex.Single -import timber.log.Timber -import java.io.Serializable -import javax.inject.Inject - -class LoginSymbolPresenter @Inject constructor( - studentRepository: StudentRepository, - schedulers: SchedulersProvider, - private val loginErrorHandler: LoginErrorHandler, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(loginErrorHandler, studentRepository, schedulers) { - - private var lastError: Throwable? = null - - var loginData: Triple? = null - - @Suppress("UNCHECKED_CAST") - fun onAttachView(view: LoginSymbolView, savedLoginData: Serializable?) { - super.onAttachView(view) - view.run { - initView() - showContact(false) - } - if (savedLoginData is Triple<*, *, *>) { - loginData = savedLoginData as Triple - } - } - - fun onSymbolTextChanged() { - view?.apply { if (symbolNameError != null) clearSymbolError() } - } - - fun attemptLogin(symbol: String) { - if (loginData == null) throw IllegalArgumentException("Login data is null") - - if (symbol.isBlank()) { - view?.setErrorSymbolRequire() - return - } - - disposable.add( - Single.fromCallable { loginData } - .flatMap { studentRepository.getStudentsScrapper(it.first, it.second, it.third, symbol) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.apply { - hideSoftKeyboard() - showProgress(true) - showContent(false) - } - Timber.i("Login with symbol started") - } - .doFinally { - view?.apply { - showProgress(false) - showContent(true) - } - } - .subscribe({ - analytics.logEvent("registration_symbol", "success" to true, "students" to it.size, "scrapperBaseUrl" to loginData?.third, "symbol" to symbol, "error" to "No error") - view?.apply { - if (it.isEmpty()) { - Timber.i("Login with symbol result: Empty student list") - setErrorSymbolIncorrect() - view?.showContact(true) - } else { - Timber.i("Login with symbol result: Success") - notifyParentAccountLogged(it) - } - } - }, { - Timber.i("Login with symbol result: An exception occurred") - analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "scrapperBaseUrl" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" }) - loginErrorHandler.dispatch(it) - lastError = it - view?.showContact(true) - })) - } - - fun onParentInitSymbolView(loginData: Triple) { - this.loginData = loginData - view?.apply { - clearAndFocusSymbol() - showSoftKeyboard() - } - } - - fun onFaqClick() { - view?.openFaqPage() - } - - fun onEmailClick() { - view?.openEmail(loginData?.third.orEmpty(), lastError?.message.ifNullOrBlank { "empty" }) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt deleted file mode 100644 index 6938bf138..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/symbol/LoginSymbolView.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.ui.modules.login.symbol - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LoginSymbolView : BaseView { - - val symbolNameError: CharSequence? - - fun initView() - - fun setErrorSymbolIncorrect() - - fun setErrorSymbolRequire() - - fun clearSymbolError() - - fun clearAndFocusSymbol() - - fun showSoftKeyboard() - - fun hideSoftKeyboard() - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun notifyParentAccountLogged(students: List) - - fun showContact(show: Boolean) - - fun openFaqPage() - - fun openEmail(host: String, lastError: String) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt deleted file mode 100644 index 0775ce189..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt +++ /dev/null @@ -1,81 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.databinding.FragmentLuckyNumberBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import javax.inject.Inject - -class LuckyNumberFragment : - BaseFragment(R.layout.fragment_lucky_number), LuckyNumberView, - MainView.TitledView { - - @Inject - lateinit var presenter: LuckyNumberPresenter - - companion object { - fun newInstance() = LuckyNumberFragment() - } - - override val titleStringId: Int - get() = R.string.lucky_number_title - - override val isViewEmpty get() = binding.luckyNumberText.text.isBlank() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLuckyNumberBinding.bind(view) - messageContainer = binding.luckyNumberSwipe - presenter.onAttachView(this) - } - - override fun initView() { - with(binding) { - luckyNumberSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - luckyNumberErrorRetry.setOnClickListener { presenter.onRetry() } - luckyNumberErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun updateData(data: LuckyNumber) { - binding.luckyNumberText.text = data.luckyNumber.toString() - } - - override fun hideRefresh() { - binding.luckyNumberSwipe.isRefreshing = false - } - - override fun showEmpty(show: Boolean) { - binding.luckyNumberEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.luckyNumberError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.luckyNumberErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.luckyNumberProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.luckyNumberSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.luckyNumberContent.visibility = if (show) VISIBLE else GONE - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt deleted file mode 100644 index e932fedc0..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberPresenter.kt +++ /dev/null @@ -1,105 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber - -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class LuckyNumberPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val luckyNumberRepository: LuckyNumberRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: LuckyNumberView) { - super.onAttachView(view) - view.run { - initView() - showContent(false) - enableSwipe(false) - } - Timber.i("Lucky number view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - private fun loadData(forceRefresh: Boolean = false) { - Timber.i("Loading lucky number started") - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMapMaybe { luckyNumberRepository.getLuckyNumber(it, forceRefresh) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading lucky number result: Success") - view?.apply { - updateData(it) - showContent(true) - showEmpty(false) - showErrorView(false) - } - analytics.logEvent( - "load_item", - "type" to "lucky_number", - "number" to it.luckyNumber, - "force_refresh" to forceRefresh - ) - }, { - Timber.i("Loading lucky number result: An exception occurred") - errorHandler.dispatch(it) - }, { - Timber.i("Loading lucky number result: No lucky number found") - view?.run { - showContent(false) - showEmpty(true) - showErrorView(false) - } - }) - ) - } - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the lucky number") - loadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt deleted file mode 100644 index a680c83eb..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber - -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.ui.base.BaseView - -interface LuckyNumberView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: LuckyNumber) - - 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) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt deleted file mode 100644 index 961ac6338..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt +++ /dev/null @@ -1,106 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumberwidget - -import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS -import android.content.Intent -import android.os.Build -import android.os.Bundle -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.base.WidgetConfigureAdapter -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.utils.AppInfo -import javax.inject.Inject - -class LuckyNumberWidgetConfigureActivity : - BaseActivity(), - LuckyNumberWidgetConfigureView { - - @Inject - lateinit var configureAdapter: WidgetConfigureAdapter - - @Inject - override lateinit var presenter: LuckyNumberWidgetConfigurePresenter - - @Inject - lateinit var appInfo: AppInfo - - private var dialog: AlertDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setResult(RESULT_CANCELED) - setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) - - intent.extras.let { - presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID)) - } - } - - override fun initView() { - with(binding.widgetConfigureRecycler) { - adapter = configureAdapter - layoutManager = LinearLayoutManager(context) - } - - configureAdapter.onClickListener = presenter::onItemSelect - } - - override fun showThemeDialog() { - var items = arrayOf( - getString(R.string.widget_timetable_theme_light), - getString(R.string.widget_timetable_theme_dark) - ) - if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += (getString(R.string.widget_timetable_theme_system)) - - dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher) - .setTitle(R.string.widget_timetable_theme_title) - .setOnDismissListener { presenter.onDismissThemeView() } - .setSingleChoiceItems(items, -1) { _, which -> - presenter.onThemeSelect(which) - } - .show() - } - - override fun updateData(data: List>) { - with(configureAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun updateLuckyNumberWidget(widgetId: Int) { - sendBroadcast(Intent(this, LuckyNumberWidgetProvider::class.java) - .apply { - action = ACTION_APPWIDGET_UPDATE - putExtra(EXTRA_APPWIDGET_IDS, intArrayOf(widgetId)) - }) - } - - override fun setSuccessResult(widgetId: Int) { - setResult(RESULT_OK, Intent().apply { putExtra(EXTRA_APPWIDGET_ID, widgetId) }) - } - - override fun showError(text: String, error: Throwable) { - Toast.makeText(this, text, Toast.LENGTH_LONG).show() - } - - override fun finishView() { - finish() - } - - override fun openLoginView() { - startActivity(LoginActivity.getStartIntent(this)) - } - - override fun onDestroy() { - super.onDestroy() - dialog?.dismiss() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt deleted file mode 100644 index 468f9b575..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt +++ /dev/null @@ -1,79 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumberwidget - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey -import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Inject - -class LuckyNumberWidgetConfigurePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val sharedPref: SharedPrefProvider -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var appWidgetId: Int? = null - - private var selectedStudent: Student? = null - - fun onAttachView(view: LuckyNumberWidgetConfigureView, appWidgetId: Int?) { - super.onAttachView(view) - this.appWidgetId = appWidgetId - view.initView() - loadData() - } - - fun onItemSelect(student: Student) { - selectedStudent = student - view?.showThemeDialog() - } - - fun onThemeSelect(index: Int) { - appWidgetId?.let { - sharedPref.putLong(getThemeWidgetKey(it), index.toLong()) - } - registerStudent(selectedStudent) - } - - fun onDismissThemeView() { - view?.finishView() - } - - private fun loadData() { - disposable.add(studentRepository.getSavedStudents(false) - .map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } } - .map { (students, currentStudentId) -> - students.map { student -> student to (student.id == currentStudentId) } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - when { - it.isEmpty() -> view?.openLoginView() - it.size == 1 -> { - selectedStudent = it.single().first - view?.showThemeDialog() - } - else -> view?.updateData(it) - } - }, { errorHandler.dispatch(it) })) - } - - private fun registerStudent(student: Student?) { - requireNotNull(student) - - appWidgetId?.let { id -> - sharedPref.putLong(getStudentWidgetKey(id), student.id) - view?.run { - updateLuckyNumberWidget(id) - setSuccessResult(id) - } - } - view?.finishView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt deleted file mode 100644 index c8c348ed3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumberwidget - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface LuckyNumberWidgetConfigureView : BaseView { - - fun initView() - - fun showThemeDialog() - - fun updateData(data: List>) - - fun updateLuckyNumberWidget(widgetId: Int) - - fun setSuccessResult(widgetId: Int) - - fun finishView() - - fun openLoginView() -} 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 deleted file mode 100644 index 55a048b32..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetProvider.kt +++ /dev/null @@ -1,179 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumberwidget - -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT -import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH -import android.appwidget.AppWidgetProvider -import android.content.Context -import android.content.Intent -import android.content.res.Configuration -import android.os.Bundle -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.RemoteViews -import dagger.android.AndroidInjection -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.SharedPrefProvider -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.data.exceptions.NoCurrentStudentException -import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Maybe -import timber.log.Timber -import javax.inject.Inject - -class LuckyNumberWidgetProvider : AppWidgetProvider() { - - @Inject - lateinit var studentRepository: StudentRepository - - @Inject - lateinit var luckyNumberRepository: LuckyNumberRepository - - @Inject - lateinit var schedulers: SchedulersProvider - - @Inject - lateinit var appWidgetManager: AppWidgetManager - - @Inject - lateinit var sharedPref: SharedPrefProvider - - companion object { - - fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId" - - fun getThemeWidgetKey(appWidgetId: Int) = "lucky_number_widget_theme_$appWidgetId" - - fun getHeightWidgetKey(appWidgetId: Int) = "lucky_number_widget_height_$appWidgetId" - - fun getWidthWidgetKey(appWidgetId: Int) = "lucky_number_widget_width_$appWidgetId" - } - - override fun onReceive(context: Context, intent: Intent) { - AndroidInjection.inject(this, context) - super.onReceive(context, intent) - } - - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray?) { - super.onUpdate(context, appWidgetManager, appWidgetIds) - appWidgetIds?.forEach { appWidgetId -> - - val luckyNumber = getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) - val appIntent = PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id, - MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT) - - val remoteView = RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context)).apply { - setTextViewText(R.id.luckyNumberWidgetNumber, luckyNumber?.luckyNumber?.toString() ?: "#") - setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent) - } - - setStyles(remoteView, appWidgetId) - appWidgetManager.updateAppWidget(appWidgetId, remoteView) - } - } - - override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { - super.onDeleted(context, appWidgetIds) - appWidgetIds?.forEach { appWidgetId -> - with(sharedPref) { - delete(getHeightWidgetKey(appWidgetId)) - delete(getStudentWidgetKey(appWidgetId)) - delete(getThemeWidgetKey(appWidgetId)) - delete(getWidthWidgetKey(appWidgetId)) - } - } - } - - override fun onAppWidgetOptionsChanged(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, newOptions: Bundle?) { - super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions) - - val remoteView = RemoteViews(context.packageName, getCorrectLayoutId(appWidgetId, context)) - - setStyles(remoteView, appWidgetId, newOptions) - appWidgetManager.updateAppWidget(appWidgetId, remoteView) - } - - private fun setStyles(views: RemoteViews, appWidgetId: Int, options: Bundle? = null) { - val width = options?.getInt(OPTION_APPWIDGET_MIN_WIDTH) ?: sharedPref.getLong(getWidthWidgetKey(appWidgetId), 74).toInt() - val height = options?.getInt(OPTION_APPWIDGET_MAX_HEIGHT) ?: sharedPref.getLong(getHeightWidgetKey(appWidgetId), 74).toInt() - - with(sharedPref) { - putLong(getWidthWidgetKey(appWidgetId), width.toLong()) - putLong(getHeightWidgetKey(appWidgetId), height.toLong()) - } - - val rows = getCellsForSize(height) - val cols = getCellsForSize(width) - - Timber.d("New lucky number widget measurement: %dx%d", width, height) - Timber.d("Widget size: $cols x $rows") - - when { - 1 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = false) - 1 == cols && 1 < rows -> views.setVisibility(imageTop = true, imageLeft = false) - 1 < cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true) - 1 == cols && 1 == rows -> views.setVisibility(imageTop = true, imageLeft = false) - 2 == cols && 1 == rows -> views.setVisibility(imageTop = false, imageLeft = true) - else -> views.setVisibility(imageTop = false, imageLeft = false, title = true) - } - } - - private fun RemoteViews.setVisibility(imageTop: Boolean, imageLeft: Boolean, title: Boolean = false) { - setViewVisibility(R.id.luckyNumberWidgetImageTop, if (imageTop) VISIBLE else GONE) - setViewVisibility(R.id.luckyNumberWidgetImageLeft, if (imageLeft) VISIBLE else GONE) - setViewVisibility(R.id.luckyNumberWidgetTitle, if (title) VISIBLE else GONE) - setViewVisibility(R.id.luckyNumberWidgetNumber, VISIBLE) - } - - private fun getCellsForSize(size: Int): Int { - var n = 2 - while (74 * n - 30 < size) ++n - return n - 1 - } - - private fun getLuckyNumber(studentId: Long, appWidgetId: Int): LuckyNumber? { - return try { - studentRepository.isStudentSaved() - .filter { true } - .flatMap { studentRepository.getSavedStudents().toMaybe() } - .flatMap { students -> - val student = students.singleOrNull { student -> student.id == studentId } - when { - student != null -> Maybe.just(student) - studentId != 0L -> { - studentRepository.isCurrentStudentSet() - .filter { true } - .flatMap { studentRepository.getCurrentStudent(false).toMaybe() } - .doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } - } - else -> Maybe.empty() - } - } - .flatMap { luckyNumberRepository.getLuckyNumber(it) } - .subscribeOn(schedulers.backgroundThread) - .blockingGet() - } catch (e: Exception) { - if (e.cause !is NoCurrentStudentException) { - Timber.e(e, "An error has occurred in lucky number provider") - } - null - } - } - - private fun getCorrectLayoutId(appWidgetId: Int, context: Context): Int { - val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0) - val isSystemDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES - - return if (savedTheme == 1L || (savedTheme == 2L && isSystemDarkMode)) { - R.layout.widget_luckynumber_dark - } else { - R.layout.widget_luckynumber - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt deleted file mode 100644 index f5b7c47c8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ /dev/null @@ -1,210 +0,0 @@ -package io.github.wulkanowy.ui.modules.main - -import android.content.Context -import android.content.Intent -import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.LOLLIPOP -import android.os.Bundle -import android.view.Menu -import android.view.MenuItem -import androidx.core.view.ViewCompat -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.Fragment -import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState.ALWAYS_SHOW -import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem -import com.google.android.material.elevation.ElevationOverlayProvider -import com.ncapdevi.fragnav.FragNavController -import com.ncapdevi.fragnav.FragNavController.Companion.HIDE -import dagger.Lazy -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.ActivityMainBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.modules.account.AccountDialog -import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment -import io.github.wulkanowy.ui.modules.exam.ExamFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.homework.HomeworkFragment -import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.more.MoreFragment -import io.github.wulkanowy.ui.modules.note.NoteFragment -import io.github.wulkanowy.ui.modules.timetable.TimetableFragment -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.safelyPopFragments -import io.github.wulkanowy.utils.setOnViewChangeListener -import timber.log.Timber -import javax.inject.Inject - -class MainActivity : BaseActivity(), MainView { - - @Inject - override lateinit var presenter: MainPresenter - - @Inject - lateinit var navController: FragNavController - - @Inject - lateinit var analytics: FirebaseAnalyticsHelper - - @Inject - lateinit var overlayProvider: Lazy - - companion object { - const val EXTRA_START_MENU = "extraStartMenu" - - fun getStartIntent(context: Context, startMenu: MainView.Section? = null, clear: Boolean = false): Intent { - return Intent(context, MainActivity::class.java) - .apply { - if (clear) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK - startMenu?.let { putExtra(EXTRA_START_MENU, it) } - } - } - } - - override val isRootView get() = navController.isRootFragment - - override val currentStackSize get() = navController.currentStack?.size - - override val currentViewTitle get() = (navController.currentFrag as? MainView.TitledView)?.titleStringId?.let { getString(it) } - - override val currentViewSubtitle get() = (navController.currentFrag as? MainView.TitledView)?.subtitleString - - override var startMenuIndex = 0 - - override var startMenuMoreIndex = -1 - - private val moreMenuFragments = mapOf( - MainView.Section.MESSAGE.id to MessageFragment.newInstance(), - MainView.Section.HOMEWORK.id to HomeworkFragment.newInstance(), - MainView.Section.NOTE.id to NoteFragment.newInstance(), - MainView.Section.LUCKY_NUMBER.id to LuckyNumberFragment.newInstance() - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(ActivityMainBinding.inflate(layoutInflater).apply { binding = this }.root) - setSupportActionBar(binding.mainToolbar) - messageContainer = binding.mainFragmentContainer - - presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_START_MENU) as? MainView.Section) - - with(navController) { - initialize(startMenuIndex, savedInstanceState) - pushFragment(moreMenuFragments[startMenuMoreIndex]) - } - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menuInflater.inflate(R.menu.action_menu_main, menu) - return true - } - - override fun initView() { - with(binding.mainToolbar) { - if (SDK_INT >= LOLLIPOP) stateListAnimator = null - setBackgroundColor(overlayProvider.get().compositeOverlayWithThemeSurfaceColorIfNeeded(dpToPx(4f))) - } - - with(binding.mainBottomNav) { - addItems(listOf( - AHBottomNavigationItem(R.string.grade_title, R.drawable.ic_main_grade, 0), - AHBottomNavigationItem(R.string.attendance_title, R.drawable.ic_main_attendance, 0), - AHBottomNavigationItem(R.string.exam_title, R.drawable.ic_main_exam, 0), - AHBottomNavigationItem(R.string.timetable_title, R.drawable.ic_main_timetable, 0), - AHBottomNavigationItem(R.string.more_title, R.drawable.ic_main_more, 0) - )) - accentColor = getThemeAttrColor(R.attr.colorPrimary) - inactiveColor = getThemeAttrColor(R.attr.colorOnSurface, 153) - defaultBackgroundColor = overlayProvider.get().compositeOverlayWithThemeSurfaceColorIfNeeded(dpToPx(8f)) - titleState = ALWAYS_SHOW - currentItem = startMenuIndex - isBehaviorTranslationEnabled = false - setTitleTextSizeInSp(10f, 10f) - setOnTabSelectedListener(presenter::onTabSelected) - } - - with(navController) { - setOnViewChangeListener(presenter::onViewChange) - fragmentHideStrategy = HIDE - rootFragments = listOf( - GradeFragment.newInstance(), - AttendanceFragment.newInstance(), - ExamFragment.newInstance(), - TimetableFragment.newInstance(), - MoreFragment.newInstance() - ) - } - } - - override fun setCurrentScreen(name: String?) { - analytics.setCurrentScreen(this, name) - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return if (item?.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() - else false - } - - override fun onSupportNavigateUp(): Boolean { - return presenter.onUpNavigate() - } - - override fun switchMenuView(position: Int) { - navController.switchTab(position) - } - - override fun setViewTitle(title: String) { - supportActionBar?.title = title - } - - override fun setViewSubTitle(subtitle: String?) { - supportActionBar?.subtitle = subtitle - } - - override fun showHomeArrow(show: Boolean) { - supportActionBar?.setDisplayHomeAsUpEnabled(show) - } - - override fun showAccountPicker() { - navController.showDialogFragment(AccountDialog.newInstance()) - } - - override fun showActionBarElevation(show: Boolean) { - ViewCompat.setElevation(binding.mainToolbar, if (show) dpToPx(4f) else 0f) - } - - override fun notifyMenuViewReselected() { - (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentReselected() - } - - override fun notifyMenuViewChanged() { - Timber.d("Menu view changed") - (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentChanged() - } - - fun showDialogFragment(dialog: DialogFragment) { - navController.showDialogFragment(dialog) - } - - fun pushView(fragment: Fragment) { - navController.pushFragment(fragment) - } - - override fun popView(depth: Int) { - navController.safelyPopFragments(depth) - } - - override fun onBackPressed() { - presenter.onBackPressed { super.onBackPressed() } - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - navController.onSaveInstanceState(outState) - intent.removeExtra(EXTRA_START_MENU) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt deleted file mode 100644 index 03f6ac382..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainModule.kt +++ /dev/null @@ -1,139 +0,0 @@ -package io.github.wulkanowy.ui.modules.main - -import com.google.android.material.elevation.ElevationOverlayProvider -import com.ncapdevi.fragnav.FragNavController -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.R -import io.github.wulkanowy.di.scopes.PerFragment -import io.github.wulkanowy.ui.modules.about.AboutFragment -import io.github.wulkanowy.ui.modules.about.contributor.ContributorFragment -import io.github.wulkanowy.ui.modules.about.license.LicenseFragment -import io.github.wulkanowy.ui.modules.about.license.LicenseModule -import io.github.wulkanowy.ui.modules.about.logviewer.LogViewerFragment -import io.github.wulkanowy.ui.modules.account.AccountDialog -import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment -import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment -import io.github.wulkanowy.ui.modules.exam.ExamFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.grade.GradeModule -import io.github.wulkanowy.ui.modules.homework.HomeworkFragment -import io.github.wulkanowy.ui.modules.homework.details.HomeworkDetailsDialog -import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.message.MessageModule -import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment -import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment -import io.github.wulkanowy.ui.modules.mobiledevice.token.MobileDeviceTokenDialog -import io.github.wulkanowy.ui.modules.more.MoreFragment -import io.github.wulkanowy.ui.modules.note.NoteFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersModule -import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.ui.modules.timetable.TimetableFragment -import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment - -@Suppress("unused") -@Module -abstract class MainModule { - - companion object { - - @Provides - fun provideFragNavController(activity: MainActivity) = - FragNavController(activity.supportFragmentManager, R.id.mainFragmentContainer) - - //In activities must be injected as Lazy - @Provides - fun provideElevationOverlayProvider(activity: MainActivity) = ElevationOverlayProvider(activity) - } - - @PerFragment - @ContributesAndroidInjector - abstract fun bindAttendanceFragment(): AttendanceFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindAttendanceSummaryFragment(): AttendanceSummaryFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindExamFragment(): ExamFragment - - @PerFragment - @ContributesAndroidInjector(modules = [GradeModule::class]) - abstract fun bindGradeFragment(): GradeFragment - - @PerFragment - @ContributesAndroidInjector(modules = [MessageModule::class]) - abstract fun bindMessagesFragment(): MessageFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindMessagePreviewFragment(): MessagePreviewFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindMoreFragment(): MoreFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindTimetableFragment(): TimetableFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindAboutFragment(): AboutFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindSettingsFragment(): SettingsFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindNoteFragment(): NoteFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindHomeworkFragment(): HomeworkFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindHomeworkDetailsDialog(): HomeworkDetailsDialog - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLuckyNumberFragment(): LuckyNumberFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindCompletedLessonsFragment(): CompletedLessonsFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindAccountDialog(): AccountDialog - - @PerFragment - @ContributesAndroidInjector - abstract fun bindMobileDevices(): MobileDeviceFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindMobileDeviceDialog(): MobileDeviceTokenDialog - - @PerFragment - @ContributesAndroidInjector(modules = [LicenseModule::class]) - abstract fun bindLicenseFragment(): LicenseFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindLogViewerFragment(): LogViewerFragment - - @PerFragment - @ContributesAndroidInjector - abstract fun bindContributorFragment(): ContributorFragment - - @PerFragment - @ContributesAndroidInjector(modules = [SchoolAndTeachersModule::class]) - abstract fun bindSchoolAndTeachersFragment(): SchoolAndTeachersFragment -} 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 deleted file mode 100644 index 233d44917..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt +++ /dev/null @@ -1,94 +0,0 @@ -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.services.sync.SyncManager -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.ui.modules.main.MainView.Section.GRADE -import io.github.wulkanowy.ui.modules.main.MainView.Section.MESSAGE -import io.github.wulkanowy.ui.modules.main.MainView.Section.SCHOOL -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class MainPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val prefRepository: PreferencesRepository, - private val syncManager: SyncManager, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - fun onAttachView(view: MainView, initMenu: MainView.Section?) { - super.onAttachView(view) - view.apply { - getProperViewIndexes(initMenu).let { (main, more) -> - startMenuIndex = main - startMenuMoreIndex = more - } - initView() - Timber.i("Main view was initialized with $startMenuIndex menu index and $startMenuMoreIndex more index") - } - - syncManager.startPeriodicSyncWorker() - analytics.logEvent("app_open", "destination" to initMenu?.name) - } - - fun onViewChange(section: MainView.Section?, name: String?) { - view?.apply { - setCurrentScreen(name) - showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL) - currentViewTitle?.let { setViewTitle(it) } - currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) } - currentStackSize?.let { - if (it > 1) showHomeArrow(true) - else showHomeArrow(false) - } - } - } - - fun onAccountManagerSelected(): Boolean { - Timber.i("Select account manager") - view?.showAccountPicker() - return true - } - - fun onUpNavigate(): Boolean { - Timber.i("Up navigate pressed") - view?.popView() - return true - } - - fun onBackPressed(default: () -> Unit) { - Timber.i("Back pressed in main view") - view?.run { - if (isRootView) default() - else popView() - } - } - - fun onTabSelected(index: Int, wasSelected: Boolean): Boolean { - return view?.run { - Timber.i("Switch main tab index: $index, reselected: $wasSelected") - if (wasSelected) { - notifyMenuViewReselected() - false - } else { - notifyMenuViewChanged() - switchMenuView(index) - true - } - } == true - } - - private fun getProperViewIndexes(initMenu: MainView.Section?): Pair { - return when (initMenu?.id) { - in 0..3 -> initMenu!!.id to -1 - in 4..10 -> 4 to initMenu!!.id - else -> prefRepository.startMenuIndex to -1 - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt deleted file mode 100644 index 7e5831471..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt +++ /dev/null @@ -1,71 +0,0 @@ -package io.github.wulkanowy.ui.modules.main - -import io.github.wulkanowy.ui.base.BaseView - -interface MainView : BaseView { - - var startMenuIndex: Int - - var startMenuMoreIndex: Int - - val isRootView: Boolean - - val currentViewTitle: String? - - val currentViewSubtitle: String? - - val currentStackSize: Int? - - fun initView() - - fun switchMenuView(position: Int) - - fun showHomeArrow(show: Boolean) - - fun showAccountPicker() - - fun setCurrentScreen(name: String?) - - fun showActionBarElevation(show: Boolean) - - fun notifyMenuViewReselected() - - fun notifyMenuViewChanged() - - fun setViewTitle(title: String) - - fun setViewSubTitle(subtitle: String?) - - fun popView(depth: Int = 1) - - interface MainChildView { - - fun onFragmentReselected() - - fun onFragmentChanged() {} - } - - interface TitledView { - - val titleStringId: Int - - var subtitleString: String - get() = "" - set(_) {} - } - - enum class Section(val id: Int) { - GRADE(0), - ATTENDANCE(1), - EXAM(2), - TIMETABLE(3), - MORE(4), - MESSAGE(5), - HOMEWORK(6), - NOTE(7), - LUCKY_NUMBER(8), - SETTINGS(9), - ABOUT(10), - SCHOOL(11) - } -} 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 deleted file mode 100644 index 4a9d217b0..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageFragment.kt +++ /dev/null @@ -1,104 +0,0 @@ -package io.github.wulkanowy.ui.modules.message - -import android.os.Bundle -import android.view.View -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Message -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.databinding.FragmentMessageBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity -import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.setOnSelectPageListener -import javax.inject.Inject - -class MessageFragment : BaseFragment(R.layout.fragment_message), - MessageView, MainView.TitledView { - - @Inject - lateinit var presenter: MessagePresenter - - @Inject - lateinit var pagerAdapter: BaseFragmentPagerAdapter - - companion object { - fun newInstance() = MessageFragment() - } - - override val titleStringId get() = R.string.message_title - - override val currentPageIndex get() = binding.messageViewPager.currentItem - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMessageBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - with(pagerAdapter) { - containerId = binding.messageViewPager.id - addFragmentsWithTitle(mapOf( - MessageTabFragment.newInstance(RECEIVED) to getString(R.string.message_inbox), - MessageTabFragment.newInstance(SENT) to getString(R.string.message_sent), - MessageTabFragment.newInstance(TRASHED) to getString(R.string.message_trash) - )) - } - - with(binding.messageViewPager) { - adapter = pagerAdapter - offscreenPageLimit = 2 - setOnSelectPageListener(presenter::onPageSelected) - } - - with(binding.messageTabLayout) { - setupWithViewPager(binding.messageViewPager) - setElevationCompat(context.dpToPx(4f)) - } - - binding.openSendMessageButton.setOnClickListener { presenter.onSendMessageButtonClicked() } - } - - override fun showContent(show: Boolean) { - with(binding) { - messageViewPager.visibility = if (show) VISIBLE else INVISIBLE - messageTabLayout.visibility = if (show) VISIBLE else INVISIBLE - } - } - - override fun showProgress(show: Boolean) { - binding.messageProgress.visibility = if (show) VISIBLE else INVISIBLE - } - - fun onDeleteMessage(message: Message) { - presenter.onDeleteMessage(message) - } - - fun onChildFragmentLoaded() { - presenter.onChildViewLoaded() - } - - override fun notifyChildMessageDeleted(tabId: Int) { - (pagerAdapter.getFragmentInstance(tabId) as? MessageTabFragment)?.onParentDeleteMessage() - } - - override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) { - (pagerAdapter.getFragmentInstance(index) as? MessageTabFragment)?.onParentLoadData(forceRefresh) - } - - override fun openSendMessage() { - context?.let { it.startActivity(SendMessageActivity.getStartIntent(it)) } - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt deleted file mode 100644 index bf7950209..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageModule.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.ui.modules.message - -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.di.scopes.PerChildFragment -import io.github.wulkanowy.di.scopes.PerFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.message.tab.MessageTabFragment - -@Suppress("unused") -@Module -abstract class MessageModule { - - companion object { - - @PerFragment - @Provides - fun provideMessageAdapter(fragment: MessageFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) - } - - @PerChildFragment - @ContributesAndroidInjector - abstract fun bindMessageTabFragment(): MessageTabFragment -} 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 deleted file mode 100644 index 0f5598b23..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessagePresenter.kt +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.wulkanowy.ui.modules.message - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Completable -import timber.log.Timber -import java.util.concurrent.TimeUnit.MILLISECONDS -import javax.inject.Inject - -class MessagePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: MessageView) { - super.onAttachView(view) - disposable.add(Completable.timer(150, MILLISECONDS, schedulers.mainThread) - .subscribe { - view.initView() - Timber.i("Message view was initialized") - loadData() - }) - } - - fun onPageSelected(index: Int) { - loadChild(index) - } - - private fun loadData() { - view?.run { loadChild(currentPageIndex) } - } - - private fun loadChild(index: Int, forceRefresh: Boolean = false) { - Timber.i("Load message child view index: $index") - view?.notifyChildLoadData(index, forceRefresh) - } - - fun onChildViewLoaded() { - view?.apply { - showContent(true) - showProgress(false) - } - } - - fun onDeleteMessage(message: Message) { - view?.notifyChildMessageDeleted( - when (message.removed) { - true -> 2 - else -> message.folderId - 1 - } - ) - } - - fun onSendMessageButtonClicked() { - view?.openSendMessage() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt deleted file mode 100644 index 2aa4d78ec..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/MessageView.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.wulkanowy.ui.modules.message - -import io.github.wulkanowy.ui.base.BaseView - -interface MessageView : BaseView { - - val currentPageIndex: Int - - fun initView() - - fun showContent(show: Boolean) - - fun showProgress(show: Boolean) - - fun notifyChildLoadData(index: Int, forceRefresh: Boolean) - - fun notifyChildMessageDeleted(tabId: Int) - - fun openSendMessage() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt deleted file mode 100644 index a94d2cfc8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt +++ /dev/null @@ -1,92 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.preview - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -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.repositories.message.MessageFolder -import io.github.wulkanowy.databinding.ItemMessageAttachmentBinding -import io.github.wulkanowy.databinding.ItemMessageDividerBinding -import io.github.wulkanowy.databinding.ItemMessagePreviewBinding -import io.github.wulkanowy.utils.openInternetBrowser -import io.github.wulkanowy.utils.toFormattedString -import javax.inject.Inject - -class MessagePreviewAdapter @Inject constructor() : - RecyclerView.Adapter() { - - enum class ViewType(val id: Int) { - MESSAGE(1), - DIVIDER(2), - ATTACHMENT(3) - } - - var messageWithAttachment: MessageWithAttachment? = null - set(value) { - field = value - attachments = value?.attachments.orEmpty() - } - - private var attachments: List = emptyList() - - override fun getItemCount() = if (messageWithAttachment == null) 0 else attachments.size + 1 + if (attachments.isNotEmpty()) 1 else 0 - - override fun getItemViewType(position: Int) = when (position) { - 0 -> ViewType.MESSAGE.id - 1 -> ViewType.DIVIDER.id - else -> ViewType.ATTACHMENT.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.MESSAGE.id -> MessageViewHolder(ItemMessagePreviewBinding.inflate(inflater, parent, false)) - ViewType.DIVIDER.id -> DividerViewHolder(ItemMessageDividerBinding.inflate(inflater, parent, false)) - ViewType.ATTACHMENT.id -> AttachmentViewHolder(ItemMessageAttachmentBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is MessageViewHolder -> bindMessage(holder, requireNotNull(messageWithAttachment).message) - is AttachmentViewHolder -> bindAttachment(holder, requireNotNull(messageWithAttachment).attachments[position - 2]) - } - } - - @SuppressLint("SetTextI18n") - private fun bindMessage(holder: MessageViewHolder, message: Message) { - with(holder.binding) { - messagePreviewSubject.text = message.subject.ifBlank { root.context.getString(R.string.message_no_subject) } - messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")) - messagePreviewContent.text = message.content - messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}" - else "${root.context.getString(R.string.message_from)} ${message.sender}" - } - } - - private fun bindAttachment(holder: AttachmentViewHolder, attachment: MessageAttachment) { - with(holder.binding) { - messagePreviewAttachment.visibility = View.VISIBLE - messagePreviewAttachment.text = attachment.filename - root.setOnClickListener { - root.context.openInternetBrowser(attachment.url) { } - } - } - } - - class MessageViewHolder(val binding: ItemMessagePreviewBinding) : - RecyclerView.ViewHolder(binding.root) - - class DividerViewHolder(val binding: ItemMessageDividerBinding) : - RecyclerView.ViewHolder(binding.root) - - class AttachmentViewHolder(val binding: ItemMessageAttachmentBinding) : - RecyclerView.ViewHolder(binding.root) -} 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 deleted file mode 100644 index 575db75b9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt +++ /dev/null @@ -1,219 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.preview - -import android.os.Build -import android.os.Bundle -import android.print.PrintAttributes -import android.print.PrintManager -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.webkit.WebResourceRequest -import android.webkit.WebView -import android.webkit.WebViewClient -import androidx.annotation.RequiresApi -import androidx.core.content.getSystemService -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.github.wulkanowy.databinding.FragmentMessagePreviewBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.shareText -import javax.inject.Inject - -class MessagePreviewFragment : - BaseFragment(R.layout.fragment_message_preview), - MessagePreviewView, MainView.TitledView { - - @Inject - lateinit var presenter: MessagePreviewPresenter - - @Inject - lateinit var previewAdapter: MessagePreviewAdapter - - @Inject - lateinit var appInfo: AppInfo - - private var menuReplyButton: MenuItem? = null - - private var menuForwardButton: MenuItem? = null - - private var menuDeleteButton: MenuItem? = null - - private var menuShareButton: MenuItem? = null - - private var menuPrintButton: MenuItem? = null - - override val titleStringId: Int - get() = R.string.message_title - - override val deleteMessageSuccessString: String - get() = getString(R.string.message_delete_success) - - override val messageNoSubjectString: String - get() = getString(R.string.message_no_subject) - - override val printHTML: String - get() = requireContext().assets.open("message-print-page.html").bufferedReader().use { it.readText() } - - companion object { - const val MESSAGE_ID_KEY = "message_id" - - fun newInstance(message: Message): MessagePreviewFragment { - return MessagePreviewFragment().apply { - arguments = Bundle().apply { putSerializable(MESSAGE_ID_KEY, message) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMessagePreviewBinding.bind(view) - messageContainer = binding.messagePreviewContainer - presenter.onAttachView(this, (savedInstanceState ?: arguments)?.getSerializable(MESSAGE_ID_KEY) as? Message) - } - - override fun initView() { - binding.messagePreviewErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - with(binding.messagePreviewRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = previewAdapter - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_message_preview, menu) - menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply) - menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward) - menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete) - menuShareButton = menu.findItem(R.id.messagePreviewMenuShare) - menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint) - presenter.onCreateOptionsMenu() - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.messagePreviewMenuReply -> presenter.onReply() - R.id.messagePreviewMenuForward -> presenter.onForward() - R.id.messagePreviewMenuDelete -> presenter.onMessageDelete() - R.id.messagePreviewMenuShare -> presenter.onShare() - R.id.messagePreviewMenuPrint -> presenter.onPrint() - else -> false - } - } - - override fun setMessageWithAttachment(item: MessageWithAttachment) { - with(previewAdapter) { - messageWithAttachment = item - notifyDataSetChanged() - } - } - - override fun showProgress(show: Boolean) { - binding.messagePreviewProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.messagePreviewRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showOptions(show: Boolean) { - menuReplyButton?.isVisible = show - menuForwardButton?.isVisible = show - menuDeleteButton?.isVisible = show - menuShareButton?.isVisible = show - menuPrintButton?.isVisible = show && appInfo.systemVersion >= Build.VERSION_CODES.LOLLIPOP - } - - override fun setDeletedOptionsLabels() { - menuDeleteButton?.setTitle(R.string.message_delete_forever) - } - - override fun setNotDeletedOptionsLabels() { - menuDeleteButton?.setTitle(R.string.message_move_to_bin) - } - - override fun showErrorView(show: Boolean) { - binding.messagePreviewError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.messagePreviewErrorMessage.text = message - } - - override fun setErrorRetryCallback(callback: () -> Unit) { - binding.messagePreviewErrorRetry.setOnClickListener { callback() } - } - - override fun openMessageReply(message: Message?) { - context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message, true)) } - } - - override fun openMessageForward(message: Message?) { - context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message)) } - } - - override fun shareText(text: String, subject: String) { - context?.shareText(text, subject) - } - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - override fun printDocument(html: String, jobName: String) { - val webView = WebView(activity) - webView.webViewClient = object : WebViewClient() { - - override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false - - override fun onPageFinished(view: WebView, url: String) { - createWebPrintJob(view, jobName) - } - } - - webView.loadDataWithBaseURL("file:///android_asset/", html, "text/HTML", "UTF-8", null) - } - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - private fun createWebPrintJob(webView: WebView, jobName: String) { - activity?.getSystemService()?.let { printManager -> - val printAdapter = webView.createPrintDocumentAdapter(jobName) - - printManager.print( - jobName, - printAdapter, - PrintAttributes.Builder().build() - ) - } - } - - override fun popView() { - (activity as MainActivity).popView() - } - - override fun notifyParentMessageDeleted(message: Message) { - parentFragmentManager.fragments.forEach { if (it is MessageFragment) it.onDeleteMessage(message) } - } - - override fun onSaveInstanceState(outState: Bundle) { - outState.putSerializable(MESSAGE_ID_KEY, presenter.message) - super.onSaveInstanceState(outState) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt deleted file mode 100644 index db7996bca..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt +++ /dev/null @@ -1,214 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.preview - -import android.annotation.SuppressLint -import android.os.Build -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageAttachment -import io.github.wulkanowy.data.repositories.message.MessageRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.toFormattedString -import timber.log.Timber -import javax.inject.Inject - -class MessagePreviewPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val messageRepository: MessageRepository, - private val analytics: FirebaseAnalyticsHelper, - private var appInfo: AppInfo -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - var message: Message? = null - - var attachments: List? = null - - private lateinit var lastError: Throwable - - private var retryCallback: () -> Unit = {} - - fun onAttachView(view: MessagePreviewView, message: Message?) { - super.onAttachView(view) - view.initView() - errorHandler.showErrorMessage = ::showErrorViewOnError - this.message = message - loadData(requireNotNull(message)) - } - - private fun onMessageLoadRetry(message: Message) { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(message) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - private fun loadData(message: Message) { - Timber.i("Loading message ${message.messageId} preview started") - disposable.apply { - clear() - add(studentRepository.getStudentById(message.studentId) - .flatMap { messageRepository.getMessage(it, message, true) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { view?.showProgress(false) } - .subscribe({ message -> - Timber.i("Loading message ${message.message.messageId} preview result: Success ") - this@MessagePreviewPresenter.message = message.message - this@MessagePreviewPresenter.attachments = message.attachments - view?.apply { - setMessageWithAttachment(message) - initOptions() - } - analytics.logEvent( - "load_item", - "type" to "message_preview", - "length" to message.message.content.length - ) - }) { - Timber.i("Loading message ${message.messageId} preview result: An exception occurred ") - retryCallback = { onMessageLoadRetry(message) } - errorHandler.dispatch(it) - }) - } - } - - fun onReply(): Boolean { - return if (message != null) { - view?.openMessageReply(message) - true - } else false - } - - fun onForward(): Boolean { - return if (message != null) { - view?.openMessageForward(message) - true - } else false - } - - fun onShare(): Boolean { - message?.let { - var text = "Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) { - true -> "Od: ${it.sender}\n" - false -> "Do: ${it.recipient}\n" - } + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}" - - attachments?.let { attachments -> - if (attachments.isNotEmpty()) { - text += "\n\nZałączniki:" - - attachments.forEach { attachment -> - text += "\n${attachment.filename}: ${attachment.url}" - } - } - } - - view?.shareText(text, "FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}") - return true - } - return false - } - - @SuppressLint("NewApi") - fun onPrint(): Boolean { - if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP) return false - message?.let { - val dateString = it.date.toFormattedString("yyyy-MM-dd HH:mm:ss") - val infoContent = "

Data wysłania

$dateString
" + when { - it.sender.isNotEmpty() -> "

Od

${it.sender}
" - else -> "

Do

${it.recipient}
" - } - - val messageContent = "

${it.content}

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

") - .replace(Regex("[\\n\\r]"), "
") - - val jobName = "Wiadomość " + when { - it.sender.isNotEmpty() -> "od ${it.sender}" - else -> "do ${it.recipient}" - } + " $dateString: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }} | Wulkanowy" - - view?.apply { - val html = printHTML - .replace("%SUBJECT%", it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }) - .replace("%CONTENT%", messageContent) - .replace("%INFO%", infoContent) - printDocument(html, jobName) - } - return true - } - return false - } - - private fun deleteMessage() { - message?.let { message -> - disposable.add(studentRepository.getCurrentStudent() - .flatMap { messageRepository.deleteMessage(it, message) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - showContent(false) - showProgress(true) - showOptions(false) - showErrorView(false) - } - } - .doFinally { - view?.showProgress(false) - } - .subscribe({ - view?.run { - notifyParentMessageDeleted(message) - showMessage(deleteMessageSuccessString) - popView() - } - }, { error -> - retryCallback = { onMessageDelete() } - errorHandler.dispatch(error) - }) - ) - } - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - lastError = error - setErrorDetails(message) - showErrorView(true) - setErrorRetryCallback { retryCallback() } - } - } - - fun onMessageDelete(): Boolean { - deleteMessage() - return true - } - - private fun initOptions() { - view?.apply { - showOptions(message != null) - message?.let { - when (it.removed) { - true -> setDeletedOptionsLabels() - false -> setNotDeletedOptionsLabels() - } - } - - } - } - - fun onCreateOptionsMenu() { - initOptions() - } -} 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 deleted file mode 100644 index 0fdb4bda3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.preview - -import android.os.Build -import androidx.annotation.RequiresApi -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.MessageWithAttachment -import io.github.wulkanowy.ui.base.BaseView - -interface MessagePreviewView : BaseView { - - val deleteMessageSuccessString: String - - val messageNoSubjectString: String - - val printHTML: String - - fun initView() - - fun setMessageWithAttachment(item: MessageWithAttachment) - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun notifyParentMessageDeleted(message: Message) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun setErrorRetryCallback(callback: () -> Unit) - - fun showOptions(show: Boolean) - - fun setDeletedOptionsLabels() - - fun setNotDeletedOptionsLabels() - - fun openMessageReply(message: Message?) - - fun openMessageForward(message: Message?) - - fun shareText(text: String, subject: String) - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - fun printDocument(html: String, jobName: String) - - fun popView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/RecipientChipItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/RecipientChipItem.kt deleted file mode 100644 index dd2d2b9bd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/RecipientChipItem.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.send - -import io.github.wulkanowy.data.db.entities.Recipient -import io.github.wulkanowy.materialchipsinput.ChipItem - -data class RecipientChipItem( - - override val title: String, - - override val summary: String, - - val recipient: Recipient - -) : ChipItem diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt deleted file mode 100644 index 7b7503433..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt +++ /dev/null @@ -1,180 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.send - -import android.content.Context -import android.content.Intent -import android.graphics.Rect -import android.os.Bundle -import android.view.Menu -import android.view.MenuItem -import android.view.TouchDelegate -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.databinding.ActivitySendMessageBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.hideSoftInput -import io.github.wulkanowy.utils.showSoftInput -import javax.inject.Inject - -class SendMessageActivity : BaseActivity(), SendMessageView { - - @Inject - override lateinit var presenter: SendMessagePresenter - - companion object { - private const val EXTRA_MESSAGE = "EXTRA_MESSAGE" - - private const val EXTRA_REPLY = "EXTRA_REPLY" - - fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java) - - fun getStartIntent(context: Context, message: Message?, reply: Boolean = false): Intent { - return getStartIntent(context) - .putExtra(EXTRA_MESSAGE, message) - .putExtra(EXTRA_REPLY, reply) - } - } - - override val isDropdownListVisible: Boolean - get() = binding.sendMessageTo.isDropdownListVisible - - @Suppress("UNCHECKED_CAST") - override val formRecipientsData: List - get() = binding.sendMessageTo.addedChipItems as List - - override val formSubjectValue: String - get() = binding.sendMessageSubject.text.toString() - - override val formContentValue: String - get() = binding.sendMessageMessageContent.text.toString() - - override val messageRequiredRecipients: String - get() = getString(R.string.message_required_recipients) - - override val messageContentMinLength: String - get() = getString(R.string.message_content_min_length) - - override val messageSuccess: String - get() = getString(R.string.message_send_successful) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(ActivitySendMessageBinding.inflate(layoutInflater).apply { binding = this }.root) - setSupportActionBar(binding.sendMessageToolbar) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - messageContainer = binding.sendMessageContainer - - presenter.onAttachView(this, intent.getSerializableExtra(EXTRA_MESSAGE) as? Message, intent.getSerializableExtra(EXTRA_REPLY) as? Boolean) - } - - override fun initView() { - setUpExtendedHitArea() - with(binding) { - sendMessageScroll.setOnTouchListener { _, _ -> presenter.onTouchScroll() } - sendMessageTo.onTextChangeListener = presenter::onRecipientsTextChange - } - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menuInflater.inflate(R.menu.action_menu_send_message, menu) - return true - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return if (item?.itemId == R.id.sendMessageMenuSend) presenter.onSend() - else false - } - - override fun onSupportNavigateUp(): Boolean { - return presenter.onUpNavigate() - } - - override fun setReportingUnit(unit: ReportingUnit) { - binding.sendMessageFrom.text = unit.senderName - } - - override fun setRecipients(recipients: List) { - binding.sendMessageTo.filterableChipItems = recipients - } - - override fun setSelectedRecipients(recipients: List) { - binding.sendMessageTo.addChips(recipients) - } - - override fun showProgress(show: Boolean) { - binding.sendMessageProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showContent(show: Boolean) { - binding.sendMessageContent.visibility = if (show) VISIBLE else GONE - } - - override fun showEmpty(show: Boolean) { - binding.sendMessageEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showActionBar(show: Boolean) { - supportActionBar?.apply { if (show) show() else hide() } - } - - override fun setSubject(subject: String) { - binding.sendMessageSubject.setText(subject) - } - - override fun setContent(content: String) { - binding.sendMessageMessageContent.setText(content) - } - - override fun showMessage(text: String) { - Toast.makeText(this, text, LENGTH_LONG).show() - } - - override fun showSoftInput(show: Boolean) { - if (show) showSoftInput() else hideSoftInput() - } - - override fun hideDropdownList() { - binding.sendMessageTo.hideDropdownList() - } - - override fun scrollToRecipients() { - with(binding.sendMessageScroll) { - post { - scrollTo(0, binding.sendMessageTo.bottom - dpToPx(53f).toInt()) - } - } - } - - override fun popView() { - finish() - } - - private fun setUpExtendedHitArea() { - fun extendHitArea() { - val containerHitRect = Rect().apply { - binding.sendMessageContent.getHitRect(this) - } - - val contentHitRect = Rect().apply { - binding.sendMessageMessageContent.getHitRect(this) - } - - contentHitRect.top = contentHitRect.bottom - contentHitRect.bottom = containerHitRect.bottom - - binding.sendMessageContent.touchDelegate = TouchDelegate(contentHitRect, binding.sendMessageMessageContent) - } - - with(binding.sendMessageMessageContent) { - post { - addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> extendHitArea() } - extendHitArea() - } - } - } -} 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 deleted file mode 100644 index aec79f9db..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessagePresenter.kt +++ /dev/null @@ -1,207 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.send - -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.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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.toFormattedString -import io.reactivex.Completable -import timber.log.Timber -import javax.inject.Inject - -class SendMessagePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val messageRepository: MessageRepository, - private val reportingUnitRepository: ReportingUnitRepository, - private val recipientRepository: RecipientRepository, - private val preferencesRepository: PreferencesRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) { - super.onAttachView(view) - view.initView() - Timber.i("Send message view was initialized") - loadData(message, reply) - view.apply { - message?.let { - setSubject(when (reply) { - true -> "RE: " - else -> "FW: " - } + message.subject) - if (preferencesRepository.fillMessageContent || reply != true) { - setContent( - when (reply) { - true -> "\n\n" - else -> "" - } + when (message.sender.isNotEmpty()) { - true -> "Od: ${message.sender}\n" - false -> "Do: ${message.recipient}\n" - } + "Data: ${message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${message.content}") - } - } - } - } - - fun onTouchScroll(): Boolean { - return view?.run { - if (isDropdownListVisible) { - hideDropdownList() - true - } else false - } == true - } - - fun onRecipientsTextChange(text: String) { - if (text.isBlank()) return - view?.scrollToRecipients() - } - - fun onUpNavigate(): Boolean { - view?.popView() - return true - } - - fun onSend(): Boolean { - view?.run { - when { - formRecipientsData.isEmpty() -> showMessage(messageRequiredRecipients) - formContentValue.length < 3 -> showMessage(messageContentMinLength) - else -> { - sendMessage( - subject = formSubjectValue, - content = formContentValue, - recipients = formRecipientsData.map { it.recipient } - ) - return true - } - } - } - return false - } - - private fun loadData(message: Message?, reply: Boolean?) { - var reportingUnit: ReportingUnit? = null - var recipientChips: List = emptyList() - var selectedRecipientChips: List = emptyList() - - Timber.i("Loading recipients started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it).map { semester -> it to semester } } - .flatMapCompletable { (student, semester) -> - reportingUnitRepository.getReportingUnit(student, semester.unitId) - .doOnSuccess { reportingUnit = it } - .flatMap { recipientRepository.getRecipients(student, 2, it).toMaybe() } - .doOnSuccess { - Timber.i("Loading recipients result: Success, fetched %d recipients", it.size) - recipientChips = createChips(it) - } - .flatMapCompletable { - if (message == null || reply != true) Completable.complete() - else recipientRepository.getMessageRecipients(student, message) - .doOnSuccess { - Timber.i("Loaded message recipients to reply result: Success, fetched %d recipients", it.size) - selectedRecipientChips = createChips(it) - } - .ignoreElement() - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - showProgress(true) - showContent(false) - } - } - .doFinally { view?.run { showProgress(false) } } - .subscribe({ - view?.run { - if (reportingUnit !== null) { - reportingUnit?.let { setReportingUnit(it) } - setRecipients(recipientChips) - if (selectedRecipientChips.isNotEmpty()) setSelectedRecipients(selectedRecipientChips) - showContent(true) - } else { - Timber.i("Loading recipients result: Can't find the reporting unit") - view?.showEmpty(true) - } - } - }, { - Timber.i("Loading recipients result: An exception occurred") - view?.showContent(true) - errorHandler.dispatch(it) - })) - } - - private fun sendMessage(subject: String, content: String, recipients: List) { - Timber.i("Sending message started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { messageRepository.sendMessage(it, subject, content, recipients) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doOnSubscribe { - view?.run { - showSoftInput(false) - showContent(false) - showProgress(true) - showActionBar(false) - } - } - .subscribe({ - Timber.i("Sending message result: Success") - analytics.logEvent("send_message", "recipients" to recipients.size) - view?.run { - showMessage(messageSuccess) - popView() - } - }, { - Timber.i("Sending message result: An exception occurred") - view?.run { - showContent(true) - showProgress(false) - showActionBar(true) - } - errorHandler.dispatch(it) - }) - ) - } - - private fun createChips(recipients: List): List { - fun generateCorrectSummary(recipientRealName: String): String { - val substring = recipientRealName.substringBeforeLast("-") - return when { - substring == recipientRealName -> recipientRealName - substring.indexOf("(") != -1 -> { - recipientRealName.indexOf("(") - .let { recipientRealName.substring(if (it != -1) it else 0) } - } - substring.indexOf("[") != -1 -> { - recipientRealName.indexOf("[") - .let { recipientRealName.substring(if (it != -1) it else 0) } - } - else -> recipientRealName.substringAfter("-") - }.trim() - } - - return recipients.map { - RecipientChipItem( - title = it.name, - summary = generateCorrectSummary(it.realName), - recipient = it - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt deleted file mode 100644 index 2839f9ce7..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.send - -import io.github.wulkanowy.data.db.entities.ReportingUnit -import io.github.wulkanowy.ui.base.BaseView - -interface SendMessageView : BaseView { - - val isDropdownListVisible: Boolean - - val formRecipientsData: List - - val formSubjectValue: String - - val formContentValue: String - - val messageRequiredRecipients: String - - val messageContentMinLength: String - - val messageSuccess: String - - fun initView() - - fun setReportingUnit(unit: ReportingUnit) - - fun setRecipients(recipients: List) - - fun setSelectedRecipients(recipients: List) - - fun showProgress(show: Boolean) - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showActionBar(show: Boolean) - - fun setSubject(subject: String) - - fun setContent(content: String) - - fun showSoftInput(show: Boolean) - - fun hideDropdownList() - - fun scrollToRecipients() - - fun popView() -} 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 deleted file mode 100644 index b58508a98..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt +++ /dev/null @@ -1,86 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.tab - -import android.graphics.Typeface -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -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.databinding.ItemMessageBinding -import io.github.wulkanowy.utils.toFormattedString -import javax.inject.Inject - -class MessageTabAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var onClickListener: (Message, position: Int) -> Unit = { _, _ -> } - - private var items = mutableListOf() - - fun setDataItems(data: List) { - val diffResult = DiffUtil.calculateDiff(MessageTabDiffUtil(items, data)) - items = data.toMutableList() - diffResult.dispatchUpdatesTo(this) - } - - fun updateItem(position: Int, item: Message) { - val currentItem = items[position] - items[position] = item - if (item != currentItem) { - notifyItemChanged(position) - } - } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemMessageBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - val style = if (item.unread) Typeface.BOLD else Typeface.NORMAL - - messageItemAuthor.run { - text = if (item.folderId == MessageFolder.SENT.id) item.recipient else item.sender - setTypeface(null, style) - } - messageItemSubject.run { - text = if (item.subject.isNotBlank()) item.subject else context.getString(R.string.message_no_subject) - setTypeface(null, style) - } - messageItemDate.run { - text = item.date.toFormattedString() - setTypeface(null, style) - } - messageItemAttachmentIcon.visibility = if (item.hasAttachments) View.VISIBLE else View.GONE - - root.setOnClickListener { - holder.adapterPosition.let { if (it != NO_POSITION) onClickListener(item, it) } - } - } - } - - class ItemViewHolder(val binding: ItemMessageBinding) : RecyclerView.ViewHolder(binding.root) - - private class MessageTabDiffUtil(private val old: List, private val new: List) : - DiffUtil.Callback() { - override fun getOldListSize(): Int = old.size - - override fun getNewListSize(): Int = new.size - - override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition].id == new[newItemPosition].id - } - - override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - return old[oldItemPosition] == new[newItemPosition] - } - } -} 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 deleted file mode 100644 index 9954c6428..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabFragment.kt +++ /dev/null @@ -1,157 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.tab - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.appcompat.widget.SearchView -import androidx.recyclerview.widget.LinearLayoutManager -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.databinding.FragmentMessageTabBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import javax.inject.Inject - -class MessageTabFragment : BaseFragment(R.layout.fragment_message_tab), - MessageTabView { - - @Inject - lateinit var presenter: MessageTabPresenter - - @Inject - lateinit var tabAdapter: MessageTabAdapter - - companion object { - const val MESSAGE_TAB_FOLDER_ID = "message_tab_folder_id" - - fun newInstance(folder: MessageFolder): MessageTabFragment { - return MessageTabFragment().apply { - arguments = Bundle().apply { - putString(MESSAGE_TAB_FOLDER_ID, folder.name) - } - } - } - } - - override val isViewEmpty - get() = tabAdapter.itemCount == 0 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMessageTabBinding.bind(view) - messageContainer = binding.messageTabRecycler - presenter.onAttachView(this, MessageFolder.valueOf( - (savedInstanceState ?: arguments)?.getString(MESSAGE_TAB_FOLDER_ID).orEmpty() - )) - } - - override fun initView() { - tabAdapter.onClickListener = presenter::onMessageItemSelected - - with(binding.messageTabRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = tabAdapter - addItemDecoration(DividerItemDecoration(context)) - } - with(binding) { - messageTabSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - messageTabErrorRetry.setOnClickListener { presenter.onRetry() } - messageTabErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - super.onCreateOptionsMenu(menu, inflater) - inflater.inflate(R.menu.action_menu_message_tab, menu) - - val searchView = menu.findItem(R.id.action_search).actionView as SearchView - searchView.queryHint = getString(R.string.all_search_hint) - searchView.maxWidth = Int.MAX_VALUE - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String) = false - override fun onQueryTextChange(query: String): Boolean { - presenter.onSearchQueryTextChange(query) - return true - } - }) - } - - override fun updateData(data: List) { - tabAdapter.setDataItems(data) - } - - override fun updateItem(item: Message, position: Int) { - tabAdapter.updateItem(position, item) - } - - override fun showProgress(show: Boolean) { - binding.messageTabProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.messageTabSwipe.isEnabled = enable - } - - override fun resetListPosition() { - binding.messageTabRecycler.scrollToPosition(0) - } - - override fun showContent(show: Boolean) { - binding.messageTabRecycler.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showEmpty(show: Boolean) { - binding.messageTabEmpty.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showErrorView(show: Boolean) { - binding.messageTabError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.messageTabErrorMessage.text = message - } - - override fun showRefresh(show: Boolean) { - binding.messageTabSwipe.isRefreshing = show - } - - override fun openMessage(message: Message) { - (activity as? MainActivity)?.pushView(MessagePreviewFragment.newInstance(message)) - } - - override fun notifyParentDataLoaded() { - (parentFragment as? MessageFragment)?.onChildFragmentLoaded() - } - - fun onParentLoadData(forceRefresh: Boolean) { - presenter.onParentViewLoadData(forceRefresh) - } - - fun onParentDeleteMessage() { - presenter.onDeleteMessage() - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putString(MESSAGE_TAB_FOLDER_ID, presenter.folder.name) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 533f5ac85..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt +++ /dev/null @@ -1,207 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.tab - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.toFormattedString -import io.reactivex.subjects.PublishSubject -import me.xdrop.fuzzywuzzy.FuzzySearch -import timber.log.Timber -import java.util.Locale -import java.util.concurrent.TimeUnit -import javax.inject.Inject -import kotlin.math.pow - -class MessageTabPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val messageRepository: MessageRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - lateinit var folder: MessageFolder - - private lateinit var lastError: Throwable - - private var lastSearchQuery = "" - - private var messages = emptyList() - - private val searchQuery = PublishSubject.create() - - fun onAttachView(view: MessageTabView, folder: MessageFolder) { - super.onAttachView(view) - view.initView() - initializeSearchStream() - errorHandler.showErrorMessage = ::showErrorViewOnError - this.folder = folder - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the $folder message") - onParentViewLoadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onDeleteMessage() { - loadData(false) - } - - fun onParentViewLoadData(forceRefresh: Boolean) { - loadData(forceRefresh) - } - - fun onMessageItemSelected(message: Message, position: Int) { - Timber.i("Select message ${message.id} item (position: $position)") - view?.run { - openMessage(message) - if (message.unread) { - message.unread = false - updateItem(message, position) - } - } - } - - private fun loadData(forceRefresh: Boolean) { - Timber.i("Loading $folder message data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student) - .flatMap { messageRepository.getMessages(student, it, folder, forceRefresh) } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - showRefresh(false) - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded() - } - } - .subscribe({ - Timber.i("Loading $folder message result: Success") - messages = it - view?.updateData(getFilteredData(lastSearchQuery)) - analytics.logEvent( - "load_data", - "type" to "messages", - "items" to it.size, - "folder" to folder.name - ) - }) { - Timber.i("Loading $folder message result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - fun onSearchQueryTextChange(query: String) { - if (query != searchQuery.toString()) - searchQuery.onNext(query) - } - - private fun initializeSearchStream() { - disposable.add(searchQuery - .debounce(250, TimeUnit.MILLISECONDS) - .map { query -> - lastSearchQuery = query - getFilteredData(query) - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - Timber.d("Applying filter. Full list: ${messages.size}, filtered: ${it.size}") - updateData(it) - }) { Timber.e(it) }) - } - - private fun getFilteredData(query: String): List { - return if (query.trim().isEmpty()) { - messages.sortedByDescending { it.date } - } else { - messages - .map { it to calculateMatchRatio(it, query) } - .sortedByDescending { it.second } - .filter { it.second > 5000 } - .map { it.first } - } - } - - private fun updateData(data: List) { - view?.run { - showEmpty(data.isEmpty()) - showContent(data.isNotEmpty()) - showErrorView(false) - updateData(data) - resetListPosition() - } - } - - private fun calculateMatchRatio(message: Message, query: String): Int { - val subjectRatio = FuzzySearch.tokenSortPartialRatio( - query.toLowerCase(Locale.getDefault()), - message.subject - ) - - val senderOrRecipientRatio = FuzzySearch.tokenSortPartialRatio( - query.toLowerCase(Locale.getDefault()), - if (message.sender.isNotEmpty()) message.sender.toLowerCase(Locale.getDefault()) - else message.recipient.toLowerCase(Locale.getDefault()) - ) - - val dateRatio = listOf( - FuzzySearch.ratio( - query.toLowerCase(Locale.getDefault()), - message.date.toFormattedString("dd.MM").toLowerCase(Locale.getDefault()) - ), - FuzzySearch.ratio( - query.toLowerCase(Locale.getDefault()), - message.date.toFormattedString("dd.MM.yyyy").toLowerCase(Locale.getDefault()) - ), - FuzzySearch.ratio( - query.toLowerCase(Locale.getDefault()), - message.date.toFormattedString("d MMMM").toLowerCase(Locale.getDefault()) - ), - FuzzySearch.ratio( - query.toLowerCase(Locale.getDefault()), - message.date.toFormattedString("d MMMM yyyy").toLowerCase(Locale.getDefault()) - ) - ).max() ?: 0 - - - return (subjectRatio.toDouble().pow(2) - + senderOrRecipientRatio.toDouble().pow(2) - + dateRatio.toDouble().pow(2) * 2 - ).toInt() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt deleted file mode 100644 index f521191cf..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabView.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.ui.modules.message.tab - -import io.github.wulkanowy.data.db.entities.Message -import io.github.wulkanowy.ui.base.BaseView - -interface MessageTabView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun resetListPosition() - - fun updateData(data: List) - - fun updateItem(item: Message, position: Int) - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showRefresh(show: Boolean) - - fun openMessage(message: Message) - - fun notifyParentDataLoaded() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceAdapter.kt deleted file mode 100644 index 4bc3097d6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceAdapter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.databinding.ItemMobileDeviceBinding -import io.github.wulkanowy.utils.toFormattedString -import javax.inject.Inject - -class MobileDeviceAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = mutableListOf() - - var onDeviceUnregisterListener: (device: MobileDevice, position: Int) -> Unit = { _, _ -> } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemMobileDeviceBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val device = items[position] - - with(holder.binding) { - mobileDeviceItemDate.text = device.date.toFormattedString("dd.MM.yyyy HH:mm:ss") - mobileDeviceItemName.text = device.name - mobileDeviceItemUnregister.setOnClickListener { - onDeviceUnregisterListener(device, position) - } - } - } - - class ItemViewHolder(val binding: ItemMobileDeviceBinding) : - RecyclerView.ViewHolder(binding.root) -} 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 deleted file mode 100644 index 6a3e5a441..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceFragment.kt +++ /dev/null @@ -1,137 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.core.view.postDelayed -import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.snackbar.Snackbar -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.databinding.FragmentMobileDeviceBinding -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.mobiledevice.token.MobileDeviceTokenDialog -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import javax.inject.Inject - -class MobileDeviceFragment : - BaseFragment(R.layout.fragment_mobile_device), MobileDeviceView, - MainView.TitledView { - - @Inject - lateinit var presenter: MobileDevicePresenter - - @Inject - lateinit var devicesAdapter: MobileDeviceAdapter - - companion object { - fun newInstance() = MobileDeviceFragment() - } - - override val titleStringId: Int - get() = R.string.mobile_devices_title - - override val isViewEmpty: Boolean - get() = devicesAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMobileDeviceBinding.bind(view) - messageContainer = binding.mobileDevicesRecycler - presenter.onAttachView(this) - } - - override fun initView() { - devicesAdapter.onDeviceUnregisterListener = presenter::onUnregisterDevice - - with(binding.mobileDevicesRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = devicesAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - mobileDevicesSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - mobileDevicesErrorRetry.setOnClickListener { presenter.onRetry() } - mobileDevicesErrorDetails.setOnClickListener { presenter.onDetailsClick() } - mobileDeviceAddButton.setOnClickListener { presenter.onRegisterDevice() } - } - } - - override fun updateData(data: List) { - with(devicesAdapter) { - items = data.toMutableList() - notifyDataSetChanged() - } - } - - override fun deleteItem(device: MobileDevice, position: Int) { - with(devicesAdapter) { - items.removeAt(position) - notifyItemRemoved(position) - notifyItemRangeChanged(position, itemCount) - } - } - - override fun restoreDeleteItem(device: MobileDevice, position: Int) { - with(devicesAdapter) { - items.add(position, device) - notifyItemInserted(position) - notifyItemRangeChanged(position, itemCount) - } - } - - override fun showUndo(device: MobileDevice, position: Int) { - var confirmed = true - - Snackbar.make(binding.mobileDevicesRecycler, getString(R.string.mobile_device_removed), 3000) - .setAction(R.string.all_undo) { - confirmed = false - presenter.onUnregisterCancelled(device, position) - }.show() - - view?.postDelayed(3000) { - if (confirmed) presenter.onUnregisterConfirmed(device) - } - } - - override fun hideRefresh() { - binding.mobileDevicesSwipe.isRefreshing = false - } - - override fun showProgress(show: Boolean) { - binding.mobileDevicesProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showEmpty(show: Boolean) { - binding.mobileDevicesEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.mobileDevicesError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.mobileDevicesErrorMessage.text = message - } - - override fun enableSwipe(enable: Boolean) { - binding.mobileDevicesSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.mobileDevicesRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showTokenDialog() { - (activity as? MainActivity)?.showDialogFragment(MobileDeviceTokenDialog.newInstance()) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt deleted file mode 100644 index 459ca17e8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDevicePresenter.kt +++ /dev/null @@ -1,145 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class MobileDevicePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val mobileDeviceRepository: MobileDeviceRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: MobileDeviceView) { - super.onAttachView(view) - view.initView() - Timber.i("Mobile device view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - fun onSwipeRefresh() { - loadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - private fun loadData(forceRefresh: Boolean = false) { - Timber.i("Loading mobile devices data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - mobileDeviceRepository.getDevices(student, semester, forceRefresh) - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - }.subscribe({ - Timber.i("Loading mobile devices result: Success") - view?.run { - updateData(it) - showContent(it.isNotEmpty()) - showEmpty(it.isEmpty()) - showErrorView(false) - } - analytics.logEvent( - "load_data", - "type" to "devices", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading mobile devices result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - fun onRegisterDevice() { - view?.showTokenDialog() - } - - fun onUnregisterDevice(device: MobileDevice, position: Int) { - view?.run { - deleteItem(device, position) - showUndo(device, position) - showEmpty(isViewEmpty) - } - } - - fun onUnregisterCancelled(device: MobileDevice, position: Int) { - view?.run { - restoreDeleteItem(device, position) - showEmpty(isViewEmpty) - } - } - - fun onUnregisterConfirmed(device: MobileDevice) { - Timber.i("Unregister device started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - mobileDeviceRepository.unregisterDevice(student, semester, device) - .flatMap { mobileDeviceRepository.getDevices(student, semester, it) } - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Unregister device result: Success") - view?.run { - updateData(it) - showContent(it.isNotEmpty()) - showEmpty(it.isEmpty()) - } - }) { - Timber.i("Unregister device result: An exception occurred") - errorHandler.dispatch(it) - } - ) - } -} 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 deleted file mode 100644 index ec2d3f87f..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/MobileDeviceView.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice - -import io.github.wulkanowy.data.db.entities.MobileDevice -import io.github.wulkanowy.ui.base.BaseView - -interface MobileDeviceView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List) - - fun deleteItem(device: MobileDevice, position: Int) - - fun restoreDeleteItem(device: MobileDevice, position: Int) - - fun showUndo(device: MobileDevice, position: Int) - - fun hideRefresh() - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun showTokenDialog() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt deleted file mode 100644 index 9ac6049e9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt +++ /dev/null @@ -1,89 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice.token - -import android.content.ClipData -import android.content.ClipboardManager -import android.graphics.BitmapFactory -import android.os.Bundle -import android.util.Base64 -import android.view.LayoutInflater -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.getSystemService -import io.github.wulkanowy.R -import io.github.wulkanowy.data.pojos.MobileDeviceToken -import io.github.wulkanowy.databinding.DialogMobileDeviceBinding -import io.github.wulkanowy.ui.base.BaseDialogFragment -import javax.inject.Inject - -class MobileDeviceTokenDialog : BaseDialogFragment(), MobileDeviceTokenVIew { - - @Inject - lateinit var presenter: MobileDeviceTokenPresenter - - companion object { - fun newInstance(): MobileDeviceTokenDialog = MobileDeviceTokenDialog() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogMobileDeviceBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - presenter.onAttachView(this) - } - - override fun initView() { - binding.mobileDeviceDialogClose.setOnClickListener { dismiss() } - } - - override fun updateData(token: MobileDeviceToken) { - with(binding.mobileDeviceDialogToken) { - text = token.token - setOnClickListener { clickCopy(token.token) } - } - with(binding.mobileDeviceDialogSymbol) { - text = token.symbol - setOnClickListener { clickCopy(token.symbol) } - } - with(binding.mobileDeviceDialogPin) { - text = token.pin - setOnClickListener { clickCopy(token.pin) } - } - - binding.mobileDeviceQr.setImageBitmap(Base64.decode(token.qr, Base64.DEFAULT).let { - BitmapFactory.decodeByteArray(it, 0, it.size) - }) - } - - private fun clickCopy(text: String) { - val clip = ClipData.newPlainText("wulkanowy", text) - activity?.getSystemService()?.setPrimaryClip(clip) - Toast.makeText(context, R.string.all_copied, Toast.LENGTH_LONG).show() - } - - override fun hideLoading() { - binding.mobileDeviceDialogProgress.visibility = GONE - } - - override fun showContent() { - binding.mobileDeviceDialogContent.visibility = VISIBLE - } - - override fun closeDialog() { - dismiss() - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 6a2a6b98b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenPresenter.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice.token - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class MobileDeviceTokenPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val mobileDeviceRepository: MobileDeviceRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: MobileDeviceTokenVIew) { - super.onAttachView(view) - view.initView() - Timber.i("Mobile device view was initialized") - loadData() - } - - private fun loadData() { - Timber.i("Mobile device registration data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - mobileDeviceRepository.getToken(student, semester) - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { view?.hideLoading() } - .subscribe({ - Timber.i("Mobile device registration result: Success") - view?.run { - updateData(it) - showContent() - } - analytics.logEvent("device_register", "symbol" to it.token.substring(0, 3)) - }) { - Timber.i("Mobile device registration result: An exception occurred") - view?.closeDialog() - errorHandler.dispatch(it) - } - ) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenVIew.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenVIew.kt deleted file mode 100644 index 950f8bcf0..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenVIew.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.wulkanowy.ui.modules.mobiledevice.token - -import io.github.wulkanowy.data.pojos.MobileDeviceToken -import io.github.wulkanowy.ui.base.BaseView - -interface MobileDeviceTokenVIew : BaseView { - - fun initView() - - fun hideLoading() - - fun showContent() - - fun closeDialog() - - fun updateData(token: MobileDeviceToken) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt deleted file mode 100644 index 70587b0cf..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreAdapter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.ui.modules.more - -import android.graphics.drawable.Drawable -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.databinding.ItemMoreBinding -import javax.inject.Inject - -class MoreAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList>() - - var onClickListener: (name: String) -> Unit = {} - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemMoreBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val (title, drawable) = items[position] - - with(holder.binding) { - moreItemTitle.text = title - moreItemImage.setImageDrawable(drawable) - - root.setOnClickListener { onClickListener(title) } - } - } - - class ItemViewHolder(val binding: ItemMoreBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt deleted file mode 100644 index a79087de2..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt +++ /dev/null @@ -1,129 +0,0 @@ -package io.github.wulkanowy.ui.modules.more - -import android.graphics.drawable.Drawable -import android.os.Bundle -import android.view.View -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentMoreBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.about.AboutFragment -import io.github.wulkanowy.ui.modules.homework.HomeworkFragment -import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment -import io.github.wulkanowy.ui.modules.note.NoteFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment -import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.utils.getCompatDrawable -import javax.inject.Inject - -class MoreFragment : BaseFragment(R.layout.fragment_more), MoreView, - MainView.TitledView, MainView.MainChildView { - - @Inject - lateinit var presenter: MorePresenter - - @Inject - lateinit var moreAdapter: MoreAdapter - - companion object { - fun newInstance() = MoreFragment() - } - - override val titleStringId: Int - get() = R.string.more_title - - override val messagesRes: Pair? - get() = context?.run { getString(R.string.message_title) to getCompatDrawable(R.drawable.ic_more_messages) } - - override val homeworkRes: Pair? - get() = context?.run { getString(R.string.homework_title) to getCompatDrawable(R.drawable.ic_more_homework) } - - override val noteRes: Pair? - get() = context?.run { getString(R.string.note_title) to getCompatDrawable(R.drawable.ic_more_note) } - - override val luckyNumberRes: Pair? - get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) } - - override val mobileDevicesRes: Pair? - get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) } - - override val schoolAndTeachersRes: Pair? - get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) } - - override val settingsRes: Pair? - get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) } - - override val aboutRes: Pair? - get() = context?.run { getString(R.string.about_title) to getCompatDrawable(R.drawable.ic_all_about) } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentMoreBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - moreAdapter.onClickListener = presenter::onItemSelected - - with(binding.moreRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = moreAdapter - } - } - - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun updateData(data: List>) { - with(moreAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun openMessagesView() { - (activity as? MainActivity)?.pushView(MessageFragment.newInstance()) - } - - override fun openHomeworkView() { - (activity as? MainActivity)?.pushView(HomeworkFragment.newInstance()) - } - - override fun openNoteView() { - (activity as? MainActivity)?.pushView(NoteFragment.newInstance()) - } - - override fun openLuckyNumberView() { - (activity as? MainActivity)?.pushView(LuckyNumberFragment.newInstance()) - } - - override fun openMobileDevicesView() { - (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance()) - } - - override fun openSchoolAndTeachersView() { - (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance()) - } - - override fun openSettingsView() { - (activity as? MainActivity)?.pushView(SettingsFragment.newInstance()) - } - - override fun openAboutView() { - (activity as? MainActivity)?.pushView(AboutFragment.newInstance()) - } - - override fun popView(depth: Int) { - (activity as? MainActivity)?.popView(depth) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 593645c19..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.wulkanowy.ui.modules.more - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class MorePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: MoreView) { - super.onAttachView(view) - view.initView() - Timber.i("More view was initialized") - loadData() - } - - fun onItemSelected(title: String) { - Timber.i("Select more item \"${title}\"") - view?.run { - when (title) { - messagesRes?.first -> openMessagesView() - homeworkRes?.first -> openHomeworkView() - noteRes?.first -> openNoteView() - luckyNumberRes?.first -> openLuckyNumberView() - mobileDevicesRes?.first -> openMobileDevicesView() - schoolAndTeachersRes?.first -> openSchoolAndTeachersView() - settingsRes?.first -> openSettingsView() - aboutRes?.first -> openAboutView() - } - } - } - - fun onViewReselected() { - Timber.i("More view is reselected") - view?.popView(2) - } - - private fun loadData() { - Timber.i("Load items for more view") - view?.run { - updateData(listOfNotNull( - messagesRes, - homeworkRes, - noteRes, - luckyNumberRes, - mobileDevicesRes, - schoolAndTeachersRes, - settingsRes, - aboutRes - )) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt deleted file mode 100644 index 922afdfd5..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.ui.modules.more - -import android.graphics.drawable.Drawable -import io.github.wulkanowy.ui.base.BaseView - -interface MoreView : BaseView { - - val messagesRes: Pair? - - val homeworkRes: Pair? - - val noteRes: Pair? - - val luckyNumberRes: Pair? - - val mobileDevicesRes: Pair? - - val schoolAndTeachersRes: Pair? - - val settingsRes: Pair? - - val aboutRes: Pair? - - fun initView() - - fun updateData(data: List>) - - fun openSettingsView() - - fun openAboutView() - - fun popView(depth: Int) - - fun openMessagesView() - - fun openHomeworkView() - - fun openNoteView() - - fun openLuckyNumberView() - - fun openMobileDevicesView() - - fun openSchoolAndTeachersView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteAdapter.kt deleted file mode 100644 index 2ffcad949..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteAdapter.kt +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.wulkanowy.ui.modules.note - -import android.annotation.SuppressLint -import android.graphics.Typeface -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.content.ContextCompat -import io.github.wulkanowy.sdk.scrapper.notes.Note.CategoryType -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.databinding.ItemNoteBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.toFormattedString -import javax.inject.Inject - -class NoteAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = mutableListOf() - - var onClickListener: (Note, position: Int) -> Unit = { _, _ -> } - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemNoteBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("SetTextI18n") - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - with(noteItemDate) { - text = item.date.toFormattedString() - setTypeface(null, if (item.isRead) Typeface.NORMAL else Typeface.BOLD) - } - with(noteItemType) { - text = item.category - setTypeface(null, if (item.isRead) Typeface.NORMAL else Typeface.BOLD) - } - with(noteItemPoints) { - text = "${if (item.points > 0) "+" else ""}${item.points}" - visibility = if (item.isPointsShow) View.VISIBLE else View.GONE - setTextColor(when (CategoryType.getByValue(item.categoryType)) { - CategoryType.POSITIVE -> ContextCompat.getColor(context, R.color.note_positive) - CategoryType.NEGATIVE -> ContextCompat.getColor(context, R.color.note_negative) - else -> context.getThemeAttrColor(android.R.attr.textColorPrimary) - }) - } - noteItemTeacher.text = item.teacher - noteItemContent.text = item.content - - root.setOnClickListener { onClickListener(item, position) } - } - } - - class ItemViewHolder(val binding: ItemNoteBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt deleted file mode 100644 index 6d1b181ac..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt +++ /dev/null @@ -1,70 +0,0 @@ -package io.github.wulkanowy.ui.modules.note - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.content.ContextCompat -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.databinding.DialogNoteBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.sdk.scrapper.notes.Note.CategoryType -import io.github.wulkanowy.utils.lifecycleAwareVariable - -class NoteDialog : DialogFragment() { - - private var binding: DialogNoteBinding by lifecycleAwareVariable() - - private lateinit var note: Note - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(exam: Note): NoteDialog { - return NoteDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - note = getSerializable(ARGUMENT_KEY) as Note - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogNoteBinding.inflate(inflater).apply { binding = this }.root - } - - @SuppressLint("SetTextI18n") - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(binding) { - noteDialogDate.text = note.date.toFormattedString() - noteDialogCategory.text = note.category - noteDialogTeacher.text = note.teacher - noteDialogContent.text = note.content - } - - if (note.isPointsShow) { - with(binding.noteDialogPoints) { - text = "${if (note.points > 0) "+" else ""}${note.points}" - setTextColor(when (CategoryType.getByValue(note.categoryType)) { - CategoryType.POSITIVE -> ContextCompat.getColor(requireContext(), R.color.note_positive) - CategoryType.NEGATIVE -> ContextCompat.getColor(requireContext(), R.color.note_negative) - else -> requireContext().getThemeAttrColor(android.R.attr.textColorPrimary) - }) - } - } - - binding.noteDialogClose.setOnClickListener { dismiss() } - } -} 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 deleted file mode 100644 index 473381659..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteFragment.kt +++ /dev/null @@ -1,114 +0,0 @@ -package io.github.wulkanowy.ui.modules.note - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.databinding.FragmentNoteBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import javax.inject.Inject - -class NoteFragment : BaseFragment(R.layout.fragment_note), NoteView, - MainView.TitledView { - - @Inject - lateinit var presenter: NotePresenter - - @Inject - lateinit var noteAdapter: NoteAdapter - - companion object { - fun newInstance() = NoteFragment() - } - - override val titleStringId: Int - get() = R.string.note_title - - override val isViewEmpty: Boolean - get() = noteAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentNoteBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - noteAdapter.onClickListener = presenter::onNoteItemSelected - - with(binding.noteRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = noteAdapter - addItemDecoration(DividerItemDecoration(context)) - } - with(binding) { - noteSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - noteErrorRetry.setOnClickListener { presenter.onRetry() } - noteErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun showNoteDialog(note: Note) { - (activity as? MainActivity)?.showDialogFragment(NoteDialog.newInstance(note)) - } - - override fun updateData(data: List) { - with(noteAdapter) { - items = data.toMutableList() - notifyDataSetChanged() - } - } - - override fun updateItem(item: Note, position: Int) { - with(noteAdapter) { - items[position] = item - notifyItemChanged(position) - } - } - - override fun clearData() { - with(noteAdapter) { - items = mutableListOf() - notifyDataSetChanged() - } - } - - override fun showEmpty(show: Boolean) { - binding.noteEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.noteError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.noteErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.noteProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.noteSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.noteRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun hideRefresh() { - binding.noteSwipe.isRefreshing = false - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt deleted file mode 100644 index 7d301c66b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NotePresenter.kt +++ /dev/null @@ -1,119 +0,0 @@ -package io.github.wulkanowy.ui.modules.note - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class NotePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val noteRepository: NoteRepository, - private val semesterRepository: SemesterRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: NoteView) { - super.onAttachView(view) - view.initView() - Timber.i("Note view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the note") - loadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - private fun loadData(forceRefresh: Boolean = false) { - Timber.i("Loading note data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it).map { semester -> semester to it } } - .flatMap { noteRepository.getNotes(it.second, it.first, forceRefresh) } - .map { items -> items.sortedByDescending { it.date } } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - }.subscribe({ - Timber.i("Loading note result: Success") - view?.apply { - updateData(it) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - } - analytics.logEvent( - "load_data", - "type" to "note", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }, { - Timber.i("Loading note result: An exception occurred") - errorHandler.dispatch(it) - }) - ) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - fun onNoteItemSelected(note: Note, position: Int) { - Timber.i("Select note item ${note.id}") - view?.run { - showNoteDialog(note) - if (!note.isRead) { - note.isRead = true - updateItem(note, position) - updateNote(note) - } - } - } - - private fun updateNote(note: Note) { - Timber.i("Attempt to update note ${note.id}") - disposable.add(noteRepository.updateNote(note) - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ Timber.i("Update note result: Success") }) - { error -> - Timber.i("Update note result: An exception occurred") - errorHandler.dispatch(error) - }) - } -} 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 deleted file mode 100644 index a7cbab8f4..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteView.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.wulkanowy.ui.modules.note - -import io.github.wulkanowy.data.db.entities.Note -import io.github.wulkanowy.ui.base.BaseView - -interface NoteView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List) - - fun updateItem(item: Note, position: Int) - - fun clearData() - - 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 hideRefresh() - - fun showNoteDialog(note: Note) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt deleted file mode 100644 index b5eedb6fd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersChildView.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers - -interface SchoolAndTeachersChildView { - - fun notifyParentDataLoaded() - - fun onParentLoadData(forceRefresh: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt deleted file mode 100644 index 0245aa076..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersFragment.kt +++ /dev/null @@ -1,86 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers - -import android.os.Bundle -import android.view.View -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import io.github.wulkanowy.R -import io.github.wulkanowy.databinding.FragmentSchoolandteachersBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.setOnSelectPageListener -import javax.inject.Inject - -class SchoolAndTeachersFragment : - BaseFragment(R.layout.fragment_schoolandteachers), - SchoolAndTeachersView, MainView.TitledView { - - @Inject - lateinit var presenter: SchoolAndTeachersPresenter - - @Inject - lateinit var pagerAdapter: BaseFragmentPagerAdapter - - companion object { - fun newInstance() = SchoolAndTeachersFragment() - } - - override val titleStringId: Int get() = R.string.schoolandteachers_title - - override val currentPageIndex get() = binding.schoolandteachersViewPager.currentItem - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentSchoolandteachersBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - with(pagerAdapter) { - containerId = binding.schoolandteachersViewPager.id - addFragmentsWithTitle(mapOf( - SchoolFragment.newInstance() to getString(R.string.school_title), - TeacherFragment.newInstance() to getString(R.string.teachers_title) - )) - } - - with(binding.schoolandteachersViewPager) { - adapter = pagerAdapter - offscreenPageLimit = 2 - setOnSelectPageListener(presenter::onPageSelected) - } - - with(binding.schoolandteachersTabLayout) { - setupWithViewPager(binding.schoolandteachersViewPager) - setElevationCompat(context.dpToPx(4f)) - } - } - - override fun showContent(show: Boolean) { - with(binding) { - schoolandteachersViewPager.visibility = if (show) VISIBLE else INVISIBLE - schoolandteachersTabLayout.visibility = if (show) VISIBLE else INVISIBLE - } - } - - override fun showProgress(show: Boolean) { - binding.schoolandteachersProgress.visibility = if (show) VISIBLE else INVISIBLE - } - - fun onChildFragmentLoaded() { - presenter.onChildViewLoaded() - } - - override fun notifyChildLoadData(index: Int, forceRefresh: Boolean) { - (pagerAdapter.getFragmentInstance(index) as? SchoolAndTeachersChildView)?.onParentLoadData(forceRefresh) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt deleted file mode 100644 index 2087b0b42..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersModule.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers - -import dagger.Module -import dagger.Provides -import dagger.android.ContributesAndroidInjector -import io.github.wulkanowy.di.scopes.PerChildFragment -import io.github.wulkanowy.di.scopes.PerFragment -import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter -import io.github.wulkanowy.ui.modules.schoolandteachers.school.SchoolFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.teacher.TeacherFragment - -@Suppress("unused") -@Module -abstract class SchoolAndTeachersModule { - - companion object { - - @PerFragment - @Provides - fun provideSchoolAndTeachersAdapter(fragment: SchoolAndTeachersFragment) = BaseFragmentPagerAdapter(fragment.childFragmentManager) - } - - @PerChildFragment - @ContributesAndroidInjector - abstract fun provideSchoolFragment(): SchoolFragment - - @PerChildFragment - @ContributesAndroidInjector - abstract fun provideTeacherFragment(): TeacherFragment -} 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 deleted file mode 100644 index 1856803c6..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersPresenter.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import io.reactivex.Completable -import timber.log.Timber -import java.util.concurrent.TimeUnit -import javax.inject.Inject - -class SchoolAndTeachersPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: SchoolAndTeachersView) { - super.onAttachView(view) - disposable.add(Completable.timer(150, TimeUnit.MILLISECONDS, schedulers.mainThread) - .subscribe { - view.initView() - Timber.i("Message view was initialized") - loadData() - }) - } - - fun onPageSelected(index: Int) { - loadChild(index) - } - - private fun loadData() { - view?.run { loadChild(currentPageIndex) } - } - - private fun loadChild(index: Int, forceRefresh: Boolean = false) { - Timber.i("Load schoolandteachers child view index: $index") - view?.notifyChildLoadData(index, forceRefresh) - } - - fun onChildViewLoaded() { - view?.apply { - showContent(true) - showProgress(false) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt deleted file mode 100644 index 594441ec7..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/SchoolAndTeachersView.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers - -import io.github.wulkanowy.ui.base.BaseView - -interface SchoolAndTeachersView : BaseView { - - val currentPageIndex: Int - - fun initView() - - fun showContent(show: Boolean) - - fun showProgress(show: Boolean) - - fun notifyChildLoadData(index: Int, forceRefresh: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt deleted file mode 100644 index 722999f86..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolFragment.kt +++ /dev/null @@ -1,109 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.school - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.databinding.FragmentSchoolBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment -import io.github.wulkanowy.utils.openDialer -import io.github.wulkanowy.utils.openNavigation -import javax.inject.Inject - -class SchoolFragment : BaseFragment(R.layout.fragment_school), SchoolView, - MainView.TitledView, SchoolAndTeachersChildView { - - @Inject - lateinit var presenter: SchoolPresenter - - override val titleStringId get() = R.string.school_title - - override val isViewEmpty get() = binding.schoolName.text.isBlank() - - companion object { - fun newInstance() = SchoolFragment() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentSchoolBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - with(binding) { - schoolSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - schoolErrorRetry.setOnClickListener { presenter.onRetry() } - schoolErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - schoolAddressButton.setOnClickListener { presenter.onAddressSelected() } - schoolTelephoneButton.setOnClickListener { presenter.onTelephoneSelected() } - } - } - - override fun updateData(data: School) { - with(binding) { - schoolName.text = data.name - schoolAddress.text = data.address.ifBlank { "-" } - schoolAddressButton.visibility = if (data.address.isNotBlank()) VISIBLE else GONE - schoolTelephone.text = data.contact.ifBlank { "-" } - schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) VISIBLE else GONE - schoolHeadmaster.text = data.headmaster - schoolPedagogue.text = data.pedagogue - } - } - - override fun showEmpty(show: Boolean) { - binding.schoolEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.schoolError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.schoolErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.schoolProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.schoolSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.schoolContent.visibility = if (show) VISIBLE else GONE - } - - override fun hideRefresh() { - binding.schoolSwipe.isRefreshing = false - } - - override fun notifyParentDataLoaded() { - (parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded() - } - - override fun onParentLoadData(forceRefresh: Boolean) { - presenter.onParentViewLoadData(forceRefresh) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } - - override fun openMapsLocation(location: String) { - context?.openNavigation(location) - } - - override fun dialPhone(phone: String) { - context?.openDialer(phone) - } -} 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 deleted file mode 100644 index 7beff922d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolPresenter.kt +++ /dev/null @@ -1,120 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.school - -import io.github.wulkanowy.data.repositories.school.SchoolRepository -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class SchoolPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val schoolRepository: SchoolRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var address: String? = null - - private var contact: String? = null - - private lateinit var lastError: Throwable - - override fun onAttachView(view: SchoolView) { - super.onAttachView(view) - view.initView() - Timber.i("School view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - fun onSwipeRefresh() { - loadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onParentViewLoadData(forceRefresh: Boolean) { - loadData(forceRefresh) - } - - fun onAddressSelected() { - address?.let { view?.openMapsLocation(it) } - } - - fun onTelephoneSelected() { - contact?.let { view?.dialPhone(it) } - } - - private fun loadData(forceRefresh: Boolean = false) { - Timber.i("Loading school info started") - disposable.add(studentRepository.getCurrentStudent() - .flatMapMaybe { student -> - semesterRepository.getCurrentSemester(student).flatMapMaybe { - schoolRepository.getSchoolInfo(student, it, forceRefresh) - } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded() - } - }.subscribe({ - Timber.i("Loading teachers result: Success") - view?.run { - address = it.address.ifBlank { null } - contact = it.contact.ifBlank { null } - updateData(it) - showContent(true) - showEmpty(false) - showErrorView(false) - } - analytics.logEvent( - "load_item", - "type" to "school", - "force_refresh" to forceRefresh - ) - }, { - Timber.i("Loading school result: An exception occurred") - errorHandler.dispatch(it) - }, { - Timber.i("Loading school result: No school info found") - view?.run { - showContent(!isViewEmpty) - showEmpty(isViewEmpty) - showErrorView(false) - } - })) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - showContent(false) - } else showError(message, error) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt deleted file mode 100644 index c42c2f91b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/school/SchoolView.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.school - -import io.github.wulkanowy.data.db.entities.School -import io.github.wulkanowy.ui.base.BaseView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView - -interface SchoolView : BaseView, SchoolAndTeachersChildView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: School) - - 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 hideRefresh() - - fun openMapsLocation(location: String) - - fun dialPhone(phone: String) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherAdapter.kt deleted file mode 100644 index 8deeae05b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherAdapter.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.teacher - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.databinding.ItemTeacherBinding -import javax.inject.Inject - -class TeacherAdapter @Inject constructor() : RecyclerView.Adapter() { - - var items = emptyList() - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemTeacherBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("SetTextI18n") - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val teacher = items[position] - - with(holder.binding) { - teacherItemName.text = teacher.name - teacherItemSubject.text = if (teacher.subject.isNotBlank()) teacher.subject else root.context.getString(R.string.teacher_no_subject) - if (teacher.shortName.isNotBlank()) { - teacherItemShortName.visibility = View.VISIBLE - teacherItemShortName.text = "[${teacher.shortName}]" - } else { - teacherItemShortName.visibility = View.GONE - } - } - } - - class ItemViewHolder(val binding: ItemTeacherBinding) : RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt deleted file mode 100644 index aa50339c1..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherFragment.kt +++ /dev/null @@ -1,105 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.teacher - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.databinding.FragmentTeacherBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import javax.inject.Inject - -class TeacherFragment : BaseFragment(R.layout.fragment_teacher), - TeacherView, MainView.TitledView, SchoolAndTeachersChildView { - - @Inject - lateinit var presenter: TeacherPresenter - - @Inject - lateinit var teacherAdapter: TeacherAdapter - - companion object { - fun newInstance() = TeacherFragment() - } - - override val titleStringId: Int - get() = R.string.teachers_title - - override val noSubjectString get() = getString(R.string.teacher_no_subject) - - override val isViewEmpty: Boolean - get() = teacherAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentTeacherBinding.bind(view) - presenter.onAttachView(this) - } - - override fun initView() { - with(binding.teacherRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = teacherAdapter - addItemDecoration(DividerItemDecoration(context)) - } - with(binding) { - teacherSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } - teacherErrorRetry.setOnClickListener { presenter.onRetry() } - teacherErrorDetails.setOnClickListener { presenter.onDetailsClick() } - } - } - - override fun updateData(data: List) { - with(teacherAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun showEmpty(show: Boolean) { - binding.teacherEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.teacherError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.teacherErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.teacherProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.teacherSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.teacherRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun hideRefresh() { - binding.teacherSwipe.isRefreshing = false - } - - override fun notifyParentDataLoaded() { - (parentFragment as? SchoolAndTeachersFragment)?.onChildFragmentLoaded() - } - - override fun onParentLoadData(forceRefresh: Boolean) { - presenter.onParentViewLoadData(forceRefresh) - } - - override fun onDestroyView() { - presenter.onDetachView() - super.onDestroyView() - } -} 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 deleted file mode 100644 index 0d8eec6d4..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherPresenter.kt +++ /dev/null @@ -1,100 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.teacher - -import io.github.wulkanowy.data.repositories.semester.SemesterRepository -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.data.repositories.teacher.TeacherRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import timber.log.Timber -import javax.inject.Inject - -class TeacherPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val teacherRepository: TeacherRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private lateinit var lastError: Throwable - - override fun onAttachView(view: TeacherView) { - super.onAttachView(view) - view.initView() - Timber.i("Teacher view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - fun onSwipeRefresh() { - loadData(true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onParentViewLoadData(forceRefresh: Boolean) { - loadData(forceRefresh) - } - - private fun loadData(forceRefresh: Boolean = false) { - Timber.i("Loading teachers data started") - disposable.add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - teacherRepository.getTeachers(student, semester, forceRefresh) - } - } - .map { it.filter { teacher -> teacher.name.isNotBlank() } } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - notifyParentDataLoaded() - } - }.subscribe({ - Timber.i("Loading teachers result: Success") - view?.run { - updateData(it) - showContent(it.isNotEmpty()) - showEmpty(it.isEmpty()) - showErrorView(false) - } - analytics.logEvent( - "load_data", - "type" to "teachers", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading teachers result: An exception occurred") - errorHandler.dispatch(it) - }) - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt deleted file mode 100644 index c655bfad8..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/schoolandteachers/teacher/TeacherView.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.ui.modules.schoolandteachers.teacher - -import io.github.wulkanowy.data.db.entities.Teacher -import io.github.wulkanowy.ui.base.BaseView -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersChildView - -interface TeacherView : BaseView, SchoolAndTeachersChildView { - - val isViewEmpty: Boolean - - val noSubjectString: String - - fun initView() - - fun updateData(data: List) - - fun hideRefresh() - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showContent(show: Boolean) - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) -} 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 deleted file mode 100644 index 248417fd1..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt +++ /dev/null @@ -1,158 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings - -import android.content.Context -import android.content.SharedPreferences -import android.os.Bundle -import androidx.appcompat.app.AlertDialog -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat -import com.thelittlefireman.appkillermanager.AppKillerManager -import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException -import com.yariksoffice.lingver.Lingver -import dagger.android.support.AndroidSupportInjection -import io.github.wulkanowy.R -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.base.ErrorDialog -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.AppInfo -import io.github.wulkanowy.utils.openInternetBrowser -import javax.inject.Inject - -class SettingsFragment : PreferenceFragmentCompat(), - SharedPreferences.OnSharedPreferenceChangeListener, - MainView.TitledView, SettingsView { - - @Inject - lateinit var presenter: SettingsPresenter - - @Inject - lateinit var appInfo: AppInfo - - @Inject - lateinit var lingver: Lingver - - companion object { - fun newInstance() = SettingsFragment() - } - - override val titleStringId get() = R.string.settings_title - - override val syncSuccessString get() = getString(R.string.pref_services_message_sync_success) - - override val syncFailedString get() = getString(R.string.pref_services_message_sync_failed) - - override fun onAttach(context: Context) { - AndroidSupportInjection.inject(this) - super.onAttach(context) - } - - override fun initView() { - findPreference(getString(R.string.pref_key_services_force_sync))?.run { - onPreferenceClickListener = Preference.OnPreferenceClickListener { - presenter.onSyncNowClicked() - true - } - } - findPreference(getString(R.string.pref_key_notifications_fix_issues))?.run { - isVisible = AppKillerManager.isDeviceSupported() && AppKillerManager.isAnyActionAvailable(requireContext()) - setOnPreferenceClickListener { - presenter.onFixSyncIssuesClicked() - true - } - } - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - presenter.onAttachView(this) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.scheme_preferences, rootKey) - findPreference(getString(R.string.pref_key_notification_debug))?.isVisible = appInfo.isDebug - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { - presenter.onSharedPreferenceChanged(key) - } - - override fun recreateView() { - activity?.recreate() - } - - override fun updateLanguage(langCode: String) { - lingver.setLocale(requireContext(), langCode) - } - - override fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) { - findPreference(serviceEnablesKey)?.run { - summary = if (isHolidays) getString(R.string.pref_services_suspended) else "" - isEnabled = !isHolidays - } - } - - override fun setSyncInProgress(inProgress: Boolean) { - if (activity == null || !isAdded) return - - findPreference(getString(R.string.pref_key_services_force_sync))?.run { - isEnabled = !inProgress - summary = if (inProgress) getString(R.string.pref_services_sync_in_progress) else "" - } - } - - override fun showError(text: String, error: Throwable) { - (activity as? BaseActivity<*, *>)?.showError(text, error) - } - - override fun showMessage(text: String) { - (activity as? BaseActivity<*, *>)?.showMessage(text) - } - - override fun showExpiredDialog() { - (activity as? BaseActivity<*, *>)?.showExpiredDialog() - } - - override fun openClearLoginView() { - (activity as? BaseActivity<*, *>)?.openClearLoginView() - } - - override fun showErrorDetailsDialog(error: Throwable) { - ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) - } - - override fun showForceSyncDialog() { - AlertDialog.Builder(requireContext()) - .setTitle(R.string.pref_services_dialog_force_sync_title) - .setMessage(R.string.pref_services_dialog_force_sync_summary) - .setPositiveButton(android.R.string.ok) { _, _ -> presenter.onForceSyncDialogSubmit() } - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .show() - } - - override fun showFixSyncDialog() { - AlertDialog.Builder(requireContext()) - .setTitle(R.string.pref_notify_fix_sync_issues) - .setMessage(R.string.pref_notify_fix_sync_issues_message) - .setNegativeButton(android.R.string.cancel) { _, _ -> } - .setPositiveButton(R.string.pref_notify_fix_sync_issues_settings_button) { _, _ -> - try { - AppKillerManager.doActionPowerSaving(requireContext()) - AppKillerManager.doActionAutoStart(requireContext()) - AppKillerManager.doActionNotification(requireContext()) - } catch (e: NoActionFoundException) { - requireContext().openInternetBrowser("https://dontkillmyapp.com/${AppKillerManager.getDevice()?.manufacturer}", ::showMessage) - } - } - .show() - } - - override fun onResume() { - super.onResume() - preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this) - } - - override fun onPause() { - super.onPause() - preferenceScreen.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) - } -} 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 deleted file mode 100644 index bccb6f0bb..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt +++ /dev/null @@ -1,94 +0,0 @@ -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.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.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.isHolidays -import org.threeten.bp.LocalDate.now -import timber.log.Timber -import javax.inject.Inject - -class SettingsPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val preferencesRepository: PreferencesRepository, - private val timetableNotificationHelper: TimetableNotificationSchedulerHelper, - private val analytics: FirebaseAnalyticsHelper, - private val syncManager: SyncManager, - private val chuckerCollector: ChuckerCollector, - private val appInfo: AppInfo -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: SettingsView) { - super.onAttachView(view) - Timber.i("Settings view was initialized") - view.setServicesSuspended(preferencesRepository.serviceEnableKey, now().isHolidays) - view.initView() - } - - fun onSharedPreferenceChanged(key: String) { - Timber.i("Change settings $key") - - preferencesRepository.apply { - when (key) { - serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startPeriodicSyncWorker() else stopSyncWorker() } - servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startPeriodicSyncWorker(true) - isDebugNotificationEnableKey -> chuckerCollector.showNotification = isDebugNotificationEnable - appThemeKey -> view?.recreateView() - isUpcomingLessonsNotificationsEnableKey -> if (!isUpcomingLessonsNotificationsEnable) timetableNotificationHelper.cancelNotification() - appLanguageKey -> view?.run { - updateLanguage(if (appLanguage == "system") appInfo.systemLanguage else appLanguage) - recreateView() - } - } - } - analytics.logEvent("setting_changed", "name" to key) - } - - fun onSyncNowClicked() { - view?.showForceSyncDialog() - } - - fun onFixSyncIssuesClicked() { - view?.showFixSyncDialog() - } - - fun onForceSyncDialogSubmit() { - view?.run { - val successString = syncSuccessString - val failedString = syncFailedString - disposable.add(syncManager.startOneTimeSyncWorker() - .doOnSubscribe { - setSyncInProgress(true) - Timber.i("Setting sync now started") - analytics.logEvent("sync_now", "status" to "started") - } - .doFinally { setSyncInProgress(false) } - .subscribe({ workInfo -> - when (workInfo.state) { - WorkInfo.State.SUCCEEDED -> { - showMessage(successString) - analytics.logEvent("sync_now", "status" to "success") - } - WorkInfo.State.FAILED -> { - showError(failedString, Throwable(workInfo.outputData.getString("error"))) - analytics.logEvent("sync_now", "status" to "failed") - } - else -> Timber.d("Sync now state: ${workInfo.state}") - } - }, { - Timber.e(it, "Sync now failed") - }) - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt deleted file mode 100644 index 3786ba4b2..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings - -import io.github.wulkanowy.ui.base.BaseView - -interface SettingsView : BaseView { - - val syncSuccessString: String - - val syncFailedString: String - - fun initView() - - fun recreateView() - - fun updateLanguage(langCode: String) - - fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) - - fun setSyncInProgress(inProgress: Boolean) - - fun showForceSyncDialog() - fun showFixSyncDialog() -} 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 deleted file mode 100644 index 23a437506..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.wulkanowy.ui.modules.splash - -import android.os.Bundle -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG -import androidx.viewbinding.ViewBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.main.MainActivity -import javax.inject.Inject - -class SplashActivity : BaseActivity(), SplashView { - - @Inject - override lateinit var presenter: SplashPresenter - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - presenter.onAttachView(this) - } - - override fun openLoginView() { - startActivity(LoginActivity.getStartIntent(this)) - finish() - } - - override fun openMainView() { - startActivity(MainActivity.getStartIntent(this)) - 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 deleted file mode 100644 index 44b53c5f9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.ui.modules.splash - -import io.github.wulkanowy.data.repositories.student.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Inject - -class SplashPresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - override fun onAttachView(view: SplashView) { - super.onAttachView(view) - disposable.add(studentRepository.isCurrentStudentSet() - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - view.apply { - if (it) openMainView() - else openLoginView() - } - }, { errorHandler.dispatch(it) })) - } -} 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 deleted file mode 100644 index 9efd8123b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.wulkanowy.ui.modules.splash - -import io.github.wulkanowy.ui.base.BaseView - -interface SplashView : BaseView { - - fun openLoginView() - - fun openMainView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt deleted file mode 100644 index 85ded2025..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableAdapter.kt +++ /dev/null @@ -1,299 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable - -import android.graphics.Paint -import android.view.LayoutInflater -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.databinding.ItemTimetableBinding -import io.github.wulkanowy.databinding.ItemTimetableSmallBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.isJustFinished -import io.github.wulkanowy.utils.isShowTimeUntil -import io.github.wulkanowy.utils.left -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.utils.until -import org.threeten.bp.LocalDateTime -import timber.log.Timber -import java.util.Timer -import javax.inject.Inject -import kotlin.concurrent.timer - -class TimetableAdapter @Inject constructor() : RecyclerView.Adapter() { - - private enum class ViewType(val id: Int) { - ITEM_NORMAL(1), - ITEM_SMALL(2) - } - - var items = mutableListOf() - set(value) { - field = value - resetTimers() - } - - var onClickListener: (Timetable) -> Unit = {} - - var showWholeClassPlan: String = "no" - - var showTimers: Boolean = false - - private val timers = mutableMapOf() - - private fun resetTimers() { - Timber.d("Timetable timers reset") - with(timers) { - forEach { (_, timer) -> timer.cancel() } - clear() - } - } - - override fun getItemCount() = items.size - - override fun getItemViewType(position: Int) = when { - !items[position].isStudentPlan && showWholeClassPlan == "small" -> ViewType.ITEM_SMALL.id - else -> ViewType.ITEM_NORMAL.id - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(parent.context) - - return when (viewType) { - ViewType.ITEM_NORMAL.id -> ItemViewHolder(ItemTimetableBinding.inflate(inflater, parent, false)) - ViewType.ITEM_SMALL.id -> SmallItemViewHolder(ItemTimetableSmallBinding.inflate(inflater, parent, false)) - else -> throw IllegalStateException() - } - } - - override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { - super.onDetachedFromRecyclerView(recyclerView) - resetTimers() - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - val lesson = items[position] - - when (holder) { - is ItemViewHolder -> bindNormalView(holder.binding, lesson, position) - is SmallItemViewHolder -> bindSmallView(holder.binding, lesson) - } - } - - private fun bindSmallView(binding: ItemTimetableSmallBinding, lesson: Timetable) { - with(binding) { - timetableSmallItemNumber.text = lesson.number.toString() - timetableSmallItemSubject.text = lesson.subject - timetableSmallItemTimeStart.text = lesson.start.toFormattedString("HH:mm") - timetableSmallItemRoom.text = lesson.room - timetableSmallItemTeacher.text = lesson.teacher - - bindSubjectStyle(timetableSmallItemSubject, lesson) - bindSmallDescription(binding, lesson) - bindSmallColors(binding, lesson) - - root.setOnClickListener { onClickListener(lesson) } - } - } - - private fun bindNormalView(binding: ItemTimetableBinding, lesson: Timetable, position: Int) { - with(binding) { - timetableItemNumber.text = lesson.number.toString() - timetableItemSubject.text = lesson.subject - timetableItemRoom.text = lesson.room - timetableItemTeacher.text = lesson.teacher - timetableItemTimeStart.text = lesson.start.toFormattedString("HH:mm") - timetableItemTimeFinish.text = lesson.end.toFormattedString("HH:mm") - - bindSubjectStyle(timetableItemSubject, lesson) - bindNormalDescription(binding, lesson) - bindNormalColors(binding, lesson) - - if (lesson.isStudentPlan && showTimers) timers[position] = timer(period = 1000) { - root.post { updateTimeLeft(binding, lesson, position) } - } else { - // reset item on set changed - timetableItemTimeUntil.visibility = GONE - timetableItemTimeLeft.visibility = GONE - } - - root.setOnClickListener { onClickListener(lesson) } - } - } - - private fun getPreviousLesson(position: Int): LocalDateTime? { - return items.filter { it.isStudentPlan }.getOrNull(position - 1 - items.filterIndexed { i, item -> i < position && !item.isStudentPlan }.size)?.let { - if (!it.canceled && it.isStudentPlan) it.end - else null - } - } - - private fun updateTimeLeft(binding: ItemTimetableBinding, lesson: Timetable, position: Int) { - val isShowTimeUntil = lesson.isShowTimeUntil(getPreviousLesson(position)) - val until = lesson.until - val left = lesson.left - val isJustFinished = lesson.isJustFinished - - with(binding) { - when { - // before lesson - isShowTimeUntil -> { - Timber.d("Show time until lesson: $position") - timetableItemTimeLeft.visibility = GONE - with(timetableItemTimeUntil) { - visibility = VISIBLE - text = context.getString(R.string.timetable_time_until, - if (until.seconds <= 60) { - context.getString(R.string.timetable_seconds, until.seconds.toString(10)) - } else { - context.getString(R.string.timetable_minutes, until.toMinutes().toString(10)) - } - ) - } - } - // after lesson start - left != null -> { - Timber.d("Show time left lesson: $position") - timetableItemTimeUntil.visibility = GONE - with(timetableItemTimeLeft) { - visibility = VISIBLE - text = context.getString( - R.string.timetable_time_left, - if (left.seconds < 60) { - context.getString(R.string.timetable_seconds, left.seconds.toString(10)) - } else { - context.getString(R.string.timetable_minutes, left.toMinutes().toString(10)) - } - ) - } - } - // right after lesson finish - isJustFinished -> { - Timber.d("Show just finished lesson: $position") - timetableItemTimeUntil.visibility = GONE - timetableItemTimeLeft.visibility = VISIBLE - timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished) - } - else -> { - timetableItemTimeUntil.visibility = GONE - timetableItemTimeLeft.visibility = GONE - } - } - } - } - - private fun bindSubjectStyle(subjectView: TextView, lesson: Timetable) { - subjectView.paintFlags = if (lesson.canceled) subjectView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG - else subjectView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() - } - - private fun bindSmallDescription(binding: ItemTimetableSmallBinding, lesson: Timetable) { - with(binding) { - if (lesson.info.isNotBlank() && !lesson.changes) { - timetableSmallItemDescription.visibility = VISIBLE - timetableSmallItemDescription.text = lesson.info - - timetableSmallItemRoom.visibility = GONE - timetableSmallItemTeacher.visibility = GONE - - timetableSmallItemDescription.setTextColor(root.context.getThemeAttrColor( - if (lesson.canceled) R.attr.colorPrimary - else R.attr.colorTimetableChange - )) - } else { - timetableSmallItemDescription.visibility = GONE - timetableSmallItemRoom.visibility = VISIBLE - timetableSmallItemTeacher.visibility = VISIBLE - } - } - } - - private fun bindNormalDescription(binding: ItemTimetableBinding, lesson: Timetable) { - with(binding) { - if (lesson.info.isNotBlank() && !lesson.changes) { - timetableItemDescription.visibility = VISIBLE - timetableItemDescription.text = lesson.info - - timetableItemRoom.visibility = GONE - timetableItemTeacher.visibility = GONE - - timetableItemDescription.setTextColor(root.context.getThemeAttrColor( - if (lesson.canceled) R.attr.colorPrimary - else R.attr.colorTimetableChange - )) - } else { - timetableItemDescription.visibility = GONE - timetableItemRoom.visibility = VISIBLE - timetableItemTeacher.visibility = VISIBLE - } - } - } - - private fun bindSmallColors(binding: ItemTimetableSmallBinding, lesson: Timetable) { - with(binding) { - if (lesson.canceled) { - updateNumberAndSubjectCanceledColor(timetableSmallItemNumber, timetableSmallItemSubject) - } else { - updateNumberColor(timetableSmallItemNumber, lesson) - updateSubjectColor(timetableSmallItemSubject, lesson) - updateRoomColor(timetableSmallItemRoom, lesson) - updateTeacherColor(timetableSmallItemTeacher, lesson) - } - } - } - - private fun bindNormalColors(binding: ItemTimetableBinding, lesson: Timetable) { - with(binding) { - if (lesson.canceled) { - updateNumberAndSubjectCanceledColor(timetableItemNumber, timetableItemSubject) - } else { - updateNumberColor(timetableItemNumber, lesson) - updateSubjectColor(timetableItemSubject, lesson) - updateRoomColor(timetableItemRoom, lesson) - updateTeacherColor(timetableItemTeacher, lesson) - } - } - } - - private fun updateNumberAndSubjectCanceledColor(numberView: TextView, subjectView: TextView) { - numberView.setTextColor(numberView.context.getThemeAttrColor(R.attr.colorPrimary)) - subjectView.setTextColor(subjectView.context.getThemeAttrColor(R.attr.colorPrimary)) - } - - private fun updateNumberColor(numberView: TextView, lesson: Timetable) { - numberView.setTextColor(numberView.context.getThemeAttrColor( - if (lesson.changes || lesson.info.isNotBlank()) R.attr.colorTimetableChange - else android.R.attr.textColorPrimary - )) - } - - private fun updateSubjectColor(subjectView: TextView, lesson: Timetable) { - subjectView.setTextColor(subjectView.context.getThemeAttrColor( - if (lesson.subjectOld.isNotBlank() && lesson.subjectOld != lesson.subject) R.attr.colorTimetableChange - else android.R.attr.textColorPrimary - )) - } - - private fun updateRoomColor(roomView: TextView, lesson: Timetable) { - roomView.setTextColor(roomView.context.getThemeAttrColor( - if (lesson.roomOld.isNotBlank() && lesson.roomOld != lesson.room) R.attr.colorTimetableChange - else android.R.attr.textColorSecondary - )) - } - - private fun updateTeacherColor(teacherTextView: TextView, lesson: Timetable) { - teacherTextView.setTextColor(teacherTextView.context.getThemeAttrColor( - if (lesson.teacherOld.isNotBlank() && lesson.teacherOld != lesson.teacher) R.attr.colorTimetableChange - else android.R.attr.textColorSecondary - )) - } - - private class ItemViewHolder(val binding: ItemTimetableBinding) : - RecyclerView.ViewHolder(binding.root) - - private class SmallItemViewHolder(val binding: ItemTimetableSmallBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt deleted file mode 100644 index 8efecf07c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt +++ /dev/null @@ -1,172 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable - -import android.annotation.SuppressLint -import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.databinding.DialogTimetableBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.lifecycleAwareVariable -import io.github.wulkanowy.utils.toFormattedString -import org.threeten.bp.LocalDateTime - -class TimetableDialog : DialogFragment() { - - private var binding: DialogTimetableBinding by lifecycleAwareVariable() - - private lateinit var lesson: Timetable - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(exam: Timetable): TimetableDialog { - return TimetableDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - lesson = getSerializable(ARGUMENT_KEY) as Timetable - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogTimetableBinding.inflate(inflater).apply { binding = this }.root - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(lesson) { - setInfo(info, teacher, canceled, changes) - setSubject(subject, subjectOld) - setTeacher(teacher, teacherOld) - setGroup(group) - setRoom(room, roomOld) - setTime(start, end) - } - - binding.timetableDialogClose.setOnClickListener { dismiss() } - } - - private fun setSubject(subject: String, subjectOld: String) { - with(binding) { - timetableDialogSubject.text = subject - if (subjectOld.isNotBlank() && subjectOld != subject) { - timetableDialogSubject.run { - paintFlags = paintFlags or STRIKE_THRU_TEXT_FLAG - text = subjectOld - } - timetableDialogSubjectNew.run { - visibility = VISIBLE - text = subject - } - } - } - } - - private fun setInfo(info: String, teacher: String, canceled: Boolean, changes: Boolean) { - with(binding) { - when { - info.isNotBlank() -> { - if (canceled) { - timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary)) - timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary)) - } else { - timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange)) - timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange)) - } - - timetableDialogChanges.text = when { - canceled && !changes -> "Lekcja odwołana: $info" - changes && teacher.isNotBlank() -> "Zastępstwo: $teacher" - changes && teacher.isBlank() -> "Zastępstwo, ${info.decapitalize()}" - else -> info.capitalize() - } - } - else -> { - timetableDialogChangesTitle.visibility = GONE - timetableDialogChanges.visibility = GONE - } - } - } - } - - private fun setTeacher(teacher: String, teacherOld: String) { - with(binding) { - when { - teacherOld.isNotBlank() && teacherOld != teacher -> { - timetableDialogTeacher.run { - visibility = VISIBLE - paintFlags = paintFlags or STRIKE_THRU_TEXT_FLAG - text = teacherOld - } - if (teacher.isNotBlank()) { - timetableDialogTeacherNew.run { - visibility = VISIBLE - text = teacher - } - } - } - teacher.isNotBlank() -> timetableDialogTeacher.text = teacher - else -> { - timetableDialogTeacherTitle.visibility = GONE - timetableDialogTeacher.visibility = GONE - } - } - } - } - - private fun setGroup(group: String) { - with(binding) { - when { - group.isNotBlank() -> timetableDialogGroup.text = group - else -> { - timetableDialogGroupTitle.visibility = GONE - timetableDialogGroup.visibility = GONE - } - } - } - } - - private fun setRoom(room: String, roomOld: String) { - with(binding) { - when { - roomOld.isNotBlank() && roomOld != room -> { - timetableDialogRoom.run { - visibility = VISIBLE - paintFlags = paintFlags or STRIKE_THRU_TEXT_FLAG - text = roomOld - } - if (room.isNotBlank()) { - timetableDialogRoomNew.run { - visibility = VISIBLE - text = room - } - } - } - room.isNotBlank() -> timetableDialogRoom.text = room - else -> { - timetableDialogRoomTitle.visibility = GONE - timetableDialogRoom.visibility = GONE - } - } - } - } - - @SuppressLint("SetTextI18n") - private fun setTime(start: LocalDateTime, end: LocalDateTime) { - binding.timetableDialogTime.text = "${start.toFormattedString("HH:mm")} - ${end.toFormattedString("HH:mm")}" - } -} 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 deleted file mode 100644 index 2f01511ad..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableFragment.kt +++ /dev/null @@ -1,189 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable - -import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import com.wdullaer.materialdatetimepicker.date.DatePickerDialog -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Timetable -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.completed.CompletedLessonsFragment -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.SchooldaysRangeLimiter -import io.github.wulkanowy.utils.dpToPx -import org.threeten.bp.LocalDate -import javax.inject.Inject - -class TimetableFragment : BaseFragment(R.layout.fragment_timetable), - TimetableView, MainView.MainChildView, MainView.TitledView { - - @Inject - lateinit var presenter: TimetablePresenter - - @Inject - lateinit var timetableAdapter: TimetableAdapter - - companion object { - private const val SAVED_DATE_KEY = "CURRENT_DATE" - - fun newInstance() = TimetableFragment() - } - - override val titleStringId get() = R.string.timetable_title - - override val isViewEmpty get() = timetableAdapter.items.isEmpty() - - override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setHasOptionsMenu(true) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentTimetableBinding.bind(view) - messageContainer = binding.timetableRecycler - presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) - } - - override fun initView() { - timetableAdapter.onClickListener = presenter::onTimetableItemSelected - - with(binding.timetableRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = timetableAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - timetableSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - timetableErrorRetry.setOnClickListener { presenter.onRetry() } - timetableErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - timetablePreviousButton.setOnClickListener { presenter.onPreviousDay() } - timetableNavDate.setOnClickListener { presenter.onPickDate() } - timetableNextButton.setOnClickListener { presenter.onNextDay() } - - timetableNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.action_menu_timetable, menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == R.id.timetableMenuCompletedLessons) presenter.onCompletedLessonsSwitchSelected() - else false - } - - override fun updateData(data: List, showWholeClassPlanType: String, showTimetableTimers: Boolean) { - with(timetableAdapter) { - items = data.toMutableList() - showTimers = showTimetableTimers - showWholeClassPlan = showWholeClassPlanType - notifyDataSetChanged() - } - } - - override fun clearData() { - with(timetableAdapter) { - items = mutableListOf() - notifyDataSetChanged() - } - } - - override fun updateNavigationDay(date: String) { - binding.timetableNavDate.text = date - } - - override fun hideRefresh() { - binding.timetableSwipe.isRefreshing = false - } - - override fun resetView() { - binding.timetableRecycler.smoothScrollToPosition(0) - } - - override fun onFragmentReselected() { - if (::presenter.isInitialized) presenter.onViewReselected() - } - - override fun popView() { - (activity as? MainActivity)?.popView() - } - - override fun showEmpty(show: Boolean) { - binding.timetableEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.timetableError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.timetableErrorMessage.text = message - } - - override fun showProgress(show: Boolean) { - binding.timetableProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.timetableSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.timetableRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showPreButton(show: Boolean) { - binding.timetablePreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding.timetableNextButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showTimetableDialog(lesson: Timetable) { - (activity as? MainActivity)?.showDialogFragment(TimetableDialog.newInstance(lesson)) - } - - 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@TimetableFragment.parentFragmentManager, null) - } - } - - override fun openCompletedLessonsView() { - (activity as? MainActivity)?.pushView(CompletedLessonsFragment.newInstance()) - } - - 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/TimetablePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt deleted file mode 100644 index e1ce005e3..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetablePresenter.kt +++ /dev/null @@ -1,202 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable - -import android.annotation.SuppressLint -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -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 org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.LocalDate.of -import org.threeten.bp.LocalDate.ofEpochDay -import timber.log.Timber -import javax.inject.Inject - -class TimetablePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val timetableRepository: TimetableRepository, - private val semesterRepository: SemesterRepository, - private val prefRepository: PreferencesRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var baseDate: LocalDate = now().nextOrSameSchoolDay - - lateinit var currentDate: LocalDate - private set - - private lateinit var lastError: Throwable - - fun onAttachView(view: TimetableView, date: Long?) { - super.onAttachView(view) - view.initView() - Timber.i("Timetable was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData(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(of(year, month, day)) - reloadView() - } - - fun onSwipeRefresh() { - Timber.i("Force refreshing the timetable") - loadData(currentDate, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentDate, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onViewReselected() { - Timber.i("Timetable view is reselected") - view?.also { view -> - if (view.currentStackSize == 1) { - baseDate.also { - if (currentDate != it) { - loadData(it) - reloadView() - } else if (!view.isViewEmpty) view.resetView() - } - } else view.popView() - } - } - - fun onTimetableItemSelected(lesson: Timetable) { - Timber.i("Select timetable item ${lesson.id}") - view?.showTimetableDialog(lesson) - } - - fun onCompletedLessonsSwitchSelected(): Boolean { - view?.openCompletedLessonsView() - return true - } - - private fun setBaseDateOnHolidays() { - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) - currentDate = baseDate - reloadNavigation() - }) { - Timber.i("Loading semester result: An exception occurred") - }) - } - - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - Timber.i("Loading timetable data started") - currentDate = date - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - timetableRepository.getTimetable(student, semester, currentDate, currentDate, forceRefresh) - } - } - .map { items -> items.filter { if (prefRepository.showWholeClassPlan == "no") it.isStudentPlan else true } } - .map { items -> items.sortedWith(compareBy({ it.number }, { !it.isStudentPlan })) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading timetable result: Success") - view?.apply { - updateData(it, prefRepository.showWholeClassPlan, prefRepository.showTimetableTimers) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - } - analytics.logEvent( - "load_data", - "type" to "timetable", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading timetable result: An exception occurred") - errorHandler.dispatch(it) - }) - } - } - - 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 timetable 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/TimetableView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt deleted file mode 100644 index 1efa320fc..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableView.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable - -import io.github.wulkanowy.data.db.entities.Timetable -import io.github.wulkanowy.ui.base.BaseView -import org.threeten.bp.LocalDate - -interface TimetableView : BaseView { - - val isViewEmpty: Boolean - - val currentStackSize: Int? - - fun initView() - - fun updateData(data: List, showWholeClassPlanType: String, showTimetableTimers: Boolean) - - fun updateNavigationDay(date: String) - - fun clearData() - - fun hideRefresh() - - fun resetView() - - 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 showTimetableDialog(lesson: Timetable) - - fun showDatePickerDialog(currentDate: LocalDate) - - fun popView() - - fun openCompletedLessonsView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt deleted file mode 100644 index 56ea16cfa..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt +++ /dev/null @@ -1,83 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.databinding.DialogLessonCompletedBinding -import io.github.wulkanowy.utils.lifecycleAwareVariable - -class CompletedLessonDialog : DialogFragment() { - - private var binding: DialogLessonCompletedBinding by lifecycleAwareVariable() - - private lateinit var completedLesson: CompletedLesson - - companion object { - private const val ARGUMENT_KEY = "Item" - - fun newInstance(exam: CompletedLesson): CompletedLessonDialog { - return CompletedLessonDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, 0) - arguments?.run { - completedLesson = getSerializable(ARGUMENT_KEY) as CompletedLesson - } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return DialogLessonCompletedBinding.inflate(inflater).apply { binding = this }.root - } - - @SuppressLint("SetTextI18n") - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - with(binding) { - completedLessonDialogSubject.text = completedLesson.subject - completedLessonDialogTopic.text = completedLesson.topic - completedLessonDialogTeacher.text = completedLesson.teacher - completedLessonDialogAbsence.text = completedLesson.absence - completedLessonDialogChanges.text = completedLesson.substitution - completedLessonDialogResources.text = completedLesson.resources - } - - completedLesson.substitution.let { - if (it.isBlank()) { - with(binding) { - completedLessonDialogChangesTitle.visibility = View.GONE - completedLessonDialogChanges.visibility = View.GONE - } - } else binding.completedLessonDialogChanges.text = it - } - - completedLesson.absence.let { - if (it.isBlank()) { - with(binding) { - completedLessonDialogAbsenceTitle.visibility = View.GONE - completedLessonDialogAbsence.visibility = View.GONE - } - } else binding.completedLessonDialogAbsence.text = it - } - - completedLesson.resources.let { - if (it.isBlank()) { - with(binding) { - completedLessonDialogResourcesTitle.visibility = View.GONE - completedLessonDialogResources.visibility = View.GONE - } - } else binding.completedLessonDialogResources.text = it - } - - binding.completedLessonDialogClose.setOnClickListener { dismiss() } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsAdapter.kt deleted file mode 100644 index 3399a8a23..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsAdapter.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.databinding.ItemCompletedLessonBinding -import io.github.wulkanowy.utils.getThemeAttrColor -import javax.inject.Inject - -class CompletedLessonsAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = emptyList() - - var onClickListener: (CompletedLesson) -> Unit = {} - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemCompletedLessonBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - completedLessonItemNumber.text = item.number.toString() - completedLessonItemNumber.setTextColor(root.context.getThemeAttrColor( - if (item.substitution.isNotEmpty()) R.attr.colorTimetableChange - else android.R.attr.textColorPrimary - )) - completedLessonItemSubject.text = item.subject - completedLessonItemTopic.text = item.topic - completedLessonItemAlert.visibility = if (item.substitution.isNotEmpty()) View.VISIBLE else View.GONE - - root.setOnClickListener { onClickListener(item) } - } - } - - class ItemViewHolder(val binding: ItemCompletedLessonBinding) : - RecyclerView.ViewHolder(binding.root) -} 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 deleted file mode 100644 index c1389cedd..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsErrorHandler.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import android.content.res.Resources -import com.chuckerteam.chucker.api.ChuckerCollector -import io.github.wulkanowy.sdk.exception.FeatureDisabledException -import io.github.wulkanowy.ui.base.ErrorHandler -import javax.inject.Inject - -class CompletedLessonsErrorHandler @Inject constructor( - resources: Resources, - chuckerCollector: ChuckerCollector -) : ErrorHandler(resources, chuckerCollector) { - - var onFeatureDisabled: () -> Unit = {} - - override fun proceed(error: Throwable) { - when (error) { - is FeatureDisabledException -> onFeatureDisabled() - else -> super.proceed(error) - } - } - - override fun clear() { - super.clear() - onFeatureDisabled = {} - } -} 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 deleted file mode 100644 index 2efd30a34..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsFragment.kt +++ /dev/null @@ -1,161 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import android.os.Bundle -import android.view.View -import android.view.View.GONE -import android.view.View.INVISIBLE -import android.view.View.VISIBLE -import androidx.recyclerview.widget.LinearLayoutManager -import com.wdullaer.materialdatetimepicker.date.DatePickerDialog -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.databinding.FragmentTimetableCompletedBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.SchooldaysRangeLimiter -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.getCompatDrawable -import org.threeten.bp.LocalDate -import javax.inject.Inject - -class CompletedLessonsFragment : - BaseFragment(R.layout.fragment_timetable_completed), - CompletedLessonsView, MainView.TitledView { - - @Inject - lateinit var presenter: CompletedLessonsPresenter - - @Inject - lateinit var completedLessonsAdapter: CompletedLessonsAdapter - - companion object { - private const val SAVED_DATE_KEY = "CURRENT_DATE" - - fun newInstance() = CompletedLessonsFragment() - } - - override val titleStringId get() = R.string.completed_lessons_title - - override val isViewEmpty get() = completedLessonsAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentTimetableCompletedBinding.bind(view) - messageContainer = binding.completedLessonsRecycler - presenter.onAttachView(this, savedInstanceState?.getLong(SAVED_DATE_KEY)) - } - - override fun initView() { - completedLessonsAdapter.onClickListener = presenter::onCompletedLessonsItemSelected - - with(binding.completedLessonsRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = completedLessonsAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - completedLessonsSwipe.setOnRefreshListener(presenter::onSwipeRefresh) - completedLessonErrorRetry.setOnClickListener { presenter.onRetry() } - completedLessonErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - completedLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() } - completedLessonsNavDate.setOnClickListener { presenter.onPickDate() } - completedLessonsNextButton.setOnClickListener { presenter.onNextDay() } - - completedLessonsNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun updateData(data: List) { - with(completedLessonsAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun clearData() { - with(completedLessonsAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun updateNavigationDay(date: String) { - binding.completedLessonsNavDate.text = date - } - - override fun hideRefresh() { - binding.completedLessonsSwipe.isRefreshing = false - } - - override fun showEmpty(show: Boolean) { - binding.completedLessonsEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.completedLessonError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.completedLessonErrorMessage.text = message - } - - override fun showFeatureDisabled() { - with(binding) { - completedLessonsInfo.text = getString(R.string.error_feature_disabled) - completedLessonsInfoImage.setImageDrawable(requireContext().getCompatDrawable(R.drawable.ic_all_close_circle)) - } - } - - override fun showProgress(show: Boolean) { - binding.completedLessonsProgress.visibility = if (show) VISIBLE else GONE - } - - override fun enableSwipe(enable: Boolean) { - binding.completedLessonsSwipe.isEnabled = enable - } - - override fun showContent(show: Boolean) { - binding.completedLessonsRecycler.visibility = if (show) VISIBLE else GONE - } - - override fun showPreButton(show: Boolean) { - binding.completedLessonsPreviousButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding.completedLessonsNextButton.visibility = if (show) VISIBLE else INVISIBLE - } - - override fun showCompletedLessonDialog(completedLesson: CompletedLesson) { - (activity as? MainActivity)?.showDialogFragment(CompletedLessonDialog.newInstance(completedLesson)) - } - - 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@CompletedLessonsFragment.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/completed/CompletedLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt deleted file mode 100644 index f72d753a9..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsPresenter.kt +++ /dev/null @@ -1,183 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import android.annotation.SuppressLint -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.ui.base.BasePresenter -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -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 org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import org.threeten.bp.LocalDate.ofEpochDay -import timber.log.Timber -import javax.inject.Inject - -class CompletedLessonsPresenter @Inject constructor( - schedulers: SchedulersProvider, - studentRepository: StudentRepository, - private val completedLessonsErrorHandler: CompletedLessonsErrorHandler, - private val semesterRepository: SemesterRepository, - private val completedLessonsRepository: CompletedLessonsRepository, - private val analytics: FirebaseAnalyticsHelper -) : BasePresenter(completedLessonsErrorHandler, studentRepository, schedulers) { - - private var baseDate: LocalDate = now().nextOrSameSchoolDay - - lateinit var currentDate: LocalDate - private set - - private lateinit var lastError: Throwable - - fun onAttachView(view: CompletedLessonsView, date: Long?) { - super.onAttachView(view) - Timber.i("Completed lessons is attached") - view.initView() - completedLessonsErrorHandler.showErrorMessage = ::showErrorViewOnError - completedLessonsErrorHandler.onFeatureDisabled = { - this.view?.showFeatureDisabled() - this.view?.showEmpty(true) - Timber.i("Completed lessons feature disabled by school") - } - loadData(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 completed lessons") - loadData(currentDate, true) - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData(currentDate, true) - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - fun onCompletedLessonsItemSelected(completedLesson: CompletedLesson) { - Timber.i("Select completed lessons item ${completedLesson.id}") - view?.showCompletedLessonDialog(completedLesson) - } - - private fun setBaseDateOnHolidays() { - disposable.add(studentRepository.getCurrentStudent() - .flatMap { semesterRepository.getCurrentSemester(it) } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear) - currentDate = baseDate - reloadNavigation() - }) { - Timber.i("Loading semester result: An exception occurred") - }) - } - - private fun loadData(date: LocalDate, forceRefresh: Boolean = false) { - Timber.i("Loading completed lessons data started") - currentDate = date - disposable.apply { - clear() - add(studentRepository.getCurrentStudent() - .flatMap { student -> - semesterRepository.getCurrentSemester(student).flatMap { semester -> - completedLessonsRepository.getCompletedLessons(student, semester, currentDate, currentDate, forceRefresh) - } - } - .map { items -> items.sortedBy { it.number } } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .doFinally { - view?.run { - hideRefresh() - showProgress(false) - enableSwipe(true) - } - } - .subscribe({ - Timber.i("Loading completed lessons lessons result: Success") - view?.apply { - updateData(it) - showEmpty(it.isEmpty()) - showErrorView(false) - showContent(it.isNotEmpty()) - } - analytics.logEvent( - "load_data", - "type" to "completed_lessons", - "items" to it.size, - "force_refresh" to forceRefresh - ) - }) { - Timber.i("Loading completed lessons result: An exception occurred") - completedLessonsErrorHandler.dispatch(it) - }) - } - } - - 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 completed 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/completed/CompletedLessonsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt deleted file mode 100644 index 170e19694..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonsView.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetable.completed - -import io.github.wulkanowy.data.db.entities.CompletedLesson -import io.github.wulkanowy.ui.base.BaseView -import org.threeten.bp.LocalDate - -interface CompletedLessonsView : 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 showFeatureDisabled() - - fun showProgress(show: Boolean) - - fun enableSwipe(enable: Boolean) - - fun showContent(show: Boolean) - - fun showPreButton(show: Boolean) - - fun showNextButton(show: Boolean) - - fun showCompletedLessonDialog(completedLesson: CompletedLesson) - - fun showDatePickerDialog(currentDate: LocalDate) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt deleted file mode 100644 index 3dc7a3a8c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt +++ /dev/null @@ -1,108 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS -import android.content.Intent -import android.os.Build -import android.os.Bundle -import android.widget.Toast -import android.widget.Toast.LENGTH_LONG -import androidx.appcompat.app.AlertDialog -import androidx.recyclerview.widget.LinearLayoutManager -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding -import io.github.wulkanowy.ui.base.BaseActivity -import io.github.wulkanowy.ui.base.WidgetConfigureAdapter -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.EXTRA_FROM_PROVIDER -import io.github.wulkanowy.utils.AppInfo -import javax.inject.Inject - -class TimetableWidgetConfigureActivity : - BaseActivity(), - TimetableWidgetConfigureView { - - @Inject - lateinit var configureAdapter: WidgetConfigureAdapter - - @Inject - override lateinit var presenter: TimetableWidgetConfigurePresenter - - @Inject - lateinit var appInfo: AppInfo - - private var dialog: AlertDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setResult(RESULT_CANCELED) - setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) - - intent.extras.let { - presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID), it?.getBoolean(EXTRA_FROM_PROVIDER)) - } - } - - override fun initView() { - with(binding.widgetConfigureRecycler) { - adapter = configureAdapter - layoutManager = LinearLayoutManager(context) - } - - configureAdapter.onClickListener = presenter::onItemSelect - } - - override fun showThemeDialog() { - var items = arrayOf( - getString(R.string.widget_timetable_theme_light), - getString(R.string.widget_timetable_theme_dark) - ) - if (appInfo.systemVersion >= Build.VERSION_CODES.Q) items += getString(R.string.widget_timetable_theme_system) - - dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher) - .setTitle(R.string.widget_timetable_theme_title) - .setOnDismissListener { presenter.onDismissThemeView() } - .setSingleChoiceItems(items, -1) { _, which -> - presenter.onThemeSelect(which) - } - .show() - } - - override fun updateData(data: List>) { - with(configureAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun updateTimetableWidget(widgetId: Int) { - sendBroadcast(Intent(this, TimetableWidgetProvider::class.java) - .apply { - action = ACTION_APPWIDGET_UPDATE - putExtra(EXTRA_APPWIDGET_IDS, intArrayOf(widgetId)) - }) - } - - override fun setSuccessResult(widgetId: Int) { - setResult(RESULT_OK, Intent().apply { putExtra(EXTRA_APPWIDGET_ID, widgetId) }) - } - - override fun showError(text: String, error: Throwable) { - Toast.makeText(this, text, LENGTH_LONG).show() - } - - override fun finishView() { - finish() - } - - override fun openLoginView() { - startActivity(LoginActivity.getStartIntent(this)) - } - - override fun onDestroy() { - super.onDestroy() - dialog?.dismiss() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt deleted file mode 100644 index 57dde824c..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt +++ /dev/null @@ -1,84 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -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.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey -import io.github.wulkanowy.utils.SchedulersProvider -import javax.inject.Inject - -class TimetableWidgetConfigurePresenter @Inject constructor( - schedulers: SchedulersProvider, - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val sharedPref: SharedPrefProvider -) : BasePresenter(errorHandler, studentRepository, schedulers) { - - private var appWidgetId: Int? = null - - private var isFromProvider = false - - private var selectedStudent: Student? = null - - fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) { - super.onAttachView(view) - this.appWidgetId = appWidgetId - this.isFromProvider = isFromProvider ?: false - view.initView() - loadData() - } - - fun onItemSelect(student: Student) { - selectedStudent = student - - if (isFromProvider) registerStudent(selectedStudent) - else view?.showThemeDialog() - } - - fun onThemeSelect(index: Int) { - appWidgetId?.let { - sharedPref.putLong(getThemeWidgetKey(it), index.toLong()) - } - registerStudent(selectedStudent) - } - - fun onDismissThemeView() { - view?.finishView() - } - - private fun loadData() { - disposable.add(studentRepository.getSavedStudents(false) - .map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } } - .map { (students, currentStudentId) -> - students.map { student -> student to (student.id == currentStudentId) } - } - .subscribeOn(schedulers.backgroundThread) - .observeOn(schedulers.mainThread) - .subscribe({ - when { - it.isEmpty() -> view?.openLoginView() - it.size == 1 && !isFromProvider -> { - selectedStudent = it.single().first - view?.showThemeDialog() - } - else -> view?.updateData(it) - } - }, { errorHandler.dispatch(it) })) - } - - private fun registerStudent(student: Student?) { - requireNotNull(student) - - appWidgetId?.let { id -> - sharedPref.putLong(getStudentWidgetKey(id), student.id) - view?.run { - updateTimetableWidget(id) - setSuccessResult(id) - } - } - view?.finishView() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt deleted file mode 100644 index 056225ab5..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.ui.base.BaseView - -interface TimetableWidgetConfigureView : BaseView { - - fun initView() - - fun updateData(data: List>) - - fun updateTimetableWidget(widgetId: Int) - - fun showThemeDialog() - - fun setSuccessResult(widgetId: Int) - - fun finishView() - - fun openLoginView() -} 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 deleted file mode 100644 index dd223ad8b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetFactory.kt +++ /dev/null @@ -1,226 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -import android.annotation.SuppressLint -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID -import android.content.Context -import android.content.Intent -import android.graphics.Paint.ANTI_ALIAS_FLAG -import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.AdapterView.INVALID_POSITION -import android.widget.RemoteViews -import android.widget.RemoteViewsService -import io.github.wulkanowy.R -import io.github.wulkanowy.data.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.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getCurrentThemeWidgetKey -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey -import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.getCompatColor -import io.github.wulkanowy.utils.toFormattedString -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import timber.log.Timber - -class TimetableWidgetFactory( - private val timetableRepository: TimetableRepository, - private val studentRepository: StudentRepository, - private val semesterRepository: SemesterRepository, - private val prefRepository: PreferencesRepository, - private val sharedPref: SharedPrefProvider, - private val schedulers: SchedulersProvider, - private val context: Context, - private val intent: Intent? -) : RemoteViewsService.RemoteViewsFactory { - - private var lessons = emptyList() - - private var savedCurrentTheme: Long? = null - - private var primaryColor: Int? = null - - private var textColor: Int? = null - - private var timetableChangeColor: Int? = null - - override fun getLoadingView() = null - - override fun hasStableIds() = true - - override fun getCount() = lessons.size - - override fun getViewTypeCount() = 2 - - override fun getItemId(position: Int) = position.toLong() - - override fun onCreate() {} - - override fun onDestroy() {} - - override fun onDataSetChanged() { - intent?.extras?.getInt(EXTRA_APPWIDGET_ID)?.let { appWidgetId -> - val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0)) - val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0) - - updateTheme(appWidgetId) - updateLessons(date, studentId) - } - } - - private fun updateTheme(appWidgetId: Int) { - savedCurrentTheme = sharedPref.getLong(getCurrentThemeWidgetKey(appWidgetId), 0) - - if (savedCurrentTheme == 0L) { - primaryColor = R.color.colorPrimary - textColor = android.R.color.black - timetableChangeColor = R.color.timetable_change_dark - } else { - primaryColor = R.color.colorPrimaryLight - textColor = android.R.color.white - timetableChangeColor = R.color.timetable_change_light - } - } - - private fun getItemLayout(lesson: Timetable): Int { - return when { - prefRepository.showWholeClassPlan == "small" && !lesson.isStudentPlan -> { - if (savedCurrentTheme == 0L) R.layout.item_widget_timetable_small - else R.layout.item_widget_timetable_small_dark - } - savedCurrentTheme == 1L -> R.layout.item_widget_timetable_dark - else -> R.layout.item_widget_timetable - } - } - - private fun updateLessons(date: LocalDate, studentId: Long) { - lessons = try { - studentRepository.isStudentSaved() - .filter { true } - .flatMap { studentRepository.getSavedStudents().toMaybe() } - .flatMap { - val student = it.singleOrNull { student -> student.id == studentId } - - if (student != null) Maybe.just(student) - else Maybe.empty() - } - .flatMap { student -> - semesterRepository.getCurrentSemester(student).toMaybe().flatMap { semester -> - timetableRepository.getTimetable(student, semester, date, date).toMaybe() - } - } - .map { items -> items.sortedWith(compareBy({ it.number }, { !it.isStudentPlan })) } - .map { lessons -> lessons.filter { if (prefRepository.showWholeClassPlan == "no") it.isStudentPlan else true } } - .subscribeOn(schedulers.backgroundThread) - .blockingGet(emptyList()) - } catch (e: Exception) { - Timber.e(e, "An error has occurred in timetable widget factory") - emptyList() - } - } - - @SuppressLint("DefaultLocale") - override fun getViewAt(position: Int): RemoteViews? { - if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null - - val lesson = lessons[position] - return RemoteViews(context.packageName, getItemLayout(lesson)).apply { - setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject) - setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString()) - setTextViewText(R.id.timetableWidgetItemTimeStart, lesson.start.toFormattedString("HH:mm")) - setTextViewText(R.id.timetableWidgetItemTimeFinish, lesson.end.toFormattedString("HH:mm")) - - updateDescription(this, lesson) - - if (lesson.canceled) { - updateStylesCanceled(this) - } else { - updateStylesNotCanceled(this, lesson) - } - - setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent()) - } - } - - private fun updateDescription(remoteViews: RemoteViews, lesson: Timetable) { - with(remoteViews) { - if (lesson.info.isNotBlank() && !lesson.changes) { - setTextViewText(R.id.timetableWidgetItemDescription, lesson.info) - setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE) - setViewVisibility(R.id.timetableWidgetItemRoom, GONE) - setViewVisibility(R.id.timetableWidgetItemTeacher, GONE) - } else { - setViewVisibility(R.id.timetableWidgetItemDescription, GONE) - setViewVisibility(R.id.timetableWidgetItemRoom, VISIBLE) - setViewVisibility(R.id.timetableWidgetItemTeacher, VISIBLE) - } - } - } - - private fun updateStylesCanceled(remoteViews: RemoteViews) { - with(remoteViews) { - setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", - STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG) - setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(primaryColor!!)) - setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(primaryColor!!)) - setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(primaryColor!!)) - } - } - - private fun updateStylesNotCanceled(remoteViews: RemoteViews, lesson: Timetable) { - with(remoteViews) { - setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG) - setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(textColor!!)) - setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(timetableChangeColor!!)) - - updateNotCanceledLessonNumberColor(this, lesson) - updateNotCanceledSubjectColor(this, lesson) - - val teacherChange = lesson.teacherOld.isNotBlank() && lesson.teacher != lesson.teacherOld - updateNotCanceledRoom(this, lesson, teacherChange) - updateNotCanceledTeacher(this, lesson, teacherChange) - } - } - - private fun updateNotCanceledLessonNumberColor(remoteViews: RemoteViews, lesson: Timetable) { - remoteViews.setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor( - if (lesson.changes || (lesson.info.isNotBlank() && !lesson.canceled)) timetableChangeColor!! - else textColor!! - )) - } - - private fun updateNotCanceledSubjectColor(remoteViews: RemoteViews, lesson: Timetable) { - remoteViews.setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor( - if (lesson.subjectOld.isNotBlank() && lesson.subject != lesson.subjectOld) timetableChangeColor!! - else textColor!! - )) - } - - private fun updateNotCanceledRoom(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) { - with(remoteViews) { - if (lesson.room.isNotBlank()) { - setTextViewText(R.id.timetableWidgetItemRoom, - if (teacherChange) lesson.room - else "${context.getString(R.string.timetable_room)} ${lesson.room}" - ) - - setTextColor(R.id.timetableWidgetItemRoom, context.getCompatColor( - if (lesson.roomOld.isNotBlank() && lesson.room != lesson.roomOld) timetableChangeColor!! - else textColor!! - )) - } else setTextViewText(R.id.timetableWidgetItemRoom, "") - } - } - - private fun updateNotCanceledTeacher(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) { - remoteViews.setTextViewText(R.id.timetableWidgetItemTeacher, - if (teacherChange) lesson.teacher - else "" - ) - } -} 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 deleted file mode 100644 index 79888f83d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt +++ /dev/null @@ -1,212 +0,0 @@ -package io.github.wulkanowy.ui.modules.timetablewidget - -import android.annotation.SuppressLint -import android.app.PendingIntent -import android.app.PendingIntent.FLAG_UPDATE_CURRENT -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED -import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID -import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK -import android.content.res.Configuration -import android.widget.RemoteViews -import dagger.android.AndroidInjection -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.services.widgets.TimetableWidgetService -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.utils.FirebaseAnalyticsHelper -import io.github.wulkanowy.utils.SchedulersProvider -import io.github.wulkanowy.utils.nextOrSameSchoolDay -import io.github.wulkanowy.utils.nextSchoolDay -import io.github.wulkanowy.utils.previousSchoolDay -import io.github.wulkanowy.utils.toFormattedString -import io.reactivex.Maybe -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDate.now -import timber.log.Timber -import javax.inject.Inject - -class TimetableWidgetProvider : BroadcastReceiver() { - - @Inject - lateinit var appWidgetManager: AppWidgetManager - - @Inject - lateinit var studentRepository: StudentRepository - - @Inject - lateinit var sharedPref: SharedPrefProvider - - @Inject - lateinit var schedulers: SchedulersProvider - - @Inject - lateinit var analytics: FirebaseAnalyticsHelper - - companion object { - - private const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget" - - private const val EXTRA_BUTTON_TYPE = "extraButtonType" - - private const val BUTTON_NEXT = "buttonNext" - - private const val BUTTON_PREV = "buttonPrev" - - private const val BUTTON_RESET = "buttonReset" - - const val EXTRA_FROM_PROVIDER = "extraFromProvider" - - fun getDateWidgetKey(appWidgetId: Int) = "timetable_widget_date_$appWidgetId" - - fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId" - - fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId" - - fun getCurrentThemeWidgetKey(appWidgetId: Int) = "timetable_widget_current_theme_$appWidgetId" - } - - override fun onReceive(context: Context, intent: Intent) { - AndroidInjection.inject(this, context) - when (intent.action) { - ACTION_APPWIDGET_UPDATE -> onUpdate(context, intent) - ACTION_APPWIDGET_DELETED -> onDelete(intent) - } - } - - private fun onUpdate(context: Context, intent: Intent) { - if (intent.getStringExtra(EXTRA_BUTTON_TYPE) === null) { - intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId -> - val student = getStudent(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId) - updateWidget(context, appWidgetId, now().nextOrSameSchoolDay, student) - } - } else { - val buttonType = intent.getStringExtra(EXTRA_BUTTON_TYPE) - val toggledWidgetId = intent.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0) - val student = getStudent(sharedPref.getLong(getStudentWidgetKey(toggledWidgetId), 0), toggledWidgetId) - val savedDate = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(toggledWidgetId), 0)) - val date = when (buttonType) { - BUTTON_RESET -> now().nextOrSameSchoolDay - BUTTON_NEXT -> savedDate.nextSchoolDay - BUTTON_PREV -> savedDate.previousSchoolDay - else -> now().nextOrSameSchoolDay - } - if (!buttonType.isNullOrBlank()) analytics.logEvent("changed_timetable_widget_day", "button" to buttonType) - updateWidget(context, toggledWidgetId, date, student) - } - } - - private fun onDelete(intent: Intent) { - val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0) - - if (appWidgetId != 0) { - with(sharedPref) { - delete(getStudentWidgetKey(appWidgetId)) - delete(getDateWidgetKey(appWidgetId)) - delete(getThemeWidgetKey(appWidgetId)) - delete(getCurrentThemeWidgetKey(appWidgetId)) - } - } - } - - @SuppressLint("DefaultLocale") - private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) { - val savedConfigureTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0) - val isSystemDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES - var currentTheme = 0L - var layoutId = R.layout.widget_timetable - - if (savedConfigureTheme == 1L || (savedConfigureTheme == 2L && isSystemDarkMode)) { - currentTheme = 1L - layoutId = R.layout.widget_timetable_dark - } - - val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT) - val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV) - val resetNavIntent = createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET) - val adapterIntent = Intent(context, TimetableWidgetService::class.java) - .apply { - putExtra(EXTRA_APPWIDGET_ID, appWidgetId) - //make Intent unique - action = appWidgetId.toString() - } - val accountIntent = PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId, - Intent(context, TimetableWidgetConfigureActivity::class.java).apply { - addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK) - putExtra(EXTRA_APPWIDGET_ID, appWidgetId) - putExtra(EXTRA_FROM_PROVIDER, true) - }, FLAG_UPDATE_CURRENT) - val appIntent = PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id, - MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT) - - val remoteView = RemoteViews(context.packageName, layoutId).apply { - setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) - setTextViewText(R.id.timetableWidgetDate, date.toFormattedString("EEEE, dd.MM").capitalize()) - setTextViewText(R.id.timetableWidgetName, student?.studentName ?: context.getString(R.string.all_no_data)) - setRemoteAdapter(R.id.timetableWidgetList, adapterIntent) - setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent) - setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent) - setOnClickPendingIntent(R.id.timetableWidgetDate, resetNavIntent) - setOnClickPendingIntent(R.id.timetableWidgetName, resetNavIntent) - setOnClickPendingIntent(R.id.timetableWidgetAccount, accountIntent) - setPendingIntentTemplate(R.id.timetableWidgetList, appIntent) - } - - with(sharedPref) { - putLong(getCurrentThemeWidgetKey(appWidgetId), currentTheme) - putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true) - } - - with(appWidgetManager) { - notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList) - updateAppWidget(appWidgetId, remoteView) - } - } - - private fun createNavIntent(context: Context, code: Int, appWidgetId: Int, buttonType: String): PendingIntent { - return PendingIntent.getBroadcast(context, code, - Intent(context, TimetableWidgetProvider::class.java).apply { - action = ACTION_APPWIDGET_UPDATE - putExtra(EXTRA_BUTTON_TYPE, buttonType) - putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId) - }, FLAG_UPDATE_CURRENT) - } - - private fun getStudent(studentId: Long, appWidgetId: Int): Student? { - return try { - studentRepository.isStudentSaved() - .filter { true } - .flatMap { studentRepository.getSavedStudents(false).toMaybe() } - .flatMap { students -> - val student = students.singleOrNull { student -> student.id == studentId } - when { - student != null -> Maybe.just(student) - studentId != 0L -> { - studentRepository.isCurrentStudentSet() - .filter { true } - .flatMap { studentRepository.getCurrentStudent(false).toMaybe() } - .doOnSuccess { sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id) } - } - else -> Maybe.empty() - } - } - .subscribeOn(schedulers.backgroundThread) - .blockingGet() - } catch (e: Exception) { - if (e.cause !is NoCurrentStudentException) { - Timber.e(e, "An error has occurred in timetable widget provider") - } - null - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.java b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.java new file mode 100644 index 000000000..c9f98d5ee --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashActivity.java @@ -0,0 +1,50 @@ +package io.github.wulkanowy.ui.splash; + +import android.os.Bundle; + +import javax.inject.Inject; + +import butterknife.ButterKnife; +import io.github.wulkanowy.services.SyncJob; +import io.github.wulkanowy.ui.base.BaseActivity; +import io.github.wulkanowy.ui.login.LoginActivity; +import io.github.wulkanowy.ui.main.MainActivity; + +public class SplashActivity extends BaseActivity implements SplashContract.View { + + @Inject + SplashContract.Presenter presenter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getActivityComponent().inject(this); + setButterKnife(ButterKnife.bind(this)); + + presenter.onStart(this); + } + + @Override + protected void onDestroy() { + presenter.onDestroy(); + super.onDestroy(); + } + + @Override + public void openLoginActivity() { + startActivity(LoginActivity.getStartIntent(this)); + finish(); + } + + @Override + public void openMainActivity() { + startActivity(MainActivity.getStartIntent(this)); + finish(); + } + + @Override + public void startSyncService() { + SyncJob.start(getApplicationContext()); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/splash/SplashContract.java b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashContract.java new file mode 100644 index 000000000..a69deb032 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashContract.java @@ -0,0 +1,21 @@ +package io.github.wulkanowy.ui.splash; + + +import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BaseContract; + +public interface SplashContract { + + interface View extends BaseContract.View { + + void openLoginActivity(); + + void openMainActivity(); + + void startSyncService(); + } + + @PerActivity + interface Presenter extends BaseContract.Presenter { + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/splash/SplashPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashPresenter.java new file mode 100644 index 000000000..c3d81215c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/splash/SplashPresenter.java @@ -0,0 +1,29 @@ +package io.github.wulkanowy.ui.splash; + +import android.support.annotation.NonNull; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; + +public class SplashPresenter extends BasePresenter + implements SplashContract.Presenter { + + @Inject + SplashPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(@NonNull SplashContract.View activity) { + super.onStart(activity); + getView().startSyncService(); + + if (getRepository().getCurrentUserId() == 0) { + getView().openLoginActivity(); + } else { + getView().openMainActivity(); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/DividerItemDecoration.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/DividerItemDecoration.kt deleted file mode 100644 index b0b6999eb..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/DividerItemDecoration.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.wulkanowy.ui.widgets - -import android.content.Context -import android.graphics.Canvas -import android.view.View -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.RecyclerView - -class DividerItemDecoration(context: Context) : DividerItemDecoration(context, VERTICAL) { - - override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { - canvas.save() - val dividerLeft = parent.paddingLeft - val dividerRight = parent.width - parent.paddingRight - val childCount = parent.childCount - - for (i in 0..childCount - 2) { - val child: View = parent.getChildAt(i) - val params = child.layoutParams as RecyclerView.LayoutParams - val dividerTop: Int = child.bottom + params.bottomMargin - val dividerBottom = dividerTop + drawable!!.intrinsicHeight - drawable?.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom) - drawable?.draw(canvas) - } - canvas.restore() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/FittedScrollableTabLayout.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/FittedScrollableTabLayout.kt deleted file mode 100644 index 0f121dc5b..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/FittedScrollableTabLayout.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.wulkanowy.ui.widgets - -import android.content.Context -import android.util.AttributeSet -import android.view.ViewGroup - -/** - * @see Tabs don't fit to screen with tabmode=scrollable, Even with a Custom Tab Layout - */ -class FittedScrollableTabLayout : MaterialTabLayout { - - constructor(context: Context) : super(context) - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - setMeasuredDimension(widthMeasureSpec, heightMeasureSpec) - val tabLayout = getChildAt(0) as ViewGroup - val childCount = tabLayout.childCount - - if (childCount == 0) return - - val tabMinWidth = context.resources.displayMetrics.widthPixels / childCount - - for (i in 0 until childCount) { - tabLayout.getChildAt(i).minimumWidth = tabMinWidth - } - - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt deleted file mode 100644 index a04922e5d..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialLinearLayout.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.wulkanowy.ui.widgets - -import android.content.Context -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.LOLLIPOP -import android.util.AttributeSet -import android.widget.LinearLayout -import androidx.core.view.ViewCompat -import com.google.android.material.elevation.ElevationOverlayProvider -import com.google.android.material.shape.MaterialShapeDrawable - -class MaterialLinearLayout : LinearLayout { - - constructor(context: Context) : super(context) - - constructor(context: Context, attr: AttributeSet) : super(context, attr) - - constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr) - - init { - val drawable = MaterialShapeDrawable.createWithElevationOverlay(context, ViewCompat.getElevation(this)) - ViewCompat.setBackground(this, drawable) - } - - override fun setElevation(elevation: Float) { - super.setElevation(elevation) - if (background is MaterialShapeDrawable) { - (background as MaterialShapeDrawable).elevation = elevation - } - } - - fun setElevationCompat(elevation: Float) { - if (SDK_INT >= LOLLIPOP) { - setElevation(elevation) - } else { - setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation)) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt deleted file mode 100644 index e19d01116..000000000 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/MaterialTabLayout.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.ui.widgets - -import android.content.Context -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.LOLLIPOP -import android.util.AttributeSet -import com.google.android.material.elevation.ElevationOverlayProvider -import com.google.android.material.tabs.TabLayout - -open class MaterialTabLayout : TabLayout { - - constructor(context: Context) : super(context) - - constructor(context: Context, attr: AttributeSet) : super(context, attr) - - constructor(context: Context, attr: AttributeSet, defStyleAttr: Int) : super(context, attr, defStyleAttr) - - fun setElevationCompat(elevation: Float) { - if (SDK_INT >= LOLLIPOP) { - setElevation(elevation) - } else { - setBackgroundColor(ElevationOverlayProvider(context).compositeOverlayWithThemeSurfaceColorIfNeeded(elevation)) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/ActivityExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ActivityExtension.kt deleted file mode 100644 index e9cac72ea..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/ActivityExtension.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.wulkanowy.utils - -import android.app.Activity -import android.view.inputmethod.InputMethodManager -import androidx.core.content.getSystemService - -fun Activity.showSoftInput() { - getSystemService()?.let { manager -> - currentFocus?.let { manager.showSoftInput(it, 0) } - } -} - -fun Activity.hideSoftInput() { - getSystemService()?.hideSoftInputFromWindow(window.decorView.applicationWindowToken, 0) -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/AppConstant.java b/app/src/main/java/io/github/wulkanowy/utils/AppConstant.java new file mode 100644 index 000000000..27d76e756 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/AppConstant.java @@ -0,0 +1,25 @@ +package io.github.wulkanowy.utils; + +public final class AppConstant { + + public static final String APP_NAME = "Wulkanowy"; + + public static final String DATABASE_NAME = "wulkanowy_db"; + + public static final String SHARED_PREFERENCES_NAME = "user_data"; + + + public static final String VULCAN_CREATE_ACCOUNT_URL = + "https://cufs.vulcan.net.pl/Default/AccountManage/CreateAccount"; + + public static final String VULCAN_FORGOT_PASS_URL = + "https://cufs.vulcan.net.pl/Default/AccountManage/UnlockAccount"; + + public static final String DEFAULT_SYMBOL = "Default"; + + public static final String DATE_PATTERN = "yyyy-MM-dd"; + + private AppConstant() { + throw new IllegalStateException("Utility class"); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt deleted file mode 100644 index 6912baa36..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.wulkanowy.utils - -import android.content.res.Resources -import android.os.Build.MANUFACTURER -import android.os.Build.MODEL -import android.os.Build.VERSION.SDK_INT -import io.github.wulkanowy.BuildConfig.DEBUG -import io.github.wulkanowy.BuildConfig.VERSION_CODE -import io.github.wulkanowy.BuildConfig.VERSION_NAME -import javax.inject.Singleton - -@Singleton -open class AppInfo { - - open val isDebug get() = DEBUG - - open val versionCode get() = VERSION_CODE - - open val versionName get() = VERSION_NAME - - open val systemVersion get() = SDK_INT - - open val systemManufacturer: String get() = MANUFACTURER - - open val systemModel: String get() = MODEL - - @Suppress("DEPRECATION") - open val systemLanguage: String - get() = Resources.getSystem().configuration.locale.language -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt deleted file mode 100644 index c2b1efaa8..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.wulkanowy.utils - -import io.github.wulkanowy.data.db.entities.AttendanceSummary - -/** - * [UONET+ - Zasady tworzenia podsumowań liczb uczniów obecnych i nieobecnych w tabeli frekwencji] - * (https://www.vulcan.edu.pl/vulcang_files/user/AABW/AABW-PDF/uonetplus/uonetplus_Frekwencja-liczby-obecnych-nieobecnych.pdf) - */ - -private inline val AttendanceSummary.allPresences: Double - get() = presence.toDouble() + absenceForSchoolReasons + lateness + latenessExcused - -private inline val AttendanceSummary.allAbsences: Double - get() = absence.toDouble() + absenceExcused - -fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences) - -fun List.calculatePercentage(): Double { - return calculatePercentage(sumByDouble { it.allPresences }, sumByDouble { it.allAbsences }) -} - -private fun calculatePercentage(presence: Double, absence: Double): Double { - return if ((presence + absence) == 0.0) 0.0 else (presence / (presence + absence)) * 100 -} - - diff --git a/app/src/main/java/io/github/wulkanowy/utils/AverageCalculator.java b/app/src/main/java/io/github/wulkanowy/utils/AverageCalculator.java new file mode 100644 index 000000000..cc33e65a9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/AverageCalculator.java @@ -0,0 +1,61 @@ +package io.github.wulkanowy.utils; + +import java.util.List; + +import io.github.wulkanowy.data.db.dao.entities.Grade; + +public final class AverageCalculator { + + private AverageCalculator() { + throw new IllegalStateException("Utility class"); + } + + public static float calculate(List gradeList) { + + float counter = 0f; + float denominator = 0f; + + for (Grade grade : gradeList) { + int integerWeight = getIntegerForWeightOfGrade(grade.getWeight()); + float floatValue = getMathematicalValueOfGrade(grade.getValue()); + + if (floatValue != -1f) { + counter += floatValue * integerWeight; + denominator += integerWeight; + } + } + + if (counter == 0f) { + return -1f; + } else { + return counter / denominator; + } + } + + private static float getMathematicalValueOfGrade(String valueOfGrade) { + if (valueOfGrade.matches("[-|+|=]{0,2}[0-6]") + || valueOfGrade.matches("[0-6][-|+|=]{0,2}")) { + if (valueOfGrade.matches("[-][0-6]") + || valueOfGrade.matches("[0-6][-]")) { + String replacedValue = valueOfGrade.replaceAll("[-]", ""); + return Float.valueOf(replacedValue) - 0.33f; + } else if (valueOfGrade.matches("[+][0-6]") + || valueOfGrade.matches("[0-6][+]")) { + String replacedValue = valueOfGrade.replaceAll("[+]", ""); + return Float.valueOf((replacedValue)) + 0.33f; + } else if (valueOfGrade.matches("[-|=]{1,2}[0-6]") + || valueOfGrade.matches("[0-6][-|=]{1,2}")) { + String replacedValue = valueOfGrade.replaceAll("[-|=]{1,2}", ""); + return Float.valueOf((replacedValue)) - 0.5f; + } else { + return Float.valueOf(valueOfGrade); + } + } else { + return -1; + } + } + + private static int getIntegerForWeightOfGrade(String weightOfGrade) { + return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3)); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/CommonUtils.java b/app/src/main/java/io/github/wulkanowy/utils/CommonUtils.java new file mode 100644 index 000000000..8ec73faf7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/CommonUtils.java @@ -0,0 +1,40 @@ +package io.github.wulkanowy.utils; + +import android.app.Activity; +import android.net.Uri; +import android.support.customtabs.CustomTabsIntent; + +import io.github.wulkanowy.R; + +public final class CommonUtils { + + private CommonUtils() { + throw new IllegalStateException("Utility class"); + } + + public static void openInternalBrowserViewer(Activity activity, String url) { + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + builder.setToolbarColor(activity.getResources().getColor(R.color.colorPrimary)); + CustomTabsIntent customTabsIntent = builder.build(); + customTabsIntent.launchUrl(activity, Uri.parse(url)); + } + + public static int colorHexToColorName(String hexColor) { + switch (hexColor) { + case "000000": + return R.string.color_black_text; + + case "F04C4C": + return R.string.color_red_text; + + case "20A4F7": + return R.string.color_blue_text; + + case "6ECD07": + return R.string.color_green_text; + + default: + return R.string.noColor_text; + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt deleted file mode 100644 index cf715e657..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.wulkanowy.utils - -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.util.DisplayMetrics.DENSITY_DEFAULT -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt -import androidx.annotation.ColorRes -import androidx.annotation.DrawableRes -import androidx.core.content.ContextCompat -import androidx.core.graphics.ColorUtils -import io.github.wulkanowy.BuildConfig.APPLICATION_ID - -@ColorInt -fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int { - val array = obtainStyledAttributes(null, intArrayOf(colorAttr)) - return try { - array.getColor(0, 0) - } finally { - array.recycle() - } -} - -@ColorInt -fun Context.getThemeAttrColor(@AttrRes colorAttr: Int, alpha: Int): Int { - return ColorUtils.setAlphaComponent(getThemeAttrColor(colorAttr), alpha) -} - -@ColorInt -fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes) - -fun Context.getCompatDrawable(@DrawableRes drawableRes: Int) = ContextCompat.getDrawable(this, drawableRes) - -fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit) { - Intent.parseUri(uri, 0).let { - if (it.resolveActivity(packageManager) != null) startActivity(it) - else onActivityNotFound(uri) - } -} - -fun Context.openAppInMarket(onActivityNotFound: (uri: String) -> Unit) { - openInternetBrowser("market://details?id=${APPLICATION_ID}") { - openInternetBrowser("https://github.com/wulkanowy/wulkanowy/releases", onActivityNotFound) - } -} - -fun Context.openEmailClient(chooserTitle: String, email: String, subject: String, body: String, onActivityNotFound: () -> Unit = {}) { - val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:")).apply { - putExtra(Intent.EXTRA_EMAIL, arrayOf(email)) - putExtra(Intent.EXTRA_SUBJECT, subject) - putExtra(Intent.EXTRA_TEXT, body) - } - - if (intent.resolveActivity(packageManager) != null) { - startActivity(Intent.createChooser(intent, chooserTitle)) - } else onActivityNotFound() -} - -fun Context.openNavigation(location: String) { - val intentUri = Uri.parse("geo:0,0?q=${Uri.encode(location)}") - val intent = Intent(Intent.ACTION_VIEW, intentUri) - if (intent.resolveActivity(packageManager) != null) { - startActivity(intent) - } -} - -fun Context.openDialer(phone: String) { - val intentUri = Uri.parse("tel:$phone") - val intent = Intent(Intent.ACTION_DIAL, intentUri) - startActivity(intent) -} - -fun Context.shareText(text: String, subject: String?) { - val sendIntent: Intent = Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_TEXT, text) - if (subject != null) { - putExtra(Intent.EXTRA_SUBJECT, subject) - } - type = "text/plain" - } - val shareIntent = Intent.createChooser(sendIntent, null) - startActivity(shareIntent) -} - -fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT diff --git a/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java new file mode 100644 index 000000000..1dd5f641f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java @@ -0,0 +1,106 @@ +package io.github.wulkanowy.utils; + + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.data.db.dao.entities.Day; +import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.Lesson; +import io.github.wulkanowy.data.db.dao.entities.Subject; +import io.github.wulkanowy.data.db.dao.entities.Week; + +public final class DataObjectConverter { + + private DataObjectConverter() { + throw new IllegalStateException("Utility class"); + } + + public static List subjectsToSubjectEntities(List subjectList) { + + List subjectEntityList = new ArrayList<>(); + + for (io.github.wulkanowy.api.grades.Subject subject : subjectList) { + Subject subjectEntity = new Subject() + .setName(subject.getName()) + .setPredictedRating(subject.getPredictedRating()) + .setFinalRating(subject.getFinalRating()); + subjectEntityList.add(subjectEntity); + } + + return subjectEntityList; + } + + public static List gradesToGradeEntities(List gradeList) { + + List gradeEntityList = new ArrayList<>(); + + for (io.github.wulkanowy.api.grades.Grade grade : gradeList) { + Grade gradeEntity = new Grade() + .setSubject(grade.getSubject()) + .setValue(grade.getValue()) + .setColor(grade.getColor()) + .setSymbol(grade.getSymbol()) + .setDescription(grade.getDescription()) + .setWeight(grade.getWeight()) + .setDate(grade.getDate()) + .setTeacher(grade.getTeacher()) + .setSemester(grade.getSemester()); + + gradeEntityList.add(gradeEntity); + } + return gradeEntityList; + } + + public static Week weekToWeekEntity(io.github.wulkanowy.api.generic.Week week) { + return new Week().setStartDayDate(week.getStartDayDate()); + } + + public static Day dayToDayEntity(io.github.wulkanowy.api.generic.Day day) { + return new Day() + .setDate(day.getDate()) + .setDayName(day.getDayName()) + .setFreeDay(day.isFreeDay()) + .setFreeDayName(day.getFreeDayName()); + } + + + public static List daysToDaysEntities(List dayList) { + + List dayEntityList = new ArrayList<>(); + + for (io.github.wulkanowy.api.generic.Day day : dayList) { + dayEntityList.add(dayToDayEntity(day)); + } + return dayEntityList; + } + + public static Lesson lessonToLessonEntity(io.github.wulkanowy.api.generic.Lesson lesson) { + return new Lesson() + .setNumber(lesson.getNumber()) + .setSubject(lesson.getSubject()) + .setTeacher(lesson.getTeacher()) + .setRoom(lesson.getRoom()) + .setDescription(lesson.getDescription()) + .setGroupName(lesson.getGroupName()) + .setStartTime(lesson.getStartTime()) + .setEndTime(lesson.getEndTime()) + .setDate(lesson.getDate()) + .setEmpty(lesson.isEmpty()) + .setDivisionIntoGroups(lesson.isDivisionIntoGroups()) + .setPlanning(lesson.isPlanning()) + .setRealized(lesson.isRealized()) + .setMovedOrCanceled(lesson.isMovedOrCanceled()) + .setNewMovedInOrChanged(lesson.isNewMovedInOrChanged()); + } + + public static List lessonsToLessonsEntities(List lessonList) { + + List lessonEntityList = new ArrayList<>(); + + for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) { + lessonEntityList.add(lessonToLessonEntity(lesson)); + } + return lessonEntityList; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/EditTextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/EditTextExtension.kt deleted file mode 100644 index 58c93729b..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/EditTextExtension.kt +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.wulkanowy.utils - -import android.view.inputmethod.EditorInfo -import android.widget.EditText - -fun EditText.setOnEditorDoneSignIn(callback: () -> Boolean) { - setOnEditorActionListener { _, id, _ -> - if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) callback() else false - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/EntitiesCompare.java b/app/src/main/java/io/github/wulkanowy/utils/EntitiesCompare.java new file mode 100644 index 000000000..5681bad17 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/EntitiesCompare.java @@ -0,0 +1,42 @@ +package io.github.wulkanowy.utils; + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.data.db.dao.entities.Grade; + +public final class EntitiesCompare { + + private EntitiesCompare() { + throw new IllegalStateException("Utility class"); + } + + public static List compareGradeList(List newList, List oldList) { + + List addedOrUpdatedGradeList = new ArrayList<>(CollectionUtils + .removeAll(newList, oldList)); + List updatedList = new ArrayList<>(CollectionUtils + .removeAll(newList, addedOrUpdatedGradeList)); + List lastList = new ArrayList<>(); + + for (Grade grade : addedOrUpdatedGradeList) { + if (!oldList.isEmpty()) { + grade.setRead(false); + } + grade.setIsNew(true); + updatedList.add(grade); + } + + for (Grade updateGrade : updatedList) { + for (Grade oldGrade : oldList) { + if (updateGrade.equals(oldGrade)) { + updateGrade.setRead(oldGrade.getRead()); + } + } + lastList.add(updateGrade); + } + return lastList; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/FragNavControlerExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/FragNavControlerExtension.kt deleted file mode 100644 index 9dc1e18a0..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/FragNavControlerExtension.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.wulkanowy.utils - -import androidx.fragment.app.Fragment -import com.ncapdevi.fragnav.FragNavController -import io.github.wulkanowy.ui.modules.main.MainView - -inline fun FragNavController.setOnViewChangeListener(crossinline listener: (section: MainView.Section?, name: String?) -> Unit) { - transactionListener = object : FragNavController.TransactionListener { - override fun onFragmentTransaction(fragment: Fragment?, transactionType: FragNavController.TransactionType) { - listener(fragment?.toSection(), fragment?.let { it::class.java.simpleName }) - } - - override fun onTabTransaction(fragment: Fragment?, index: Int) { - listener(fragment?.toSection(), fragment?.let { it::class.java.simpleName }) - } - } -} - -fun FragNavController.safelyPopFragments(depth: Int) { - if (!isRootFragment) popFragments(depth) -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt deleted file mode 100644 index 0b71c964b..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/FragmentExtension.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.wulkanowy.utils - -import androidx.fragment.app.Fragment -import io.github.wulkanowy.ui.modules.about.AboutFragment -import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment -import io.github.wulkanowy.ui.modules.exam.ExamFragment -import io.github.wulkanowy.ui.modules.grade.GradeFragment -import io.github.wulkanowy.ui.modules.homework.HomeworkFragment -import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.modules.message.MessageFragment -import io.github.wulkanowy.ui.modules.more.MoreFragment -import io.github.wulkanowy.ui.modules.note.NoteFragment -import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment -import io.github.wulkanowy.ui.modules.settings.SettingsFragment -import io.github.wulkanowy.ui.modules.timetable.TimetableFragment - -fun Fragment.toSection(): MainView.Section? { - return when (this) { - is GradeFragment -> MainView.Section.GRADE - is AttendanceFragment -> MainView.Section.ATTENDANCE - is ExamFragment -> MainView.Section.EXAM - is TimetableFragment -> MainView.Section.TIMETABLE - is MoreFragment -> MainView.Section.MORE - is MessageFragment -> MainView.Section.MESSAGE - is HomeworkFragment -> MainView.Section.HOMEWORK - is NoteFragment -> MainView.Section.NOTE - is LuckyNumberFragment -> MainView.Section.LUCKY_NUMBER - is SettingsFragment -> MainView.Section.SETTINGS - is AboutFragment -> MainView.Section.ABOUT - is SchoolAndTeachersFragment -> MainView.Section.SCHOOL - else -> null - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt deleted file mode 100644 index c57b62470..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/GradeExtension.kt +++ /dev/null @@ -1,78 +0,0 @@ -package io.github.wulkanowy.utils - -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Grade -import io.github.wulkanowy.data.db.entities.GradeSummary - -fun List.calcAverage(): Double { - var counter = 0.0 - var denominator = 0.0 - - forEach { - counter += (it.value + it.modifier) * it.weightValue - denominator += it.weightValue - } - return if (denominator != 0.0) counter / denominator else 0.0 -} - -@JvmName("calcSummaryAverage") -fun List.calcAverage(): Double { - return asSequence().mapNotNull { - if (it.finalGrade.matches("[0-6]".toRegex())) it.finalGrade.toDouble() else null - }.average().let { if (it.isNaN()) 0.0 else it } -} - -fun Grade.getBackgroundColor(theme: String): Int { - return when (theme) { - "grade_color" -> getGradeColor() - "material" -> when (value.toInt()) { - 6 -> R.color.grade_material_six - 5 -> R.color.grade_material_five - 4 -> R.color.grade_material_four - 3 -> R.color.grade_material_three - 2 -> R.color.grade_material_two - 1 -> R.color.grade_material_one - else -> R.color.grade_material_default - } - else -> when (value.toInt()) { - 6 -> R.color.grade_vulcan_six - 5 -> R.color.grade_vulcan_five - 4 -> R.color.grade_vulcan_four - 3 -> R.color.grade_vulcan_three - 2 -> R.color.grade_vulcan_two - 1 -> R.color.grade_vulcan_one - else -> R.color.grade_vulcan_default - } - } -} - -fun Grade.getGradeColor(): Int { - return when (color) { - "000000" -> R.color.grade_black - "F04C4C" -> R.color.grade_red - "20A4F7" -> R.color.grade_blue - "6ECD07" -> R.color.grade_green - "B16CF1" -> R.color.grade_purple - else -> R.color.grade_material_default - } -} - -inline val Grade.colorStringId: Int - get() { - return when (color) { - "000000" -> R.string.all_black - "F04C4C" -> R.string.all_red - "20A4F7" -> R.string.all_blue - "6ECD07" -> R.string.all_green - "B16CF1" -> R.string.all_purple - else -> R.string.all_empty_color - } - } - -fun Grade.changeModifier(plusModifier: Double, minusModifier: Double): Grade { - return when { - modifier > 0 -> copy(modifier = plusModifier) - modifier < 0 -> copy(modifier = -minusModifier) - else -> this - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/KeyboardUtils.java b/app/src/main/java/io/github/wulkanowy/utils/KeyboardUtils.java new file mode 100644 index 000000000..6be1b76f4 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/KeyboardUtils.java @@ -0,0 +1,33 @@ +package io.github.wulkanowy.utils; + +import android.app.Activity; +import android.content.Context; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +public final class KeyboardUtils { + + private KeyboardUtils() { + throw new IllegalStateException("Utility class"); + } + + public static void hideSoftInput(Activity activity) { + InputMethodManager manager = (InputMethodManager) + activity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (manager != null) { + manager.hideSoftInputFromWindow(activity.getWindow() + .getDecorView().getApplicationWindowToken(), 0); + } + } + + public static void showSoftInput(EditText editText, Context context) { + editText.setFocusable(true); + editText.setFocusableInTouchMode(true); + editText.requestFocus(); + InputMethodManager inputMethodManager = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + inputMethodManager.showSoftInput(editText, 0); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt b/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt deleted file mode 100644 index b96faeb21..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.github.wulkanowy.utils - -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.Fragment -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleObserver -import androidx.lifecycle.OnLifecycleEvent -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty - -class LifecycleAwareVariable : ReadWriteProperty, LifecycleObserver { - - private var _value: T? = null - - override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) { - thisRef.viewLifecycleOwner.lifecycle.removeObserver(this) - _value = value - thisRef.viewLifecycleOwner.lifecycle.addObserver(this) - } - - override fun getValue(thisRef: Fragment, property: KProperty<*>) = _value - ?: throw IllegalStateException("Trying to call an lifecycle-aware value outside of the view lifecycle, or the value has not been initialized") - - @Suppress("unused") - @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) - fun onDestroyView() { - _value = null - } -} - -class LifecycleAwareVariableActivity : ReadWriteProperty, LifecycleObserver { - - private var _value: T? = null - - override fun setValue(thisRef: AppCompatActivity, property: KProperty<*>, value: T) { - thisRef.lifecycle.removeObserver(this) - _value = value - thisRef.lifecycle.addObserver(this) - } - - override fun getValue(thisRef: AppCompatActivity, property: KProperty<*>) = _value - ?: throw IllegalStateException("Trying to call an lifecycle-aware value outside of the view lifecycle, or the value has not been initialized") - - @Suppress("unused") - @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) - fun onDestroyView() { - _value = null - } -} - - -@Suppress("unused") -fun Fragment.lifecycleAwareVariable() = LifecycleAwareVariable() - -fun lifecycleAwareVariable() = LifecycleAwareVariableActivity() diff --git a/app/src/main/java/io/github/wulkanowy/utils/ListExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ListExtension.kt deleted file mode 100644 index 4374aeb41..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/ListExtension.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.wulkanowy.utils - -infix fun List.uniqueSubtract(other: List): List { - val list = toMutableList() - other.forEach { - list.remove(it) - } - return list.toList() -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/LogUtils.java b/app/src/main/java/io/github/wulkanowy/utils/LogUtils.java new file mode 100644 index 000000000..f3b5b3ec2 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/LogUtils.java @@ -0,0 +1,22 @@ +package io.github.wulkanowy.utils; + +import android.util.Log; + +public final class LogUtils { + + private LogUtils() { + throw new IllegalStateException("Utility class"); + } + + public static void debug(String message) { + Log.d(AppConstant.APP_NAME, message); + } + + public static void error(String message, Throwable throwable) { + Log.e(AppConstant.APP_NAME, message, throwable); + } + + public static void error(String message) { + Log.e(AppConstant.APP_NAME, message); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt deleted file mode 100644 index fc3528495..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.kt +++ /dev/null @@ -1,104 +0,0 @@ -package io.github.wulkanowy.utils - -import android.app.Activity -import android.app.Application -import android.content.Context -import android.os.Bundle -import android.view.View -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import timber.log.Timber -import javax.inject.Inject -import javax.inject.Singleton - -class DebugLogTree : Timber.DebugTree() { - - override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { - super.log(priority, "Wulkanowy", message, t) - } -} - -private fun Bundle?.checkSavedState() = if (this == null) "(STATE IS NULL)" else "(STATE IS NOT NULL)" - -class ActivityLifecycleLogger : Application.ActivityLifecycleCallbacks { - - override fun onActivityPaused(activity: Activity?) { - activity?.let { Timber.d("${it::class.java.simpleName} PAUSED") } - } - - override fun onActivityResumed(activity: Activity?) { - activity?.let { Timber.d("${it::class.java.simpleName} RESUMED") } - } - - override fun onActivityStarted(activity: Activity?) { - activity?.let { Timber.d("${it::class.java.simpleName} STARTED") } - } - - override fun onActivityDestroyed(activity: Activity?) { - activity?.let { Timber.d("${it::class.java.simpleName} DESTROYED") } - } - - override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) { - activity?.let { Timber.d("${it::class.java.simpleName} SAVED INSTANCE STATE") } - } - - override fun onActivityStopped(activity: Activity?) { - activity?.let { Timber.d("${it::class.java.simpleName} STOPPED") } - } - - override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { - activity?.let { Timber.d("${it::class.java.simpleName} CREATED ${savedInstanceState.checkSavedState()}") } - } -} - -@Singleton -class FragmentLifecycleLogger @Inject constructor() : FragmentManager.FragmentLifecycleCallbacks() { - - override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) { - Timber.d("${f::class.java.simpleName} VIEW CREATED ${savedInstanceState.checkSavedState()}") - } - - override fun onFragmentStopped(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} STOPPED") - } - - override fun onFragmentCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?) { - Timber.d("${f::class.java.simpleName} CREATED ${savedInstanceState.checkSavedState()}") - } - - override fun onFragmentResumed(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} RESUMED") - } - - override fun onFragmentAttached(fm: FragmentManager, f: Fragment, context: Context) { - Timber.d("${f::class.java.simpleName} ATTACHED") - } - - override fun onFragmentDestroyed(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} DESTROYED") - } - - override fun onFragmentSaveInstanceState(fm: FragmentManager, f: Fragment, outState: Bundle) { - Timber.d("${f::class.java.simpleName} SAVED INSTANCE STATE") - } - - override fun onFragmentStarted(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} STARTED") - } - - override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} VIEW DESTROYED") - } - - override fun onFragmentActivityCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?) { - Timber.d("${f::class.java.simpleName} ACTIVITY CREATED ${savedInstanceState.checkSavedState()}") - } - - override fun onFragmentPaused(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} PAUSED") - } - - override fun onFragmentDetached(fm: FragmentManager, f: Fragment) { - Timber.d("${f::class.java.simpleName} DETACHED") - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/NetworkUtils.java b/app/src/main/java/io/github/wulkanowy/utils/NetworkUtils.java new file mode 100644 index 000000000..a1484eb9e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/NetworkUtils.java @@ -0,0 +1,18 @@ +package io.github.wulkanowy.utils; + +import android.content.Context; +import android.net.ConnectivityManager; + +public final class NetworkUtils { + + private NetworkUtils() { + throw new IllegalStateException("Utility class"); + } + + public static boolean isOnline(Context context) { + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + return connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null + && connectivityManager.getActiveNetworkInfo().isConnectedOrConnecting(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/ResourcesExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ResourcesExtension.kt deleted file mode 100644 index a2d0384e3..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/ResourcesExtension.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.utils - -import android.content.res.Resources -import io.github.wulkanowy.R -import io.github.wulkanowy.sdk.exception.FeatureDisabledException -import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException -import io.github.wulkanowy.sdk.exception.NotLoggedInException -import io.github.wulkanowy.sdk.exception.PasswordChangeRequiredException -import io.github.wulkanowy.sdk.exception.ServiceUnavailableException -import java.io.InterruptedIOException -import java.net.SocketTimeoutException -import java.net.UnknownHostException - -fun Resources.getString(error: Throwable) = when (error) { - is UnknownHostException -> getString(R.string.error_no_internet) - is SocketTimeoutException, is InterruptedIOException -> getString(R.string.error_timeout) - is NotLoggedInException -> getString(R.string.error_login_failed) - is PasswordChangeRequiredException -> getString(R.string.error_password_change_required) - is ServiceUnavailableException -> getString(R.string.error_service_unavailable) - is FeatureDisabledException -> getString(R.string.error_feature_disabled) - is FeatureNotAvailableException -> getString(R.string.error_feature_not_available) - else -> getString(R.string.error_unknown) -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/RootChecker.java b/app/src/main/java/io/github/wulkanowy/utils/RootChecker.java new file mode 100644 index 000000000..9c23c217f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/RootChecker.java @@ -0,0 +1,38 @@ +package io.github.wulkanowy.utils; + +import android.os.Build; + +import java.io.File; + +public final class RootChecker { + + private RootChecker() { + throw new IllegalStateException("Utility class"); + } + + public static boolean isRooted() { + return checkOne() || checkTwo() || checkThree(); + } + + private static boolean checkOne() { + return Build.TAGS != null && Build.TAGS.contains("test-keys"); + } + + private static boolean checkTwo() { + return new File("/system/app/Superuser.apk").exists(); + } + + private static boolean checkThree() { + String[] commands = {"/system/xbin/which su", "/system/bin/which su", "which su"}; + for (String command : commands) { + try { + Runtime.getRuntime().exec(command); + return true; + } catch (Exception e) { + // ignore + } + } + return false; + } + +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SchedulersProvider.kt b/app/src/main/java/io/github/wulkanowy/utils/SchedulersProvider.kt deleted file mode 100644 index e426d4d5d..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/SchedulersProvider.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.wulkanowy.utils - -import io.reactivex.Scheduler -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers - -open class SchedulersProvider { - - open val mainThread: Scheduler - get() = AndroidSchedulers.mainThread() - - open val backgroundThread: Scheduler - get() = Schedulers.io() -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt b/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt deleted file mode 100644 index 46a707abb..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/SchooldaysRangeLimiter.kt +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.wulkanowy.utils - -import android.os.Parcel -import android.os.Parcelable -import com.wdullaer.materialdatetimepicker.date.DateRangeLimiter -import org.threeten.bp.DayOfWeek -import org.threeten.bp.LocalDate -import java.util.Calendar - -@Suppress("UNUSED_PARAMETER") -class SchooldaysRangeLimiter : DateRangeLimiter { - - private val now = LocalDate.now() - - override fun setToNearestDate(day: Calendar): Calendar = day - - override fun isOutOfRange(year: Int, month: Int, day: Int): Boolean { - val date = LocalDate.of(year, month + 1, day) - val dayOfWeek = date.dayOfWeek - return dayOfWeek == DayOfWeek.SUNDAY || date.isHolidays - } - - override fun getStartDate(): Calendar { - val startYear = if (now.monthValue <= 6) now.year - 1 else now.year - val startOfSchoolYear = now.withYear(startYear).firstSchoolDay - - val calendar = Calendar.getInstance() - calendar.set(startOfSchoolYear.year, startOfSchoolYear.monthValue - 1, startOfSchoolYear.dayOfMonth) - return calendar - } - - override fun getEndDate(): Calendar { - val endYear = if (now.monthValue > 6) now.year + 1 else now.year - val endOfSchoolYear = now.withYear(endYear).lastSchoolDay - - val calendar = Calendar.getInstance() - calendar.set(endOfSchoolYear.year, endOfSchoolYear.monthValue - 1, endOfSchoolYear.dayOfMonth) - return calendar - } - - override fun writeToParcel(parcel: Parcel, flags: Int) {} - - override fun describeContents() = 0 - - companion object CREATOR : Parcelable.Creator { - - override fun createFromParcel(parcel: Parcel): SchooldaysRangeLimiter = SchooldaysRangeLimiter() - - override fun newArray(size: Int): Array = arrayOfNulls(size) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt deleted file mode 100644 index 63a30db8c..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/SdkExtension.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.utils - -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.sdk.Sdk -import timber.log.Timber - -fun Sdk.init(student: Student): Sdk { - email = student.email - password = student.password - symbol = student.symbol - schoolSymbol = student.schoolSymbol - studentId = student.studentId - classId = student.classId - - if (Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { - scrapperBaseUrl = student.scrapperBaseUrl - loginType = Sdk.ScrapperLoginType.valueOf(student.loginType) - } - loginId = student.userLoginId - - mode = Sdk.Mode.valueOf(student.loginMode) - mobileBaseUrl = student.mobileBaseUrl - certKey = student.certificateKey - privateKey = student.privateKey - - emptyCookieJarInterceptor = true - - Timber.d("Sdk in ${student.loginMode} mode reinitialized") - - return this -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt deleted file mode 100644 index b3c479c38..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/SemesterExtension.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.wulkanowy.utils - -import io.github.wulkanowy.data.db.entities.Semester -import org.threeten.bp.LocalDate.now - -inline val Semester.isCurrent: Boolean - get() = now() in start..end - -fun List.getCurrentOrLast(): Semester { - if (isEmpty()) throw RuntimeException("Empty semester list") - - // when there is only one current semester - singleOrNull { it.isCurrent }?.let { return it } - - // when there is more than one current semester - find one with higher id - singleOrNull { semester -> semester.semesterId == maxBy { it.semesterId }?.semesterId }?.let { return it } - - throw IllegalArgumentException("Duplicated last semester! Semesters: ${joinToString(separator = "\n")}") -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/SpinnerExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/SpinnerExtension.kt deleted file mode 100644 index 1f7216906..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/SpinnerExtension.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.wulkanowy.utils - -import android.view.View -import android.widget.AdapterView -import android.widget.Spinner - -/** - * @see How to keep onItemSelected from firing off on a newly instantiated Spinner? - */ -@Suppress("UNCHECKED_CAST") -inline fun Spinner.setOnItemSelectedListener(crossinline listener: (view: T?) -> Unit) { - onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onNothingSelected(parent: AdapterView<*>?) {} - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onNothingSelected(parent: AdapterView<*>?) {} - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - listener(view as T?) - } - } - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt deleted file mode 100644 index 65167fd78..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/StringExtension.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.wulkanowy.utils - -inline fun String?.ifNullOrBlank(defaultValue: () -> String) = if (this.isNullOrBlank()) defaultValue() else this diff --git a/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt deleted file mode 100644 index 802b2ee0f..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/TimeExtension.kt +++ /dev/null @@ -1,131 +0,0 @@ -package io.github.wulkanowy.utils - -import org.threeten.bp.DayOfWeek.FRIDAY -import org.threeten.bp.DayOfWeek.MONDAY -import org.threeten.bp.DayOfWeek.SATURDAY -import org.threeten.bp.DayOfWeek.SUNDAY -import org.threeten.bp.Instant.ofEpochMilli -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime -import org.threeten.bp.LocalDateTime.ofInstant -import org.threeten.bp.Month -import org.threeten.bp.ZoneId -import org.threeten.bp.ZoneOffset -import org.threeten.bp.format.DateTimeFormatter.ofPattern -import org.threeten.bp.format.TextStyle.FULL_STANDALONE -import org.threeten.bp.temporal.TemporalAdjusters.firstInMonth -import org.threeten.bp.temporal.TemporalAdjusters.next -import org.threeten.bp.temporal.TemporalAdjusters.previous -import java.util.Locale - -private const val DATE_PATTERN = "dd.MM.yyyy" - -fun String.toLocalDate(format: String = DATE_PATTERN): LocalDate = LocalDate.parse(this, ofPattern(format)) - -fun LocalDateTime.toTimestamp() = atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli() - -fun Long.toLocalDateTime() = ofInstant(ofEpochMilli(this), ZoneId.systemDefault()) - -fun LocalDate.toFormattedString(format: String = DATE_PATTERN): String = format(ofPattern(format)) - -fun LocalDateTime.toFormattedString(format: String = DATE_PATTERN): String = format(ofPattern(format)) - -/** - * https://github.com/ThreeTen/threetenbp/issues/55 - */ -fun Month.getFormattedName(): String { - return getDisplayName(FULL_STANDALONE, Locale.getDefault()) - .let { - when (it) { - "stycznia" -> "Styczeń" - "lutego" -> "Luty" - "marca" -> "Marzec" - "kwietnia" -> "Kwiecień" - "maja" -> "Maj" - "czerwca" -> "Czerwiec" - "lipca" -> "Lipiec" - "sierpnia" -> "Sierpień" - "września" -> "Wrzesień" - "października" -> "Październik" - "listopada" -> "Listopad" - "grudnia" -> "Grudzień" - else -> it - } - } -} - -inline val LocalDate.nextSchoolDay: LocalDate - get() { - return when (dayOfWeek) { - FRIDAY, SATURDAY, SUNDAY -> with(next(MONDAY)) - else -> plusDays(1) - } - } - -inline val LocalDate.previousSchoolDay: LocalDate - get() { - return when (dayOfWeek) { - SATURDAY, SUNDAY, MONDAY -> with(previous(FRIDAY)) - else -> minusDays(1) - } - } - -inline val LocalDate.nextOrSameSchoolDay: LocalDate - get() { - return when (dayOfWeek) { - SATURDAY, SUNDAY -> with(next(MONDAY)) - else -> this - } - } - -inline val LocalDate.previousOrSameSchoolDay: LocalDate - get() { - return when (dayOfWeek) { - SATURDAY, SUNDAY -> with(previous(FRIDAY)) - else -> this - } - } - -inline val LocalDate.weekDayName: String - get() = format(ofPattern("EEEE", Locale.getDefault())) - -inline val LocalDate.monday: LocalDate - get() = with(MONDAY) - -inline val LocalDate.sunday: LocalDate - get() = with(SUNDAY) - -/** - * [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335) - */ -inline val LocalDate.isHolidays: Boolean - get() = isBefore(firstSchoolDay) && isAfter(lastSchoolDay) - -inline val LocalDate.firstSchoolDay: LocalDate - get() = LocalDate.of(year, 9, 1).run { - when (dayOfWeek) { - FRIDAY, SATURDAY, SUNDAY -> with(firstInMonth(MONDAY)) - else -> this - } - } - -inline val LocalDate.lastSchoolDay: LocalDate - get() = LocalDate.of(year, 6, 20) - .with(next(FRIDAY)) - -private fun Int.getSchoolYearByMonth(monthValue: Int): Int { - return when (monthValue) { - in 9..12 -> this - else -> this + 1 - } -} - -fun LocalDate.getLastSchoolDayIfHoliday(schoolYear: Int): LocalDate { - val date = LocalDate.of(schoolYear.getSchoolYearByMonth(monthValue), monthValue, dayOfMonth) - - if (date.isHolidays) { - return date.lastSchoolDay - } - - return date -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.java b/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.java new file mode 100644 index 000000000..717ed42a9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.java @@ -0,0 +1,89 @@ +package io.github.wulkanowy.utils; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeConstants; +import org.joda.time.LocalDate; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; + +import static io.github.wulkanowy.utils.AppConstant.DATE_PATTERN; + +public final class TimeUtils { + + private static final long TICKS_AT_EPOCH = 621355968000000000L; + + private static final long TICKS_PER_MILLISECOND = 10000; + + private TimeUtils() { + throw new IllegalStateException("Utility class"); + } + + public static long getNetTicks(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + return (calendar.getTimeInMillis() * TICKS_PER_MILLISECOND) + TICKS_AT_EPOCH; + } + + public static long getNetTicks(String dateString) throws ParseException { + return getNetTicks(dateString, DATE_PATTERN); + } + + public static long getNetTicks(String dateString, String dateFormat) throws ParseException { + SimpleDateFormat format = new SimpleDateFormat(dateFormat, Locale.ROOT); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + Date dateObject = format.parse(dateString); + + return getNetTicks(dateObject); + } + + public static Date getDate(long netTicks) { + return new Date((netTicks - TICKS_AT_EPOCH) / TICKS_PER_MILLISECOND); + } + + public static List getMondaysFromCurrentSchoolYear() { + LocalDate startDate = new LocalDate(getCurrentSchoolYear(), 9, 1); + LocalDate endDate = new LocalDate(getCurrentSchoolYear() + 1, 8, 31); + + List dateList = new ArrayList<>(); + + LocalDate thisMonday = startDate.withDayOfWeek(DateTimeConstants.MONDAY); + + if (startDate.isAfter(thisMonday)) { + startDate = thisMonday.plusWeeks(1); + } else { + startDate = thisMonday; + } + + while (startDate.isBefore(endDate)) { + dateList.add(startDate.toString(DATE_PATTERN)); + startDate = startDate.plusWeeks(1); + } + return dateList; + } + + public static int getCurrentSchoolYear() { + DateTime dateTime = new DateTime(); + return dateTime.getMonthOfYear() <= 8 ? dateTime.getYear() - 1 : dateTime.getYear(); + } + + public static String getDateOfCurrentMonday(boolean normalize) { + DateTime currentDate = new DateTime(); + + if (currentDate.getDayOfWeek() == DateTimeConstants.SATURDAY && normalize) { + currentDate = currentDate.plusDays(2); + } else if (currentDate.getDayOfWeek() == DateTimeConstants.SUNDAY && normalize) { + currentDate = currentDate.plusDays(1); + } else { + currentDate = currentDate.withDayOfWeek(DateTimeConstants.MONDAY); + } + return currentDate.toString(DATE_PATTERN); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/TimetableExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/TimetableExtension.kt deleted file mode 100644 index ccb2afeb0..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/TimetableExtension.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.wulkanowy.utils - -import io.github.wulkanowy.data.db.entities.Timetable -import org.threeten.bp.Duration -import org.threeten.bp.Duration.between -import org.threeten.bp.LocalDateTime -import org.threeten.bp.LocalDateTime.now - -fun Timetable.isShowTimeUntil(previousLessonEnd: LocalDateTime?) = when { - !isStudentPlan -> false - canceled -> false - now().isAfter(start) -> false - previousLessonEnd != null && now().isBefore(previousLessonEnd) -> false - else -> between(now(), start) <= Duration.ofMinutes(60) -} - -inline val Timetable.left: Duration? - get() = when { - canceled -> null - !isStudentPlan -> null - end.isAfter(now()) && start.isBefore(now()) -> between(now(), end) - else -> null - } - -inline val Timetable.until: Duration - get() = between(now(), start) - -inline val Timetable.isJustFinished: Boolean - get() = end.isBefore(now()) && end.plusSeconds(15).isAfter(now()) && !canceled diff --git a/app/src/main/java/io/github/wulkanowy/utils/ViewPagerExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ViewPagerExtension.kt deleted file mode 100644 index 6a5ad880a..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/ViewPagerExtension.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.wulkanowy.utils - -import androidx.viewpager.widget.ViewPager - -inline fun ViewPager.setOnSelectPageListener(crossinline selectListener: (position: Int) -> Unit) { - addOnPageChangeListener(object : ViewPager.OnPageChangeListener { - override fun onPageSelected(position: Int) { - selectListener(position) - } - override fun onPageScrollStateChanged(state: Int) {} - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} - }) -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/async/AbstractTask.java b/app/src/main/java/io/github/wulkanowy/utils/async/AbstractTask.java new file mode 100644 index 000000000..5106d6417 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/async/AbstractTask.java @@ -0,0 +1,63 @@ +package io.github.wulkanowy.utils.async; + +import android.os.AsyncTask; + +import io.github.wulkanowy.utils.LogUtils; + +public class AbstractTask extends AsyncTask { + + private Exception exception; + + private AsyncListeners.OnRefreshListener onRefreshListener; + + private AsyncListeners.OnFirstLoadingListener onFirstLoadingListener; + + public void setOnFirstLoadingListener(AsyncListeners.OnFirstLoadingListener onFirstLoadingListener) { + this.onFirstLoadingListener = onFirstLoadingListener; + } + + public void setOnRefreshListener(AsyncListeners.OnRefreshListener onRefreshListener) { + this.onRefreshListener = onRefreshListener; + } + + @Override + protected Boolean doInBackground(Void... voids) { + try { + if (onFirstLoadingListener != null) { + onFirstLoadingListener.onDoInBackgroundLoading(); + } else if (onRefreshListener != null) { + onRefreshListener.onDoInBackgroundRefresh(); + } else { + LogUtils.error("AbstractTask does not have a listener assigned"); + } + return true; + } catch (Exception e) { + exception = e; + return false; + } + } + + @Override + protected void onCancelled() { + super.onCancelled(); + if (onFirstLoadingListener != null) { + onFirstLoadingListener.onCanceledLoadingAsync(); + } else if (onRefreshListener != null) { + onRefreshListener.onCanceledRefreshAsync(); + } else { + LogUtils.error("AbstractTask does not have a listener assigned"); + } + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + if (onFirstLoadingListener != null) { + onFirstLoadingListener.onEndLoadingAsync(result, exception); + } else if (onRefreshListener != null) { + onRefreshListener.onEndRefreshAsync(result, exception); + } else { + LogUtils.error("AbstractTask does not have a listener assigned"); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/async/AsyncListeners.java b/app/src/main/java/io/github/wulkanowy/utils/async/AsyncListeners.java new file mode 100644 index 000000000..0d33c57cf --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/async/AsyncListeners.java @@ -0,0 +1,23 @@ +package io.github.wulkanowy.utils.async; + +public interface AsyncListeners { + + interface OnRefreshListener { + + void onDoInBackgroundRefresh() throws Exception; + + void onCanceledRefreshAsync(); + + void onEndRefreshAsync(boolean result, Exception exception); + + } + + interface OnFirstLoadingListener { + + void onDoInBackgroundLoading() throws Exception; + + void onCanceledLoadingAsync(); + + void onEndLoadingAsync(boolean result, Exception exception); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/security/CryptoException.java b/app/src/main/java/io/github/wulkanowy/utils/security/CryptoException.java new file mode 100644 index 000000000..1ee4a9fa8 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/security/CryptoException.java @@ -0,0 +1,9 @@ +package io.github.wulkanowy.utils.security; + + +public class CryptoException extends Exception { + + public CryptoException(String message) { + super(message); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.java b/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.java new file mode 100644 index 000000000..93da1d0bd --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.java @@ -0,0 +1,184 @@ +package io.github.wulkanowy.utils.security; + + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.security.KeyPairGeneratorSpec; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import android.util.Base64; + +import org.apache.commons.lang3.ArrayUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.Calendar; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.security.auth.x500.X500Principal; + +import io.github.wulkanowy.utils.LogUtils; +import io.github.wulkanowy.utils.RootChecker; + +public final class Scrambler { + + private static final String ANDROID_KEYSTORE = "AndroidKeyStore"; + + private static KeyStore keyStore; + + private Scrambler() { + throw new IllegalStateException("Utility class"); + } + + public static String encrypt(String email, String plainText, Context context) + throws CryptoException { + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + loadKeyStore(); + generateNewKey(email, context); + return encryptString(email, plainText); + } else { + if (RootChecker.isRooted()) { + return new String(Base64.encode(plainText.getBytes(), Base64.DEFAULT)); + } else { + throw new UnsupportedOperationException("Stored data in this devices " + + "isn't safe because android is rooted"); + } + } + } + + public static String decrypt(String email, String encryptedText) throws CryptoException { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + loadKeyStore(); + return decryptString(email, encryptedText); + } else { + return new String(Base64.decode(encryptedText, Base64.DEFAULT)); + } + } + + private static void loadKeyStore() throws CryptoException { + try { + keyStore = KeyStore.getInstance(ANDROID_KEYSTORE); + keyStore.load(null); + } catch (Exception e) { + throw new CryptoException(e.getMessage()); + } + } + + @SuppressWarnings("deprecation") + @TargetApi(18) + private static void generateNewKey(String alias, Context context) throws CryptoException { + + Calendar start = Calendar.getInstance(); + Calendar end = Calendar.getInstance(); + + AlgorithmParameterSpec spec; + + end.add(Calendar.YEAR, 10); + if (!"".equals(alias)) { + try { + if (!keyStore.containsAlias(alias)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + spec = new KeyGenParameterSpec.Builder(alias, + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) + .setDigests(KeyProperties.DIGEST_SHA256) + .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) + .setCertificateNotBefore(start.getTime()) + .setCertificateNotAfter(end.getTime()) + .build(); + + } else { + spec = new KeyPairGeneratorSpec.Builder(context) + .setAlias(alias) + .setSubject(new X500Principal("CN=" + alias)) + .setSerialNumber(BigInteger.TEN) + .setStartDate(start.getTime()) + .setEndDate(end.getTime()) + .build(); + } + + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", + ANDROID_KEYSTORE); + keyPairGenerator.initialize(spec); + keyPairGenerator.generateKeyPair(); + } + } catch (Exception e) { + throw new CryptoException(e.getMessage()); + } + } else { + throw new CryptoException("GenerateNewKey - String is empty"); + } + + LogUtils.debug("Key pair are create"); + + } + + private static String encryptString(String alias, String text) throws CryptoException { + + if (!alias.isEmpty() && !text.isEmpty()) { + try { + KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null); + RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey(); + + Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + input.init(Cipher.ENCRYPT_MODE, publicKey); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + CipherOutputStream cipherOutputStream = new CipherOutputStream( + outputStream, input); + cipherOutputStream.write(text.getBytes("UTF-8")); + cipherOutputStream.close(); + + byte[] values = outputStream.toByteArray(); + + return Base64.encodeToString(values, Base64.DEFAULT); + + } catch (Exception e) { + throw new CryptoException(e.getMessage()); + } + } else { + throw new CryptoException("EncryptString - String is empty"); + } + } + + private static String decryptString(String alias, String text) throws CryptoException { + + if (!alias.isEmpty() && !text.isEmpty()) { + try { + KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null); + + Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey()); + + CipherInputStream cipherInputStream = new CipherInputStream( + new ByteArrayInputStream(Base64.decode(text, Base64.DEFAULT)), output); + + ArrayList values = new ArrayList<>(); + + int nextByte; + + while ((nextByte = cipherInputStream.read()) != -1) { + values.add((byte) nextByte); + } + + Byte[] bytes = values.toArray(new Byte[values.size()]); + + return new String(ArrayUtils.toPrimitive(bytes), 0, bytes.length, "UTF-8"); + } catch (Exception e) { + throw new CryptoException(e.getMessage()); + } + } else { + throw new CryptoException("EncryptString - String is empty"); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt b/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt deleted file mode 100644 index 264f45426..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/security/Scrambler.kt +++ /dev/null @@ -1,148 +0,0 @@ -@file:Suppress("DEPRECATION") - -package io.github.wulkanowy.utils.security - -import android.annotation.TargetApi -import android.content.Context -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES.JELLY_BEAN_MR2 -import android.os.Build.VERSION_CODES.M -import android.security.KeyPairGeneratorSpec -import android.security.keystore.KeyGenParameterSpec -import android.security.keystore.KeyProperties.DIGEST_SHA256 -import android.security.keystore.KeyProperties.DIGEST_SHA512 -import android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_OAEP -import android.security.keystore.KeyProperties.PURPOSE_DECRYPT -import android.security.keystore.KeyProperties.PURPOSE_ENCRYPT -import android.util.Base64.DEFAULT -import android.util.Base64.decode -import android.util.Base64.encode -import android.util.Base64.encodeToString -import timber.log.Timber -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.math.BigInteger -import java.nio.charset.Charset -import java.security.KeyPairGenerator -import java.security.KeyStore -import java.security.spec.MGF1ParameterSpec.SHA1 -import java.util.Calendar -import java.util.Calendar.YEAR -import javax.crypto.Cipher -import javax.crypto.Cipher.DECRYPT_MODE -import javax.crypto.Cipher.ENCRYPT_MODE -import javax.crypto.CipherInputStream -import javax.crypto.CipherOutputStream -import javax.crypto.spec.OAEPParameterSpec -import javax.crypto.spec.PSource.PSpecified -import javax.security.auth.x500.X500Principal - -private const val KEYSTORE_NAME = "AndroidKeyStore" - -private const val KEY_ALIAS = "wulkanowy_password" - -private val KEY_CHARSET = Charset.forName("UTF-8") - -private val isKeyPairExists: Boolean - get() = keyStore.getKey(KEY_ALIAS, null) != null - -private val keyStore: KeyStore - get() = KeyStore.getInstance(KEYSTORE_NAME).apply { load(null) } - -private val cipher: Cipher - get() { - return if (SDK_INT >= M) Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", "AndroidKeyStoreBCWorkaround") - else Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL") - } - -fun encrypt(plainText: String, context: Context): String { - if (plainText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") - - if (SDK_INT < JELLY_BEAN_MR2) { - return String(encode(plainText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET) - } - - return try { - if (!isKeyPairExists) generateKeyPair(context) - - cipher.let { - if (SDK_INT >= M) { - OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> - it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey, spec) - } - } else it.init(ENCRYPT_MODE, keyStore.getCertificate(KEY_ALIAS).publicKey) - - ByteArrayOutputStream().let { output -> - CipherOutputStream(output, it).apply { - write(plainText.toByteArray(KEY_CHARSET)) - close() - } - encodeToString(output.toByteArray(), DEFAULT) - } - } - } catch (exception: Exception) { - Timber.e(exception, "An error occurred while encrypting text") - String(encode(plainText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET) - } -} - -fun decrypt(cipherText: String): String { - if (cipherText.isEmpty()) throw ScramblerException("Text to be encrypted is empty") - - return try { - if (SDK_INT < JELLY_BEAN_MR2 || cipherText.length < 250) { - return String(decode(cipherText.toByteArray(KEY_CHARSET), DEFAULT), KEY_CHARSET) - } - - if (!isKeyPairExists) throw ScramblerException("KeyPair doesn't exist") - - cipher.let { - if (SDK_INT >= M) { - OAEPParameterSpec("SHA-256", "MGF1", SHA1, PSpecified.DEFAULT).let { spec -> - it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null), spec) - } - } else it.init(DECRYPT_MODE, keyStore.getKey(KEY_ALIAS, null)) - - CipherInputStream(ByteArrayInputStream(decode(cipherText, DEFAULT)), it).let { input -> - val values = ArrayList() - var nextByte = 0 - while ({ nextByte = input.read(); nextByte }() != -1) { - values.add(nextByte.toByte()) - } - val bytes = ByteArray(values.size) - for (i in bytes.indices) { - bytes[i] = values[i] - } - String(bytes, 0, bytes.size, KEY_CHARSET) - } - } - } catch (e: Exception) { - throw ScramblerException("An error occurred while decrypting text", e) - } -} - -@TargetApi(JELLY_BEAN_MR2) -private fun generateKeyPair(context: Context) { - (if (SDK_INT >= M) { - KeyGenParameterSpec.Builder(KEY_ALIAS, PURPOSE_DECRYPT or PURPOSE_ENCRYPT) - .setDigests(DIGEST_SHA256, DIGEST_SHA512) - .setEncryptionPaddings(ENCRYPTION_PADDING_RSA_OAEP) - .setCertificateSerialNumber(BigInteger.TEN) - .setCertificateSubject(X500Principal("CN=Wulkanowy")) - .build() - } else { - KeyPairGeneratorSpec.Builder(context) - .setAlias(KEY_ALIAS) - .setSubject(X500Principal("CN=Wulkanowy")) - .setSerialNumber(BigInteger.TEN) - .setStartDate(Calendar.getInstance().time) - .setEndDate(Calendar.getInstance().apply { add(YEAR, 99) }.time) - .build() - }).let { - KeyPairGenerator.getInstance("RSA", KEYSTORE_NAME).apply { - initialize(it) - genKeyPair() - } - } - Timber.i("A new KeyPair has been generated") -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/security/ScramblerException.kt b/app/src/main/java/io/github/wulkanowy/utils/security/ScramblerException.kt deleted file mode 100644 index 59f830fad..000000000 --- a/app/src/main/java/io/github/wulkanowy/utils/security/ScramblerException.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.github.wulkanowy.utils.security - -class ScramblerException : Exception { - constructor(message: String, cause: Throwable) : super(message, cause) - constructor(message: String) : super(message) -} diff --git a/app/src/main/play/contact-email.txt b/app/src/main/play/contact-email.txt deleted file mode 100644 index 851521eb7..000000000 --- a/app/src/main/play/contact-email.txt +++ /dev/null @@ -1 +0,0 @@ -wulkanowyinc@gmail.com diff --git a/app/src/main/play/contact-phone.txt b/app/src/main/play/contact-phone.txt deleted file mode 100644 index 552e53a58..000000000 --- a/app/src/main/play/contact-phone.txt +++ /dev/null @@ -1 +0,0 @@ -+48733393622 diff --git a/app/src/main/play/contact-website.txt b/app/src/main/play/contact-website.txt deleted file mode 100644 index 53f7bee6b..000000000 --- a/app/src/main/play/contact-website.txt +++ /dev/null @@ -1 +0,0 @@ -https://wulkanowy.github.io/ diff --git a/app/src/main/play/default-language.txt b/app/src/main/play/default-language.txt deleted file mode 100644 index 1134c4d5c..000000000 --- a/app/src/main/play/default-language.txt +++ /dev/null @@ -1 +0,0 @@ -pl-PL diff --git a/app/src/main/play/listings/pl-PL/full-description.txt b/app/src/main/play/listings/pl-PL/full-description.txt deleted file mode 100644 index 641b7706d..000000000 --- a/app/src/main/play/listings/pl-PL/full-description.txt +++ /dev/null @@ -1,14 +0,0 @@ -Aplikacja jest przeznaczona dla użytkowników dziennika VULCAN UONET+. - -Wyróżnione cechy i funkcje: -- obliczanie średniej ważonej, -- procentowy podgląd frekwencji, -- szczęśliwy numerek, -- podgląd lekcji zrealizowanych, -- ciemny motyw. -- brak reklam, -- tryb offline, -- powiadomienia. - -GitHub: https://github.com/wulkanowy/wulkanowy -Discord: https://discord.gg/vccAQBr diff --git a/app/src/main/play/listings/pl-PL/graphics/feature-graphic/feature.png b/app/src/main/play/listings/pl-PL/graphics/feature-graphic/feature.png deleted file mode 100644 index 094b25b6c..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/feature-graphic/feature.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/icon/icon.png b/app/src/main/play/listings/pl-PL/graphics/icon/icon.png deleted file mode 100644 index 8c33c2f92..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/icon/icon.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png deleted file mode 100644 index 56768bf57..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png deleted file mode 100644 index 83d9353ae..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png deleted file mode 100644 index f83a7af8b..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png deleted file mode 100644 index 90d5fef4f..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png deleted file mode 100644 index eadbf2db2..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png deleted file mode 100644 index 2a11a3db9..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png deleted file mode 100644 index d9b2f1c76..000000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/short-description.txt b/app/src/main/play/listings/pl-PL/short-description.txt deleted file mode 100644 index c850c159a..000000000 --- a/app/src/main/play/listings/pl-PL/short-description.txt +++ /dev/null @@ -1 +0,0 @@ -Nieoficjalna aplikacja ucznia i rodzica dla dziennika VULCAN UONET+ diff --git a/app/src/main/play/listings/pl-PL/title.txt b/app/src/main/play/listings/pl-PL/title.txt deleted file mode 100644 index 2d53a62a8..000000000 --- a/app/src/main/play/listings/pl-PL/title.txt +++ /dev/null @@ -1 +0,0 @@ -Wulkanowy Dzienniczek diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt deleted file mode 100644 index 68045da4a..000000000 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ /dev/null @@ -1,8 +0,0 @@ -Wersja 0.19.0 -- naprawiliśmy pokazywanie brakujących przedmiotów na liście podsumowania ocen -- ulepszyliśmy wygląd menadżera kont -- ulepszyliśmy wyszukiwarkę wiadomości -- dodaliśmy powiadomienia o proponowanych i końcowych ocenach -- dodaliśmy opcję udostępniania i drukowania wiadomości - -Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases diff --git a/app/src/main/res/drawable-anydpi-v24/ic_stat_grade.xml b/app/src/main/res/drawable-anydpi-v24/ic_stat_grade.xml deleted file mode 100644 index 21b406fdc..000000000 --- a/app/src/main/res/drawable-anydpi-v24/ic_stat_grade.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-anydpi-v24/ic_stat_luckynumber.xml b/app/src/main/res/drawable-anydpi-v24/ic_stat_luckynumber.xml deleted file mode 100644 index bee1c7072..000000000 --- a/app/src/main/res/drawable-anydpi-v24/ic_stat_luckynumber.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-anydpi-v24/ic_stat_message.xml b/app/src/main/res/drawable-anydpi-v24/ic_stat_message.xml deleted file mode 100644 index 89a8aef29..000000000 --- a/app/src/main/res/drawable-anydpi-v24/ic_stat_message.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-anydpi-v24/ic_stat_note.xml b/app/src/main/res/drawable-anydpi-v24/ic_stat_note.xml deleted file mode 100644 index 0f335336b..000000000 --- a/app/src/main/res/drawable-anydpi-v24/ic_stat_note.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-hdpi/ic_stat_grade.png b/app/src/main/res/drawable-hdpi/ic_stat_grade.png deleted file mode 100644 index d97efb5d4..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_luckynumber.png b/app/src/main/res/drawable-hdpi/ic_stat_luckynumber.png deleted file mode 100644 index b91c4ae6c..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_message.png b/app/src/main/res/drawable-hdpi/ic_stat_message.png deleted file mode 100644 index ce0fdabcb..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_note.png b/app/src/main/res/drawable-hdpi/ic_stat_note.png deleted file mode 100644 index 7318c4195..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_notify.png b/app/src/main/res/drawable-hdpi/ic_stat_notify.png new file mode 100644 index 000000000..34544980a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_stat_notify.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_push.png b/app/src/main/res/drawable-hdpi/ic_stat_push.png deleted file mode 100644 index 84578183f..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_push.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_stat_timetable.png b/app/src/main/res/drawable-hdpi/ic_stat_timetable.png deleted file mode 100644 index 201419d5d..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_stat_timetable.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_widget_account.png b/app/src/main/res/drawable-hdpi/ic_widget_account.png deleted file mode 100644 index 4cb5ac89e..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_widget_account.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_grade.png b/app/src/main/res/drawable-mdpi/ic_stat_grade.png deleted file mode 100644 index c85b2702c..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_luckynumber.png b/app/src/main/res/drawable-mdpi/ic_stat_luckynumber.png deleted file mode 100644 index bfced4eb0..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_message.png b/app/src/main/res/drawable-mdpi/ic_stat_message.png deleted file mode 100644 index b357b3210..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_note.png b/app/src/main/res/drawable-mdpi/ic_stat_note.png deleted file mode 100644 index 55a4fbbf4..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_notify.png b/app/src/main/res/drawable-mdpi/ic_stat_notify.png new file mode 100644 index 000000000..5564049af Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_stat_notify.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_push.png b/app/src/main/res/drawable-mdpi/ic_stat_push.png deleted file mode 100644 index d1e954b0c..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_push.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_stat_timetable.png b/app/src/main/res/drawable-mdpi/ic_stat_timetable.png deleted file mode 100644 index dcfe95f26..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_stat_timetable.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_widget_account.png b/app/src/main/res/drawable-mdpi/ic_widget_account.png deleted file mode 100644 index 237a6b6c2..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_widget_account.png and /dev/null differ diff --git a/app/src/main/res/drawable-night/background_header_note.xml b/app/src/main/res/drawable-night/background_header_note.xml deleted file mode 100644 index 6b594e7c6..000000000 --- a/app/src/main/res/drawable-night/background_header_note.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable-night/ic_all_divider.xml b/app/src/main/res/drawable-night/ic_all_divider.xml deleted file mode 100644 index cd444a285..000000000 --- a/app/src/main/res/drawable-night/ic_all_divider.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/layer_splash_background.xml b/app/src/main/res/drawable-v15/splash_background.xml similarity index 51% rename from app/src/main/res/drawable/layer_splash_background.xml rename to app/src/main/res/drawable-v15/splash_background.xml index 2cf46d1d0..c58c374a1 100644 --- a/app/src/main/res/drawable/layer_splash_background.xml +++ b/app/src/main/res/drawable-v15/splash_background.xml @@ -1,12 +1,14 @@ + - + + + android:gravity="center" + android:src="@mipmap/ic_launcher"/> diff --git a/app/src/main/res/drawable-v23/img_splash_logo.png b/app/src/main/res/drawable-v23/img_splash_logo.png deleted file mode 100644 index 61489d81b..000000000 Binary files a/app/src/main/res/drawable-v23/img_splash_logo.png and /dev/null differ diff --git a/app/src/main/res/drawable-v23/layer_splash_background.xml b/app/src/main/res/drawable-v23/layer_splash_background.xml deleted file mode 100644 index 1b4b64ec9..000000000 --- a/app/src/main/res/drawable-v23/layer_splash_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/drawable-v23/splash_background.xml b/app/src/main/res/drawable-v23/splash_background.xml new file mode 100644 index 000000000..611bb2a7a --- /dev/null +++ b/app/src/main/res/drawable-v23/splash_background.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_grade.png b/app/src/main/res/drawable-xhdpi/ic_stat_grade.png deleted file mode 100644 index c55ca7fdd..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_luckynumber.png b/app/src/main/res/drawable-xhdpi/ic_stat_luckynumber.png deleted file mode 100644 index 49e502ac0..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_message.png b/app/src/main/res/drawable-xhdpi/ic_stat_message.png deleted file mode 100644 index 0e67ade37..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_note.png b/app/src/main/res/drawable-xhdpi/ic_stat_note.png deleted file mode 100644 index ea674a793..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_notify.png b/app/src/main/res/drawable-xhdpi/ic_stat_notify.png new file mode 100644 index 000000000..fabb8760c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_stat_notify.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_push.png b/app/src/main/res/drawable-xhdpi/ic_stat_push.png deleted file mode 100644 index 79b38e63f..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_push.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_timetable.png b/app/src/main/res/drawable-xhdpi/ic_stat_timetable.png deleted file mode 100644 index 7264bd92a..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_stat_timetable.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_widget_account.png b/app/src/main/res/drawable-xhdpi/ic_widget_account.png deleted file mode 100644 index 0ea798a8a..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_widget_account.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_grade.png b/app/src/main/res/drawable-xxhdpi/ic_stat_grade.png deleted file mode 100644 index eeb6fa41b..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_grade.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_luckynumber.png b/app/src/main/res/drawable-xxhdpi/ic_stat_luckynumber.png deleted file mode 100644 index 9bab13731..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_luckynumber.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_message.png b/app/src/main/res/drawable-xxhdpi/ic_stat_message.png deleted file mode 100644 index 2e8818242..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_message.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_note.png b/app/src/main/res/drawable-xxhdpi/ic_stat_note.png deleted file mode 100644 index 174e1509b..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_note.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png b/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png new file mode 100644 index 000000000..c1d78d465 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_push.png b/app/src/main/res/drawable-xxhdpi/ic_stat_push.png deleted file mode 100644 index bc33cb5b1..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_push.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_timetable.png b/app/src/main/res/drawable-xxhdpi/ic_stat_timetable.png deleted file mode 100644 index 1fb37b092..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_stat_timetable.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_widget_account.png b/app/src/main/res/drawable-xxhdpi/ic_widget_account.png deleted file mode 100644 index 0f8933b17..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_widget_account.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_stat_notify.png b/app/src/main/res/drawable-xxxhdpi/ic_stat_notify.png new file mode 100644 index 000000000..ee89e6015 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_stat_notify.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_stat_push.png b/app/src/main/res/drawable-xxxhdpi/ic_stat_push.png deleted file mode 100644 index b354bd06c..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_stat_push.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_stat_timetable.png b/app/src/main/res/drawable-xxxhdpi/ic_stat_timetable.png deleted file mode 100644 index a95cc4f5d..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_stat_timetable.png and /dev/null differ diff --git a/app/src/main/res/drawable/background_header_note.xml b/app/src/main/res/drawable/background_header_note.xml deleted file mode 100644 index c21e55c6b..000000000 --- a/app/src/main/res/drawable/background_header_note.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/background_luckynumber_widget.xml b/app/src/main/res/drawable/background_luckynumber_widget.xml deleted file mode 100644 index f29744d0c..000000000 --- a/app/src/main/res/drawable/background_luckynumber_widget.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/background_luckynumber_widget_dark.xml b/app/src/main/res/drawable/background_luckynumber_widget_dark.xml deleted file mode 100644 index fa15fd857..000000000 --- a/app/src/main/res/drawable/background_luckynumber_widget_dark.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/background_timetable_time_left.xml b/app/src/main/res/drawable/background_timetable_time_left.xml deleted file mode 100644 index 0f3326112..000000000 --- a/app/src/main/res/drawable/background_timetable_time_left.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_about_creator.xml b/app/src/main/res/drawable/ic_about_creator.xml deleted file mode 100644 index c3daf609d..000000000 --- a/app/src/main/res/drawable/ic_about_creator.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_discord.xml b/app/src/main/res/drawable/ic_about_discord.xml deleted file mode 100644 index bcca42bf1..000000000 --- a/app/src/main/res/drawable/ic_about_discord.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_faq.xml b/app/src/main/res/drawable/ic_about_faq.xml deleted file mode 100644 index d6ab255b2..000000000 --- a/app/src/main/res/drawable/ic_about_faq.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_feedback.xml b/app/src/main/res/drawable/ic_about_feedback.xml deleted file mode 100644 index a348cb6a3..000000000 --- a/app/src/main/res/drawable/ic_about_feedback.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_homepage.xml b/app/src/main/res/drawable/ic_about_homepage.xml deleted file mode 100644 index 1ec608120..000000000 --- a/app/src/main/res/drawable/ic_about_homepage.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_licenses.xml b/app/src/main/res/drawable/ic_about_licenses.xml deleted file mode 100644 index 1a052734c..000000000 --- a/app/src/main/res/drawable/ic_about_licenses.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_about_privacy.xml b/app/src/main/res/drawable/ic_about_privacy.xml deleted file mode 100644 index 109f05df8..000000000 --- a/app/src/main/res/drawable/ic_about_privacy.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_alert_24dp.xml b/app/src/main/res/drawable/ic_alert_24dp.xml new file mode 100644 index 000000000..1c41b556d --- /dev/null +++ b/app/src/main/res/drawable/ic_alert_24dp.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_all_about.xml b/app/src/main/res/drawable/ic_all_about.xml deleted file mode 100644 index 3dfbbda19..000000000 --- a/app/src/main/res/drawable/ic_all_about.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_all_account.xml b/app/src/main/res/drawable/ic_all_account.xml deleted file mode 100644 index 0e917d5f9..000000000 --- a/app/src/main/res/drawable/ic_all_account.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_add.xml b/app/src/main/res/drawable/ic_all_add.xml deleted file mode 100644 index e45662935..000000000 --- a/app/src/main/res/drawable/ic_all_add.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_close_circle.xml b/app/src/main/res/drawable/ic_all_close_circle.xml deleted file mode 100644 index 3f89a8fa3..000000000 --- a/app/src/main/res/drawable/ic_all_close_circle.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_done.xml b/app/src/main/res/drawable/ic_all_done.xml deleted file mode 100644 index bb657f6ec..000000000 --- a/app/src/main/res/drawable/ic_all_done.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_done_all.xml b/app/src/main/res/drawable/ic_all_done_all.xml deleted file mode 100644 index e27672efa..000000000 --- a/app/src/main/res/drawable/ic_all_done_all.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_round_mark.xml b/app/src/main/res/drawable/ic_all_round_mark.xml deleted file mode 100644 index 91afb2334..000000000 --- a/app/src/main/res/drawable/ic_all_round_mark.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_attachment.xml b/app/src/main/res/drawable/ic_attachment.xml deleted file mode 100644 index c18714f5c..000000000 --- a/app/src/main/res/drawable/ic_attachment.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_divider.xml b/app/src/main/res/drawable/ic_border.xml similarity index 81% rename from app/src/main/res/drawable/ic_all_divider.xml rename to app/src/main/res/drawable/ic_border.xml index 61e964979..dc33b8aa2 100644 --- a/app/src/main/res/drawable/ic_all_divider.xml +++ b/app/src/main/res/drawable/ic_border.xml @@ -5,5 +5,5 @@ android:angle="270" android:centerColor="@android:color/transparent" android:centerX="0.01" - android:startColor="@color/colorDivider" /> - + android:startColor="#60606060" /> + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml deleted file mode 100644 index 3c728c59f..000000000 --- a/app/src/main/res/drawable/ic_check.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_chevron_left.xml b/app/src/main/res/drawable/ic_chevron_left.xml deleted file mode 100644 index ee3ff4be8..000000000 --- a/app/src/main/res/drawable/ic_chevron_left.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml deleted file mode 100644 index a6d734973..000000000 --- a/app/src/main/res/drawable/ic_chevron_right.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_error.xml b/app/src/main/res/drawable/ic_error.xml deleted file mode 100644 index bb4cb3025..000000000 --- a/app/src/main/res/drawable/ic_error.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_all_mark.xml b/app/src/main/res/drawable/ic_exclamation_24dp.xml similarity index 55% rename from app/src/main/res/drawable/ic_all_mark.xml rename to app/src/main/res/drawable/ic_exclamation_24dp.xml index 127216490..4d3c91cfb 100644 --- a/app/src/main/res/drawable/ic_all_mark.xml +++ b/app/src/main/res/drawable/ic_exclamation_24dp.xml @@ -1,9 +1,10 @@ + + android:viewportHeight="24" + android:viewportWidth="24"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_excuse_denied.xml b/app/src/main/res/drawable/ic_excuse_denied.xml deleted file mode 100644 index 218cfbdc4..000000000 --- a/app/src/main/res/drawable/ic_excuse_denied.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_excuse_waiting.xml b/app/src/main/res/drawable/ic_excuse_waiting.xml deleted file mode 100644 index 863418b7b..000000000 --- a/app/src/main/res/drawable/ic_excuse_waiting.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_fullscreen.xml b/app/src/main/res/drawable/ic_fullscreen.xml deleted file mode 100644 index 86b7649b6..000000000 --- a/app/src/main/res/drawable/ic_fullscreen.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_fullscreen_exit.xml b/app/src/main/res/drawable/ic_fullscreen_exit.xml deleted file mode 100644 index bb7140f29..000000000 --- a/app/src/main/res/drawable/ic_fullscreen_exit.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index ee11f89d1..c5ecc7474 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,15 +1,17 @@ - - - + android:viewportHeight="51.67464" + android:viewportWidth="51.67464"> + + + diff --git a/app/src/main/res/drawable/ic_main_attendance.xml b/app/src/main/res/drawable/ic_main_attendance.xml deleted file mode 100644 index c42a17b3d..000000000 --- a/app/src/main/res/drawable/ic_main_attendance.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_main_exam.xml b/app/src/main/res/drawable/ic_main_exam.xml deleted file mode 100644 index a705c0a4b..000000000 --- a/app/src/main/res/drawable/ic_main_exam.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_main_grade.xml b/app/src/main/res/drawable/ic_main_grade.xml deleted file mode 100644 index bf4c2cf20..000000000 --- a/app/src/main/res/drawable/ic_main_grade.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_main_more.xml b/app/src/main/res/drawable/ic_main_more.xml deleted file mode 100644 index f57a72456..000000000 --- a/app/src/main/res/drawable/ic_main_more.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_main_timetable.xml b/app/src/main/res/drawable/ic_main_timetable.xml deleted file mode 100644 index b8f5cb855..000000000 --- a/app/src/main/res/drawable/ic_main_timetable.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_attendance_24dp.xml b/app/src/main/res/drawable/ic_menu_attendance_24dp.xml new file mode 100644 index 000000000..fdef73225 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_attendance_24dp.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_attendance_summary.xml b/app/src/main/res/drawable/ic_menu_attendance_summary.xml deleted file mode 100644 index f0dab549d..000000000 --- a/app/src/main/res/drawable/ic_menu_attendance_summary.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml b/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml new file mode 100644 index 000000000..50726abd1 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_grade_26dp.xml b/app/src/main/res/drawable/ic_menu_grade_26dp.xml new file mode 100644 index 000000000..61506dada --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_grade_26dp.xml @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_grade_semester.xml b/app/src/main/res/drawable/ic_menu_grade_semester.xml deleted file mode 100644 index 8eb86922a..000000000 --- a/app/src/main/res/drawable/ic_menu_grade_semester.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_delete.xml b/app/src/main/res/drawable/ic_menu_message_delete.xml deleted file mode 100644 index e60947c89..000000000 --- a/app/src/main/res/drawable/ic_menu_message_delete.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_forward.xml b/app/src/main/res/drawable/ic_menu_message_forward.xml deleted file mode 100644 index 97e34ddac..000000000 --- a/app/src/main/res/drawable/ic_menu_message_forward.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_print.xml b/app/src/main/res/drawable/ic_menu_message_print.xml deleted file mode 100644 index 204b0f6e3..000000000 --- a/app/src/main/res/drawable/ic_menu_message_print.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_menu_message_reply.xml b/app/src/main/res/drawable/ic_menu_message_reply.xml deleted file mode 100644 index d9c667114..000000000 --- a/app/src/main/res/drawable/ic_menu_message_reply.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_send.xml b/app/src/main/res/drawable/ic_menu_message_send.xml deleted file mode 100644 index fe72265f6..000000000 --- a/app/src/main/res/drawable/ic_menu_message_send.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_share.xml b/app/src/main/res/drawable/ic_menu_message_share.xml deleted file mode 100644 index 67a8ee494..000000000 --- a/app/src/main/res/drawable/ic_menu_message_share.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_message_write.xml b/app/src/main/res/drawable/ic_menu_message_write.xml deleted file mode 100644 index 7068aa5fe..000000000 --- a/app/src/main/res/drawable/ic_menu_message_write.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_other_24dp.xml b/app/src/main/res/drawable/ic_menu_other_24dp.xml new file mode 100644 index 000000000..9fed586b0 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_other_24dp.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_timetable_24dp.xml b/app/src/main/res/drawable/ic_menu_timetable_24dp.xml new file mode 100644 index 000000000..a689dc064 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_timetable_24dp.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_timetable_lessons_completed.xml b/app/src/main/res/drawable/ic_menu_timetable_lessons_completed.xml deleted file mode 100644 index a521adeea..000000000 --- a/app/src/main/res/drawable/ic_menu_timetable_lessons_completed.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_homework.xml b/app/src/main/res/drawable/ic_more_homework.xml deleted file mode 100644 index 9641ff70f..000000000 --- a/app/src/main/res/drawable/ic_more_homework.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_lucky_number.xml b/app/src/main/res/drawable/ic_more_lucky_number.xml deleted file mode 100644 index d644288c0..000000000 --- a/app/src/main/res/drawable/ic_more_lucky_number.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_messages.xml b/app/src/main/res/drawable/ic_more_messages.xml deleted file mode 100644 index 20c54e01f..000000000 --- a/app/src/main/res/drawable/ic_more_messages.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_mobile_devices.xml b/app/src/main/res/drawable/ic_more_mobile_devices.xml deleted file mode 100644 index 6adeb6cff..000000000 --- a/app/src/main/res/drawable/ic_more_mobile_devices.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_note.xml b/app/src/main/res/drawable/ic_more_note.xml deleted file mode 100644 index 47ba29cbe..000000000 --- a/app/src/main/res/drawable/ic_more_note.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_schoolandteachers.xml b/app/src/main/res/drawable/ic_more_schoolandteachers.xml deleted file mode 100644 index 9cb9aee0e..000000000 --- a/app/src/main/res/drawable/ic_more_schoolandteachers.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_more_settings.xml b/app/src/main/res/drawable/ic_more_settings.xml deleted file mode 100644 index 334eb11f7..000000000 --- a/app/src/main/res/drawable/ic_more_settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml deleted file mode 100644 index cc2d1e04f..000000000 --- a/app/src/main/res/drawable/ic_refresh.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_school_directions.xml b/app/src/main/res/drawable/ic_school_directions.xml deleted file mode 100644 index c48db1da0..000000000 --- a/app/src/main/res/drawable/ic_school_directions.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_school_phone.xml b/app/src/main/res/drawable/ic_school_phone.xml deleted file mode 100644 index 7e3d7991e..000000000 --- a/app/src/main/res/drawable/ic_school_phone.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml deleted file mode 100644 index cd9985cb1..000000000 --- a/app/src/main/res/drawable/ic_search.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml deleted file mode 100644 index 045bbc0c0..000000000 --- a/app/src/main/res/drawable/ic_share.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_timetable_swap.xml b/app/src/main/res/drawable/ic_swap_30dp.xml similarity index 85% rename from app/src/main/res/drawable/ic_timetable_swap.xml rename to app/src/main/res/drawable/ic_swap_30dp.xml index 4055623a7..01eee893c 100644 --- a/app/src/main/res/drawable/ic_timetable_swap.xml +++ b/app/src/main/res/drawable/ic_swap_30dp.xml @@ -4,6 +4,6 @@ android:viewportHeight="24.0" android:viewportWidth="24.0"> diff --git a/app/src/main/res/drawable/ic_widget_chevron.png b/app/src/main/res/drawable/ic_widget_chevron.png deleted file mode 100644 index 34345521a..000000000 Binary files a/app/src/main/res/drawable/ic_widget_chevron.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_widget_clover.png b/app/src/main/res/drawable/ic_widget_clover.png deleted file mode 100644 index b1a7832a2..000000000 Binary files a/app/src/main/res/drawable/ic_widget_clover.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_wrench_24dp.xml b/app/src/main/res/drawable/ic_wrench_24dp.xml new file mode 100644 index 000000000..8f3a86faa --- /dev/null +++ b/app/src/main/res/drawable/ic_wrench_24dp.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/img_luckynumber_widget_preview.png b/app/src/main/res/drawable/img_luckynumber_widget_preview.png deleted file mode 100644 index 539b0a598..000000000 Binary files a/app/src/main/res/drawable/img_luckynumber_widget_preview.png and /dev/null differ diff --git a/app/src/main/res/drawable/img_splash_512px.png b/app/src/main/res/drawable/img_splash_512px.png new file mode 100644 index 000000000..9d8f403c2 Binary files /dev/null and b/app/src/main/res/drawable/img_splash_512px.png differ diff --git a/app/src/main/res/drawable/img_splash_logo.png b/app/src/main/res/drawable/img_splash_logo.png deleted file mode 100644 index fb521bf65..000000000 Binary files a/app/src/main/res/drawable/img_splash_logo.png and /dev/null differ diff --git a/app/src/main/res/drawable/img_timetable_widget_preview.png b/app/src/main/res/drawable/img_timetable_widget_preview.png deleted file mode 100644 index 550260258..000000000 Binary files a/app/src/main/res/drawable/img_timetable_widget_preview.png and /dev/null differ diff --git a/app/src/main/res/drawable/splash_background.xml b/app/src/main/res/drawable/splash_background.xml new file mode 100644 index 000000000..0b79b6729 --- /dev/null +++ b/app/src/main/res/drawable/splash_background.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 3841b25cd..670959826 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -1,17 +1,138 @@ - + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context="io.github.wulkanowy.ui.login.LoginActivity"> - + + android:layout_height="match_parent" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:gravity="center" + android:visibility="gone"> - + + + + + - + android:layout_height="wrap_content"> + + + + + + + + + + + + + + + + + + + + + + + +