diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a81b333f..d744bdd1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,14 +10,39 @@ on: workflow_dispatch: jobs: + build: + name: Pre-build + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: fkirc/skip-duplicate-actions@master + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - name: Build + run: ./gradlew --build-cache compileFdroidDebugUnitTestKotlin preFdroidDebugAndroidTestBuild dexBuilderFdroidDebugAndroidTest packageFdroidDebug packageFdroidDebugAndroidTest + - name: Prepare build cache + run: tar -cf prebuild.tar .build-cache .gradle app/build + - uses: actions/upload-artifact@v2 + with: + name: prebuild.tar + path: prebuild.tar + unit-tests: name: Unit tests runs-on: ubuntu-latest timeout-minutes: 10 + needs: [ build ] steps: - - uses: fkirc/skip-duplicate-actions@master - uses: actions/checkout@v2 - - uses: gradle/wrapper-validation-action@v1 - uses: actions/setup-java@v1 with: java-version: 11 @@ -27,6 +52,11 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar - name: Unit tests run: | ./gradlew --build-cache -Pcoverage testFdroidDebugUnitTest --stacktrace @@ -35,12 +65,49 @@ jobs: with: flags: unit + instrumentation-tests: + name: Instrumentation tests + runs-on: macOS-latest + timeout-minutes: 15 + needs: [ build ] + strategy: + fail-fast: true + matrix: + api-level: [21, 29] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar + - name: Instrumentation tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86 + script: | + ./gradlew --build-cache -Pcoverage connectedFdroidDebugAndroidTest --stacktrace + ./gradlew --build-cache -Pcoverage jacocoTestReport --stacktrace + - uses: codecov/codecov-action@v1 + with: + flags: instrumented,api-${{ matrix.api-level }} + deploy-google-play: name: Deploy to google play runs-on: ubuntu-latest timeout-minutes: 10 environment: google-play - needs: [ unit-tests ] + needs: [ build, unit-tests, instrumentation-tests ] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') steps: - uses: actions/checkout@v2 @@ -53,6 +120,11 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} + - uses: actions/download-artifact@v2 + with: + name: prebuild.tar + - name: Extract build cache + run: tar -xf prebuild.tar - name: Decrypt keys env: ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }} @@ -68,135 +140,3 @@ jobs: PLAY_SERVICE_ACCOUNT_EMAIL: ${{ secrets.PLAY_SERVICE_ACCOUNT_EMAIL }} PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }} run: ./gradlew publishPlayRelease -PenableFirebase --stacktrace; - - deploy-appcenter: - name: Deploy to App Center - runs-on: ubuntu-latest - timeout-minutes: 10 - environment: app-center - if: github.ref != 'refs/heads/develop' - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: 11 - - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }} - - name: Set run number with offset - env: - BUILD_NUMBER_OFFSET: ${{ secrets.BUILD_NUMBER_OFFSET }} - run: echo "RUN_NUMBER=$((GITHUB_RUN_NUMBER+BUILD_NUMBER_OFFSET))" >> $GITHUB_ENV - - name: Prepare build configuration - run: | - sed -i -e "s#applicationIdSuffix \".dev\"#applicationIdSuffix \".${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/build.gradle - sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/google-services.json - sed -i -e "s#.dev\"#.${GITHUB_HEAD_REF//[-.\/]/_}\"#" app/src/debug/agconnect-services.json - sed -i -e '/versionNameSuffix/d' app/build.gradle - - name: Add signing config - run: | - cat >> app/build.gradle <> $GITHUB_ENV - - name: Add signing config - run: | - cat >> app/build.gradle <; +} diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json deleted file mode 100644 index 6a56ac64..00000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/34.json +++ /dev/null @@ -1,2142 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 34, - "identityHash": "c024cc4e19e009a03303e2bfe5c34b48", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mobileBaseUrl", - "columnName": "mobile_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "login_type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginMode", - "columnName": "login_mode", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "certificateKey", - "columnName": "certificate_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "privateKey", - "columnName": "private_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isParent", - "columnName": "is_parent", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "user_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "school_short", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolName", - "columnName": "school_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "className", - "columnName": "class_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isCurrent", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "registrationDate", - "columnName": "registration_date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Semesters", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryName", - "columnName": "diary_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolYear", - "columnName": "school_year", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterName", - "columnName": "semester_name", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unitId", - "columnName": "unit_id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "semester_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "entryDate", - "columnName": "entry_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subjectOld", - "columnName": "subjectOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "room", - "columnName": "room", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "roomOld", - "columnName": "roomOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherOld", - "columnName": "teacherOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "info", - "columnName": "info", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isStudentPlan", - "columnName": "student_plan", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "changes", - "columnName": "changes", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "canceled", - "columnName": "canceled", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "timeId", - "columnName": "time_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excused", - "columnName": "excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "deleted", - "columnName": "deleted", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excusable", - "columnName": "excusable", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excuseStatus", - "columnName": "excuse_status", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subjectId", - "columnName": "subject_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "month", - "columnName": "month", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceExcused", - "columnName": "absence_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceForSchoolReasons", - "columnName": "absence_for_school_reasons", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "latenessExcused", - "columnName": "lateness_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isRead", - "columnName": "is_read", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "entry", - "columnName": "entry", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "value", - "columnName": "value", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "modifier", - "columnName": "modifier", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "comment", - "columnName": "comment", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "color", - "columnName": "color", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gradeSymbol", - "columnName": "grade_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weight", - "columnName": "weight", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weightValue", - "columnName": "weightValue", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isPredictedGradeNotified", - "columnName": "is_predicted_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isFinalGradeNotified", - "columnName": "is_final_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "predictedGradeLastChange", - "columnName": "predicted_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "finalGradeLastChange", - "columnName": "final_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classAverage", - "columnName": "class_average", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentAverage", - "columnName": "student_average", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classAmounts", - "columnName": "class_amounts", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentAmounts", - "columnName": "student_amounts", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "amounts", - "columnName": "amounts", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentGrade", - "columnName": "student_grade", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "senderId", - "columnName": "sender_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "recipient", - "columnName": "recipient_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "folderId", - "columnName": "folder_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unread", - "columnName": "unread", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", - "fields": [ - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "oneDriveId", - "columnName": "one_drive_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "real_id" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isRead", - "columnName": "is_read", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "category", - "columnName": "category", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "categoryType", - "columnName": "category_type", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isPointsShow", - "columnName": "is_points_show", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "points", - "columnName": "points", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "entryDate", - "columnName": "entry_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "attachments", - "columnName": "attachments", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "luckyNumber", - "columnName": "lucky_number", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "topic", - "columnName": "topic", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "substitution", - "columnName": "substitution", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "resources", - "columnName": "resources", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "ReportingUnits", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unitId", - "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": "userLoginId", - "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": "userLoginId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "deviceId", - "columnName": "device_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "shortName", - "columnName": "short_name", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "contact", - "columnName": "contact", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "headmaster", - "columnName": "headmaster", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pedagogue", - "columnName": "pedagogue", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "agenda", - "columnName": "agenda", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "presentOnConference", - "columnName": "present_on_conference", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "conferenceId", - "columnName": "conference_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "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, 'c024cc4e19e009a03303e2bfe5c34b48')" - ] - } -} \ No newline at end of file diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/35.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/35.json deleted file mode 100644 index f166b2d7..00000000 --- a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/35.json +++ /dev/null @@ -1,2148 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 35, - "identityHash": "15fb91ec180fe60bf400cfa729c3418d", - "entities": [ - { - "tableName": "Students", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "nick", - "columnName": "nick", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "avatarColor", - "columnName": "avatar_color", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "scrapperBaseUrl", - "columnName": "scrapper_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "mobileBaseUrl", - "columnName": "mobile_base_url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginType", - "columnName": "login_type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "loginMode", - "columnName": "login_mode", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "certificateKey", - "columnName": "certificate_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "privateKey", - "columnName": "private_key", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isParent", - "columnName": "is_parent", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "symbol", - "columnName": "symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "userLoginId", - "columnName": "user_login_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "userName", - "columnName": "user_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentName", - "columnName": "student_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolSymbol", - "columnName": "school_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolShortName", - "columnName": "school_short", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolName", - "columnName": "school_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "className", - "columnName": "class_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isCurrent", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "registrationDate", - "columnName": "registration_date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Students_email_symbol_student_id_school_id_class_id", - "unique": true, - "columnNames": [ - "email", - "symbol", - "student_id", - "school_id", - "class_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Semesters", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "current", - "columnName": "is_current", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryName", - "columnName": "diary_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "schoolYear", - "columnName": "school_year", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterName", - "columnName": "semester_name", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unitId", - "columnName": "unit_id", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [ - { - "name": "index_Semesters_student_id_diary_id_semester_id", - "unique": true, - "columnNames": [ - "student_id", - "diary_id", - "semester_id" - ], - "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" - } - ], - "foreignKeys": [] - }, - { - "tableName": "Exams", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "entryDate", - "columnName": "entry_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Timetable", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subjectOld", - "columnName": "subjectOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "group", - "columnName": "group", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "room", - "columnName": "room", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "roomOld", - "columnName": "roomOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherOld", - "columnName": "teacherOld", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "info", - "columnName": "info", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "isStudentPlan", - "columnName": "student_plan", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "changes", - "columnName": "changes", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "canceled", - "columnName": "canceled", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Attendance", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "timeId", - "columnName": "time_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excused", - "columnName": "excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "deleted", - "columnName": "deleted", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excusable", - "columnName": "excusable", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "excuseStatus", - "columnName": "excuse_status", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "AttendanceSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subjectId", - "columnName": "subject_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "month", - "columnName": "month", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "presence", - "columnName": "presence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceExcused", - "columnName": "absence_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "absenceForSchoolReasons", - "columnName": "absence_for_school_reasons", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "lateness", - "columnName": "lateness", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "latenessExcused", - "columnName": "lateness_excused", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "exemption", - "columnName": "exemption", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Grades", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isRead", - "columnName": "is_read", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "entry", - "columnName": "entry", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "value", - "columnName": "value", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "modifier", - "columnName": "modifier", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "comment", - "columnName": "comment", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "color", - "columnName": "color", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gradeSymbol", - "columnName": "grade_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "description", - "columnName": "description", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weight", - "columnName": "weight", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "weightValue", - "columnName": "weightValue", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesSummary", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isPredictedGradeNotified", - "columnName": "is_predicted_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isFinalGradeNotified", - "columnName": "is_final_grade_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "predictedGradeLastChange", - "columnName": "predicted_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "finalGradeLastChange", - "columnName": "final_grade_last_change", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "position", - "columnName": "position", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "predictedGrade", - "columnName": "predicted_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalGrade", - "columnName": "final_grade", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "proposedPoints", - "columnName": "proposed_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "finalPoints", - "columnName": "final_points", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pointsSum", - "columnName": "points_sum", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "average", - "columnName": "average", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradePartialStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classAverage", - "columnName": "class_average", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentAverage", - "columnName": "student_average", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "classAmounts", - "columnName": "class_amounts", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentAmounts", - "columnName": "student_amounts", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradesPointsStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "others", - "columnName": "others", - "affinity": "REAL", - "notNull": true - }, - { - "fieldPath": "student", - "columnName": "student", - "affinity": "REAL", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "GradeSemesterStatistics", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "amounts", - "columnName": "amounts", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentGrade", - "columnName": "student_grade", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Messages", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unreadBy", - "columnName": "unread_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "readBy", - "columnName": "read_by", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sender", - "columnName": "sender_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "senderId", - "columnName": "sender_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "recipient", - "columnName": "recipient_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "folderId", - "columnName": "folder_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unread", - "columnName": "unread", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "removed", - "columnName": "removed", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "hasAttachments", - "columnName": "has_attachments", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "MessageAttachments", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", - "fields": [ - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "messageId", - "columnName": "message_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "oneDriveId", - "columnName": "one_drive_id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "filename", - "columnName": "filename", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "real_id" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Notes", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isRead", - "columnName": "is_read", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "category", - "columnName": "category", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "categoryType", - "columnName": "category_type", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isPointsShow", - "columnName": "is_points_show", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "points", - "columnName": "points", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Homework", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDone", - "columnName": "is_done", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "semesterId", - "columnName": "semester_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "entryDate", - "columnName": "entry_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "content", - "columnName": "content", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "attachments", - "columnName": "attachments", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Subjects", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "realId", - "columnName": "real_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "LuckyNumbers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isNotified", - "columnName": "is_notified", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "luckyNumber", - "columnName": "lucky_number", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "CompletedLesson", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "number", - "columnName": "number", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "topic", - "columnName": "topic", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacher", - "columnName": "teacher", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "teacherSymbol", - "columnName": "teacher_symbol", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "substitution", - "columnName": "substitution", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "absence", - "columnName": "absence", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "resources", - "columnName": "resources", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "ReportingUnits", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "unitId", - "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": "userLoginId", - "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": "userLoginId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "deviceId", - "columnName": "device_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Teachers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "shortName", - "columnName": "short_name", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "School", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "classId", - "columnName": "class_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "contact", - "columnName": "contact", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "headmaster", - "columnName": "headmaster", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "pedagogue", - "columnName": "pedagogue", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "Conferences", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "title", - "columnName": "title", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "agenda", - "columnName": "agenda", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "presentOnConference", - "columnName": "present_on_conference", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "conferenceId", - "columnName": "conference_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "TimetableAdditional", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "diaryId", - "columnName": "diary_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "start", - "columnName": "start", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "end", - "columnName": "end", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "date", - "columnName": "date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "subject", - "columnName": "subject", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "StudentInfo", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "studentId", - "columnName": "student_id", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "fullName", - "columnName": "full_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstName", - "columnName": "first_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "secondName", - "columnName": "second_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "surname", - "columnName": "surname", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "birthDate", - "columnName": "birth_date", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "birthPlace", - "columnName": "birth_place", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "gender", - "columnName": "gender", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "hasPolishCitizenship", - "columnName": "has_polish_citizenship", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "familyName", - "columnName": "family_name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "parentsNames", - "columnName": "parents_names", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "address", - "columnName": "address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "registeredAddress", - "columnName": "registered_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "correspondenceAddress", - "columnName": "correspondence_address", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "phoneNumber", - "columnName": "phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "cellPhoneNumber", - "columnName": "cell_phone_number", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "email", - "columnName": "email", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "firstGuardian.fullName", - "columnName": "first_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.kinship", - "columnName": "first_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.address", - "columnName": "first_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.phones", - "columnName": "first_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "firstGuardian.email", - "columnName": "first_guardian_email", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.fullName", - "columnName": "second_guardian_full_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.kinship", - "columnName": "second_guardian_kinship", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.address", - "columnName": "second_guardian_address", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.phones", - "columnName": "second_guardian_phones", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "secondGuardian.email", - "columnName": "second_guardian_email", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "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, '15fb91ec180fe60bf400cfa729c3418d')" - ] - } -} \ No newline at end of file diff --git a/app/src/test/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt similarity index 73% rename from app/src/test/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt index f9fc7631..aca28732 100644 --- a/app/src/test/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/AbstractMigrationTest.kt @@ -9,7 +9,6 @@ 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 io.github.wulkanowy.utils.AppInfo import org.junit.Rule abstract class AbstractMigrationTest { @@ -25,16 +24,12 @@ abstract class AbstractMigrationTest { fun getMigratedRoomDatabase(): AppDatabase { val context = ApplicationProvider.getApplicationContext() - val database = Room.databaseBuilder( - ApplicationProvider.getApplicationContext(), - AppDatabase::class.java, - dbName - ).addMigrations( - *AppDatabase.getMigrations( - SharedPrefProvider(PreferenceManager.getDefaultSharedPreferences(context)), - AppInfo() + val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(), + AppDatabase::class.java, dbName) + .addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager + .getDefaultSharedPreferences(context))) ) - ).build() + .build() // close the database and release any stream resources when the test finishes helper.closeWhenFinished(database) return database diff --git a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt similarity index 92% rename from app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt index a0290473..b312048d 100644 --- a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration12Test.kt @@ -2,20 +2,14 @@ package io.github.wulkanowy.data.db.migrations import android.content.ContentValues import android.database.sqlite.SQLiteDatabase.CONFLICT_FAIL -import android.os.Build import androidx.sqlite.db.SupportSQLiteDatabase -import dagger.hilt.android.testing.HiltAndroidTest -import dagger.hilt.android.testing.HiltTestApplication +import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking import org.junit.Test import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config import kotlin.test.assertEquals -@HiltAndroidTest -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class) +@RunWith(AndroidJUnit4::class) class Migration12Test : AbstractMigrationTest() { @Test diff --git a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt similarity index 95% rename from app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt index 2350da45..15e99f5f 100644 --- a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration13Test.kt @@ -2,26 +2,17 @@ package io.github.wulkanowy.data.db.migrations import android.content.ContentValues import android.database.sqlite.SQLiteDatabase -import android.os.Build import androidx.sqlite.db.SupportSQLiteDatabase -import dagger.hilt.android.testing.HiltAndroidTest -import dagger.hilt.android.testing.HiltTestApplication import io.github.wulkanowy.data.db.Converters import io.github.wulkanowy.data.db.entities.Semester import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config import java.time.LocalDate.of import kotlin.test.assertFalse import kotlin.test.assertTrue -@HiltAndroidTest -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class) class Migration13Test : AbstractMigrationTest() { @Test diff --git a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt similarity index 91% rename from app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt rename to app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt index 8e744f27..75955258 100644 --- a/app/src/test/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/migrations/Migration27Test.kt @@ -2,21 +2,12 @@ package io.github.wulkanowy.data.db.migrations import android.content.ContentValues import android.database.sqlite.SQLiteDatabase -import android.os.Build import androidx.sqlite.db.SupportSQLiteDatabase -import dagger.hilt.android.testing.HiltAndroidTest -import dagger.hilt.android.testing.HiltTestApplication import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config import kotlin.random.Random -@HiltAndroidTest -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1], application = HiltTestApplication::class) class Migration27Test : AbstractMigrationTest() { @Test diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7b714fb2..ac8d3be4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,7 +56,7 @@ android:name=".ui.modules.login.LoginActivity" android:configChanges="orientation|screenSize" android:label="@string/login_title" - android:theme="@style/WulkanowyTheme.Login" + android:theme="@style/WulkanowyTheme.NoActionBar" android:windowSoftInputMode="adjustResize" /> { + 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(), + Migration27(), + Migration28(), + Migration29(), + Migration30(), + Migration31(), + Migration32(), + Migration33() + ) + } - fun newInstance( - context: Context, - sharedPrefProvider: SharedPrefProvider, - appInfo: AppInfo - ) = Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database") - .setJournalMode(TRUNCATE) - .fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1) - .fallbackToDestructiveMigrationOnDowngrade() - .addMigrations(*getMigrations(sharedPrefProvider, appInfo)) - .build() + 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 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 index d9aa2436..57f3005a 100644 --- 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 @@ -13,7 +13,4 @@ interface LuckyNumberDao : BaseDao { @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date") fun load(studentId: Int, date: LocalDate): Flow - - @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date >= :start AND date <= :end") - fun getAll(studentId: Int, start: LocalDate, end: LocalDate): Flow> } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt index c2787ac3..943f3f0c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt @@ -9,6 +9,6 @@ import javax.inject.Singleton @Dao interface RecipientDao : BaseDao { - @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role") - suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List + @Query("SELECT * FROM Recipients WHERE student_id = :userLoginId AND unit_id = :unitId AND role = :role") + suspend fun loadAll(userLoginId: Int, unitId: Int, role: Int): List } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt index 0ad2ee59..e9c5f157 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt @@ -8,7 +8,7 @@ import androidx.room.Query import androidx.room.Transaction import androidx.room.Update import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar +import io.github.wulkanowy.data.db.entities.StudentNick import io.github.wulkanowy.data.db.entities.StudentWithSemesters import javax.inject.Singleton @@ -23,13 +23,13 @@ interface StudentDao { suspend fun delete(student: Student) @Update(entity = Student::class) - suspend fun update(studentNickAndAvatar: StudentNickAndAvatar) + suspend fun update(studentNick: StudentNick) @Query("SELECT * FROM Students WHERE is_current = 1") suspend fun loadCurrent(): Student? @Query("SELECT * FROM Students WHERE id = :id") - suspend fun loadById(id: Long): Student? + suspend fun loadById(id: Int): Student? @Query("SELECT * FROM Students") suspend fun loadAll(): List 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 index 7b6e0dbf..1f10a164 100644 --- 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 @@ -10,7 +10,7 @@ import java.time.LocalDateTime data class Message( @ColumnInfo(name = "student_id") - val studentId: Long, + val studentId: Int, @ColumnInfo(name = "real_id") val realId: Int, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt index 3021da72..b1f1f353 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt @@ -9,7 +9,7 @@ import java.io.Serializable data class Recipient( @ColumnInfo(name = "student_id") - val studentId: Int, + val userLoginId: Int, @ColumnInfo(name = "real_id") val realId: String, diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt index af9fe831..6b60c814 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt @@ -81,7 +81,4 @@ data class Student( var id: Long = 0 var nick = "" - - @ColumnInfo(name = "avatar_color") - var avatarColor = 0L } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNick.kt similarity index 57% rename from app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt rename to app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNick.kt index 546059ee..71f48f7a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNick.kt @@ -1,17 +1,13 @@ package io.github.wulkanowy.data.db.entities -import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import java.io.Serializable @Entity -data class StudentNickAndAvatar( +data class StudentNick( - val nick: String, - - @ColumnInfo(name = "avatar_color") - var avatarColor: Long + val nick: String ) : Serializable { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt deleted file mode 100644 index 2c57eb00..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.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 Migration34 : Migration(33, 34) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("DELETE FROM ReportingUnits") - database.execSQL("DELETE FROM Recipients") - } -} - diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt deleted file mode 100644 index cc540388..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.wulkanowy.data.db.migrations - -import androidx.core.database.getLongOrNull -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase -import io.github.wulkanowy.utils.AppInfo - -class Migration35(private val appInfo: AppInfo) : Migration(34, 35) { - - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0") - - val studentsCursor = database.query("SELECT * FROM Students") - - while (studentsCursor.moveToNext()) { - val studentId = studentsCursor.getLongOrNull(0) - database.execSQL( - """UPDATE Students - SET avatar_color = ${appInfo.defaultColorsForAvatar.random()} - WHERE id = $studentId""" - ) - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt index b25802d2..fbd40433 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt @@ -5,9 +5,10 @@ import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.pojos.GradeStatisticsItem -import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics -import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester +import io.github.wulkanowy.ui.modules.grade.statistics.ViewType import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject +import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester +import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics @JvmName("mapToEntitiesSubject") fun List.mapToEntities(semester: Semester) = map { @@ -50,7 +51,7 @@ fun List.mapToEntities(semester: Semester) = map { fun List.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map { GradeStatisticsItem( - type = GradeStatisticsItem.DataType.PARTIAL, + type = ViewType.PARTIAL, average = it.classAverage, partial = it, points = null, @@ -60,7 +61,7 @@ fun List.mapPartialToStatisticItems() = filterNot { it.c fun List.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map { GradeStatisticsItem( - type = GradeStatisticsItem.DataType.SEMESTER, + type = ViewType.SEMESTER, partial = null, points = null, average = "", @@ -70,7 +71,7 @@ fun List.mapSemesterToStatisticItems() = filterNot { it fun List.mapPointsToStatisticsItems() = map { GradeStatisticsItem( - type = GradeStatisticsItem.DataType.POINTS, + type = ViewType.POINTS, partial = null, semester = null, average = "", diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt index 913e4d03..2c815b30 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt @@ -4,14 +4,14 @@ import io.github.wulkanowy.data.db.entities.Message import io.github.wulkanowy.data.db.entities.MessageAttachment import io.github.wulkanowy.data.db.entities.Recipient import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient +import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment import java.time.LocalDateTime import io.github.wulkanowy.sdk.pojo.Message as SdkMessage -import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment -import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient fun List.mapToEntities(student: Student) = map { Message( - studentId = student.id, + studentId = student.id.toInt(), realId = it.id ?: 0, messageId = it.messageId ?: 0, sender = it.sender?.name.orEmpty(), diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt index 80bddaab..9996f680 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt @@ -5,7 +5,7 @@ import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient fun List.mapToEntities(userLoginId: Int) = map { Recipient( - studentId = userLoginId, + userLoginId = userLoginId, realId = it.id, realName = it.name, name = it.shortName, diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt index 6a21d59f..71ea7099 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt @@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit fun List.mapToEntities(student: Student) = map { ReportingUnit( - studentId = student.id.toInt(), + studentId = student.studentId, unitId = it.id, roles = it.roles, senderId = it.senderId, diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt index c9332303..67f56c62 100644 --- a/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt +++ b/app/src/main/java/io/github/wulkanowy/data/mappers/StudentMapper.kt @@ -5,7 +5,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters import java.time.LocalDateTime import io.github.wulkanowy.sdk.pojo.Student as SdkStudent -fun List.mapToEntities(password: String = "", colors: List) = map { +fun List.mapToEntities(password: String = "") = map { StudentWithSemesters( student = Student( email = it.email, @@ -28,10 +28,8 @@ fun List.mapToEntities(password: String = "", colors: List) = mobileBaseUrl = it.mobileBaseUrl, privateKey = it.privateKey, certificateKey = it.certificateKey, - loginMode = it.loginMode.name, - ).apply { - avatarColor = colors.random() - }, + loginMode = it.loginMode.name + ), semesters = it.semesters.mapToEntities(it.studentId) ) } diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt index bdcd049d..88257470 100644 --- a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt +++ b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt @@ -3,10 +3,11 @@ package io.github.wulkanowy.data.pojos import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics +import io.github.wulkanowy.ui.modules.grade.statistics.ViewType data class GradeStatisticsItem( - val type: DataType, + val type: ViewType, val average: String, @@ -15,11 +16,4 @@ data class GradeStatisticsItem( val semester: GradeSemesterStatistics?, val points: GradePointsStatistics? - -) { - enum class DataType { - SEMESTER, - PARTIAL, - POINTS, - } -} +) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt index ffccb059..9a6528f3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceRepository.kt @@ -14,7 +14,6 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime @@ -28,12 +27,9 @@ class AttendanceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "attendance" fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt index cd4403c7..4edb507b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/AttendanceSummaryRepository.kt @@ -10,7 +10,6 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -21,12 +20,9 @@ class AttendanceSummaryRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "attendance_summary" fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt index 99ef56f4..59aabdd5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/CompletedLessonsRepository.kt @@ -12,7 +12,6 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -24,12 +23,9 @@ class CompletedLessonsRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "completed" fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { completedLessonsDb.loadAll(semester.studentId, semester.diaryId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt index 0a839d27..befcf9e6 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ConferenceRepository.kt @@ -10,7 +10,6 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -21,12 +20,9 @@ class ConferenceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "conference" fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { conferenceDb.loadAll(semester.diaryId, student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt index a8912f10..bd6e7d2d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ExamRepository.kt @@ -12,7 +12,6 @@ import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.startExamsDay import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -24,12 +23,9 @@ class ExamRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "exam" fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { examDb.loadAll(semester.diaryId, semester.studentId, start.startExamsDay, start.endExamsDay) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt index 9880e464..bab290f3 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeRepository.kt @@ -16,7 +16,6 @@ import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map -import kotlinx.coroutines.sync.Mutex import java.time.LocalDateTime import javax.inject.Inject import javax.inject.Singleton @@ -29,20 +28,14 @@ class GradeRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "grade" fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, - shouldFetch = { (details, summaries) -> - val isShouldBeRefreshed = refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) - details.isEmpty() || summaries.isEmpty() || forceRefresh || isShouldBeRefreshed - }, + shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { - val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId) - val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) - detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries } + gradeDb.loadAll(semester.semesterId, semester.studentId).combine(gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)) { details, summaries -> + details to summaries + } }, fetch = { val (details, summary) = sdk.init(student) @@ -99,27 +92,19 @@ class GradeRepository @Inject constructor( } fun getUnreadGrades(semester: Semester): Flow> { - return gradeDb.loadAll(semester.semesterId, semester.studentId).map { - it.filter { grade -> !grade.isRead } - } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isRead } } } fun getNotNotifiedGrades(semester: Semester): Flow> { - return gradeDb.loadAll(semester.semesterId, semester.studentId).map { - it.filter { grade -> !grade.isNotified } - } + return gradeDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { grade -> !grade.isNotified } } } fun getNotNotifiedPredictedGrades(semester: Semester): Flow> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { - it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } - } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } } } fun getNotNotifiedFinalGrades(semester: Semester): Flow> { - return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { - it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } - } + return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } } } suspend fun updateGrade(grade: Grade) { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt index 9cd8e711..ab65fb14 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/GradeStatisticsRepository.kt @@ -17,7 +17,6 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import java.util.Locale import javax.inject.Inject import javax.inject.Singleton @@ -31,16 +30,11 @@ class GradeStatisticsRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val partialMutex = Mutex() - private val semesterMutex = Mutex() - private val pointsMutex = Mutex() - private val partialCacheKey = "grade_stats_partial" private val semesterCacheKey = "grade_stats_semester" private val pointsCacheKey = "grade_stats_points" fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - mutex = partialMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(partialCacheKey, semester)) }, query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { @@ -77,7 +71,6 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - mutex = semesterMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(semesterCacheKey, semester)) }, query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { @@ -119,7 +112,6 @@ class GradeStatisticsRepository @Inject constructor( ) fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( - mutex = pointsMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(pointsCacheKey, semester)) }, query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt index 068fd9a5..7625dbbc 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/HomeworkRepository.kt @@ -13,7 +13,6 @@ import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -25,12 +24,9 @@ class HomeworkRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "homework" fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { homeworkDb.loadAll(semester.semesterId, semester.studentId, start.monday, end.sunday) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt index b904b7db..801292b4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/LuckyNumberRepository.kt @@ -9,8 +9,6 @@ import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map -import kotlinx.coroutines.sync.Mutex -import java.time.LocalDate import java.time.LocalDate.now import javax.inject.Inject import javax.inject.Singleton @@ -21,10 +19,7 @@ class LuckyNumberRepository @Inject constructor( private val sdk: Sdk ) { - private val saveFetchResultMutex = Mutex() - fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { luckyNumberDb.load(student.studentId, now()) }, fetch = { sdk.init(student).getLuckyNumber(student.schoolShortName)?.mapToEntity(student) }, @@ -38,9 +33,6 @@ class LuckyNumberRepository @Inject constructor( } ) - fun getLuckyNumberHistory(student: Student, start: LocalDate, end: LocalDate) = - luckyNumberDb.getAll(student.studentId, start, end) - suspend fun getNotNotifiedLuckyNumber(student: Student) = luckyNumberDb.load(student.studentId, now()).map { if (it?.isNotified == false) it else null }.first() diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt index 5f555418..ea7b2b0e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt @@ -20,7 +20,6 @@ import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.sync.Mutex import timber.log.Timber import java.time.LocalDateTime.now import javax.inject.Inject @@ -34,13 +33,10 @@ class MessageRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "message" @Suppress("UNUSED_PARAMETER") fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student, folder)) }, query = { messagesDb.loadAll(student.id.toInt(), folder.id) }, fetch = { sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).mapToEntities(student) }, diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt index 4b333bc6..7e83ef7d 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MobileDeviceRepository.kt @@ -13,7 +13,6 @@ import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -24,12 +23,9 @@ class MobileDeviceRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "devices" fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student)) }, query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt index 85339dfa..85789f09 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/NoteRepository.kt @@ -13,7 +13,6 @@ import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -24,12 +23,9 @@ class NoteRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "note" fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) }, query = { noteDb.loadAll(student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt index 5bd1f3c1..8cb815cc 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt @@ -2,7 +2,6 @@ package io.github.wulkanowy.data.repositories import android.content.Context import android.content.SharedPreferences -import androidx.core.content.edit import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.R import io.github.wulkanowy.ui.modules.grade.GradeAverageMode @@ -19,43 +18,26 @@ class PreferencesRepository @Inject constructor( 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 - ) + 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 - ) - ) + 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 - ) + 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 - ) + 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 - ) + 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 @@ -73,90 +55,50 @@ class PreferencesRepository @Inject constructor( val isServicesOnlyWifi: Boolean get() = getBoolean(servicesOnlyWifiKey, R.bool.pref_default_services_wifi_only) - val notificationsEnableKey = context.getString(R.string.pref_key_notifications_enable) val isNotificationsEnable: Boolean - get() = getBoolean(notificationsEnableKey, R.bool.pref_default_notifications_enable) + 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 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 - ) + 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() + 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() + 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 - ) + get() = getBoolean(R.string.pref_key_fill_message_content, R.bool.pref_default_fill_message_content) val showGroupsInPlan: Boolean - get() = getBoolean( - R.string.pref_key_timetable_show_groups, - R.bool.pref_default_timetable_show_groups - ) + get() = getBoolean(R.string.pref_key_timetable_show_groups, R.bool.pref_default_timetable_show_groups) val showWholeClassPlan: String - get() = getString( - R.string.pref_key_timetable_show_whole_class, - R.string.pref_default_timetable_show_whole_class - ) + get() = getString(R.string.pref_key_timetable_show_whole_class, R.string.pref_default_timetable_show_whole_class) val gradeSortingMode: GradeSortingMode - get() = GradeSortingMode.getByValue( - getString( - R.string.pref_key_grade_sorting_mode, - R.string.pref_default_grade_sorting_mode - ) - ) + get() = GradeSortingMode.getByValue(getString(R.string.pref_key_grade_sorting_mode, R.string.pref_default_grade_sorting_mode)) val showTimetableTimers: Boolean - get() = getBoolean( - R.string.pref_key_timetable_show_timers, - R.bool.pref_default_timetable_show_timers - ) + get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers) var isHomeworkFullscreen: Boolean - get() = getBoolean( - R.string.pref_key_homework_fullscreen, - R.bool.pref_default_homework_fullscreen - ) + get() = getBoolean(R.string.pref_key_homework_fullscreen, R.bool.pref_default_homework_fullscreen) set(value) = sharedPref.edit().putBoolean("homework_fullscreen", value).apply() val showSubjectsWithoutGrades: Boolean - get() = getBoolean( - R.string.pref_key_subjects_without_grades, - R.bool.pref_default_subjects_without_grades - ) - - var isKitkatDialogDisabled: Boolean - get() = sharedPref.getBoolean("kitkat_dialog_disabled", false) - set(value) = sharedPref.edit { putBoolean("kitkat_dialog_disabled", value) } + get() = getBoolean(R.string.pref_key_subjects_without_grades, R.bool.pref_default_subjects_without_grades) 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 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)) + 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/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt index 975a30a2..24ab5f0c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt @@ -19,22 +19,22 @@ class RecipientRepository @Inject constructor( ) { suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) { - val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.studentId) - val old = recipientDb.loadAll(unit.studentId, unit.unitId, role) + val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.senderId) + val old = recipientDb.loadAll(unit.senderId, unit.unitId, role) recipientDb.deleteAll(old uniqueSubtract new) recipientDb.insertAll(new uniqueSubtract old) } suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List { - return recipientDb.loadAll(unit.studentId, unit.unitId, role).ifEmpty { + return recipientDb.loadAll(unit.senderId, unit.unitId, role).ifEmpty { refreshRecipients(student, unit, role) - recipientDb.loadAll(unit.studentId, unit.unitId, role) + recipientDb.loadAll(unit.senderId, unit.unitId, role) } } suspend fun getMessageRecipients(student: Student, message: Message): List { - return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.studentId) + return sdk.init(student).getMessageRecipients(message.messageId, message.senderId).mapToEntities(student.userLoginId) } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt index b9caf978..792e66b5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt @@ -18,25 +18,25 @@ class ReportingUnitRepository @Inject constructor( suspend fun refreshReportingUnits(student: Student) { val new = sdk.init(student).getReportingUnits().mapToEntities(student) - val old = reportingUnitDb.load(student.id.toInt()) + val old = reportingUnitDb.load(student.studentId) reportingUnitDb.deleteAll(old.uniqueSubtract(new)) reportingUnitDb.insertAll(new.uniqueSubtract(old)) } suspend fun getReportingUnits(student: Student): List { - return reportingUnitDb.load(student.id.toInt()).ifEmpty { + return reportingUnitDb.load(student.studentId).ifEmpty { refreshReportingUnits(student) - reportingUnitDb.load(student.id.toInt()) + reportingUnitDb.load(student.studentId) } } suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? { - return reportingUnitDb.loadOne(student.id.toInt(), unitId) ?: run { + return reportingUnitDb.loadOne(student.studentId, unitId) ?: run { refreshReportingUnits(student) - return reportingUnitDb.loadOne(student.id.toInt(), unitId) + return reportingUnitDb.loadOne(student.studentId, unitId) } } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt index 8b59cb58..6b22b32c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SchoolRepository.kt @@ -7,7 +7,6 @@ import io.github.wulkanowy.data.mappers.mapToEntity import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -17,11 +16,8 @@ class SchoolRepository @Inject constructor( private val sdk: Sdk ) { - private val saveFetchResultMutex = Mutex() - fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { schoolDb.load(semester.studentId, semester.classId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt index de66ad20..e3deb447 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentInfoRepository.kt @@ -7,7 +7,6 @@ import io.github.wulkanowy.data.mappers.mapToEntity import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -17,11 +16,8 @@ class StudentInfoRepository @Inject constructor( private val sdk: Sdk ) { - private val saveFetchResultMutex = Mutex() - fun getStudentInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it == null || forceRefresh }, query = { studentInfoDao.loadStudentInfo(student.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt index c2f364b3..55821479 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/StudentRepository.kt @@ -5,12 +5,11 @@ import dagger.hilt.android.qualifiers.ApplicationContext import io.github.wulkanowy.data.db.dao.SemesterDao import io.github.wulkanowy.data.db.dao.StudentDao import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar +import io.github.wulkanowy.data.db.entities.StudentNick import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.exceptions.NoCurrentStudentException import io.github.wulkanowy.data.mappers.mapToEntities import io.github.wulkanowy.sdk.Sdk -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.DispatchersProvider import io.github.wulkanowy.utils.security.decrypt import io.github.wulkanowy.utils.security.encrypt @@ -24,8 +23,7 @@ class StudentRepository @Inject constructor( private val dispatchers: DispatchersProvider, private val studentDb: StudentDao, private val semesterDb: SemesterDao, - private val sdk: Sdk, - private val appInfo: AppInfo + private val sdk: Sdk ) { suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty() @@ -37,8 +35,7 @@ class StudentRepository @Inject constructor( symbol: String, token: String ): List = - sdk.getStudentsFromMobileApi(token, pin, symbol, "") - .mapToEntities(colors = appInfo.defaultColorsForAvatar) + sdk.getStudentsFromMobileApi(token, pin, symbol, "").mapToEntities() suspend fun getStudentsScrapper( email: String, @@ -47,7 +44,7 @@ class StudentRepository @Inject constructor( symbol: String ): List = sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol) - .mapToEntities(password, appInfo.defaultColorsForAvatar) + .mapToEntities(password) suspend fun getStudentsHybrid( email: String, @@ -55,58 +52,46 @@ class StudentRepository @Inject constructor( scrapperBaseUrl: String, symbol: String ): List = - sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol) - .mapToEntities(password, appInfo.defaultColorsForAvatar) + sdk.getStudentsHybrid(email, password, scrapperBaseUrl, "", symbol).mapToEntities(password) suspend fun getSavedStudents(decryptPass: Boolean = true) = - studentDb.loadStudentsWithSemesters() - .map { + withContext(dispatchers.backgroundThread) { + studentDb.loadStudentsWithSemesters().map { it.apply { if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { - student.password = withContext(dispatchers.backgroundThread) { - decrypt(student.password) - } + student.password = decrypt(student.password) } } } + } - suspend fun getStudentById(id: Long, decryptPass: Boolean = true): Student { - val student = studentDb.loadById(id) ?: throw NoCurrentStudentException() - - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { - student.password = withContext(dispatchers.backgroundThread) { - decrypt(student.password) + suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) { + studentDb.loadById(id)?.apply { + if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) { + password = decrypt(password) } } - return student - } + } ?: throw NoCurrentStudentException() - suspend fun getCurrentStudent(decryptPass: Boolean = true): Student { - val student = studentDb.loadCurrent() ?: throw NoCurrentStudentException() - - if (decryptPass && Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) { - student.password = withContext(dispatchers.backgroundThread) { - decrypt(student.password) + suspend fun getCurrentStudent(decryptPass: Boolean = true) = + withContext(dispatchers.backgroundThread) { + studentDb.loadCurrent()?.apply { + if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) { + password = decrypt(password) + } } - } - return student - } + } ?: throw NoCurrentStudentException() suspend fun saveStudents(studentsWithSemesters: List): List { - val semesters = studentsWithSemesters.flatMap { it.semesters } - val students = studentsWithSemesters.map { it.student } - .map { - it.apply { - if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) { - password = withContext(dispatchers.backgroundThread) { - encrypt(password, context) - } - } - } - } + semesterDb.insertSemesters(studentsWithSemesters.flatMap { it.semesters }) - semesterDb.insertSemesters(semesters) - return studentDb.insertAll(students) + return withContext(dispatchers.backgroundThread) { + studentDb.insertAll(studentsWithSemesters.map { it.student }.map { + if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) { + it.copy(password = encrypt(it.password, context)) + } else it + }) + } } suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) { @@ -118,6 +103,5 @@ class StudentRepository @Inject constructor( suspend fun logoutStudent(student: Student) = studentDb.delete(student) - suspend fun updateStudentNickAndAvatar(studentNickAndAvatar: StudentNickAndAvatar) = - studentDb.update(studentNickAndAvatar) + suspend fun updateStudentNick(studentNick: StudentNick) = studentDb.update(studentNick) } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt index b4bfef18..ef07a1d4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/SubjectRepository.kt @@ -8,7 +8,6 @@ import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -18,10 +17,7 @@ class SubjectRepository @Inject constructor( private val sdk: Sdk ) { - private val saveFetchResultMutex = Mutex() - fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh }, query = { subjectDao.loadAll(semester.diaryId, semester.studentId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt index 7135edbe..25da718c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TeacherRepository.kt @@ -8,7 +8,6 @@ import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.utils.init import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract -import kotlinx.coroutines.sync.Mutex import javax.inject.Inject import javax.inject.Singleton @@ -18,10 +17,7 @@ class TeacherRepository @Inject constructor( private val sdk: Sdk ) { - private val saveFetchResultMutex = Mutex() - fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { it.isEmpty() || forceRefresh }, query = { teacherDb.loadAll(semester.studentId, semester.classId) }, fetch = { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt index 927565b5..fa1898f5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/TimetableRepository.kt @@ -18,7 +18,6 @@ import io.github.wulkanowy.utils.sunday import io.github.wulkanowy.utils.uniqueSubtract import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map -import kotlinx.coroutines.sync.Mutex import java.time.LocalDate import javax.inject.Inject import javax.inject.Singleton @@ -32,12 +31,9 @@ class TimetableRepository @Inject constructor( private val refreshHelper: AutoRefreshHelper, ) { - private val saveFetchResultMutex = Mutex() - private val cacheKey = "timetable" fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean, refreshAdditional: Boolean = false) = networkBoundResource( - mutex = saveFetchResultMutex, shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) }, query = { timetableDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) 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 new file mode 100644 index 00000000..e69de29b diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt index 9b93953d..86b6701b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseActivity.kt @@ -37,7 +37,6 @@ abstract class BaseActivity, VB : ViewBinding> : abstract var presenter: T override fun onCreate(savedInstanceState: Bundle?) { - inject() themeManager.applyActivityTheme(this) super.onCreate(savedInstanceState) supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleLogger, true) @@ -45,9 +44,7 @@ abstract class BaseActivity, VB : ViewBinding> : if (SDK_INT >= LOLLIPOP) { @Suppress("DEPRECATION") - setTaskDescription( - ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface)) - ) + setTaskDescription(ActivityManager.TaskDescription(null, null, getThemeAttrColor(R.attr.colorSurface))) } } @@ -87,9 +84,4 @@ abstract class BaseActivity, VB : ViewBinding> : invalidateOptionsMenu() presenter.onDetachView() } - - //https://github.com/google/dagger/releases/tag/dagger-2.33 - protected open fun inject() { - throw UnsupportedOperationException() - } } 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 index bd735535..5f8bf417 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragmentPagerAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseFragmentPagerAdapter.kt @@ -4,7 +4,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter -//TODO Use ViewPager2 class BaseFragmentPagerAdapter(private val fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt index 4ce97770..f76614e1 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ErrorDialog.kt @@ -42,8 +42,10 @@ class ErrorDialog : BaseDialogFragment() { companion object { private const val ARGUMENT_KEY = "Data" - fun newInstance(error: Throwable) = ErrorDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, error) } + fun newInstance(error: Throwable): ErrorDialog { + return ErrorDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, error) } + } } } @@ -55,14 +57,12 @@ class ErrorDialog : BaseDialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogErrorBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return DialogErrorBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) val stringWriter = StringWriter().apply { error.printStackTrace(PrintWriter(this)) diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt index b560ed2e..a2379c3e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/ThemeManager.kt @@ -8,9 +8,6 @@ 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.PreferencesRepository -import io.github.wulkanowy.ui.modules.login.LoginActivity -import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity import javax.inject.Inject import javax.inject.Singleton @@ -20,13 +17,7 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer fun applyActivityTheme(activity: AppCompatActivity) { if (isThemeApplicable(activity)) { applyDefaultTheme() - if (preferencesRepository.appTheme == "black") { - when (activity) { - is MainActivity -> activity.setTheme(R.style.WulkanowyTheme_Black) - is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black) - is SendMessageActivity -> activity.setTheme(R.style.WulkanowyTheme_MessageSend_Black) - } - } + if (preferencesRepository.appTheme == "black") activity.setTheme(R.style.WulkanowyTheme_Black) } } @@ -42,13 +33,8 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer } 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 - || it == R.style.WulkanowyTheme_Login || it == R.style.WulkanowyTheme_Login_Black - || it == R.style.WulkanowyTheme_MessageSend || it == R.style.WulkanowyTheme_MessageSend_Black - } + 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 index a43aaffb..8e6130fb 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/WidgetConfigureAdapter.kt @@ -1,25 +1,20 @@ package io.github.wulkanowy.ui.base import android.annotation.SuppressLint +import android.graphics.PorterDuff import android.view.LayoutInflater 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.Student -import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ItemAccountBinding -import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.nickOrName import javax.inject.Inject -class WidgetConfigureAdapter @Inject constructor() : - RecyclerView.Adapter() { +class WidgetConfigureAdapter @Inject constructor() : RecyclerView.Adapter() { - var items = emptyList() - - var selectedId = -1L + var items = emptyList>() var onClickListener: (Student) -> Unit = {} @@ -31,33 +26,17 @@ class WidgetConfigureAdapter @Inject constructor() : @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val (student, semesters) = items[position] - val semester = semesters.maxByOrNull { it.semesterId } - val context = holder.binding.root.context - val checkBackgroundColor = context.getThemeAttrColor(R.attr.colorSurface) - val avatar = context.createNameInitialsDrawable(student.nickOrName, student.avatarColor) - val isDuplicatedStudent = items.filter { - val studentToCompare = it.student - - studentToCompare.studentId == student.studentId - && studentToCompare.schoolSymbol == student.schoolSymbol - && studentToCompare.symbol == student.symbol - }.size > 1 + val (student, isCurrent) = items[position] with(holder.binding) { - accountItemName.text = "${student.nickOrName} ${semester?.diaryName.orEmpty()}" + accountItemName.text = "${student.nickOrName} ${student.className}" accountItemSchool.text = student.schoolName - accountItemImage.setImageDrawable(avatar) - with(accountItemAccountType) { - setText(if (student.isParent) R.string.account_type_parent else R.string.account_type_student) - isVisible = isDuplicatedStudent - } + with(accountItemImage) { + val colorImage = if (isCurrent) context.getThemeAttrColor(R.attr.colorPrimary) + else context.getThemeAttrColor(R.attr.colorOnSurface, 153) - with(accountItemCheck) { - isVisible = student.id == selectedId - borderColor = checkBackgroundColor - circleColor = checkBackgroundColor + setColorFilter(colorImage, PorterDuff.Mode.SRC_IN) } root.setOnClickListener { onClickListener(student) } 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 index 4c3b608a..cdd29b41 100644 --- 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 @@ -4,9 +4,9 @@ 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.google.android.material.dialog.MaterialAlertDialogBuilder import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.entity.Library import dagger.hilt.android.AndroidEntryPoint @@ -26,9 +26,14 @@ class LicenseFragment : BaseFragment(R.layout.fragment_l @Inject lateinit var licenseAdapter: LicenseAdapter + private val libs by lazy { Libs(requireContext()) } + override val titleStringId get() = R.string.license_title - override val appLibraries by lazy { Libs(requireContext()).libraries } + override val appLibraries: ArrayList? + get() = context?.let { + libs.prepareLibraries(it, emptyArray(), emptyArray(), autoDetect = true, checkCachedDetection = true, sort = true) + } companion object { fun newInstance() = LicenseFragment() @@ -58,7 +63,7 @@ class LicenseFragment : BaseFragment(R.layout.fragment_l override fun openLicense(licenseHtml: String) { context?.let { - MaterialAlertDialogBuilder(it).apply { + AlertDialog.Builder(it).apply { setTitle(R.string.license_dialog_title) setMessage(licenseHtml.parseAsHtml()) setPositiveButton(android.R.string.ok) { _, _ -> } 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 index 6c97d875..0680dbb7 100644 --- 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 @@ -5,7 +5,7 @@ import io.github.wulkanowy.ui.base.BaseView interface LicenseView : BaseView { - val appLibraries: List + val appLibraries: ArrayList? fun initView() 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 index 523fbbd7..342fd2d4 100644 --- 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 @@ -1,17 +1,16 @@ 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.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.HeaderAccountBinding import io.github.wulkanowy.databinding.ItemAccountBinding -import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.nickOrName import javax.inject.Inject @@ -73,12 +72,9 @@ class AccountAdapter @Inject constructor() : RecyclerView.Adapter 1 && isAccountQuickDialogMode with(binding) { - accountItemName.text = "${student.nickOrName} ${semester?.diaryName.orEmpty()}" + accountItemName.text = "${student.nickOrName} ${diary?.diaryName.orEmpty()}" accountItemSchool.text = studentWithSemesters.student.schoolName - accountItemImage.setImageDrawable(avatar) + accountItemAccountType.setText(if (student.isParent) R.string.account_type_parent else R.string.account_type_student) + accountItemAccountType.visibility = if (isDuplicatedStudent) VISIBLE else GONE - with(accountItemAccountType) { - setText(if (student.isParent) R.string.account_type_parent else R.string.account_type_student) - isVisible = isDuplicatedStudent - } + with(accountItemImage) { + val colorImage = + if (student.isCurrent) context.getThemeAttrColor(R.attr.colorPrimary) + else context.getThemeAttrColor(R.attr.colorOnSurface, 153) - with(accountItemCheck) { - isVisible = student.isCurrent - borderColor = checkBackgroundColor - circleColor = checkBackgroundColor + setColorFilter(colorImage, PorterDuff.Mode.SRC_IN) } root.setOnClickListener { onClickListener(studentWithSemesters) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt index 7a8f8585..7293527e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountFragment.kt @@ -34,20 +34,25 @@ class AccountFragment : BaseFragment(R.layout.fragment_a override val titleStringId = R.string.account_title + override var subtitleString = "" + + override val isViewEmpty get() = accountAdapter.items.isEmpty() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) } - @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding = FragmentAccountBinding.bind(view) presenter.onAttachView(this) } override fun initView() { + binding.accountErrorRetry.setOnClickListener { presenter.onRetry() } + binding.accountErrorDetails.setOnClickListener { presenter.onDetailsClick() } + binding.accountRecycler.apply { layoutManager = LinearLayoutManager(context) adapter = accountAdapter @@ -55,7 +60,9 @@ class AccountFragment : BaseFragment(R.layout.fragment_a accountAdapter.onClickListener = presenter::onItemSelected - binding.accountAdd.setOnClickListener { presenter.onAddSelected() } + with(binding) { + accountAdd.setOnClickListener { presenter.onAddSelected() } + } } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -77,7 +84,28 @@ class AccountFragment : BaseFragment(R.layout.fragment_a override fun openAccountDetailsView(studentWithSemesters: StudentWithSemesters) { (activity as? MainActivity)?.pushView( - AccountDetailsFragment.newInstance(studentWithSemesters) + AccountDetailsFragment.newInstance( + studentWithSemesters + ) ) } + + override fun showErrorView(show: Boolean) { + binding.accountError.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun setErrorDetails(message: String) { + binding.accountErrorMessage.text = message + } + + override fun showProgress(show: Boolean) { + binding.accountProgress.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showContent(show: Boolean) { + with(binding) { + accountRecycler.visibility = if (show) View.VISIBLE else View.GONE + accountAdd.visibility = if (show) View.VISIBLE else View.GONE + } + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt index 8d165139..366793b6 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/AccountPresenter.kt @@ -5,6 +5,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.flowWithResource import kotlinx.coroutines.flow.onEach import timber.log.Timber @@ -15,13 +16,28 @@ class AccountPresenter @Inject constructor( studentRepository: StudentRepository, ) : BasePresenter(errorHandler, studentRepository) { + private lateinit var lastError: Throwable + override fun onAttachView(view: AccountView) { super.onAttachView(view) view.initView() Timber.i("Account view was initialized") + errorHandler.showErrorMessage = ::showErrorViewOnError loadData() } + fun onRetry() { + view?.run { + showErrorView(false) + showProgress(true) + } + loadData() + } + + fun onDetailsClick() { + view?.showErrorDetailsDialog(lastError) + } + fun onAddSelected() { Timber.i("Select add account") view?.openLoginView() @@ -31,24 +47,6 @@ class AccountPresenter @Inject constructor( view?.openAccountDetailsView(studentWithSemesters) } - private fun loadData() { - flowWithResource { studentRepository.getSavedStudents(false) } - .onEach { - when (it.status) { - Status.LOADING -> Timber.i("Loading account data started") - Status.SUCCESS -> { - Timber.i("Loading account result: Success") - view?.updateData(createAccountItems(it.data!!)) - } - Status.ERROR -> { - Timber.i("Loading account result: An exception occurred") - errorHandler.dispatch(it.error!!) - } - } - } - .launch("load") - } - private fun createAccountItems(items: List): List> { return items.groupBy { Account("${it.student.userName} (${it.student.email})", it.student.isParent) @@ -62,4 +60,45 @@ class AccountPresenter @Inject constructor( } .flatten() } + + private fun loadData() { + flowWithResource { studentRepository.getSavedStudents(false) } + .onEach { + when (it.status) { + Status.LOADING -> { + Timber.i("Loading account data started") + view?.run { + showProgress(true) + showContent(false) + } + } + Status.SUCCESS -> { + Timber.i("Loading account result: Success") + view?.updateData(createAccountItems(it.data!!)) + view?.run { + showContent(true) + showErrorView(false) + } + } + Status.ERROR -> { + Timber.i("Loading account result: An exception occurred") + errorHandler.dispatch(it.error!!) + } + } + } + .afterLoading { view?.showProgress(false) } + .launch() + } + + private fun showErrorViewOnError(message: String, error: Throwable) { + view?.run { + if (isViewEmpty) { + lastError = error + setErrorDetails(message) + showErrorView(true) + showContent(false) + showProgress(false) + } else showError(message, error) + } + } } 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 index d7deefaf..3453909d 100644 --- 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 @@ -5,6 +5,8 @@ import io.github.wulkanowy.ui.base.BaseView interface AccountView : BaseView { + val isViewEmpty: Boolean + fun initView() fun updateData(data: List>) @@ -12,4 +14,13 @@ interface AccountView : BaseView { fun openLoginView() fun openAccountDetailsView(studentWithSemesters: StudentWithSemesters) + + fun showErrorView(show: Boolean) + + fun setErrorDetails(message: String) + + fun showProgress(show: Boolean) + + fun showContent(show: Boolean) } + diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt index f1c7f7bd..f4b2c833 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsFragment.kt @@ -7,7 +7,6 @@ import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog import androidx.core.view.get -import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R import io.github.wulkanowy.data.db.entities.Student @@ -19,7 +18,6 @@ import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoFragment import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView -import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.nickOrName import javax.inject.Inject @@ -33,6 +31,8 @@ class AccountDetailsFragment : override val titleStringId = R.string.account_details_title + override var subtitleString = "" + companion object { private const val ARGUMENT_KEY = "Data" @@ -88,15 +88,8 @@ class AccountDetailsFragment : override fun showAccountData(student: Student) { with(binding) { - accountDetailsCheck.isVisible = student.isCurrent accountDetailsName.text = student.nickOrName accountDetailsSchool.text = student.schoolName - accountDetailsAvatar.setImageDrawable( - requireContext().createNameInitialsDrawable( - student.nickOrName, - student.avatarColor - ) - ) } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsPresenter.kt index cc53c9b6..7b93d3d8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountdetails/AccountDetailsPresenter.kt @@ -21,7 +21,7 @@ class AccountDetailsPresenter @Inject constructor( private val syncManager: SyncManager ) : BasePresenter(errorHandler, studentRepository) { - private var studentWithSemesters: StudentWithSemesters? = null + private lateinit var studentWithSemesters: StudentWithSemesters private lateinit var lastError: Throwable @@ -69,10 +69,10 @@ class AccountDetailsPresenter @Inject constructor( } Status.SUCCESS -> { Timber.i("Loading account details view result: Success") - studentWithSemesters = it.data + studentWithSemesters = it.data!! view?.run { - showAccountData(studentWithSemesters!!.student) - enableSelectStudentButton(!studentWithSemesters!!.student.isCurrent) + showAccountData(studentWithSemesters.student) + enableSelectStudentButton(!studentWithSemesters.student.isCurrent) showContent(true) showErrorView(false) } @@ -88,23 +88,17 @@ class AccountDetailsPresenter @Inject constructor( } fun onAccountEditSelected() { - studentWithSemesters?.let { - view?.showAccountEditDetailsDialog(it.student) - } + view?.showAccountEditDetailsDialog(studentWithSemesters.student) } fun onStudentInfoSelected(infoType: StudentInfoView.Type) { - studentWithSemesters?.let { - view?.openStudentInfoView(infoType, it) - } + view?.openStudentInfoView(infoType, studentWithSemesters) } fun onStudentSelect() { - if (studentWithSemesters == null) return + Timber.i("Select student ${studentWithSemesters.student.id}") - Timber.i("Select student ${studentWithSemesters!!.student.id}") - - flowWithResource { studentRepository.switchStudent(studentWithSemesters!!) } + flowWithResource { studentRepository.switchStudent(studentWithSemesters) } .onEach { when (it.status) { Status.LOADING -> Timber.i("Attempt to change a student") @@ -128,10 +122,8 @@ class AccountDetailsPresenter @Inject constructor( } fun onLogoutConfirm() { - if (studentWithSemesters == null) return - flowWithResource { - val studentToLogout = studentWithSemesters!!.student + val studentToLogout = studentWithSemesters.student studentRepository.logoutStudent(studentToLogout) val students = studentRepository.getSavedStudents(false) @@ -151,7 +143,7 @@ class AccountDetailsPresenter @Inject constructor( syncManager.stopSyncWorker() openClearLoginView() } - studentWithSemesters!!.student.isCurrent -> { + studentWithSemesters.student.isCurrent -> { Timber.i("Logout result: Logout student and switch to another") recreateMainView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditColorAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditColorAdapter.kt deleted file mode 100644 index ab6eec41..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditColorAdapter.kt +++ /dev/null @@ -1,90 +0,0 @@ -package io.github.wulkanowy.ui.modules.account.accountedit - -import android.annotation.SuppressLint -import android.content.res.ColorStateList -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable -import android.graphics.drawable.GradientDrawable -import android.graphics.drawable.RippleDrawable -import android.graphics.drawable.StateListDrawable -import android.os.Build -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.databinding.ItemAccountEditColorBinding -import javax.inject.Inject - -class AccountEditColorAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = listOf() - - var selectedColor = 0 - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( - ItemAccountEditColorBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("RestrictedApi", "NewApi") - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val item = items[position] - - with(holder.binding) { - accountEditItemColor.setImageDrawable(GradientDrawable().apply { - shape = GradientDrawable.OVAL - setColor(item) - }) - - accountEditItemColorContainer.foreground = item.createForegroundDrawable() - accountEditCheck.isVisible = selectedColor == item - - root.setOnClickListener { - val oldSelectedPosition = items.indexOf(selectedColor) - selectedColor = item - - notifyItemChanged(oldSelectedPosition) - notifyItemChanged(position) - } - } - } - - private fun Int.createForegroundDrawable(): Drawable = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - val mask = GradientDrawable().apply { - shape = GradientDrawable.OVAL - setColor(Color.BLACK) - } - RippleDrawable(ColorStateList.valueOf(this.rippleColor), null, mask) - } else { - val foreground = StateListDrawable().apply { - alpha = 80 - setEnterFadeDuration(250) - setExitFadeDuration(250) - } - - val mask = GradientDrawable().apply { - shape = GradientDrawable.OVAL - setColor(this@createForegroundDrawable.rippleColor) - } - - foreground.apply { - addState(intArrayOf(android.R.attr.state_pressed), mask) - addState(intArrayOf(), ColorDrawable(Color.TRANSPARENT)) - } - } - - private inline val Int.rippleColor: Int - get() { - val hsv = FloatArray(3) - Color.colorToHSV(this, hsv) - hsv[2] = hsv[2] * 0.5f - return Color.HSVToColor(hsv) - } - - class ViewHolder(val binding: ItemAccountEditColorBinding) : - RecyclerView.ViewHolder(binding.root) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt index 21a7a492..89f23e29 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditDialog.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.GridLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.DialogAccountEditBinding @@ -17,9 +16,6 @@ class AccountEditDialog : BaseDialogFragment(), Accoun @Inject lateinit var presenter: AccountEditPresenter - @Inject - lateinit var accountEditColorAdapter: AccountEditColorAdapter - companion object { private const val ARGUMENT_KEY = "student_with_semesters" @@ -52,30 +48,8 @@ class AccountEditDialog : BaseDialogFragment(), Accoun with(binding) { accountEditDetailsCancel.setOnClickListener { dismiss() } accountEditDetailsSave.setOnClickListener { - presenter.changeStudentNickAndAvatar( - binding.accountEditDetailsNickText.text.toString(), - accountEditColorAdapter.selectedColor - ) + presenter.changeStudentNick(binding.accountEditDetailsNickText.text.toString()) } - - with(binding.accountEditColors) { - layoutManager = GridLayoutManager(context, 4) - adapter = accountEditColorAdapter - } - } - } - - override fun updateSelectedColorData(color: Int) { - with(accountEditColorAdapter) { - selectedColor = color - notifyDataSetChanged() - } - } - - override fun updateColorsData(colors: List) { - with(accountEditColorAdapter) { - items = colors - notifyDataSetChanged() } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditPresenter.kt index 62dd70ab..7830605c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditPresenter.kt @@ -2,11 +2,10 @@ package io.github.wulkanowy.ui.modules.account.accountedit import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar +import io.github.wulkanowy.data.db.entities.StudentNick import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.afterLoading import io.github.wulkanowy.utils.flowWithResource import kotlinx.coroutines.flow.onEach @@ -14,15 +13,12 @@ import timber.log.Timber import javax.inject.Inject class AccountEditPresenter @Inject constructor( - private val appInfo: AppInfo, errorHandler: ErrorHandler, studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { lateinit var student: Student - private val colors = appInfo.defaultColorsForAvatar.map { it.toInt() } - fun onAttachView(view: AccountEditView, student: Student) { super.onAttachView(view) this.student = student @@ -32,49 +28,27 @@ class AccountEditPresenter @Inject constructor( showCurrentNick(student.nick.trim()) } Timber.i("Account edit dialog view was initialized") - loadData() - - view.updateColorsData(colors) } - private fun loadData() { - flowWithResource { - studentRepository.getStudentById(student.id, false).avatarColor - }.onEach { resource -> - when (resource.status) { - Status.LOADING -> Timber.i("Attempt to load student") - Status.SUCCESS -> { - view?.updateSelectedColorData(resource.data?.toInt()!!) - Timber.i("Attempt to load student: Success") - } - Status.ERROR -> { - Timber.i("Attempt to load student: An exception occurred") - errorHandler.dispatch(resource.error!!) - } - } - }.launch("load_data") - } - - fun changeStudentNickAndAvatar(nick: String, avatarColor: Int) { + fun changeStudentNick(nick: String) { flowWithResource { val studentNick = - StudentNickAndAvatar(nick = nick.trim(), avatarColor = avatarColor.toLong()) - .apply { id = student.id } - studentRepository.updateStudentNickAndAvatar(studentNick) + StudentNick(nick = nick.trim()).apply { id = student.id } + studentRepository.updateStudentNick(studentNick) }.onEach { when (it.status) { - Status.LOADING -> Timber.i("Attempt to change a student nick and avatar") + Status.LOADING -> Timber.i("Attempt to change a student nick") Status.SUCCESS -> { - Timber.i("Change a student nick and avatar result: Success") + Timber.i("Change a student nick result: Success") view?.recreateMainView() } Status.ERROR -> { - Timber.i("Change a student nick and avatar result: An exception occurred") + Timber.i("Change a student result: An exception occurred") errorHandler.dispatch(it.error!!) } } } .afterLoading { view?.popView() } - .launch("update_student") + .launch() } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditView.kt index 517492de..b25eec6c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountedit/AccountEditView.kt @@ -11,8 +11,4 @@ interface AccountEditView : BaseView { fun recreateMainView() fun showCurrentNick(nick: String) - - fun updateSelectedColorData(color: Int) - - fun updateColorsData(colors: List) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt index 4279102e..cb64a8fd 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickDialog.kt @@ -6,7 +6,6 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.DialogAccountQuickBinding import io.github.wulkanowy.ui.base.BaseDialogFragment import io.github.wulkanowy.ui.modules.account.AccountAdapter @@ -25,15 +24,7 @@ class AccountQuickDialog : BaseDialogFragment(), Acco lateinit var presenter: AccountQuickPresenter companion object { - - private const val STUDENTS_ARGUMENT_KEY = "students" - - fun newInstance(studentsWithSemesters: List) = - AccountQuickDialog().apply { - arguments = Bundle().apply { - putSerializable(STUDENTS_ARGUMENT_KEY, studentsWithSemesters.toTypedArray()) - } - } + fun newInstance() = AccountQuickDialog() } override fun onCreate(savedInstanceState: Bundle?) { @@ -47,12 +38,8 @@ class AccountQuickDialog : BaseDialogFragment(), Acco savedInstanceState: Bundle? ) = DialogAccountQuickBinding.inflate(inflater).apply { binding = this }.root - @Suppress("UNCHECKED_CAST") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - val studentsWithSemesters = - (requireArguments()[STUDENTS_ARGUMENT_KEY] as Array).toList() - - presenter.onAttachView(this, studentsWithSemesters) + presenter.onAttachView(this) } override fun initView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickPresenter.kt index 39d8fce2..43cc8bc7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/account/accountquick/AccountQuickPresenter.kt @@ -17,15 +17,11 @@ class AccountQuickPresenter @Inject constructor( studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { - private lateinit var studentsWithSemesters: List - - fun onAttachView(view: AccountQuickView, studentsWithSemesters: List) { + override fun onAttachView(view: AccountQuickView) { super.onAttachView(view) - this.studentsWithSemesters = studentsWithSemesters - view.initView() Timber.i("Account quick dialog view was initialized") - view.updateData(createAccountItems(studentsWithSemesters)) + loadData() } fun onManagerSelected() { @@ -61,6 +57,22 @@ class AccountQuickPresenter @Inject constructor( .launch("switch") } + private fun loadData() { + flowWithResource { studentRepository.getSavedStudents(false) }.onEach { + when (it.status) { + Status.LOADING -> Timber.i("Loading account data started") + Status.SUCCESS -> { + Timber.i("Loading account result: Success") + view?.updateData(createAccountItems(it.data!!)) + } + Status.ERROR -> { + Timber.i("Loading account result: An exception occurred") + errorHandler.dispatch(it.error!!) + } + } + }.launch() + } + private fun createAccountItems(items: List) = items.map { AccountItem(it, AccountItem.ViewType.ITEM) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt index 8b6526cd..d5e2fe12 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceDialog.kt @@ -18,11 +18,12 @@ class AttendanceDialog : DialogFragment() { private lateinit var attendance: Attendance companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Attendance) = AttendanceDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(exam: Attendance): AttendanceDialog { + return AttendanceDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + } } } @@ -34,14 +35,12 @@ class AttendanceDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogAttendanceBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogAttendanceBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(binding) { attendanceDialogSubject.text = attendance.subject diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt index cb718c72..00d5aae8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendanceFragment.kt @@ -192,7 +192,7 @@ class AttendanceFragment : BaseFragment(R.layout.frag } override fun showContent(show: Boolean) { - binding.attendanceRecycler.visibility = if (show) VISIBLE else GONE + binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE } override fun showRefresh(show: Boolean) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt index b03db91a..68802c0c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/AttendancePresenter.kt @@ -190,48 +190,35 @@ class AttendancePresenter @Inject constructor( flowWithResourceIn { val student = studentRepository.getCurrentStudent() val semester = semesterRepository.getCurrentSemester(student) - attendanceRepository.getAttendance( - student, - semester, - currentDate, - currentDate, - forceRefresh - ) + attendanceRepository.getAttendance(student, semester, currentDate, currentDate, forceRefresh) }.onEach { when (it.status) { Status.LOADING -> { view?.showExcuseButton(false) if (!it.data.isNullOrEmpty()) { - val filteredAttendance = if (prefRepository.isShowPresent) { - it.data - } else { - it.data.filter { item -> !item.presence } - } - view?.run { enableSwipe(true) showRefresh(true) showProgress(false) - showEmpty(filteredAttendance.isEmpty()) - showContent(filteredAttendance.isNotEmpty()) - updateData(filteredAttendance.sortedBy { item -> item.number }) + showContent(true) + updateData(it.data.let { items -> + if (prefRepository.isShowPresent) items + else items.filter { item -> !item.presence } + }.sortedBy { item -> item.number }) } } } Status.SUCCESS -> { Timber.i("Loading attendance result: Success") - val filteredAttendance = if (prefRepository.isShowPresent) { - it.data.orEmpty() - } else { - it.data?.filter { item -> !item.presence }.orEmpty() - } - view?.apply { - updateData(filteredAttendance.sortedBy { item -> item.number }) - showEmpty(filteredAttendance.isEmpty()) + updateData(it.data!!.let { items -> + if (prefRepository.isShowPresent) items + else items.filter { item -> !item.presence } + }.sortedBy { item -> item.number }) + showEmpty(it.data.isEmpty()) showErrorView(false) - showContent(filteredAttendance.isNotEmpty()) - showExcuseButton(filteredAttendance.any { item -> item.excusable }) + showContent(it.data.isNotEmpty()) + showExcuseButton(it.data.any { item -> item.excusable }) } analytics.logEvent( "load_data", diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt index 3f815a2c..c1a6f1f0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/exam/ExamDialog.kt @@ -17,11 +17,12 @@ class ExamDialog : DialogFragment() { private lateinit var exam: Exam companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Exam) = ExamDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(exam: Exam): ExamDialog { + return ExamDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + } } } @@ -33,14 +34,12 @@ class ExamDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogExamBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogExamBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(binding) { examDialogSubjectValue.text = exam.subject diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt index 7e9b56b9..36c3c4f8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeAverageProvider.kt @@ -86,11 +86,7 @@ class GradeAverageProvider @Inject constructor( return@combine firstSemesterGradeSubject } - val isAnyVulcanAverageInFirstSemester = - firstSemesterGradeSubject.data.orEmpty().any { it.average != .0 } - val isAnyVulcanAverageInSecondSemester = - secondSemesterGradeSubject.data.orEmpty().any { it.average != .0 } - + val isAnyAverage = secondSemesterGradeSubject.data.orEmpty().any { it.average != .0 } val updatedData = secondSemesterGradeSubject.data?.map { secondSemesterSubject -> val firstSemesterSubject = firstSemesterGradeSubject.data.orEmpty() .singleOrNull { it.subject == secondSemesterSubject.subject } @@ -98,7 +94,7 @@ class GradeAverageProvider @Inject constructor( val updatedAverage = if (averageMode == ALL_YEAR) { calculateAllYearAverage( student = student, - isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, + isAnyAverage = isAnyAverage, gradeAverageForceCalc = gradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, firstSemesterSubject = firstSemesterSubject @@ -106,7 +102,7 @@ class GradeAverageProvider @Inject constructor( } else { calculateBothSemestersAverage( student = student, - isAnyVulcanAverage = isAnyVulcanAverageInFirstSemester || isAnyVulcanAverageInSecondSemester, + isAnyAverage = isAnyAverage, gradeAverageForceCalc = gradeAverageForceCalc, secondSemesterSubject = secondSemesterSubject, firstSemesterSubject = firstSemesterSubject @@ -120,11 +116,11 @@ class GradeAverageProvider @Inject constructor( private fun calculateAllYearAverage( student: Student, - isAnyVulcanAverage: Boolean, + isAnyAverage: Boolean, gradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, firstSemesterSubject: GradeSubject? - ) = if (!isAnyVulcanAverage || gradeAverageForceCalc) { + ) = if (!isAnyAverage || gradeAverageForceCalc) { val updatedSecondSemesterGrades = secondSemesterSubject.grades.updateModifiers(student) val updatedFirstSemesterGrades = @@ -137,23 +133,20 @@ class GradeAverageProvider @Inject constructor( private fun calculateBothSemestersAverage( student: Student, - isAnyVulcanAverage: Boolean, + isAnyAverage: Boolean, gradeAverageForceCalc: Boolean, secondSemesterSubject: GradeSubject, firstSemesterSubject: GradeSubject? - ): Double { + ) = if (!isAnyAverage || gradeAverageForceCalc) { + val secondSemesterAverage = + secondSemesterSubject.grades.updateModifiers(student).calcAverage() + val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student) + ?.calcAverage() ?: secondSemesterAverage val divider = if (secondSemesterSubject.grades.any { it.weightValue > .0 }) 2 else 1 - return if (!isAnyVulcanAverage || gradeAverageForceCalc) { - val secondSemesterAverage = - secondSemesterSubject.grades.updateModifiers(student).calcAverage() - val firstSemesterAverage = firstSemesterSubject?.grades?.updateModifiers(student) - ?.calcAverage() ?: secondSemesterAverage - - (secondSemesterAverage + firstSemesterAverage) / divider - } else { - (secondSemesterSubject.average + (firstSemesterSubject?.average ?: secondSemesterSubject.average)) / divider - } + (secondSemesterAverage + firstSemesterAverage) / divider + } else { + (secondSemesterSubject.average + (firstSemesterSubject?.average ?: secondSemesterSubject.average)) / 2 } private fun getGradeSubjects( diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt index b3ef3037..91e39e06 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeFragment.kt @@ -10,7 +10,6 @@ import android.view.View.VISIBLE import androidx.appcompat.app.AlertDialog import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.databinding.FragmentGradeBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter @@ -64,13 +63,11 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade 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) - ) - ) + 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) { @@ -122,9 +119,11 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade semesterSwitchMenu?.isVisible = show } - override fun showSemesterDialog(selectedIndex: Int, semesters: List) { - val choices = semesters.map { getString(R.string.grade_semester, it.semesterName) } - .toTypedArray() + 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 -> @@ -138,10 +137,7 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade override fun setCurrentSemesterName(semester: Int, schoolYear: Int) { subtitleString = getString(R.string.grade_subtitle, semester, schoolYear, schoolYear + 1) - - if (isVisible) { - (activity as MainView?)?.setViewSubTitle(subtitleString) - } + (activity as MainView).setViewSubTitle(subtitleString) } fun onChildRefresh() { @@ -153,8 +149,7 @@ class GradeFragment : BaseFragment(R.layout.fragment_grade } override fun notifyChildLoadData(index: Int, semesterId: Int, forceRefresh: Boolean) { - (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView) - ?.onParentLoadData(semesterId, forceRefresh) + (pagerAdapter.getFragmentInstance(index) as? GradeView.GradeChildView)?.onParentLoadData(semesterId, forceRefresh) } override fun notifyChildParentReselected(index: Int) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt index 504c730d..bfc504d2 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradePresenter.kt @@ -49,9 +49,7 @@ class GradePresenter @Inject constructor( } fun onSemesterSwitch(): Boolean { - if (semesters.isNotEmpty()) { - view?.showSemesterDialog(selectedIndex - 1, semesters.take(2)) - } + if (semesters.isNotEmpty()) view?.showSemesterDialog(selectedIndex - 1) return true } @@ -139,17 +137,11 @@ class GradePresenter @Inject constructor( private fun loadChild(index: Int, forceRefresh: Boolean = false) { Timber.d("Load grade tab child. Selected semester: $selectedIndex, semesters: ${semesters.joinToString { it.semesterName.toString() }}") - - val newSelectedSemesterId = try { - semesters.first { it.semesterName == selectedIndex }.semesterId - } catch (e: NoSuchElementException) { - Timber.e(e, "Selected semester no exists") - return - } - - if (forceRefresh || loadedSemesterId[index] != newSelectedSemesterId) { - Timber.i("Load grade child view index: $index") - view?.notifyChildLoadData(index, newSelectedSemesterId, forceRefresh) + 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) + } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt index 104f8505..7b52daa8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/GradeView.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.grade -import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.ui.base.BaseView interface GradeView : BaseView { @@ -19,7 +18,7 @@ interface GradeView : BaseView { fun showSemesterSwitch(show: Boolean) - fun showSemesterDialog(selectedIndex: Int, semesters: List) + fun showSemesterDialog(selectedIndex: Int) fun setCurrentSemesterName(semester: Int, schoolYear: Int) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt index 28619446..698aff3e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/details/GradeDetailsDialog.kt @@ -24,18 +24,17 @@ class GradeDetailsDialog : DialogFragment() { 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().apply { + 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?) { @@ -47,14 +46,12 @@ class GradeDetailsDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogGradeBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogGradeBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(binding) { gradeDialogSubject.text = grade.subject diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt index bf0b2014..0ffb4225 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt @@ -22,7 +22,6 @@ import io.github.wulkanowy.data.db.entities.GradePointsStatistics import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.pojos.GradeStatisticsItem import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding -import io.github.wulkanowy.databinding.ItemGradeStatisticsHeaderBinding import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding import io.github.wulkanowy.utils.getThemeAttrColor import javax.inject.Inject @@ -30,16 +29,12 @@ import javax.inject.Inject class GradeStatisticsAdapter @Inject constructor() : RecyclerView.Adapter() { - var currentDataType = GradeStatisticsItem.DataType.PARTIAL - var items = emptyList() var theme: String = "vulcan" var showAllSubjectsOnList: Boolean = false - var onDataTypeChangeListener: () -> Unit = {} - private val vulcanGradeColors = listOf( 6 to R.color.grade_vulcan_six, 5 to R.color.grade_vulcan_five, @@ -67,90 +62,37 @@ class GradeStatisticsAdapter @Inject constructor() : "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)) + 1 + override fun getItemCount() = if (showAllSubjectsOnList) items.size else (if (items.isEmpty()) 0 else 1) - override fun getItemViewType(position: Int) = - if (position == 0) { - ViewType.HEADER.id - } else { - when (items[position - 1].type) { - GradeStatisticsItem.DataType.PARTIAL -> ViewType.PARTIAL.id - GradeStatisticsItem.DataType.POINTS -> ViewType.POINTS.id - GradeStatisticsItem.DataType.SEMESTER -> ViewType.SEMESTER.id - } - } + 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 -> PartialViewHolder( - ItemGradeStatisticsPieBinding.inflate(inflater, parent, false) - ) - ViewType.SEMESTER.id -> SemesterViewHolder( - ItemGradeStatisticsPieBinding.inflate(inflater, parent, false) - ) - ViewType.POINTS.id -> PointsViewHolder( - ItemGradeStatisticsBarBinding.inflate(inflater, parent, false) - ) - ViewType.HEADER.id -> HeaderViewHolder( - ItemGradeStatisticsHeaderBinding.inflate(inflater, parent, false) - ) + ViewType.PARTIAL.id -> PartialViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) + ViewType.SEMESTER.id -> SemesterViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) + ViewType.POINTS.id -> PointsViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)) else -> throw IllegalStateException() } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - val index = position - 1 - when (holder) { - is PartialViewHolder -> bindPartialChart(holder.binding, items[index].partial!!) - is SemesterViewHolder -> bindSemesterChart(holder.binding, items[index].semester!!) - is PointsViewHolder -> bindBarChart(holder.binding, items[index].points!!) - is HeaderViewHolder -> bindHeader(holder.binding) + is PartialViewHolder -> bindPartialChart(holder.binding, items[position].partial!!) + is SemesterViewHolder -> bindSemesterChart(holder.binding, items[position].semester!!) + is PointsViewHolder -> bindBarChart(holder.binding, items[position].points!!) } } - private fun bindHeader(binding: ItemGradeStatisticsHeaderBinding) { - binding.gradeStatisticsTypeSwitch.check( - when (currentDataType) { - GradeStatisticsItem.DataType.PARTIAL -> R.id.gradeStatisticsTypePartial - GradeStatisticsItem.DataType.SEMESTER -> R.id.gradeStatisticsTypeSemester - GradeStatisticsItem.DataType.POINTS -> R.id.gradeStatisticsTypePoints - } - ) - - binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId -> - currentDataType = when (checkedId) { - R.id.gradeStatisticsTypePartial -> GradeStatisticsItem.DataType.PARTIAL - R.id.gradeStatisticsTypeSemester -> GradeStatisticsItem.DataType.SEMESTER - R.id.gradeStatisticsTypePoints -> GradeStatisticsItem.DataType.POINTS - else -> GradeStatisticsItem.DataType.PARTIAL - } - onDataTypeChangeListener() - } - } - - private fun bindPartialChart( - binding: ItemGradeStatisticsPieBinding, - partials: GradePartialStatistics - ) { + private fun bindPartialChart(binding: ItemGradeStatisticsPieBinding, partials: GradePartialStatistics) { bindPieChart(binding, partials.subject, partials.classAverage, partials.classAmounts) } - private fun bindSemesterChart( - binding: ItemGradeStatisticsPieBinding, - semester: GradeSemesterStatistics - ) { + private fun bindSemesterChart(binding: ItemGradeStatisticsPieBinding, semester: GradeSemesterStatistics) { bindPieChart(binding, semester.subject, semester.average, semester.amounts) } - private fun bindPieChart( - binding: ItemGradeStatisticsPieBinding, - subject: String, - average: String, - amounts: List - ) { + private fun bindPieChart(binding: ItemGradeStatisticsPieBinding, subject: String, average: String, amounts: List) { with(binding.gradeStatisticsPieTitle) { text = subject visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE @@ -172,8 +114,7 @@ class GradeStatisticsAdapter @Inject constructor() : valueTextSize = 12f sliceSpace = 1f valueTextColor = Color.WHITE - val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount } - .filterNot { it.second == 0 } + val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }.filterNot { it.second == 0 } setColors(grades.reversed().map { (grade, _) -> gradeColors.single { color -> color.first == grade }.second }.toIntArray(), binding.root.context) @@ -185,11 +126,7 @@ class GradeStatisticsAdapter @Inject constructor() : 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() - ) + return resources.getQuantityString(R.plurals.grade_number_item, value.toInt(), value.toInt()) } }) } @@ -206,14 +143,11 @@ class GradeStatisticsAdapter @Inject constructor() : val numberOfGradesString = amounts.fold(0) { acc, it -> acc + it } .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } - val averageString = - binding.root.context.getString(R.string.grade_statistics_average, average) + val averageString = binding.root.context.getString(R.string.grade_statistics_average, average) minAngleForSlices = 25f description.isEnabled = false - centerText = - numberOfGradesString + ("\n\n" + averageString).takeIf { average.isNotBlank() } - .orEmpty() + centerText = numberOfGradesString + ("\n\n" + averageString).takeIf { average.isNotBlank() }.orEmpty() setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground)) setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) @@ -221,21 +155,16 @@ class GradeStatisticsAdapter @Inject constructor() : } } - private fun bindBarChart( - binding: ItemGradeStatisticsBarBinding, - points: GradePointsStatistics - ) { + private fun bindBarChart(binding: ItemGradeStatisticsBarBinding, points: GradePointsStatistics) { with(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()) - ), binding.root.context.getString(R.string.grade_statistics_legend) - ) + val dataset = BarDataSet(listOf( + BarEntry(1f, points.others.toFloat()), + BarEntry(2f, points.student.toFloat()) + ), binding.root.context.getString(R.string.grade_statistics_legend)) with(dataset) { valueTextSize = 12f @@ -260,8 +189,7 @@ class GradeStatisticsAdapter @Inject constructor() : form = Legend.LegendForm.SQUARE }, LegendEntry().apply { - label = - binding.root.context.getString(R.string.grade_statistics_average_student) + label = binding.root.context.getString(R.string.grade_statistics_average_student) formColor = gradePointsColors[1] form = Legend.LegendForm.SQUARE } @@ -298,7 +226,4 @@ class GradeStatisticsAdapter @Inject constructor() : private class PointsViewHolder(val binding: ItemGradeStatisticsBarBinding) : RecyclerView.ViewHolder(binding.root) - - private class HeaderViewHolder(val binding: ItemGradeStatisticsHeaderBinding) : - 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 index 0adac300..1ce7a202 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsFragment.kt @@ -38,28 +38,27 @@ class GradeStatisticsFragment : override val isViewEmpty get() = statisticsAdapter.items.isEmpty() - override val currentType get() = statisticsAdapter.currentDataType + 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? GradeStatisticsItem.DataType - ) + presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? ViewType) } override fun initView() { - statisticsAdapter.onDataTypeChangeListener = presenter::onTypeChange - with(binding.gradeStatisticsRecycler) { layoutManager = LinearLayoutManager(requireContext()) adapter = statisticsAdapter } - subjectsAdapter = - ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf()) + subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf()) subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject) with(binding.gradeStatisticsSubjects) { @@ -72,9 +71,7 @@ class GradeStatisticsFragment : gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh) gradeStatisticsSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary)) - gradeStatisticsSwipe.setProgressBackgroundColorSchemeColor( - requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh) - ) + gradeStatisticsSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)) gradeStatisticsErrorRetry.setOnClickListener { presenter.onRetry() } gradeStatisticsErrorDetails.setOnClickListener { presenter.onDetailsClick() } } @@ -88,15 +85,11 @@ class GradeStatisticsFragment : } } - override fun updateData( - newItems: List, - newTheme: String, - showAllSubjectsOnStatisticsList: Boolean - ) { + override fun updateData(items: List, theme: String, showAllSubjectsOnStatisticsList: Boolean) { with(statisticsAdapter) { - showAllSubjectsOnList = showAllSubjectsOnStatisticsList - theme = newTheme - items = newItems + this.showAllSubjectsOnList = showAllSubjectsOnStatisticsList + this.theme = theme + this.items = items notifyDataSetChanged() } } @@ -110,7 +103,11 @@ class GradeStatisticsFragment : } override fun resetView() { - binding.gradeStatisticsRecycler.scrollToPosition(0) + 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) { @@ -157,6 +154,11 @@ class GradeStatisticsFragment : (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) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt index 53eccad6..47ea52d3 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt @@ -35,12 +35,12 @@ class GradeStatisticsPresenter @Inject constructor( private lateinit var lastError: Throwable - var currentType: GradeStatisticsItem.DataType = GradeStatisticsItem.DataType.PARTIAL + var currentType: ViewType = ViewType.PARTIAL private set - fun onAttachView(view: GradeStatisticsView, type: GradeStatisticsItem.DataType?) { + fun onAttachView(view: GradeStatisticsView, type: ViewType?) { super.onAttachView(view) - currentType = type ?: GradeStatisticsItem.DataType.PARTIAL + currentType = type ?: ViewType.PARTIAL view.initView() errorHandler.showErrorMessage = ::showErrorViewOnError } @@ -59,11 +59,11 @@ class GradeStatisticsPresenter @Inject constructor( } fun onParentViewChangeSemester() { - clearDataInView() view?.run { showProgress(true) enableSwipe(false) showRefresh(false) + showContent(false) showErrorView(false) showEmpty(false) clearView() @@ -90,8 +90,8 @@ class GradeStatisticsPresenter @Inject constructor( fun onSubjectSelected(name: String?) { Timber.i("Select grade stats subject $name") - clearDataInView() view?.run { + showContent(false) showProgress(true) enableSwipe(false) showEmpty(false) @@ -104,11 +104,11 @@ class GradeStatisticsPresenter @Inject constructor( } fun onTypeChange() { - val type = view?.currentType ?: GradeStatisticsItem.DataType.POINTS + val type = view?.currentType ?: ViewType.POINTS Timber.i("Select grade stats semester: $type") cancelJobs("load") - clearDataInView() view?.run { + showContent(false) showProgress(true) enableSwipe(false) showEmpty(false) @@ -143,16 +143,10 @@ class GradeStatisticsPresenter @Inject constructor( }.launch("subjects") } - private fun loadDataByType( - semesterId: Int, - subjectName: String, - type: GradeStatisticsItem.DataType, - forceRefresh: Boolean = false - ) { + private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) { Timber.i("Loading grade stats data started") - currentSubjectName = - if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName + currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName currentType = type flowWithResourceIn { @@ -162,30 +156,9 @@ class GradeStatisticsPresenter @Inject constructor( with(gradeStatisticsRepository) { when (type) { - GradeStatisticsItem.DataType.PARTIAL -> { - getGradesPartialStatistics( - student = student, - semester = semester, - subjectName = currentSubjectName, - forceRefresh = forceRefresh - ) - } - GradeStatisticsItem.DataType.SEMESTER -> { - getGradesSemesterStatistics( - student = student, - semester = semester, - subjectName = currentSubjectName, - forceRefresh = forceRefresh - ) - } - GradeStatisticsItem.DataType.POINTS -> { - getGradesPointsStatistics( - student = student, - semester = semester, - subjectName = currentSubjectName, - forceRefresh = forceRefresh - ) - } + ViewType.PARTIAL -> getGradesPartialStatistics(student, semester, currentSubjectName, forceRefresh) + ViewType.SEMESTER -> getGradesSemesterStatistics(student, semester, currentSubjectName, forceRefresh) + ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh) } } }.onEach { @@ -195,15 +168,12 @@ class GradeStatisticsPresenter @Inject constructor( if (!isNoContent) { view?.run { showEmpty(isNoContent) + showContent(!isNoContent) showErrorView(false) enableSwipe(true) showRefresh(true) showProgress(false) - updateData( - if (isNoContent) emptyList() else it.data!!, - preferencesRepository.gradeColorTheme, - preferencesRepository.showAllSubjectsOnStatisticsList - ) + updateData(it.data!!, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) } } @@ -213,12 +183,9 @@ class GradeStatisticsPresenter @Inject constructor( view?.run { val isNoContent = checkIsNoContent(it.data!!, type) showEmpty(isNoContent) + showContent(!isNoContent) showErrorView(false) - updateData( - if (isNoContent) emptyList() else it.data, - preferencesRepository.gradeColorTheme, - preferencesRepository.showAllSubjectsOnStatisticsList - ) + updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) } analytics.logEvent( @@ -242,31 +209,16 @@ class GradeStatisticsPresenter @Inject constructor( }.launch("load") } - private fun checkIsNoContent( - items: List, - type: GradeStatisticsItem.DataType - ): Boolean { + private fun checkIsNoContent(items: List, type: ViewType): Boolean { return items.isEmpty() || when (type) { - GradeStatisticsItem.DataType.SEMESTER -> { - items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0 - } - GradeStatisticsItem.DataType.PARTIAL -> { - items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0 - } - GradeStatisticsItem.DataType.POINTS -> { - items.firstOrNull()?.points?.let { points -> points.student == .0 && points.others == .0 } ?: false - } + ViewType.SEMESTER -> items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0 + ViewType.PARTIAL -> items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0 + ViewType.POINTS -> items.firstOrNull()?.points?.let { points -> + points.student == .0 && points.others == .0 + } ?: false } } - private fun clearDataInView() { - view?.updateData( - emptyList(), - preferencesRepository.gradeColorTheme, - preferencesRepository.showAllSubjectsOnStatisticsList - ) - } - private fun showErrorViewOnError(message: String, error: Throwable) { view?.run { if (isViewEmpty) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsView.kt index 40511817..26b4a119 100644 --- 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 @@ -7,17 +7,13 @@ interface GradeStatisticsView : BaseView { val isViewEmpty: Boolean - val currentType: GradeStatisticsItem.DataType + val currentType: ViewType fun initView() fun updateSubjects(data: ArrayList) - fun updateData( - newItems: List, - newTheme: String, - showAllSubjectsOnStatisticsList: Boolean - ) + fun updateData(items: List, theme: String, showAllSubjectsOnStatisticsList: Boolean) fun showSubjects(show: Boolean) @@ -29,6 +25,8 @@ interface GradeStatisticsView : BaseView { fun resetView() + fun showContent(show: Boolean) + fun showEmpty(show: Boolean) fun showErrorView(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 index f695eaf9..02e95b0e 100644 --- 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 @@ -3,6 +3,5 @@ package io.github.wulkanowy.ui.modules.grade.statistics enum class ViewType(val id: Int) { SEMESTER(1), PARTIAL(2), - POINTS(3), - HEADER(4) + POINTS(3) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt index 93045a48..aecaa394 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/homework/details/HomeworkDetailsDialog.kt @@ -28,11 +28,12 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew private lateinit var homework: Homework companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(homework: Homework) = HomeworkDetailsDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) } + fun newInstance(homework: Homework): HomeworkDetailsDialog { + return HomeworkDetailsDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, homework) } + } } } @@ -44,22 +45,19 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogHomeworkBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogHomeworkBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + 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.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() } } @@ -89,8 +87,7 @@ class HomeworkDetailsDialog : BaseDialogFragment(), Homew } override fun updateMarkAsDoneLabel(isDone: Boolean) { - binding.homeworkDialogRead.text = - view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done) + binding.homeworkDialogRead.text = view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done) } override fun onDestroyView() { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt index 8d96a498..aff1c84c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/LoginActivity.kt @@ -52,8 +52,6 @@ class LoginActivity : BaseActivity(), Logi updateHelper.onResume(this) } - //https://developer.android.com/guide/playcore/in-app-updates#status_callback - @Suppress("DEPRECATION") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) updateHelper.onActivityResult(requestCode, resultCode) @@ -67,15 +65,13 @@ class LoginActivity : BaseActivity(), Logi with(loginAdapter) { containerId = binding.loginViewpager.id - addFragments( - listOf( - LoginFormFragment.newInstance(), - LoginSymbolFragment.newInstance(), - LoginStudentSelectFragment.newInstance(), - LoginAdvancedFragment.newInstance(), - LoginRecoverFragment.newInstance() - ) - ) + addFragments(listOf( + LoginFormFragment.newInstance(), + LoginSymbolFragment.newInstance(), + LoginStudentSelectFragment.newInstance(), + LoginAdvancedFragment.newInstance(), + LoginRecoverFragment.newInstance() + )) } with(binding.loginViewpager) { @@ -103,20 +99,14 @@ class LoginActivity : BaseActivity(), Logi } override fun notifyInitSymbolFragment(loginData: Triple) { - (loginAdapter.getFragmentInstance(1) as? LoginSymbolFragment)?.onParentInitSymbolFragment( - loginData - ) + (loginAdapter.getFragmentInstance(1) as? LoginSymbolFragment)?.onParentInitSymbolFragment(loginData) } override fun notifyInitStudentSelectFragment(studentsWithSemesters: List) { - (loginAdapter.getFragmentInstance(2) as? LoginStudentSelectFragment) - ?.onParentInitStudentSelectFragment(studentsWithSemesters) + (loginAdapter.getFragmentInstance(2) as? LoginStudentSelectFragment)?.onParentInitStudentSelectFragment(studentsWithSemesters) } - fun onFormFragmentAccountLogged( - studentsWithSemesters: List, - loginData: Triple - ) { + fun onFormFragmentAccountLogged(studentsWithSemesters: List, loginData: Triple) { presenter.onFormViewAccountLogged(studentsWithSemesters, loginData) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt index 4e09bd4d..c6d0209d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormFragment.kt @@ -150,13 +150,6 @@ class LoginFormFragment : BaseFragment(R.layout.fragme } } - override fun setErrorEmailInvalid(domain: String) { - with(binding.loginFormUsernameLayout) { - requestFocus() - error = getString(R.string.login_invalid_custom_email,domain) - } - } - override fun clearUsernameError() { binding.loginFormUsernameLayout.error = null } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt index 99dcf1bb..f6a528ae 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt @@ -11,7 +11,6 @@ import io.github.wulkanowy.utils.flowWithResource import io.github.wulkanowy.utils.ifNullOrBlank import kotlinx.coroutines.flow.onEach import timber.log.Timber -import java.net.URL import javax.inject.Inject class LoginFormPresenter @Inject constructor( @@ -88,14 +87,7 @@ class LoginFormPresenter @Inject constructor( if (!validateCredentials(email, password, host)) return - flowWithResource { - studentRepository.getStudentsScrapper( - email, - password, - host, - symbol - ) - }.onEach { + flowWithResource { studentRepository.getStudentsScrapper(email, password, host, symbol) }.onEach { when (it.status) { Status.LOADING -> view?.run { Timber.i("Login started") @@ -158,18 +150,11 @@ class LoginFormPresenter @Inject constructor( view?.setErrorLoginRequired() isCorrect = false } + if ("@" !in login && "email" in host) { view?.setErrorEmailRequired() isCorrect = false } - if ("@" in login && "||" !in login && "login" !in host && "email" !in host) { - val emailHost = login.substringAfter("@") - val emailDomain = URL(host).host - if (emailHost != emailDomain) { - view?.setErrorEmailInvalid(domain = emailDomain) - isCorrect = false - } - } } if (password.isEmpty()) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt index 079629ef..31f8a621 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt @@ -39,8 +39,6 @@ interface LoginFormView : BaseView { fun setErrorPassIncorrect() - fun setErrorEmailInvalid(domain: String) - fun clearUsernameError() fun clearPassError() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt index 2e2f9f5c..f0c9652f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/recover/LoginRecoverFragment.kt @@ -9,7 +9,6 @@ import android.view.View.VISIBLE import android.webkit.JavascriptInterface import android.webkit.WebView import android.webkit.WebViewClient -import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -43,12 +42,10 @@ class LoginRecoverFragment : private lateinit var hostSymbols: Array override val recoverHostValue: String - get() = hostValues.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())) - .orEmpty() + get() = hostValues.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() override val formHostSymbol: String - get() = hostSymbols.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())) - .orEmpty() + get() = hostSymbols.getOrNull(hostKeys.indexOf(bindingLocal.loginRecoverHost.text.toString())).orEmpty() override val recoverNameValue: String get() = bindingLocal.loginRecoverName.text.toString().trim() @@ -85,9 +82,7 @@ class LoginRecoverFragment : with(bindingLocal.loginRecoverHost) { setText(hostKeys.getOrNull(0).orEmpty()) - setAdapter( - LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys) - ) + setAdapter(LoginSymbolAdapter(context, R.layout.support_simple_spinner_dropdown_item, hostKeys)) setOnClickListener { if (bindingLocal.loginRecoverFormContainer.visibility == GONE) dismissDropDown() } } } @@ -132,7 +127,6 @@ class LoginRecoverFragment : override fun showErrorView(show: Boolean) { bindingLocal.loginRecoverError.visibility = if (show) VISIBLE else GONE - bindingLocal.loginRecoverErrorDetails.isVisible = true } override fun setErrorDetails(message: String) { @@ -172,7 +166,7 @@ class LoginRecoverFragment : with(bindingLocal.loginRecoverWebView) { settings.javaScriptEnabled = true webViewClient = object : WebViewClient() { - private var recoverWebViewSuccess = true + private var recoverWebViewSuccess: Boolean = true override fun onPageFinished(view: WebView?, url: String?) { if (recoverWebViewSuccess) { @@ -181,16 +175,10 @@ class LoginRecoverFragment : } else { showProgress(false) showErrorView(true) - bindingLocal.loginRecoverErrorDetails.isVisible = false } } - override fun onReceivedError( - view: WebView, - errorCode: Int, - description: String, - failingUrl: String - ) { + override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) { recoverWebViewSuccess = false } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt index 0a73fe15..3de23585 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberFragment.kt @@ -9,8 +9,6 @@ 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.luckynumber.history.LuckyNumberHistoryFragment -import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.utils.getThemeAttrColor import javax.inject.Inject @@ -44,7 +42,6 @@ class LuckyNumberFragment : luckyNumberSwipe.setOnRefreshListener(presenter::onSwipeRefresh) luckyNumberSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary)) luckyNumberSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)) - luckyNumberHistoryButton.setOnClickListener { openLuckyNumberHistory() } luckyNumberErrorRetry.setOnClickListener { presenter.onRetry() } luckyNumberErrorDetails.setOnClickListener { presenter.onDetailsClick() } } @@ -82,10 +79,6 @@ class LuckyNumberFragment : binding.luckyNumberContent.visibility = if (show) VISIBLE else GONE } - override fun openLuckyNumberHistory() { - (activity as? MainActivity)?.pushView(LuckyNumberHistoryFragment.newInstance()) - } - override fun onDestroyView() { presenter.onDetachView() super.onDestroyView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt index 0c05a156..a680c83e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/LuckyNumberView.kt @@ -24,6 +24,4 @@ interface LuckyNumberView : BaseView { fun enableSwipe(enable: Boolean) fun showContent(show: Boolean) - - fun openLuckyNumberHistory() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt deleted file mode 100644 index 7c09c96f..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryAdapter.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber.history - -import android.annotation.SuppressLint -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.databinding.ItemLuckyNumberHistoryBinding -import io.github.wulkanowy.utils.toFormattedString -import io.github.wulkanowy.utils.weekDayName -import java.util.Locale -import javax.inject.Inject - -class LuckyNumberHistoryAdapter @Inject constructor() : - RecyclerView.Adapter() { - - var items = emptyList() - - override fun getItemCount() = items.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( - ItemLuckyNumberHistoryBinding.inflate(LayoutInflater.from(parent.context), parent, false) - ) - - @SuppressLint("DefaultLocale") - override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - val item = items[position] - with(holder.binding) { - luckyNumberHistoryWeekName.text = item.date.weekDayName.capitalize() - luckyNumberHistoryDate.text = item.date.toFormattedString() - luckyNumberHistory.text = item.luckyNumber.toString() - } - } - - class ItemViewHolder(val binding: ItemLuckyNumberHistoryBinding) : RecyclerView.ViewHolder(binding.root) -} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt deleted file mode 100644 index 6e991ba1..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryFragment.kt +++ /dev/null @@ -1,134 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber.history - -import android.os.Bundle -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 dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.databinding.FragmentLuckyNumberHistoryBinding -import io.github.wulkanowy.ui.base.BaseFragment -import io.github.wulkanowy.ui.modules.main.MainView -import io.github.wulkanowy.ui.widgets.DividerItemDecoration -import io.github.wulkanowy.utils.SchooldaysRangeLimiter -import io.github.wulkanowy.utils.dpToPx -import io.github.wulkanowy.utils.getThemeAttrColor -import java.time.LocalDate -import javax.inject.Inject - -@AndroidEntryPoint -class LuckyNumberHistoryFragment : - BaseFragment(R.layout.fragment_lucky_number_history), LuckyNumberHistoryView, - MainView.TitledView { - - @Inject - lateinit var presenter: LuckyNumberHistoryPresenter - - @Inject - lateinit var luckyNumberHistoryAdapter: LuckyNumberHistoryAdapter - - companion object { - fun newInstance() = LuckyNumberHistoryFragment() - } - - override val titleStringId: Int - get() = R.string.lucky_number_history_title - - override val isViewEmpty get() = luckyNumberHistoryAdapter.items.isEmpty() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding = FragmentLuckyNumberHistoryBinding.bind(view) - messageContainer = binding.luckyNumberHistoryRecycler - presenter.onAttachView(this) - } - - override fun initView() { - with(binding.luckyNumberHistoryRecycler) { - layoutManager = LinearLayoutManager(context) - adapter = luckyNumberHistoryAdapter - addItemDecoration(DividerItemDecoration(context)) - } - - with(binding) { - luckyNumberHistoryNavDate.setOnClickListener { presenter.onPickDate() } - luckyNumberHistoryErrorRetry.setOnClickListener { presenter.onRetry() } - luckyNumberHistoryErrorDetails.setOnClickListener { presenter.onDetailsClick() } - - luckyNumberHistoryPreviousButton.setOnClickListener { presenter.onPreviousWeek() } - luckyNumberHistoryNextButton.setOnClickListener { presenter.onNextWeek() } - - luckyNumberHistoryNavContainer.setElevationCompat(requireContext().dpToPx(8f)) - } - } - - override fun updateData(data: List) { - with(luckyNumberHistoryAdapter) { - items = data - notifyDataSetChanged() - } - } - - override fun clearData() { - with(luckyNumberHistoryAdapter) { - items = emptyList() - notifyDataSetChanged() - } - } - - override fun showEmpty(show: Boolean) { - binding.luckyNumberHistoryEmpty.visibility = if (show) VISIBLE else GONE - } - - override fun showErrorView(show: Boolean) { - binding.luckyNumberHistoryError.visibility = if (show) VISIBLE else GONE - } - - override fun setErrorDetails(message: String) { - binding.luckyNumberHistoryErrorMessage.text = message - } - - override fun updateNavigationWeek(date: String) { - binding.luckyNumberHistoryNavDate.text = date - } - - override fun showProgress(show: Boolean) { - binding.luckyNumberHistoryProgress.visibility = if (show) VISIBLE else GONE - } - - override fun showPreButton(show: Boolean) { - binding.luckyNumberHistoryPreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showNextButton(show: Boolean) { - binding.luckyNumberHistoryNextButton.visibility = if (show) VISIBLE else View.INVISIBLE - } - - override fun showDatePickerDialog(currentDate: LocalDate) { - val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, dayOfMonth -> - presenter.onDateSet(year, month + 1, dayOfMonth) - } - val datePickerDialog = DatePickerDialog.newInstance(dateSetListener, - currentDate.year, currentDate.monthValue - 1, currentDate.dayOfMonth) - - with(datePickerDialog) { - setDateRangeLimiter(SchooldaysRangeLimiter()) - version = DatePickerDialog.Version.VERSION_2 - scrollOrientation = DatePickerDialog.ScrollOrientation.VERTICAL - vibrate(false) - show(this@LuckyNumberHistoryFragment.parentFragmentManager, null) - } - } - - override fun showContent(show: Boolean) { - binding.luckyNumberHistoryRecycler.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/history/LuckyNumberHistoryPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt deleted file mode 100644 index 556dda75..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryPresenter.kt +++ /dev/null @@ -1,151 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber.history - -import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.LuckyNumberRepository -import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.afterLoading -import io.github.wulkanowy.utils.flowWithResource -import io.github.wulkanowy.utils.isHolidays -import io.github.wulkanowy.utils.monday -import io.github.wulkanowy.utils.previousOrSameSchoolDay -import io.github.wulkanowy.utils.sunday -import io.github.wulkanowy.utils.toFormattedString -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.onEach -import timber.log.Timber -import java.time.LocalDate -import javax.inject.Inject - -class LuckyNumberHistoryPresenter @Inject constructor( - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val luckyNumberRepository: LuckyNumberRepository, - private val analytics: AnalyticsHelper -) : BasePresenter(errorHandler, studentRepository) { - - private lateinit var lastError: Throwable - - var currentDate: LocalDate = LocalDate.now().previousOrSameSchoolDay - - override fun onAttachView(view: LuckyNumberHistoryView) { - super.onAttachView(view) - view.run { - initView() - reloadNavigation() - showContent(false) - } - Timber.i("Lucky number history view was initialized") - errorHandler.showErrorMessage = ::showErrorViewOnError - loadData() - } - - private fun loadData() { - flowWithResource { - val student = studentRepository.getCurrentStudent() - luckyNumberRepository.getLuckyNumberHistory(student, currentDate.monday, currentDate.sunday) - }.onEach { - when (it.status) { - Status.LOADING -> Timber.i("Loading lucky number history started") - Status.SUCCESS -> { - if (!it.data?.first().isNullOrEmpty()) { - Timber.i("Loading lucky number result: Success") - view?.apply { - updateData(it.data!!.first()) - showContent(true) - showEmpty(false) - showErrorView(false) - showProgress(false) - } - analytics.logEvent( - "load_items", - "type" to "lucky_number_history", - "numbers" to it.data - ) - } else { - Timber.i("Loading lucky number history result: No lucky numbers found") - view?.run { - showContent(false) - showEmpty(true) - showErrorView(false) - } - } - } - Status.ERROR -> { - Timber.i("Loading lucky number history result: An exception occurred") - errorHandler.dispatch(it.error!!) - } - } - }.afterLoading { - view?.run { - showProgress(false) - } - }.launch() - } - - private fun showErrorViewOnError(message: String, error: Throwable) { - view?.run { - if (isViewEmpty) { - lastError = error - setErrorDetails(message) - showErrorView(true) - showEmpty(false) - } else showError(message, error) - } - } - - private fun reloadView(date: LocalDate) { - currentDate = date - Timber.i("Reload lucky number history view with the date ${currentDate.toFormattedString()}") - view?.apply { - showProgress(true) - showContent(false) - showEmpty(false) - showErrorView(false) - clearData() - reloadNavigation() - } - } - - fun onRetry() { - view?.run { - showErrorView(false) - showProgress(true) - } - loadData() - } - - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - - 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")) - } - } - - fun onDateSet(year: Int, month: Int, day: Int) { - reloadView(LocalDate.of(year, month, day)) - loadData() - } - - fun onPickDate() { - view?.showDatePickerDialog(currentDate) - } - - fun onPreviousWeek() { - reloadView(currentDate.minusDays(7)) - loadData() - } - - fun onNextWeek() { - reloadView(currentDate.plusDays(7)) - loadData() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt deleted file mode 100644 index 331e4ff8..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumber/history/LuckyNumberHistoryView.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.ui.modules.luckynumber.history - -import io.github.wulkanowy.data.db.entities.LuckyNumber -import io.github.wulkanowy.ui.base.BaseView -import java.time.LocalDate - -interface LuckyNumberHistoryView : BaseView { - - val isViewEmpty: Boolean - - fun initView() - - fun updateData(data: List) - - fun clearData() - - fun showEmpty(show: Boolean) - - fun showErrorView(show: Boolean) - - fun setErrorDetails(message: String) - - fun updateNavigationWeek(date: String) - - fun showProgress(show: Boolean) - - fun showPreButton(show: Boolean) - - fun showNextButton(show: Boolean) - - fun showDatePickerDialog(currentDate: LocalDate) - - fun showContent(show: Boolean) - - fun onDestroyView() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt index 024beff8..692615d9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureActivity.kt @@ -11,7 +11,7 @@ import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.WidgetConfigureAdapter @@ -38,9 +38,7 @@ class LuckyNumberWidgetConfigureActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResult(RESULT_CANCELED) - setContentView( - ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root - ) + setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) intent.extras.let { presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID)) @@ -72,9 +70,8 @@ class LuckyNumberWidgetConfigureActivity : .show() } - override fun updateData(data: List, selectedStudentId: Long) { + override fun updateData(data: List>) { with(configureAdapter) { - selectedId = selectedStudentId items = data notifyDataSetChanged() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt index 5b6af69a..f4041e9e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigurePresenter.kt @@ -51,17 +51,16 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor( when (it.status) { Status.LOADING -> Timber.d("Lucky number widget configure students data load") Status.SUCCESS -> { - val selectedStudentId = appWidgetId?.let { id -> - sharedPref.getLong(getStudentWidgetKey(id), 0) - } ?: -1 - + val widgetId = appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } when { it.data!!.isEmpty() -> view?.openLoginView() it.data.size == 1 -> { selectedStudent = it.data.single().student view?.showThemeDialog() } - else -> view?.updateData(it.data, selectedStudentId) + else -> view?.updateData(it.data.map { entity -> + entity.student to (entity.student.id == widgetId) + }) } } Status.ERROR -> errorHandler.dispatch(it.error!!) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt index b4556f7e..c8c348ed 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/luckynumberwidget/LuckyNumberWidgetConfigureView.kt @@ -1,6 +1,6 @@ package io.github.wulkanowy.ui.modules.luckynumberwidget -import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.ui.base.BaseView interface LuckyNumberWidgetConfigureView : BaseView { @@ -9,7 +9,7 @@ interface LuckyNumberWidgetConfigureView : BaseView { fun showThemeDialog() - fun updateData(data: List, selectedStudentId: Long) + fun updateData(data: List>) fun updateLuckyNumberWidget(widgetId: Int) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 37c6c6e7..5d93c594 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -11,21 +11,15 @@ import android.graphics.drawable.Icon import android.os.Build import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.LOLLIPOP -import android.os.Build.VERSION_CODES.P import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.ViewGroup +import android.view.View import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import androidx.core.view.ViewCompat -import androidx.core.view.isVisible -import androidx.core.view.updateLayoutParams -import androidx.core.view.updateMargins import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState.ALWAYS_SHOW import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem import com.google.android.material.elevation.ElevationOverlayProvider @@ -33,8 +27,6 @@ import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavController.Companion.HIDE import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.databinding.ActivityMainBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog @@ -50,18 +42,15 @@ import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.UpdateHelper -import io.github.wulkanowy.utils.createNameInitialsDrawable import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor -import io.github.wulkanowy.utils.nickOrName import io.github.wulkanowy.utils.safelyPopFragments import io.github.wulkanowy.utils.setOnViewChangeListener import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint -class MainActivity : BaseActivity(), MainView, - PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { +class MainActivity : BaseActivity(), MainView { @Inject override lateinit var presenter: MainPresenter @@ -75,8 +64,6 @@ class MainActivity : BaseActivity(), MainVie @Inject lateinit var appInfo: AppInfo - private var accountMenu: MenuItem? = null - private val overlayProvider by lazy { ElevationOverlayProvider(this) } private val navController = @@ -134,11 +121,6 @@ class MainActivity : BaseActivity(), MainVie initialize(startMenuIndex, savedInstanceState) pushFragment(moreMenuFragments[startMenuMoreIndex]) } - - if (appInfo.systemVersion >= Build.VERSION_CODES.N_MR1) { - initShortcuts() - } - updateHelper.checkAndInstallUpdates(this) } @@ -147,11 +129,11 @@ class MainActivity : BaseActivity(), MainVie updateHelper.onResume(this) } - //https://developer.android.com/guide/playcore/in-app-updates#status_callback - @Suppress("DEPRECATION") + @SuppressLint("NewApi") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) updateHelper.onActivityResult(requestCode, resultCode) + if (appInfo.systemVersion >= Build.VERSION_CODES.N_MR1) initShortcuts() } @RequiresApi(Build.VERSION_CODES.N_MR1) @@ -178,6 +160,11 @@ class MainActivity : BaseActivity(), MainVie getString(R.string.timetable_title), R.drawable.ic_shortcut_timetable, MainView.Section.TIMETABLE + ), + Triple( + getString(R.string.message_title), + R.drawable.ic_shortcut_message, + MainView.Section.MESSAGE ) ).forEach { (title, icon, enum) -> shortcutsList.add( @@ -204,13 +191,9 @@ class MainActivity : BaseActivity(), MainVie override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.action_menu_main, menu) - accountMenu = menu?.findItem(R.id.mainMenuAccount) - - presenter.onActionMenuCreated() return true } - @SuppressLint("NewApi") override fun initView() { with(binding.mainToolbar) { if (SDK_INT >= LOLLIPOP) stateListAnimator = null @@ -250,27 +233,13 @@ class MainActivity : BaseActivity(), MainVie with(navController) { setOnViewChangeListener { section, name -> - if (section == MainView.Section.ACCOUNT || section == MainView.Section.STUDENT_INFO) { - binding.mainBottomNav.isVisible = false - binding.mainFragmentContainer.updateLayoutParams { - updateMargins(bottom = 0) + binding.mainBottomNav.visibility = + if (section == MainView.Section.ACCOUNT || section == MainView.Section.STUDENT_INFO) { + View.GONE + } else { + View.VISIBLE } - if (appInfo.systemVersion >= P) { - window.navigationBarColor = getThemeAttrColor(R.attr.colorSurface) - } - } else { - binding.mainBottomNav.isVisible = true - binding.mainFragmentContainer.updateLayoutParams { - updateMargins(bottom = dpToPx(56f).toInt()) - } - - if (appInfo.systemVersion >= P) { - window.navigationBarColor = - getThemeAttrColor(android.R.attr.navigationBarColor) - } - } - analytics.setCurrentScreen(this@MainActivity, name) presenter.onViewChange(section) } @@ -285,16 +254,6 @@ class MainActivity : BaseActivity(), MainVie } } - override fun onPreferenceStartFragment( - caller: PreferenceFragmentCompat, - pref: Preference - ): Boolean { - val fragment = - supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment) - pushView(fragment) - return true - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() else false @@ -305,8 +264,6 @@ class MainActivity : BaseActivity(), MainVie } override fun switchMenuView(position: Int) { - if (supportFragmentManager.isStateSaved) return - analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.switchTab(position) } @@ -323,8 +280,8 @@ class MainActivity : BaseActivity(), MainVie supportActionBar?.setDisplayHomeAsUpEnabled(show) } - override fun showAccountPicker(studentWithSemesters: List) { - showDialogFragment(AccountQuickDialog.newInstance(studentWithSemesters)) + override fun showAccountPicker() { + navController.showDialogFragment(AccountQuickDialog.newInstance()) } override fun showActionBarElevation(show: Boolean) { @@ -340,31 +297,16 @@ class MainActivity : BaseActivity(), MainVie (navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentChanged() } - @Suppress("DEPRECATION") fun showDialogFragment(dialog: DialogFragment) { - if (supportFragmentManager.isStateSaved) return - - //Deprecated method is used here to avoid fragnav bug - if (navController.currentDialogFrag?.fragmentManager == null) { - FragNavController::class.java.getDeclaredField("mCurrentDialogFrag").apply { - isAccessible = true - set(navController, null) - } - } - navController.showDialogFragment(dialog) } fun pushView(fragment: Fragment) { - if (supportFragmentManager.isStateSaved) return - analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.pushFragment(fragment) } override fun popView(depth: Int) { - if (supportFragmentManager.isStateSaved) return - analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.safelyPopFragments(depth) } @@ -373,13 +315,6 @@ class MainActivity : BaseActivity(), MainVie presenter.onBackPressed { super.onBackPressed() } } - override fun showStudentAvatar(student: Student) { - accountMenu?.run { - icon = createNameInitialsDrawable(student.nickOrName, student.avatarColor, 0.44f) - title = getString(R.string.main_account_picker) - } - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) navController.onSaveInstanceState(outState) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt index ffcfcb61..59937b33 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt @@ -1,7 +1,5 @@ package io.github.wulkanowy.ui.modules.main -import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.services.sync.SyncManager @@ -11,8 +9,6 @@ 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.AnalyticsHelper -import io.github.wulkanowy.utils.flowWithResource -import kotlinx.coroutines.flow.onEach import timber.log.Timber import javax.inject.Inject @@ -21,11 +17,9 @@ class MainPresenter @Inject constructor( studentRepository: StudentRepository, private val prefRepository: PreferencesRepository, private val syncManager: SyncManager, - private val analytics: AnalyticsHelper, + private val analytics: AnalyticsHelper ) : BasePresenter(errorHandler, studentRepository) { - var studentsWitSemesters: List? = null - fun onAttachView(view: MainView, initMenu: MainView.Section?) { super.onAttachView(view) view.apply { @@ -41,28 +35,6 @@ class MainPresenter @Inject constructor( analytics.logEvent("app_open", "destination" to initMenu?.name) } - fun onActionMenuCreated() { - if (!studentsWitSemesters.isNullOrEmpty()) { - showCurrentStudentAvatar() - return - } - - flowWithResource { studentRepository.getSavedStudents(false) } - .onEach { resource -> - when (resource.status) { - Status.LOADING -> Timber.i("Loading student avatar data started") - Status.SUCCESS -> { - studentsWitSemesters = resource.data - showCurrentStudentAvatar() - } - Status.ERROR -> { - Timber.i("Loading student avatar result: An exception occurred") - errorHandler.dispatch(resource.error!!) - } - } - }.launch("avatar") - } - fun onViewChange(section: MainView.Section?) { view?.apply { showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL) @@ -76,10 +48,8 @@ class MainPresenter @Inject constructor( } fun onAccountManagerSelected(): Boolean { - if (studentsWitSemesters.isNullOrEmpty()) return true - Timber.i("Select account manager") - view?.showAccountPicker(studentsWitSemesters!!) + view?.showAccountPicker() return true } @@ -111,13 +81,6 @@ class MainPresenter @Inject constructor( } == true } - private fun showCurrentStudentAvatar() { - val currentStudent = - studentsWitSemesters?.singleOrNull { it.student.isCurrent }?.student ?: return - - view?.showStudentAvatar(currentStudent) - } - private fun getProperViewIndexes(initMenu: MainView.Section?): Pair { return when (initMenu?.id) { in 0..3 -> initMenu!!.id 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 index a4b7d094..7f409814 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt @@ -1,7 +1,5 @@ package io.github.wulkanowy.ui.modules.main -import io.github.wulkanowy.data.db.entities.Student -import io.github.wulkanowy.data.db.entities.StudentWithSemesters import io.github.wulkanowy.ui.base.BaseView interface MainView : BaseView { @@ -24,7 +22,7 @@ interface MainView : BaseView { fun showHomeArrow(show: Boolean) - fun showAccountPicker(studentWithSemesters: List) + fun showAccountPicker() fun showActionBarElevation(show: Boolean) @@ -38,8 +36,6 @@ interface MainView : BaseView { fun popView(depth: Int = 1) - fun showStudentAvatar(student: Student) - interface MainChildView { fun onFragmentReselected() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt index 6357c495..48150d8d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/mobiledevice/token/MobileDeviceTokenDialog.kt @@ -20,15 +20,13 @@ import io.github.wulkanowy.ui.base.BaseDialogFragment import javax.inject.Inject @AndroidEntryPoint -class MobileDeviceTokenDialog : BaseDialogFragment(), - MobileDeviceTokenVIew { +class MobileDeviceTokenDialog : BaseDialogFragment(), MobileDeviceTokenVIew { @Inject lateinit var presenter: MobileDeviceTokenPresenter companion object { - - fun newInstance() = MobileDeviceTokenDialog() + fun newInstance(): MobileDeviceTokenDialog = MobileDeviceTokenDialog() } override fun onCreate(savedInstanceState: Bundle?) { @@ -36,14 +34,12 @@ class MobileDeviceTokenDialog : BaseDialogFragment(), setStyle(STYLE_NO_TITLE, 0) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogMobileDeviceBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogMobileDeviceBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) presenter.onAttachView(this) } 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 index c4a14a52..bf8918fc 100644 --- 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 @@ -63,6 +63,9 @@ class MoreFragment : BaseFragment(R.layout.fragment_more), 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) @@ -121,6 +124,10 @@ class MoreFragment : BaseFragment(R.layout.fragment_more), (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) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt index 6079141f..d119000d 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt @@ -30,6 +30,7 @@ class MorePresenter @Inject constructor( conferencesRes?.first -> openConferencesView() schoolAndTeachersRes?.first -> openSchoolAndTeachersView() settingsRes?.first -> openSettingsView() + aboutRes?.first -> openAboutView() } } } @@ -50,7 +51,8 @@ class MorePresenter @Inject constructor( mobileDevicesRes, conferencesRes, schoolAndTeachersRes, - settingsRes + 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 index 0543742e..bb1faeda 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt @@ -21,12 +21,16 @@ interface MoreView : BaseView { val settingsRes: Pair? + val aboutRes: Pair? + fun initView() fun updateData(data: List>) fun openSettingsView() + fun openAboutView() + fun popView(depth: Int) fun openMessagesView() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt index 4cb1cda0..e016fe0b 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/note/NoteDialog.kt @@ -22,11 +22,12 @@ class NoteDialog : DialogFragment() { private lateinit var note: Note companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Note) = NoteDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(exam: Note): NoteDialog { + return NoteDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + } } } @@ -38,15 +39,13 @@ class NoteDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogNoteBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogNoteBinding.inflate(inflater).apply { binding = this }.root + } @SuppressLint("SetTextI18n") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(binding) { noteDialogDate.text = note.date.toFormattedString() @@ -58,19 +57,11 @@ class NoteDialog : DialogFragment() { if (note.isPointsShow) { with(binding.noteDialogPoints) { text = "${if (note.points > 0) "+" else ""}${note.points}" - setTextColor( - when (NoteCategory.getByValue(note.categoryType)) { - NoteCategory.POSITIVE -> ContextCompat.getColor( - requireContext(), - R.color.note_positive - ) - NoteCategory.NEGATIVE -> ContextCompat.getColor( - requireContext(), - R.color.note_negative - ) - else -> requireContext().getThemeAttrColor(android.R.attr.textColorPrimary) - } - ) + setTextColor(when (NoteCategory.getByValue(note.categoryType)) { + NoteCategory.POSITIVE -> ContextCompat.getColor(requireContext(), R.color.note_positive) + NoteCategory.NEGATIVE -> ContextCompat.getColor(requireContext(), R.color.note_negative) + else -> requireContext().getThemeAttrColor(android.R.attr.textColorPrimary) + }) } } 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 index fba2f040..03ad7ba0 100644 --- 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 @@ -53,14 +53,13 @@ class SchoolFragment : BaseFragment(R.layout.fragment_sch override fun updateData(data: School) { with(binding) { - val noDataString = getString(R.string.all_no_data) - schoolName.text = data.name.ifBlank { noDataString } - schoolAddress.text = data.address.ifBlank { noDataString } + schoolName.text = data.name + schoolAddress.text = data.address.ifBlank { "-" } schoolAddressButton.visibility = if (data.address.isNotBlank()) VISIBLE else GONE - schoolTelephone.text = data.contact.ifBlank { noDataString } + schoolTelephone.text = data.contact.ifBlank { "-" } schoolTelephoneButton.visibility = if (data.contact.isNotBlank()) VISIBLE else GONE - schoolHeadmaster.text = data.headmaster.ifBlank { noDataString } - schoolPedagogue.text = data.pedagogue.ifBlank { noDataString } + schoolHeadmaster.text = data.headmaster + schoolPedagogue.text = data.pedagogue } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt index 2612fab3..ad4692b9 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsFragment.kt @@ -1,22 +1,148 @@ package io.github.wulkanowy.ui.modules.settings +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.hilt.android.AndroidEntryPoint 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 timber.log.Timber +import io.github.wulkanowy.utils.AppInfo +import io.github.wulkanowy.utils.openInternetBrowser +import javax.inject.Inject -class SettingsFragment : PreferenceFragmentCompat(), MainView.TitledView { +@AndroidEntryPoint +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 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) - Timber.i("Settings view was initialized") + 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 updateLanguageToFollowSystem() { + lingver.setFollowSystemLocale(requireContext()) + } + + 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 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/sync/SyncPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt similarity index 63% rename from app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt index 36b8d792..e3b2e232 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsPresenter.kt @@ -1,12 +1,15 @@ -package io.github.wulkanowy.ui.modules.settings.sync +package io.github.wulkanowy.ui.modules.settings import androidx.work.WorkInfo +import com.chuckerteam.chucker.api.ChuckerCollector import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository +import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper import io.github.wulkanowy.services.sync.SyncManager import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.isHolidays import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.onEach @@ -14,17 +17,20 @@ import timber.log.Timber import java.time.LocalDate.now import javax.inject.Inject -class SyncPresenter @Inject constructor( +class SettingsPresenter @Inject constructor( errorHandler: ErrorHandler, studentRepository: StudentRepository, private val preferencesRepository: PreferencesRepository, + private val timetableNotificationHelper: TimetableNotificationSchedulerHelper, private val analytics: AnalyticsHelper, private val syncManager: SyncManager, -) : BasePresenter(errorHandler, studentRepository) { + private val chuckerCollector: ChuckerCollector, + private val appInfo: AppInfo +) : BasePresenter(errorHandler, studentRepository) { - override fun onAttachView(view: SyncView) { + override fun onAttachView(view: SettingsView) { super.onAttachView(view) - Timber.i("Settings sync view was initialized") + Timber.i("Settings view was initialized") view.setServicesSuspended(preferencesRepository.serviceEnableKey, now().isHolidays) view.initView() } @@ -36,6 +42,20 @@ class SyncPresenter @Inject constructor( 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 { + if (appLanguage == "system") { + updateLanguageToFollowSystem() + analytics.logEvent("language", "setting_changed" to appInfo.systemLanguage) + } else { + updateLanguage(appLanguage) + analytics.logEvent("language", "setting_changed" to appLanguage) + } + recreateView() + } } } analytics.logEvent("setting_changed", "name" to key) @@ -69,4 +89,8 @@ class SyncPresenter @Inject constructor( }.launch("sync") } } + + fun onFixSyncIssuesClicked() { + view?.showFixSyncDialog() + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt similarity index 54% rename from app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncView.kt rename to app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt index 9da473ba..80271741 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/SettingsView.kt @@ -1,8 +1,8 @@ -package io.github.wulkanowy.ui.modules.settings.sync +package io.github.wulkanowy.ui.modules.settings import io.github.wulkanowy.ui.base.BaseView -interface SyncView : BaseView { +interface SettingsView : BaseView { val syncSuccessString: String @@ -10,7 +10,15 @@ interface SyncView : BaseView { fun initView() + fun recreateView() + + fun updateLanguage(langCode: String) + + fun updateLanguageToFollowSystem() + fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) fun setSyncInProgress(inProgress: Boolean) + + fun showFixSyncDialog() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedFragment.kt deleted file mode 100644 index 524d7ba6..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedFragment.kt +++ /dev/null @@ -1,78 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.advanced - -import android.content.SharedPreferences -import android.os.Bundle -import android.view.View -import androidx.preference.PreferenceFragmentCompat -import com.yariksoffice.lingver.Lingver -import dagger.hilt.android.AndroidEntryPoint -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 javax.inject.Inject - -@AndroidEntryPoint -class AdvancedFragment : PreferenceFragmentCompat(), - SharedPreferences.OnSharedPreferenceChangeListener, - MainView.TitledView, AdvancedView { - - @Inject - lateinit var presenter: AdvancedPresenter - - @Inject - lateinit var appInfo: AppInfo - - @Inject - lateinit var lingver: Lingver - - companion object { - fun newInstance() = AdvancedFragment() - } - - override val titleStringId get() = R.string.pref_settings_advanced_title - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.scheme_preferences_advanced, rootKey) - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { - presenter.onSharedPreferenceChanged(key) - } - - 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 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/advanced/AdvancedPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt deleted file mode 100644 index d38f841f..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedPresenter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.advanced - -import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AnalyticsHelper -import timber.log.Timber -import javax.inject.Inject - -class AdvancedPresenter @Inject constructor( - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val analytics: AnalyticsHelper, -) : BasePresenter(errorHandler, studentRepository) { - - override fun onAttachView(view: AdvancedView) { - super.onAttachView(view) - Timber.i("Settings advanced view was initialized") - } - - fun onSharedPreferenceChanged(key: String) { - Timber.i("Change settings $key") - analytics.logEvent("setting_changed", "name" to key) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedView.kt deleted file mode 100644 index c2e8e52d..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/advanced/AdvancedView.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.advanced - -import io.github.wulkanowy.ui.base.BaseView - -interface AdvancedView : BaseView {} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt deleted file mode 100644 index 5ac801dc..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceFragment.kt +++ /dev/null @@ -1,90 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance - -import android.content.SharedPreferences -import android.os.Bundle -import android.view.View -import androidx.preference.PreferenceFragmentCompat -import com.yariksoffice.lingver.Lingver -import dagger.hilt.android.AndroidEntryPoint -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 javax.inject.Inject - -@AndroidEntryPoint -class AppearanceFragment : PreferenceFragmentCompat(), - SharedPreferences.OnSharedPreferenceChangeListener, - MainView.TitledView, AppearanceView { - - @Inject - lateinit var presenter: AppearancePresenter - - @Inject - lateinit var appInfo: AppInfo - - @Inject - lateinit var lingver: Lingver - - companion object { - fun newInstance() = AppearanceFragment() - } - - override val titleStringId get() = R.string.pref_settings_appearance_title - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.scheme_preferences_appearance, rootKey) - } - - 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 updateLanguageToFollowSystem() { - lingver.setFollowSystemLocale(requireContext()) - } - - 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 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/appearance/AppearancePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt deleted file mode 100644 index 14592a6c..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearancePresenter.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance - -import io.github.wulkanowy.data.repositories.PreferencesRepository -import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.AppInfo -import timber.log.Timber -import javax.inject.Inject - -class AppearancePresenter @Inject constructor( - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val preferencesRepository: PreferencesRepository, - private val analytics: AnalyticsHelper, - private val appInfo: AppInfo -) : BasePresenter(errorHandler, studentRepository) { - - override fun onAttachView(view: AppearanceView) { - super.onAttachView(view) - Timber.i("Settings appearance view was initialized") - } - - fun onSharedPreferenceChanged(key: String) { - Timber.i("Change settings $key") - - preferencesRepository.apply { - when (key) { - appThemeKey -> view?.recreateView() - appLanguageKey -> view?.run { - if (appLanguage == "system") { - updateLanguageToFollowSystem() - analytics.logEvent("language", "setting_changed" to appInfo.systemLanguage) - } else { - updateLanguage(appLanguage) - analytics.logEvent("language", "setting_changed" to appLanguage) - } - recreateView() - } - } - } - analytics.logEvent("setting_changed", "name" to key) - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceView.kt deleted file mode 100644 index ecee4f42..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/appearance/AppearanceView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.appearance - -import io.github.wulkanowy.ui.base.BaseView - -interface AppearanceView : BaseView { - - fun recreateView() - - fun updateLanguage(langCode: String) - - fun updateLanguageToFollowSystem() -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt deleted file mode 100644 index a9641d88..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt +++ /dev/null @@ -1,130 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.notifications - -import android.content.SharedPreferences -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat -import androidx.recyclerview.widget.RecyclerView -import com.thelittlefireman.appkillermanager.AppKillerManager -import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException -import dagger.hilt.android.AndroidEntryPoint -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.openInternetBrowser -import javax.inject.Inject - -@AndroidEntryPoint -class NotificationsFragment : PreferenceFragmentCompat(), - SharedPreferences.OnSharedPreferenceChangeListener, - MainView.TitledView, NotificationsView { - - @Inject - lateinit var presenter: NotificationsPresenter - - companion object { - fun newInstance() = NotificationsFragment() - } - - override val titleStringId get() = R.string.pref_settings_notifications_title - - override fun initView(showDebugNotificationSwitch: Boolean) { - findPreference(getString(R.string.pref_key_notification_debug))?.isVisible = - showDebugNotificationSwitch - - findPreference(getString(R.string.pref_key_notifications_fix_issues))?.run { - isVisible = AppKillerManager.isDeviceSupported() - && AppKillerManager.isAnyActionAvailable(requireContext()) - - setOnPreferenceClickListener { - presenter.onFixSyncIssuesClicked() - true - } - } - } - - override fun onCreateRecyclerView( - inflater: LayoutInflater?, - parent: ViewGroup?, - state: Bundle? - ): RecyclerView? = super.onCreateRecyclerView(inflater, parent, state) - .also { - it.itemAnimator = null - it.layoutAnimation = null - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.scheme_preferences_notifications, rootKey) - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { - presenter.onSharedPreferenceChanged(key) - } - - override fun enableNotification(notificationKey: String, enable: Boolean) { - findPreference(notificationKey)?.run { - isEnabled = enable - summary = if (enable) null else getString(R.string.pref_notify_disabled_summary) - } - } - - 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 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/notifications/NotificationsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt deleted file mode 100644 index 981af17d..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.notifications - -import com.chuckerteam.chucker.api.ChuckerCollector -import io.github.wulkanowy.data.repositories.PreferencesRepository -import io.github.wulkanowy.data.repositories.StudentRepository -import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper -import io.github.wulkanowy.ui.base.BasePresenter -import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AnalyticsHelper -import io.github.wulkanowy.utils.AppInfo -import timber.log.Timber -import javax.inject.Inject - -class NotificationsPresenter @Inject constructor( - errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val preferencesRepository: PreferencesRepository, - private val timetableNotificationHelper: TimetableNotificationSchedulerHelper, - private val appInfo: AppInfo, - private val analytics: AnalyticsHelper, - private val chuckerCollector: ChuckerCollector -) : BasePresenter(errorHandler, studentRepository) { - - override fun onAttachView(view: NotificationsView) { - super.onAttachView(view) - - with(view) { - enableNotification( - preferencesRepository.notificationsEnableKey, - preferencesRepository.isServiceEnabled - ) - initView(appInfo.isDebug) - } - Timber.i("Settings notifications view was initialized") - } - - fun onSharedPreferenceChanged(key: String) { - Timber.i("Change settings $key") - - preferencesRepository.apply { - when (key) { - isUpcomingLessonsNotificationsEnableKey -> { - if (!isUpcomingLessonsNotificationsEnable) { - timetableNotificationHelper.cancelNotification() - } - } - isDebugNotificationEnableKey -> { - chuckerCollector.showNotification = isDebugNotificationEnable - } - } - } - analytics.logEvent("setting_changed", "name" to key) - } - - fun onFixSyncIssuesClicked() { - view?.showFixSyncDialog() - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt deleted file mode 100644 index 2618cde1..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.notifications - -import io.github.wulkanowy.ui.base.BaseView - -interface NotificationsView : BaseView { - - fun initView(showDebugNotificationSwitch: Boolean) - - fun showFixSyncDialog() - - fun enableNotification(notificationKey: String, enable: Boolean) -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt deleted file mode 100644 index 207fe2ff..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/sync/SyncFragment.kt +++ /dev/null @@ -1,100 +0,0 @@ -package io.github.wulkanowy.ui.modules.settings.sync - -import android.content.SharedPreferences -import android.os.Bundle -import android.view.View -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat -import dagger.hilt.android.AndroidEntryPoint -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 javax.inject.Inject - -@AndroidEntryPoint -class SyncFragment : PreferenceFragmentCompat(), - SharedPreferences.OnSharedPreferenceChangeListener, - MainView.TitledView, SyncView { - - @Inject - lateinit var presenter: SyncPresenter - - companion object { - fun newInstance() = SyncFragment() - } - - override val titleStringId get() = R.string.pref_settings_sync_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 initView() { - findPreference(getString(R.string.pref_key_services_force_sync))?.run { - onPreferenceClickListener = Preference.OnPreferenceClickListener { - presenter.onSyncNowClicked() - true - } - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - presenter.onAttachView(this) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.scheme_preferences_sync, rootKey) - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { - presenter.onSharedPreferenceChanged(key) - } - - 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 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/splash/SplashActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt index 2b96a9a0..80138175 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashActivity.kt @@ -3,23 +3,17 @@ package io.github.wulkanowy.ui.modules.splash import android.os.Bundle import android.widget.Toast import android.widget.Toast.LENGTH_LONG -import androidx.appcompat.app.AlertDialog import androidx.viewbinding.ViewBinding import dagger.hilt.android.AndroidEntryPoint -import io.github.wulkanowy.R import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.main.MainActivity -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.openInternetBrowser import javax.inject.Inject @AndroidEntryPoint class SplashActivity : BaseActivity(), SplashView { - @Inject - lateinit var appInfo: AppInfo - @Inject override lateinit var presenter: SplashPresenter @@ -46,14 +40,4 @@ class SplashActivity : BaseActivity(), SplashView override fun showError(text: String, error: Throwable) { Toast.makeText(this, text, LENGTH_LONG).show() } - - override fun showKitkatView() { - AlertDialog.Builder(this) - .setTitle(R.string.drop_kitkat_title) - .setMessage(R.string.drop_kitkat_content) - .setPositiveButton(android.R.string.ok, null) - .setNeutralButton(R.string.drop_kitkat_again) { _, _ -> presenter.onNeutralButtonSelected() } - .setOnDismissListener { presenter.onKitkatViewDismissed() } - .show() - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt index 4590d91a..79588917 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashPresenter.kt @@ -1,12 +1,9 @@ package io.github.wulkanowy.ui.modules.splash -import android.os.Build import io.github.wulkanowy.data.Status -import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.flowWithResource import kotlinx.coroutines.flow.onEach import timber.log.Timber @@ -14,47 +11,25 @@ import javax.inject.Inject class SplashPresenter @Inject constructor( errorHandler: ErrorHandler, - studentRepository: StudentRepository, - private val preferencesRepository: PreferencesRepository, - private val appInfo: AppInfo + studentRepository: StudentRepository ) : BasePresenter(errorHandler, studentRepository) { - private var externalUrl: String? = null - fun onAttachView(view: SplashView, externalUrl: String?) { super.onAttachView(view) - this.externalUrl = externalUrl - if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP && !preferencesRepository.isKitkatDialogDisabled) { - view.showKitkatView() - } else { - loadCorrectDataOrUser() - } - } - - private fun loadCorrectDataOrUser() { if (!externalUrl.isNullOrBlank()) { - view?.openExternalUrlAndFinish(externalUrl!!) - return + return view.openExternalUrlAndFinish(externalUrl) } flowWithResource { studentRepository.isCurrentStudentSet() }.onEach { when (it.status) { Status.LOADING -> Timber.d("Is current user set check started") - Status.SUCCESS -> { - if (it.data!!) view?.openMainView() - else view?.openLoginView() + Status.SUCCESS -> with(view) { + if (it.data!!) openMainView() + else openLoginView() } Status.ERROR -> errorHandler.dispatch(it.error!!) } }.launch() } - - fun onKitkatViewDismissed() { - loadCorrectDataOrUser() - } - - fun onNeutralButtonSelected() { - preferencesRepository.isKitkatDialogDisabled = true - } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt index c9c5fe9a..a5aa1409 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/splash/SplashView.kt @@ -9,6 +9,4 @@ interface SplashView : BaseView { fun openMainView() fun openExternalUrlAndFinish(url: String) - - fun showKitkatView() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt index 7744515d..f7d5b1ed 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/TimetableDialog.kt @@ -24,11 +24,12 @@ class TimetableDialog : DialogFragment() { private lateinit var lesson: Timetable companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: Timetable) = TimetableDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(exam: Timetable): TimetableDialog { + return TimetableDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + } } } @@ -40,14 +41,12 @@ class TimetableDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogTimetableBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogTimetableBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(lesson) { setInfo(info, teacher, canceled, changes) @@ -77,24 +76,15 @@ class TimetableDialog : DialogFragment() { } } - @SuppressLint("DefaultLocale") 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 - ) - ) + timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary)) timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorPrimary)) } else { - timetableDialogChangesTitle.setTextColor( - requireContext().getThemeAttrColor( - R.attr.colorTimetableChange - ) - ) + timetableDialogChangesTitle.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange)) timetableDialogChanges.setTextColor(requireContext().getThemeAttrColor(R.attr.colorTimetableChange)) } @@ -177,7 +167,6 @@ class TimetableDialog : DialogFragment() { @SuppressLint("SetTextI18n") private fun setTime(start: LocalDateTime, end: LocalDateTime) { - binding.timetableDialogTime.text = - "${start.toFormattedString("HH:mm")} - ${end.toFormattedString("HH:mm")}" + binding.timetableDialogTime.text = "${start.toFormattedString("HH:mm")} - ${end.toFormattedString("HH:mm")}" } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt index 7982387d..18551faa 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsFragment.kt @@ -57,7 +57,6 @@ class AdditionalLessonsFragment : additionalLessonsSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary)) additionalLessonsSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)) additionalLessonsErrorRetry.setOnClickListener { presenter.onRetry() } - additionalLessonsErrorDetails.setOnClickListener { presenter.onDetailsClick() } additionalLessonsPreviousButton.setOnClickListener { presenter.onPreviousDay() } additionalLessonsNavDate.setOnClickListener { presenter.onPickDate() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt index 21997b33..623160e7 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/additional/AdditionalLessonsPresenter.kt @@ -80,10 +80,6 @@ class AdditionalLessonsPresenter @Inject constructor( loadData(currentDate, true) } - fun onDetailsClick() { - view?.showErrorDetailsDialog(lastError) - } - private fun setBaseDateOnHolidays() { flow { val student = studentRepository.getCurrentStudent() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt index 258fc59d..56ea16cf 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetable/completed/CompletedLessonDialog.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.timetable.completed +import android.annotation.SuppressLint import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -16,11 +17,12 @@ class CompletedLessonDialog : DialogFragment() { private lateinit var completedLesson: CompletedLesson companion object { - private const val ARGUMENT_KEY = "Item" - fun newInstance(exam: CompletedLesson) = CompletedLessonDialog().apply { - arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + fun newInstance(exam: CompletedLesson): CompletedLessonDialog { + return CompletedLessonDialog().apply { + arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) } + } } } @@ -32,14 +34,13 @@ class CompletedLessonDialog : DialogFragment() { } } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogLessonCompletedBinding.inflate(inflater).apply { binding = this }.root + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return DialogLessonCompletedBinding.inflate(inflater).apply { binding = this }.root + } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + @SuppressLint("SetTextI18n") + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) with(binding) { completedLessonDialogSubject.text = completedLesson.subject diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt index a27dba88..23d1f27a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureActivity.kt @@ -12,7 +12,7 @@ import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R -import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.databinding.ActivityWidgetConfigureBinding import io.github.wulkanowy.ui.base.BaseActivity import io.github.wulkanowy.ui.base.WidgetConfigureAdapter @@ -37,19 +37,13 @@ class TimetableWidgetConfigureActivity : private var dialog: AlertDialog? = null - override fun onCreate(savedInstanceState: Bundle?) { + override public fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResult(RESULT_CANCELED) - setContentView( - ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root - ) + setContentView(ActivityWidgetConfigureBinding.inflate(layoutInflater).apply { binding = this }.root) intent.extras.let { - presenter.onAttachView( - this, - it?.getInt(EXTRA_APPWIDGET_ID), - it?.getBoolean(EXTRA_FROM_PROVIDER) - ) + presenter.onAttachView(this, it?.getInt(EXTRA_APPWIDGET_ID), it?.getBoolean(EXTRA_FROM_PROVIDER)) } } @@ -67,7 +61,6 @@ class TimetableWidgetConfigureActivity : 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) @@ -79,9 +72,8 @@ class TimetableWidgetConfigureActivity : .show() } - override fun updateData(data: List, selectedStudentId: Long) { + override fun updateData(data: List>) { with(configureAdapter) { - selectedId = selectedStudentId items = data notifyDataSetChanged() } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt index 2a40c8e4..67805fe0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigurePresenter.kt @@ -25,11 +25,7 @@ class TimetableWidgetConfigurePresenter @Inject constructor( private var selectedStudent: Student? = null - fun onAttachView( - view: TimetableWidgetConfigureView, - appWidgetId: Int?, - isFromProvider: Boolean? - ) { + fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) { super.onAttachView(view) this.appWidgetId = appWidgetId this.isFromProvider = isFromProvider ?: false @@ -60,17 +56,16 @@ class TimetableWidgetConfigurePresenter @Inject constructor( when (it.status) { Status.LOADING -> Timber.d("Timetable widget configure students data load") Status.SUCCESS -> { - val selectedStudentId = appWidgetId?.let { id -> - sharedPref.getLong(getStudentWidgetKey(id), 0) - } ?: -1 - + val widgetId = appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } when { it.data!!.isEmpty() -> view?.openLoginView() it.data.size == 1 && !isFromProvider -> { selectedStudent = it.data.single().student view?.showThemeDialog() } - else -> view?.updateData(it.data, selectedStudentId) + else -> view?.updateData(it.data.map { entity -> + entity.student to (entity.student.id == widgetId) + }) } } Status.ERROR -> errorHandler.dispatch(it.error!!) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt index accdc28d..056225ab 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetConfigureView.kt @@ -1,13 +1,13 @@ package io.github.wulkanowy.ui.modules.timetablewidget -import io.github.wulkanowy.data.db.entities.StudentWithSemesters +import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.ui.base.BaseView interface TimetableWidgetConfigureView : BaseView { fun initView() - fun updateData(data: List, selectedStudentId: Long) + fun updateData(data: List>) fun updateTimetableWidget(widgetId: Int) diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt index 071a2d17..1d63f094 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/timetablewidget/TimetableWidgetProvider.kt @@ -13,8 +13,6 @@ import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.res.Configuration -import android.graphics.Bitmap -import android.graphics.Canvas import android.widget.RemoteViews import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R @@ -27,8 +25,6 @@ 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.AnalyticsHelper -import io.github.wulkanowy.utils.createNameInitialsDrawable -import io.github.wulkanowy.utils.getCompatColor import io.github.wulkanowy.utils.nextOrSameSchoolDay import io.github.wulkanowy.utils.nextSchoolDay import io.github.wulkanowy.utils.nickOrName @@ -76,8 +72,7 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId" - fun getCurrentThemeWidgetKey(appWidgetId: Int) = - "timetable_widget_current_theme_$appWidgetId" + fun getCurrentThemeWidgetKey(appWidgetId: Int) = "timetable_widget_current_theme_$appWidgetId" } override fun onReceive(context: Context, intent: Intent) { @@ -93,29 +88,21 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { private suspend 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) + 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 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 - ) + if (!buttonType.isNullOrBlank()) analytics.logEvent("changed_timetable_widget_day", "button" to buttonType) updateWidget(context, toggledWidgetId, date, student) } } @@ -134,15 +121,9 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } @SuppressLint("DefaultLocale") - private fun updateWidget( - context: Context, - appWidgetId: Int, - date: LocalDate, - student: Student? - ) { + 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 + 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 @@ -153,28 +134,21 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { 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 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, + 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 - ) + }, 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) @@ -186,11 +160,6 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { R.id.timetableWidgetName, student?.nickOrName ?: context.getString(R.string.all_no_data) ) - - student?.let { - setImageViewBitmap(R.id.timetableWidgetAccount, context.createAvatarBitmap(it)) - } - setRemoteAdapter(R.id.timetableWidgetList, adapterIntent) setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent) setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent) @@ -212,20 +181,13 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } } - private fun createNavIntent( - context: Context, - code: Int, - appWidgetId: Int, - buttonType: String - ): PendingIntent { - return PendingIntent.getBroadcast( - context, code, + 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 - ) + }, FLAG_UPDATE_CURRENT) } private suspend fun getStudent(studentId: Long, appWidgetId: Int) = try { @@ -246,29 +208,4 @@ class TimetableWidgetProvider : HiltBroadcastReceiver() { } null } - - private fun Context.createAvatarBitmap(student: Student): Bitmap { - val avatarColor = if (student.avatarColor == -2937041L) { - getCompatColor(R.color.colorPrimaryLight).toLong() - } else { - student.avatarColor - } - val avatarDrawable = createNameInitialsDrawable(student.nickOrName, avatarColor, 0.5f) - - val avatarBitmap = - if (avatarDrawable.intrinsicWidth <= 0 || avatarDrawable.intrinsicHeight <= 0) { - Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) - } else { - Bitmap.createBitmap( - avatarDrawable.intrinsicWidth, - avatarDrawable.intrinsicHeight, - Bitmap.Config.ARGB_8888 - ) - } - - val canvas = Canvas(avatarBitmap) - avatarDrawable.setBounds(0, 0, canvas.width, canvas.height) - avatarDrawable.draw(canvas) - return avatarBitmap - } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt index a3961aed..82671a7f 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/AppInfo.kt @@ -35,8 +35,8 @@ open class AppInfo @Inject constructor() { open val systemLanguage: String get() = Resources.getSystem().configuration.locale.language - val defaultColorsForAvatar = listOf( - 0xd32f2f, 0xE64A19, 0xFFA000, 0xAFB42B, 0x689F38, 0x388E3C, 0x00796B, 0x0097A7, - 0x1976D2, 0x3647b5, 0x6236c9, 0x9225c1, 0xC2185B, 0x616161, 0x455A64, 0x7a5348 - ).map { (it and 0x00ffffff or (255 shl 24)).toLong() } + open val defaultColorsForAvatar = listOf( + 0xe57373, 0xf06292, 0xba68c8, 0x9575cd, 0x7986cb, 0x64b5f6, 0x4fc3f7, 0x4dd0e1, 0x4db6ac, + 0x81c784, 0xaed581, 0xff8a65, 0xd4e157, 0xffd54f, 0xffb74d, 0xa1887f, 0x90a4ae + ) } diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt index 92c0ddfc..cf715e65 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt @@ -1,15 +1,8 @@ package io.github.wulkanowy.utils -import android.annotation.SuppressLint import android.content.Context import android.content.Intent -import android.graphics.Bitmap -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.Typeface import android.net.Uri -import android.text.TextPaint import android.util.DisplayMetrics.DENSITY_DEFAULT import androidx.annotation.AttrRes import androidx.annotation.ColorInt @@ -17,9 +10,6 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils -import androidx.core.graphics.applyCanvas -import androidx.core.graphics.drawable.RoundedBitmapDrawable -import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory import io.github.wulkanowy.BuildConfig.APPLICATION_ID @ColorInt @@ -40,8 +30,7 @@ fun Context.getThemeAttrColor(@AttrRes colorAttr: Int, alpha: Int): Int { @ColorInt fun Context.getCompatColor(@ColorRes colorRes: Int) = ContextCompat.getColor(this, colorRes) -fun Context.getCompatDrawable(@DrawableRes drawableRes: Int) = - ContextCompat.getDrawable(this, drawableRes) +fun Context.getCompatDrawable(@DrawableRes drawableRes: Int) = ContextCompat.getDrawable(this, drawableRes) fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit) { Intent.parseUri(uri, 0).let { @@ -56,13 +45,7 @@ fun Context.openAppInMarket(onActivityNotFound: (uri: String) -> Unit) { } } -fun Context.openEmailClient( - chooserTitle: String, - email: String, - subject: String, - body: String, - onActivityNotFound: () -> Unit = {} -) { +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) @@ -102,39 +85,3 @@ fun Context.shareText(text: String, subject: String?) { } fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT - -@SuppressLint("DefaultLocale") -fun Context.createNameInitialsDrawable( - text: String, - backgroundColor: Long, - scaleFactory: Float = 1f -): RoundedBitmapDrawable { - val words = text.split(" ") - val firstCharFirstWord = words.getOrNull(0)?.firstOrNull() ?: "" - val firstCharSecondWord = words.getOrNull(1)?.firstOrNull() ?: "" - - val initials = "$firstCharFirstWord$firstCharSecondWord".toUpperCase() - - val bounds = Rect() - val dimension = this.dpToPx(64f * scaleFactory).toInt() - val textPaint = TextPaint().apply { - typeface = Typeface.SANS_SERIF - color = Color.WHITE - textAlign = Paint.Align.CENTER - isAntiAlias = true - textSize = this@createNameInitialsDrawable.dpToPx(30f * scaleFactory) - getTextBounds(initials, 0, initials.length, bounds) - } - - val xCoordinate = (dimension / 2).toFloat() - val yCoordinate = (dimension / 2 + (bounds.bottom - bounds.top) / 2).toFloat() - - val bitmap = Bitmap.createBitmap(dimension, dimension, Bitmap.Config.ARGB_8888) - .applyCanvas { - drawColor(backgroundColor.toInt()) - drawText(initials, 0, initials.length, xCoordinate, yCoordinate, textPaint) - } - - return RoundedBitmapDrawableFactory.create(this.resources, bitmap) - .apply { isCircular = true } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt index 5dd28967..049e1d42 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/FlowUtils.kt @@ -13,11 +13,8 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.takeWhile -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock inline fun networkBoundResource( - mutex: Mutex = Mutex(), showSavedOnLoading: Boolean = true, crossinline query: () -> Flow, crossinline fetch: suspend (ResultType) -> RequestType, @@ -34,7 +31,7 @@ inline fun networkBoundResource( try { val newData = fetch(data) - mutex.withLock { saveFetchResult(query().first(), newData) } + saveFetchResult(data, newData) query().map { Resource.success(filterResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) @@ -47,12 +44,11 @@ inline fun networkBoundResource( @JvmName("networkBoundResourceWithMap") inline fun networkBoundResource( - mutex: Mutex = Mutex(), showSavedOnLoading: Boolean = true, crossinline query: () -> Flow, crossinline fetch: suspend (ResultType) -> RequestType, crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, - crossinline onFetchFailed: (Throwable) -> Unit = { }, + crossinline onFetchFailed: (Throwable) -> Unit = { Unit }, crossinline shouldFetch: (ResultType) -> Boolean = { true }, crossinline mapResult: (ResultType) -> T ) = flow { @@ -63,8 +59,7 @@ inline fun networkBoundResource( if (showSavedOnLoading) emit(Resource.loading(mapResult(data))) try { - val newData = fetch(data) - mutex.withLock { saveFetchResult(query().first(), newData) } + saveFetchResult(data, fetch(data)) query().map { Resource.success(mapResult(it)) } } catch (throwable: Throwable) { onFetchFailed(throwable) diff --git a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt b/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt index d2a8908c..b96faeb2 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/LifecycleAwareVariable.kt @@ -1,7 +1,5 @@ package io.github.wulkanowy.utils -import android.os.Handler -import android.os.Looper import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle @@ -30,8 +28,7 @@ class LifecycleAwareVariable : ReadWriteProperty, Lifecycl } } -class LifecycleAwareVariableActivity : ReadWriteProperty, - LifecycleObserver { +class LifecycleAwareVariableActivity : ReadWriteProperty, LifecycleObserver { private var _value: T? = null @@ -47,12 +44,11 @@ class LifecycleAwareVariableActivity : ReadWriteProperty Fragment.lifecycleAwareVariable() = LifecycleAwareVariable() diff --git a/app/src/main/play/listings/pl-PL/full-description.txt b/app/src/main/play/listings/pl-PL/full-description.txt index 7da51da2..641b7706 100644 --- a/app/src/main/play/listings/pl-PL/full-description.txt +++ b/app/src/main/play/listings/pl-PL/full-description.txt @@ -4,7 +4,7 @@ Wyróżnione cechy i funkcje: - obliczanie średniej ważonej, - procentowy podgląd frekwencji, - szczęśliwy numerek, -- podgląd lekcji dodatkowych i zrealizowanych, +- podgląd lekcji zrealizowanych, - ciemny motyw. - brak reklam, - tryb offline, 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 new file mode 100644 index 00000000..56768bf5 Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-grades.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-start.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-start.jpg deleted file mode 100644 index 0ed20c04..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/1-start.jpg 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 new file mode 100644 index 00000000..83d9353a Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2-timetable-dialog.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2.jpg deleted file mode 100644 index f70e2c43..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/2.jpg 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 new file mode 100644 index 00000000..f83a7af8 Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-exams.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-timetable-dialog.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-timetable-dialog.jpg deleted file mode 100644 index 968fccdb..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/3-timetable-dialog.jpg and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-exams.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-exams.jpg deleted file mode 100644 index 3f49e774..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-exams.jpg 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 new file mode 100644 index 00000000..90d5fef4 Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/4-timetable-widget.png 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 new file mode 100644 index 00000000..eadbf2db Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-messages.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-timetable-widget.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-timetable-widget.jpg deleted file mode 100644 index f68daaf1..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/5-timetable-widget.jpg 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 new file mode 100644 index 00000000..2a11a3db Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-account-switcher.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-class-grades.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-class-grades.jpg deleted file mode 100644 index ca5446a2..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/6-class-grades.jpg and /dev/null differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-account-switcher.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-account-switcher.jpg deleted file mode 100644 index ca747aff..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-account-switcher.jpg 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 new file mode 100644 index 00000000..d9b2f1c7 Binary files /dev/null and b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/7-class-grades.png differ diff --git a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/8-themes.jpg b/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/8-themes.jpg deleted file mode 100644 index ce3af9bb..00000000 Binary files a/app/src/main/play/listings/pl-PL/graphics/phone-screenshots/8-themes.jpg and /dev/null differ diff --git a/app/src/main/play/release-notes/pl-PL/default.txt b/app/src/main/play/release-notes/pl-PL/default.txt index 8b264d44..dc5ed918 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,11 +1,8 @@ -Wersja 1.1.3 - -Oprócz tego naprawiliśmy: -- rzadkie problemy ze stabilnością przy logowaniu i w innych miejscach -- brakujące awatary przy zmianie konta z poziomu widżetu -- wysyłanie wiadomości gdy w aplikacji jest zalogowany jednocześnie uczeń i rodzic - -Ta wersja jest ostatnią, która będzie działać na starszych urządzeniach z Androidem 4. -Od tej pory do końca roku bedziemy dla nich udostępniać wyłącznie krytyczne poprawki błędów +Wersja 0.25.1 +- naprawiliśmy przełączanie semestrów przy przełączaniu uczniów +- naprawiliśmy błąd przy odświeżaniu ocen gdy włączony był inny niż domyślny tryb liczenia średniej +- do średniej końcowej wliczają się teraz również oceny z plusami i minusami +- dodaliśmy menadżer kont, gdzie można podejrzeć informacje o uczniu oraz zmienić pseudonim +- zmieniliśmy ikonę planu lekcji oraz kolor animacji odświeżania w ciemnym motywie Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases diff --git a/app/src/main/res/drawable/ic_all_about.xml b/app/src/main/res/drawable/ic_all_about.xml index 3868f85c..3dfbbda1 100644 --- a/app/src/main/res/drawable/ic_all_about.xml +++ b/app/src/main/res/drawable/ic_all_about.xml @@ -2,7 +2,6 @@ android:width="24dp" android:height="24dp" android:viewportWidth="24" - android:tint="?colorOnSurface" android:viewportHeight="24"> - - diff --git a/app/src/main/res/drawable/ic_settings_advanced.xml b/app/src/main/res/drawable/ic_settings_advanced.xml deleted file mode 100644 index 2fd7e590..00000000 --- a/app/src/main/res/drawable/ic_settings_advanced.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_settings_appearance.xml b/app/src/main/res/drawable/ic_settings_appearance.xml deleted file mode 100644 index afea27f2..00000000 --- a/app/src/main/res/drawable/ic_settings_appearance.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/drawable/ic_settings_notifications.xml b/app/src/main/res/drawable/ic_settings_notifications.xml deleted file mode 100644 index f4ff247f..00000000 --- a/app/src/main/res/drawable/ic_settings_notifications.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_settings_sync.xml b/app/src/main/res/drawable/ic_settings_sync.xml deleted file mode 100644 index 3697ac0b..00000000 --- a/app/src/main/res/drawable/ic_settings_sync.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2ea0a4d3..2f88ecc8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - + app:contentInsetStartWithNavigation="0dp" + app:layout_constraintTop_toTopOf="parent" /> + android:layout_height="0dp" + app:layout_constraintBottom_toTopOf="@id/mainBottomNav" + app:layout_constraintTop_toBottomOf="@id/mainToolbar" /> - + app:layout_constraintBottom_toBottomOf="parent" /> + diff --git a/app/src/main/res/layout/dialog_account_edit.xml b/app/src/main/res/layout/dialog_account_edit.xml index 9f617e44..b65f85ac 100644 --- a/app/src/main/res/layout/dialog_account_edit.xml +++ b/app/src/main/res/layout/dialog_account_edit.xml @@ -1,125 +1,87 @@ - - + + + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:layout_marginTop="24dp" + android:layout_marginEnd="24dp" + android:text="@string/account_edit_header" + android:textSize="21sp" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + - + - + + - + - - - - - - - - - - - - + + diff --git a/app/src/main/res/layout/dialog_account_quick.xml b/app/src/main/res/layout/dialog_account_quick.xml index 4095c91a..da31d31d 100644 --- a/app/src/main/res/layout/dialog_account_quick.xml +++ b/app/src/main/res/layout/dialog_account_quick.xml @@ -2,7 +2,7 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_account_details.xml b/app/src/main/res/layout/fragment_account_details.xml index af9564b5..1a0de147 100644 --- a/app/src/main/res/layout/fragment_account_details.xml +++ b/app/src/main/res/layout/fragment_account_details.xml @@ -21,9 +21,9 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - android:visibility="gone" + android:visibility="invisible" tools:ignore="UseCompoundDrawables" - tools:visibility="gone"> + tools:visibility="visible"> + android:layout_height="match_parent"> - - + app:srcCompat="@drawable/ic_all_account" + app:tint="?colorPrimary" + tools:ignore="ContentDescription" /> + android:orientation="vertical" + tools:context=".ui.modules.grade.statistics.GradeStatisticsFragment"> @@ -34,101 +34,153 @@ + android:layout_height="wrap_content"> - + android:layout_height="match_parent" + android:fillViewport="true"> - + android:orientation="vertical"> - - - - - - - - + android:layout_gravity="center"> - + - + - + - + + + + + android:layout_height="match_parent"> - + + + android:layout_gravity="center" + android:indeterminate="true" + tools:visibility="gone" /> - - + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/app/src/main/res/layout/fragment_login_recover.xml b/app/src/main/res/layout/fragment_login_recover.xml index 4277155b..629ed54d 100644 --- a/app/src/main/res/layout/fragment_login_recover.xml +++ b/app/src/main/res/layout/fragment_login_recover.xml @@ -26,7 +26,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="16dp" - android:visibility="gone"> + android:visibility="visible"> @@ -156,7 +156,7 @@ android:orientation="vertical" android:visibility="invisible" tools:ignore="UseCompoundDrawables" - tools:visibility="visible"> + tools:visibility="invisible"> - + android:layout_marginTop="16dp" + android:gravity="center" + android:orientation="horizontal"> + android:text="@string/all_details" /> - + android:text="@string/all_retry" /> + + tools:visibility="invisible"> + diff --git a/app/src/main/res/layout/fragment_lucky_number.xml b/app/src/main/res/layout/fragment_lucky_number.xml index b2d4f40a..f6de01e6 100644 --- a/app/src/main/res/layout/fragment_lucky_number.xml +++ b/app/src/main/res/layout/fragment_lucky_number.xml @@ -67,26 +67,6 @@ android:textSize="20sp" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/item_account.xml b/app/src/main/res/layout/item_account.xml index 563e6b1e..95fdb0e8 100644 --- a/app/src/main/res/layout/item_account.xml +++ b/app/src/main/res/layout/item_account.xml @@ -18,27 +18,15 @@ android:layout_height="40dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_all_account" tools:ignore="ContentDescription" - tools:src="@tools:sample/avatars" /> - - + tools:tint="@color/colorPrimary" /> - - - - - diff --git a/app/src/main/res/layout/item_grade_statistics_header.xml b/app/src/main/res/layout/item_grade_statistics_header.xml deleted file mode 100644 index 92f522ba..00000000 --- a/app/src/main/res/layout/item_grade_statistics_header.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_grade_statistics_pie.xml b/app/src/main/res/layout/item_grade_statistics_pie.xml index 2ea91ecf..15992a37 100644 --- a/app/src/main/res/layout/item_grade_statistics_pie.xml +++ b/app/src/main/res/layout/item_grade_statistics_pie.xml @@ -23,4 +23,5 @@ android:layout_margin="10dp" android:background="?android:windowBackground" tools:context=".ui.modules.grade.statistics.GradeStatisticsAdapter" /> + diff --git a/app/src/main/res/layout/item_lucky_number_history.xml b/app/src/main/res/layout/item_lucky_number_history.xml deleted file mode 100644 index 79a0fcb2..00000000 --- a/app/src/main/res/layout/item_lucky_number_history.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/action_menu_main.xml b/app/src/main/res/menu/action_menu_main.xml index 21905939..72bea25a 100644 --- a/app/src/main/res/menu/action_menu_main.xml +++ b/app/src/main/res/menu/action_menu_main.xml @@ -1,11 +1,11 @@ - + xmlns:app="http://schemas.android.com/apk/res-auto"> + android:title="@string/main_account_picker" + app:iconTint="@color/material_on_surface_emphasis_medium" + app:showAsAction="always" /> diff --git a/app/src/main/res/values-cs/preferences_values.xml b/app/src/main/res/values-cs-rCZ/preferences_values.xml similarity index 92% rename from app/src/main/res/values-cs/preferences_values.xml rename to app/src/main/res/values-cs-rCZ/preferences_values.xml index 7abbb10b..bcb690e5 100644 --- a/app/src/main/res/values-cs/preferences_values.xml +++ b/app/src/main/res/values-cs-rCZ/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 minut @@ -46,8 +45,8 @@ Průměr známek z celého roku - Nezobrazovat - Zobrazit vše - Zobrazit menší + Neukaž + Ukázat vše + Ukázat menší diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml similarity index 76% rename from app/src/main/res/values-cs/strings.xml rename to app/src/main/res/values-cs-rCZ/strings.xml index a2118955..fc01584b 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -19,7 +19,7 @@ Domácí úkoly Manažer účtů Vyberte účet - Podrobnosti účtu + Manažer účtů Informace o žáku Semestr %1$d, %2$d/%3$d @@ -43,18 +43,17 @@ Přihlašovací údaje jsou nesprávné. Ujistěte se, že je v poli níže vybrána správná variace deníku UONET+ Neplatný PIN Neplatný token - Token vypršel + Platnost tokenu vypršela Neplatný e-mail Místo e-mailu použijte přiřazené přihlašovací údaje - Použijte přiřazené přihlašovací nebo e-mail v @%1$s Neplatný symbol Žák nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+ Toto pole je povinné - Vybraný žák je už přihlášen - Symbol najdete na stránce deníku v  Uczeń → Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole Variace deníku UONET+. Wulkanowy v tuto chvíli nezjistí předškolní żaków + Vybraný žák je již přihlášen + Symbol najdete na stránce deníku v  Uczeń →  Dostęp Mobilny →  Zarejestruj urządzenie mobilne.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole Variace deníku UONET+. Wulkanowy v tuto chvíli nezjistí předškolní studenty Vyberte žáky, kteří se mají do aplikace přihlásit Jiné možnosti - V tomto režimu nefungují následující: šťastné číslo, statistiky třídy, shrnutí docházky, ospravedlnění nepřítomnosti, dokončené lekce, informace o škole a prohlížení seznamu registrovaných zařízení + V tomto režimu nefungují následující: šťastné číslo, statistiky třídy, shrnutí docházky, ospravedlnění nepřítomnosti, absolvované lekce, informace o škole a prohlížení seznamu registrovaných zařízení Tento režim zobrazuje stejná data, která se zobrazují na webových stránkách deníka Kombinace nejlepších vlastností ostatních dvou režimů. Funguje rychleji než scraper a poskytuje funkce, které nejsou k dispozici v režimu Mobile API. Je to v experimentální fázi Zásady ochrany osobních údajů @@ -67,12 +66,12 @@ Zapomněl jsem své heslo Obnovte svůj účet Obnovit - Žák je už přihlášen + Žák je již přihlášen Manažer účtů Přihlásit se - Relace vypršela - Relace vypršela. Přihlaste se prosím znovu + Platnost relace vypršela + Vaše relace vypršela, přihlaste se prosím znovu Známka Semestr %d @@ -86,7 +85,7 @@ Průměr: %1$.2f Body: %s Bez průměru - Předpokládaná: %1$s + Předpovězeno: %1$s Konečná: %1$s Součet bodů Konečná známka @@ -130,20 +129,20 @@ Máte %1$d novou známku Máte %1$d nové známky - Máte %1$d nových známek - Máte %1$d nových známek + Máte %1$d nové známky + Máte %1$d nové známky Máte %1$d novou předpokládanou známku Máte %1$d nové předpokládané známky - Máte %1$d nových předpokládaných známek - Máte %1$d nových předpokládaných známek + Máte %1$d nové předpokládané známky + Máte %1$d nové předpokládané známky Máte %1$d novou konečnou známku Máte %1$d nové konečné známky - Máte %1$d nových konečných známek - Máte %1$d nových konečných známek + Máte %1$d nové konečné známky + Máte %1$d nové konečné známky Lekce @@ -154,11 +153,11 @@ Žádné lekce tento den %s min %s sek - ještě %1$s + dosud %1$s za %1$s - Ukončila - Teď: %s - Za chvíli: %s + Lekce skončila + Nyní: %s + Okamžik: %s Později: %s Dokončené lekce @@ -173,14 +172,14 @@ Žádné informace o dalších lekcích Shrnutí docházky - Neprítomnosť zo školských dôvodov + Nepřítomen ze školních důvodů Omluvená nepřítomnost Neomluvená nepřítomnost Osvobození Omluvené zpoždění Neomluvené zpoždění Přítomnost - Odstraněno + Smazáno Neznámý Číslo lekce Žádné položky @@ -192,11 +191,11 @@ Důvod nepřítomnosti (volitelný) Poslat - Žádost o omluvu nepřítomnosti byla úspěšně odeslána! + Nepřítomnost úspěšně omluvena! Musíte vybrat alespoň jednu nepřítomnost! Ospravedlnit - Docházka + Účast Společně Tento týden žádné testy @@ -206,7 +205,7 @@ Doručená pošta Odesláno Koš - (žádný předmět) + (žádné téma) Žádné zprávy Při stahování obsahu zprávy došlo k chybě Od: @@ -214,13 +213,13 @@ Datum: %s Odpověď Poslat dále - Odstranit + Vymazat Přesunout do koše - Odstranit natrvalo - Zpráva byla úspěšně odstraněna - Sdílet + Trvale smazat + Zpráva byla úspěšně smazána + Podíl Vytisknout - Předmět + Téma Obsah Zpráva úspěšně odeslána Zpráva neexistuje @@ -229,8 +228,8 @@ %d zpráva %d zprávy - %d zpráv - %d zpráv + %d zprávy + %d zprávy Nová zpráva @@ -241,8 +240,8 @@ Máte %1$d novou zprávu Máte %1$d nové zprávy - Máte %1$d nových zpráv - Máte %1$d nových zpráv + Máte %1$d nové zprávy + Máte %1$d nové zprávy Žádné informace o poznámkách @@ -250,8 +249,8 @@ %d poznámka %d poznámky - %d poznámek - %d poznámek + %d poznámky + %d poznámky Nová poznámka @@ -262,15 +261,15 @@ Máte %1$d novou poznámku Máte %1$d nové poznámky - Máte %1$d nových poznámek - Máte %1$d nových poznámek + Máte %1$d nové poznámky + Máte %1$d nové poznámky %d chvála %d chvály - %d chvál - %d chvál + %d chvály + %d chvály Nová chvála @@ -281,8 +280,8 @@ Máte %1$d novou chválu Máte %1$d nové chvály - Máte %1$d nových chvál - Máte %1$d nových chvál + Máte %1$d nové chvály + Máte %1$d nové chvály @@ -298,10 +297,10 @@ Nové neutrální poznámky - Máte %1$d novou neutrální poznámku - Máte %1$d nové neutrální poznámky - Máte %1$d nových neutrální poznámek - Máte %1$d nových neutrální poznámek + Máte %1$d novou neutrální pozornost + Máte %1$d nové neutrální pozornosti + Máte %1$d nové neutrální pozornosti + Máte %1$d nové neutrální pozornosti Žádné informace o domácích úkolech @@ -314,15 +313,11 @@ Žádné informace o šťastném čísle Šťastné číslo pro dnešek Dnes je šťastným číslem: %d - Zobrazit historii - - Historie šťastných čísel - Žádné informace o šťastných číslech Mobilní přístup Žádná zařízení Zrušit registraci - Zařízení odstranění + Zařízení odstraněno QR kód Token Symbol @@ -338,17 +333,17 @@ Jméno ředitele Jméno pedagoga Zobrazit na mapě - Volat + Volání Učitelé Žádné informace o učitelích Žádný předmět Setkání - Žádné informace o setkáních + Žádné informace o setkání Přidat účet - Odhlásit + Odhlásit se Chcete se odhlásit z aktivního žáka? Odhlášení žáků Žákův účet @@ -365,19 +360,19 @@ Verze aplikace Tvůrci - Seznam vývojářů Wulkanového + Seznam vývojářů Wulkanowy Nahlásit chybu Odeslat zprávu o chybě e-mailem FAQ Přečtěte si často kladené otázky Server Discord - Připojte se ke komunitě Wulkanového + Připojte se ke komunitě Wulkanowy Facebooková fanpage Stejně jako naše facebooková fanpage Zásady ochrany osobních údajů Pravidla pro shromažďování osobních údajů Domovská stránka - Navštivte stránku a pomozte s vývojem aplikace + Navštivte web a pomozte s vývojem aplikace Licence Licence knihoven použitých v aplikaci @@ -386,7 +381,7 @@ Avatar Zobrazit více na GitHub - Žádné informace o žáků nebo rodině žáka + Žádné informace o žácích Jméno Druhé jméno Pohlaví @@ -409,23 +404,22 @@ Přezdívka Přidat přezdívku - Vybrat barvu avataru - Sdílet protokoly + Sdílejte protokoly Obnovit Zkontrolovat aktualizace Před hlášením chyby zkontrolujte, zda je k dispozici aktualizace s opravou chyb Obsah - Zkusit znovu + Zkuste to znovu Popis - Žádný popis + Bez popisu Učitel Datum Datum vstupu Barva - Podrobnosti + Detaily Kategorie Zavřít Žádná data @@ -444,78 +438,60 @@ Tmavý Motiv systému - Vzhled a chování aplikací + Vzhled Výchozí zobrazení Výpočet koncoročního průměru Vynutit průměrný výpočet podle aplikace - Zobrazit přítomnost - Motiv + Zobrazit přítomnost v účasti + Motiv aplikace Rozbalit známky - Označit aktuální lekci - Zobrazit skupiny vedle předmětů - Zobrazit seznam grafů v známkách třídy - Zobrazit lekce pro celou třídu - Zobrazit předměty bez známek + Označte aktuální lekci v plánu lekce + Ukázat skupiny vedle předmětů v plánu lekce + Ukázat seznam grafů ve třídních známkách + Ukázat lekce pro celou třídu + Ukázat předměty bez známek v \"Známky\" Známky barevné schéma - Třídění předmětů - Jazyk - Upozornění - Zobrazit upozornění - Zobrazit upozornění o nadcházející lekci + Předměty seřazené v \"Známky\" + Jazyk aplikace + Oznámení + Ukázat notifikace + Ukázat nadcházející oznámení o lekci Opravte problémy se synchronizací a upozorněním - Vaše zařízení může mít problémy se synchronizací dat as upozorněními.\n\nChcete-li je opravit, přidejte Wulkanového do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. + Ve vašem zařízení mohou nastat problémy se synchronizací dat a oznámenímii.\n\nChcete-li je opravit, přidejte Wulkanowy do funkce Autostart a vypněte optimalizaci/úsporu baterie v nastavení systému telefonu. Přejít do nastavení - Zobrazit upozornění o ladění - Synchronizace je vypnutá + Ukázat oznámení o ladění Synchronizace Automatická aktualizace Pozastaveno na dovolené Interval aktualizací Pouze Wi-Fi - Synchronizovat teď + Synchronizovat nyní Synchronizováno! Synchronizace selhala Probíhá synchronizace + Synchronizace + Ruční synchronizace neobnoví zobrazení aplikace. + \nChcete-li zobrazit synchronizovaná data, restartujte aplikaci po synchronizaci. + + Jiné Hodnota plusu Hodnota mínusu Odpovědět s historií zpráv - Pokročilé - Vzhled a chování - Upozornění - Synchronizace - Známky - Docházka - Plán lekce - Známky - Zprávy - Vzhled a chování - Jazyky, motivy, třídění předmětů - Upozornění aplikace, oprava problémů - Upozornění - Synchronizace - Automatická aktualizace, interval aktualizací - Hodnota plusu a mínusu, výpočet průměru - Pokročilé - Verze aplikace, tvůrci, sociální portály, licence - Nové položky v deníku + Nové položky v deník Nové známky Šťastné číslo Nové zprávy Nové poznámky - Push upozornění + Push oznámení Nadcházející lekce - Ladění - - Konec podpory - Ukončujeme podporu pro vaše zařízení. V Wulkanovým už pro něj nebudou žádné nové funkce. Kritické opravy však budeme vydávat až do konce roku 2021, abyste měli čas přejít na novější model - Nezobrazovat znovu + Debug Černý Červený Modrý Zelený - Fialový + Nachový Žádná barva Zkopírováno @@ -533,7 +509,7 @@ Probíhá údržba UONET+ deník. Zkuste to později znovu Neznámá chyba denika UONET+. Prosím zkuste to znovu později Neznámá chyba aplikace. Prosím zkuste to znovu později - Vyskytla se neočekávaná chyba - Funkce je deaktivována přes vaší školou + Došlo k neočekávané chybě + Funkce deaktivována vaší školou Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API diff --git a/app/src/main/res/values-cs-v29/preferences_values.xml b/app/src/main/res/values-cs-v29/preferences_values.xml deleted file mode 100644 index 25125a30..00000000 --- a/app/src/main/res/values-cs-v29/preferences_values.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Motiv systému - Světlý - Tmavý - Černý (AMOLED) - - \ No newline at end of file diff --git a/app/src/main/res/values-de/preferences_values.xml b/app/src/main/res/values-de/preferences_values.xml index f578ff11..7226ff2d 100644 --- a/app/src/main/res/values-de/preferences_values.xml +++ b/app/src/main/res/values-de/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 Minuten diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 2880996a..8d0bf3e9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -46,7 +46,6 @@ Token ist nicht mehr gültig Ungültige email Den zugewiesenen Login anstelle von email verwenden - Benutze den zugewiesenen Login oder E-Mail in @%1$s Ungültige symbol Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers Dieses Datenfeld ist erforderlich @@ -176,7 +175,7 @@ Abwesenheitsgrund (optional) Senden - Abwesenheitsentschuldigungsanfrage erfolgreich gesendet! + Abwesenheit erfolgreich entschuldigt! Sie müssen mindestens eine Abwesenheit auswählen! Verzeihung @@ -274,10 +273,6 @@ Keine Information über die Glücksnummer. Glücksnummer für heute Die heutige Glücksnummer ist: %d - Verlauf anzeigen - - Glücksnummerverlauf - Keine Information über die Glücksnummer Mobile Geräte Keine Geräte @@ -346,7 +341,7 @@ Benutzerbild Sehen Sie mehr auf GitHub - Keine Informationen über Schüler- oder Studentenfamilie + Keine Informationen über Schüler Name Zweite Name Geschlecht @@ -369,7 +364,6 @@ Nick Nick hinzufügen - Avatar-Farbe wählen Logs teilen Aktualisieren @@ -389,7 +383,7 @@ Kategorie Schließ Keine Daten - Schulfach + Thema Zurück Nächste Suchen @@ -404,21 +398,21 @@ Dunkel Systemthema - Aussehen & Verhalten + Erscheinungsbild Standard Ansicht Berechnung des Jahresenddurchschnitts Mittelwertberechnung durch App erzwingen - Anwesendheit zeigen - Thema + Anwesenheit in Schulbesuch zeigen + Thema der Anwendung Noten erweitern - Aktuelle Lektion markieren - Gruppen neben Schulfächen anzeigen + Aktuelle Lektion im Stundenplan markieren + Zeige Gruppen neben Themen im Zeitplan Liste der Diagramme in Klassenbewertungen anzeigen Unterricht der ganzen Klasse anzeigen - Schulfächer ohne Noten anzeigen + Zeigen Sie Themen ohne Noten in Noten Farbschema der Noten - Schulfachen sortieren - Sprache + Themen sortieren in \"Noten\" + App Sprache Benachrichtigungen Benachrichtigungen anzeigen Benachrichtigungen über bevorstehende Lektionen anzeigen @@ -426,7 +420,6 @@ Ihr Gerät hat möglicherweise Probleme mit der Datensynchronisierung und Benachrichtigungen.\n\nUm diese zu reparieren, fügen Sie Wulkanowy zum Autostart hinzu und deaktivieren Sie die Batterieoptimierung in den Systemeinstellungen des Geräts. Gehe zu den Einstellungen Debug-Benachrichtigungen anzeigen - Synchronisierung ist deaktiviert Synchronisierung Automatische Aktualisierung An Feiertagen suspendiert @@ -436,27 +429,14 @@ Synchronisiert! Synchronisierung fehlgeschlagen Synchronisierung läuft + Synchronisation + Die manuelle Synchronisierung aktualisiert die App-Ansichten nicht. + \nUm die synchronisierten Daten anzuzeigen, starten Sie die App nach der Synchronisierung neu. + + Andere Wert des Plus Wert des Minus Antwort mit Nachrichtenhistorie - Erweitert - Aussehen & Verhalten - Benachrichtigungen - Synchronisierung - Noten - Schulbesuch - Zeitplan - Noten - Nachrichten - Aussehen & Verhalten - Sprachen, Themen, Schulfachen sortieren - App-Benachrichtigungen, Probleme beheben - Benachrichtigungen - Synchronisierung - Automatisches Update, Synchronisierungsintervall - Plus und Minus Werte, Durchschnittsberechnung - Erweitert - App-Version, Mitarbeiter, soziale Portale, Lizenzen Neue Einträge im Klassenbuch Neue Noten @@ -466,10 +446,6 @@ Push-Benachrichtigungen Bevorstehende Lektionen Debuggen - - Ende der Unterstützung - Wir beenden die Unterstützung für dein Gerät. Es werden keine neuen Funktionen mehr in Wulkanowy erscheinen. Allerdings werden wir bis Ende 2021 kritische Patches veröffentlichen, so dass du Zeit hast, zu einem neueren Modell zu wechseln - Nicht mehr fragen Schwarz Rot diff --git a/app/src/main/res/values-lt-v29/preferences_values.xml b/app/src/main/res/values-lt-v29/preferences_values.xml deleted file mode 100644 index 18cbd4cf..00000000 --- a/app/src/main/res/values-lt-v29/preferences_values.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Sistemos tema - Šviesi - Tamsi - Juoda (AMOLED) - - diff --git a/app/src/main/res/values-lt/preferences_values.xml b/app/src/main/res/values-lt/preferences_values.xml deleted file mode 100644 index fcb637d2..00000000 --- a/app/src/main/res/values-lt/preferences_values.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - Šviesi - Tamsi - Juoda (AMOLED) - - - Sistemos kalba - Polski - English - Pусский - Українська - Deutsch - Čeština - Slovenčina - - - 15 minučių - 30 minučių - 1 valandą - 2 valandas - 6 valandas - 12 valandas - 24 valandas - - - 0,00 - 0,25 - 0,33 - 0,5 - 0,75 - - - Pagal abėcėlę - Pagal datą - - - Dzienniczek+ - Wulkanowy - Laipsnio spalvos registre - - - Antrojo semestro laipsnių vidurkis - Abiejų semestrų laipsnių vidurkis - Visų metų laipsnių vidurkis - - - Nerodyti - Rodyti viską - Rodyti mažesnį - - diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index 68a9fa2f..bf5cd769 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -10,51 +10,14 @@ @color/colorSwipeRefreshDark ?colorSurface ?android:textColorPrimary - - @color/colorNavigationBarLight - - - @color/colorStatusBarLight + @android:color/black + @android:color/black false true - false - - - - - - - - - - diff --git a/app/src/main/res/values-pl/preferences_values.xml b/app/src/main/res/values-pl/preferences_values.xml index b25dc3e5..0634f657 100644 --- a/app/src/main/res/values-pl/preferences_values.xml +++ b/app/src/main/res/values-pl/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 minut @@ -25,7 +24,7 @@ 24 godziny - 0,00 + 0,0 0,25 0,33 0,5 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index fb538fad..2f849bc1 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -46,7 +46,6 @@ Token stracił ważność Niepoprawny adres email Użyj przydzielonego loginu zamiast emaila - Użyj przypisanego loginu lub adresu e-mail w @%1$s Niepoprawny symbol Nie znaleziono ucznia. Sprawdź poprawność symbolu i wybranej odmiany dziennika UONET+ To pole jest wymagane @@ -192,7 +191,7 @@ Powód nieobecności (opcjonalny) Wyślij - Prośba o usprawiedliwienie została pomyślnie wysłana! + Usprawiedliwiono pomyślnie! Musisz wybrać co najmniej jedną nieobecność! Usprawiedliw @@ -314,10 +313,6 @@ Brak informacji o szczęśliwym numerku Szczęśliwy numerek na dzisiaj Dziś szczęśliwym numerkiem jest: %d - Pokaż historię - - Historia numerków - Brak informacji o szczęśliwych numerkach Dostęp mobilny Brak urządzeń @@ -386,7 +381,7 @@ Awatar Zobacz więcej na GitHub - Brak informacji o uczniu lub rodzinie ucznia + Brak informacji o uczniu Imię Drugie imię Płeć @@ -409,7 +404,6 @@ Pseudonim Dodaj pseudonim - Wybierz kolor awatara Udostępnij logi Odśwież @@ -444,21 +438,21 @@ Ciemny Motyw systemu - Wygląd i zachowanie aplikacji + Wygląd Domyślny widok Obliczanie średniej końcoworocznej Wymuś obliczanie średniej przez aplikację - Pokazuj obecność - Motyw + Pokazuj obecność we frekwencji + Motyw aplikacji Rozwiń oceny - Oznaczaj bieżącą lekcję - Pokazuj grupę obok przedmiotu + Oznaczaj bieżącą lekcję na planie + Pokazuj grupę obok przedmiotu na planie Pokazuj listę wykresów w ocenach klasy Pokazuj lekcje całej klasy - Pokazuj przedmioty bez ocen + Pokazuj przedmioty bez ocen w Ocenach Schemat kolorów ocen - Sortowanie przedmiotów - Język + Sortowanie przedmiotów w Ocenach + Język aplikacji Powiadomienia Pokazuj powiadomienia Pokazuj powiadomienia o nadchodzących lekcjach @@ -466,7 +460,6 @@ Na twoim urządzeniu mogą występować problemy z synchronizacją danych i powiadomieniami.\n\nBy je naprawić, dodaj Wulkanowego do autostartu i wyłącz optymalizację/oszczędzanie baterii w ustawieniach systemowych telefonu. Przejdź do ustawień Pokazuj powiadomienia debugowania - Synchronizacja jest wyłączona Synchronizacja Automatyczna aktualizacja Zawieszona na wakacjach @@ -476,27 +469,14 @@ Zsynchronizowano! Synchronizacja nie powiodła się Synchronizacja w trakcie + Synchronizacja + Ręczna synchronizacja nie odświeża widoków w aplikacji. + \nAby zobaczyć zsynchronizowane informacje, uruchom ponownie aplikację po zsynchronizowaniu. + + Inne Wartość plusa Wartość minusa Odpowiadaj z historią wiadomości - Zaawansowane - Wygląd i zachowanie - Powiadomienia - Synchronizacja - Oceny - Frekwencja - Plan lekcji - Oceny - Wiadomości - Wygląd i zachowanie - Języki, motywy, sortowanie przedmiotów - Powiadomienia aplikacji, naprawianie problemów - Powiadomienia - Synchronizacja - Automatyczna aktualizacja, interwał synchronizacji - Wartości plusa i minusa, obliczanie średniej - Zaawansowane - Wersja aplikacji, twórcy, media społecznościowe, licencje Nowe wpisy w dzienniku Nowe oceny @@ -506,10 +486,6 @@ Powiadomienia push Nadchodzące lekcje Debugowanie - - Koniec wsparcia - Kończymy wsparcie dla Twojego urządzenia. Nie pojawią się już dla niego żadne nowe funkcje w Wulkanowym. Będziemy jednak wypuszczać krytyczne poprawki do końca 2021 roku, abyś miał czas na przeniesienie się na nowszy model - Nie pokazuj ponownie Czarny Czerwony diff --git a/app/src/main/res/values-ru/preferences_values.xml b/app/src/main/res/values-ru/preferences_values.xml index 64b777fb..304d678f 100644 --- a/app/src/main/res/values-ru/preferences_values.xml +++ b/app/src/main/res/values-ru/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 минут diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 665d9dc4..158c91bc 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -46,7 +46,6 @@ Token просрочен Неверный адрес электронной почты Используйте назначенный логин вместо электронной почты - Использовать назначенный логин или email в @%1$s Неправильный символ Студент не найден. Подтвердите символ и выбранный вариант регистра UONET+ Это обязательное поле @@ -192,7 +191,7 @@ Причина отсутствия (необязательно) Послать - Запрос на освобождение оправдания успешно отправлен! + Статус отсутствия изменён Выберите хотя-бы одно отсутствие Изменить статус @@ -314,10 +313,6 @@ Нет данных о счастливом номере Сегодняшний счастливый номер Сегодняшний счастливый номер это: %d - Показать историю - - История удачных чисел - Нет информации о номерах удачи Мобильные устройства Нет устройств @@ -386,7 +381,7 @@ Aватар Страница проекта на GitHub - Нет информации об ученике или семье ученика + Нет информации о студенте Имя Фамилия Пол @@ -409,7 +404,6 @@ Ник Добавить ник - Выберите цвет аватара Поделиться логами Обновить @@ -444,21 +438,21 @@ Тёмная Тема системы - Внешний вид приложения & поведение + Вид Окно по умолчанию Способ определения средней годовой оценки Принудительно высчитать среднюю оценку через приложение - Показать присутствие - Тема + Показывать присутствия в посещаемости + Тема приложения Разворачивать оценки - Отметить текущий урок - Показать группы рядом с темами + Отмечать текущий урок в расписании + Показать группу возле предмета в расписании Показывать диаграммы в оценках класса Показать уроки всего класса - Показать предметы без оценок + Показывать предметы без оценок в \"Оценках\" Схема цветов оценок - Сортировка уроков - Язык + Сортировка предметов в \"Оценках\" + Язык приложения Уведомления Показывать уведомления Показывать уведомления о будущих уроках @@ -466,7 +460,6 @@ На вашем устройстве могут быть проблемы с синхронизацией данных и уведомлениями.\n\nЧтобы их исправить, вам необходимо добавить Wulkanowy в авто-старт и выключить оптимизацию/экономию батареи в настройках устройства. Перейти в настройски Показывать дебаг-уведомления - Синхронизация отключена Синхронизация Автоматическая синхронизация Приостановить синхронизации во время каникул @@ -476,27 +469,14 @@ Синхронизировано! Синхронизация не удалась Идёт синхронизация + Синхронизация + Ручная синхронизация не обновляет данные в приложении. + \nЧтобы увидеть обновлённые данные, перезапустите приложение. + + Другие Стоимость плюса Стоимость минуса Отвечать с историей сообщений - Расширенные - Внешний вид & Поведение - Уведомления - Синхронизация - Оценки - Посещаемость - Расписание - Оценки - Сообщения - Внешний вид & Поведение - Языки, темы, темы сортировки темы - Уведомления приложений, проблемы с устранением - Уведомления - Синхронизация - Автоматическое обновление, интервал синхронизации - Значения плюс и минус, средний расчет - Расширенные - Версия приложения, участники, социальные порталы, лицензии Новые данные в дневнике Новые оценки @@ -506,10 +486,6 @@ Показывать push-уведомления Будущие уроки Дебаг - - Конец поддержки - Поддержка заканчивается на вашем устройстве. В Wulkanowy больше не появятся новые возможности. Однако до конца 2021 года мы выпустим критические патчи, чтобы у вас было время перейти на новую модель - Не показывать снова Чёрный Красный diff --git a/app/src/main/res/values-sk/preferences_values.xml b/app/src/main/res/values-sk-rSK/preferences_values.xml similarity index 92% rename from app/src/main/res/values-sk/preferences_values.xml rename to app/src/main/res/values-sk-rSK/preferences_values.xml index b0ba9839..d57e603b 100644 --- a/app/src/main/res/values-sk/preferences_values.xml +++ b/app/src/main/res/values-sk-rSK/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 minút @@ -46,8 +45,8 @@ Priemer známok z celého roka - Nezobrazovať - Zobraziť všetko - Zobraziť menšie + Neukaz + Zobrazit vše + Zobrazit menší diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml similarity index 67% rename from app/src/main/res/values-lt/strings.xml rename to app/src/main/res/values-sk-rSK/strings.xml index 424cc252..b5c0116e 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -1,162 +1,161 @@ - Prisijungti + Prihlásenie Wulkanowy - Laipsnis - Attendance - Exams - Timetable - Nustatymai - Daugiau - Apie - Peržiūrėti žurnalą - Prisidėję - Licencijos - Žinutės - Nauja žinutė - Pastabos ir pasiekimai - Namų darbai - Paskyros valdymas - Pasirinkite paskyrą - Paskyros informacija - Studentų informacija + Známky + Dochádzka + Skúšky + Plán lekcie + Nastavenia + Viac + O aplikácii + Prehliadač protokolov + Tvorcovia + Licencie + Správy + Nová správa + Poznámky a úspechy + Domáce úlohy + Accounts manager + Select account + Account details + Student info - Semestras %1$d, %2$d/%3$d + Semester %1$d, %2$d/%3$d - Sign in with the student or parent account - Enter the symbol from the register page - Vartotojo vardas - El. paštas - Prisijunkite, PESEL arba el. paštas - Slaptažodis - UONET+ register variant + Prihláste sa pomocou študentského alebo rodičovského konta + Zadajte symbol zo stránky denníka + Užívateľské meno + Email + Prihlásenie, číslo PESEL alebo e-mail + Heslo + Variácie denníka UONET+ Mobile API Scraper - Hibridas + Hybridné Token PIN - API raktas + Kľúč API Symbol - Prisijungti - Slaptažodis per trumpas - Login details are incorrect. Make sure the correct UONET+ register variation is selected in the field below - Netinkamas PIN kodas - Invalid token - Token expired - Neteisingas el. paštas - Use the assigned login instead of email - Use the assigned login or email in @%1$s - Netinkamas simbolis - Student not found. Validate the symbol and the chosen variation of the UONET+ register - This field is required - Selected student is already logged in + Prihlásiť + Toto heslo je príliš krátke + Prihlasovacie údaje sú nesprávne. Uistite sa, že je v poli nižšie vybraná správna variácie denníka UONET+ + Neplatný PIN + Neplatný token + Platnosť tokenu vypršala + Neplatný e-mail + Namiesto e-mailu použite priradené prihlasovacie údaje + Neplatný symbol + Žiak nebol nájdený. Skontrolujte správnosť symbolu a vybrané varianty denníka UONET+ + Toto pole je povinné + Vybraný žiak už je prihlásený The symbol can be found on the register page in Uczeń → Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nMake sure that you have set the appropriate register variant in the UONET+ register variant field on the previous screen. Wulkanowy does not detect pre-school students at the moment - Select students to log in to the application - Papildomi nustatymai + Vyberte žiakov, ktorí sa majú do aplikácie prihlásiť + Iné možnosti In this mode, a lucky number does not work, a class grade stats, summary of attendance, excuse for absence, completed lessons, school information and preview of the list of registered devices This mode displays the same data as it appears on the register website The combination of the best features of the other two modes. It works faster than scraper and provides features not available in the Mobile API mode. It is in the experimental phase - Privatumo politika - Trouble signing in? Contact us! - El. paštas + Zásady ochrany osobných údajov + Problémy s prihlásením? Napíšte nám! + Email Discord - Send email - Describe details of problem: - Make sure you select the correct UONET+ register variation! - I forgot my password - Recover your account - Atkurti - Student is already signed in + Poslať e-mail + Opíšte podrobnosti problému: + Uistite sa, že ste vybrali správny variant denníka UONET+! + Zabudol som heslo + Obnovte svoj účet + Obnoviť + Študent je už prihlásený - Paskyros valdymas - Prisijungti - Sesijos laikas baigėsi - Sesijos laikas baigėsi, prašome prisijungti iš naujo + Manažér účtov + Prihlásiť sa + Platnosť relácie vypršala + Vaša relácia vypršala, prihláste sa prosím znovu - Laipsnis - Semestras %d - Keisti semestrą - Jokių laipsnių - Svoris - Svoris: %s - Pastabos - Jokių naujų laipsnių + Známka + Semester %d + Zmeniť semester + Žiadne známky + Váha + Váha: %s + Komentár + Žiadne nové známky Number of new ratings: %1$d - Vidurkis: %1$.2f - Puantai: %s - Jokiu vidurkis - Numatomas: %1$s - Galutinis: %1$s - Bendras punktų skaičius - Galutinis laipsnis - Numatomas laipsnis - Calculated average - Final average - Summary - Class - Mark as read - Partial + Priemer: %1$.2f + Body: %s + Bez priemeru + Predpovedané: %1$s + Konečná: %1$s + Súčet bodov + Konečná známka + Predpokladaná známka + Vypočítaný priemer + Konečný priemer + Zhrnutie + Trieda + Označiť ako prečítané + Čiastočné Semester - Points - Legend + Body + Legenda Average: %1$s - Class - Student + Trieda + Žiák - %d grade - %d grades - %d grades - %d grades + %d známka + %d známky + %d známok + %d známok - New grade - New grades - New grades - New grades + Nová známka + Nové známky + Nové známky + Nové známky - New predicted grade - New predicted grades - New predicted grades - New predicted grades + Nová predpokladaná známka + Nové predpokladané známky + Nové predpokladané známky + Nové predpokladané známky - New final grade - New final grades - New final grades - New final grades + Nová konečná známka + Nové konečné známky + Nové konečné známky + Nové konečné známky - You received %1$d grade - You received %1$d grades - You received %1$d grades - You received %1$d grades + Máte %1$d novú známku + Máte %1$d nové známky + Máte %1$d nových známok + Máte %1$d nových známok - You received %1$d predicted grade - You received %1$d predicted grades - You received %1$d predicted grades - You received %1$d predicted grades + Máte %1$d novú predpokladanú známku + Máte %1$d nové predpokladané známky + Máte %1$d nových predpokladaných známok + Máte %1$d nových predpokladaných známok - You received %1$d final grade + Máte %1$d novú konečnú známku You received %1$d final grades You received %1$d final grades You received %1$d final grades - Lesson - Room - Group - Hours - Changes - No lessons this day + Lekcia + Učebňa + Skupina + Hodiny + Zmeny + Žiadne lekcie tento deň %s min %s sec %1$s left in %1$s - Finished + Lekcia skončila Now: %s Next: %s Later: %s @@ -164,11 +163,11 @@ Completed lessons Show completed lessons No info about completed lessons - Topic - Absence - Resources + Téma + Neprítomnosť + Zdroje - Additional lessons + Ďalší lekcie Show additional lessons No info about additional lessons @@ -179,11 +178,11 @@ Exemption Excused lateness Unexcused lateness - Present + Prítomnosť Deleted - Unknown + Neznámy Number of lesson - No entries + Žiadne položky %1$d absence %1$d absences @@ -191,8 +190,8 @@ %1$d absences Absence reason (optional) - Send - Absence excuse request sent successfully! + Poslať + Absence excused successfully! You must select at least one absence! Excuse @@ -314,10 +313,6 @@ No info about the lucky number Lucky number for today Today\'s lucky number is: %d - Show history - - Lucky number history - No info about lucky numbers Mobile devices No devices @@ -386,7 +381,7 @@ Avatar See more on GitHub - No info about student or student family + No info about student Name Second name Gender @@ -409,7 +404,6 @@ Nick Add nick - Choose avatar color Share logs Refresh @@ -444,21 +438,21 @@ Dark System Theme - App appearance & behavior + Appearance Default view Calculation of the end-of-year average Force average calculation by app - Show presence - Theme + Show presence in attendance + Application theme Expand grades - Mark current lesson - Show groups next to subjects + Mark current lesson in timetable + Show groups next to subjects in timetable Show chart list in class grades Show whole class lessons - Show subjects without grades + Show subjects without grades in Grades Grades color scheme - Subjects sorting - Language + Subjects sorting in \"Grades\" + App language Notifications Show notifications Show upcoming lesson notifications @@ -466,7 +460,6 @@ Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings. Go to settings Show debug notifications - Synchronization is disabled Synchronization Automatic update Suspended on holidays @@ -476,27 +469,14 @@ Synced! Sync failed Sync in progress + Synchronization + Manual sync doesn\'t refresh app views. + \nTo see the synced data relaunch the app after syncing. + + Other Value of the plus Value of the minus Reply with message history - Advanced - Appearance & Behavior - Notifications - Synchronization - Grades - Attendance - Timetable - Grades - Messages - Appearance & Behavior - Languages, themes, subjects sorting - App notifications, fix problems - Notifications - Synchronization - Automatic update, synchronization interval - Plus and minus values, average calculation - Advanced - App version, contributors, social portals, licenses New entries in register New grades @@ -506,10 +486,6 @@ Push notifications Upcoming lessons Debug - - End of support - We are ending support for your device. No more new features will appear for it in Wulkanowy. However, we will be releasing critical patches until the end of 2021 so you have time to switch to a newer model - Don\'t show again Black Red diff --git a/app/src/main/res/values-sk-v29/preferences_values.xml b/app/src/main/res/values-sk-v29/preferences_values.xml deleted file mode 100644 index 8c5306bb..00000000 --- a/app/src/main/res/values-sk-v29/preferences_values.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Motív systému - Svetlý - Tmavý - Čierny (AMOLED) - - \ No newline at end of file diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml deleted file mode 100644 index 8a5b8d24..00000000 --- a/app/src/main/res/values-sk/strings.xml +++ /dev/null @@ -1,539 +0,0 @@ - - - - Prihlásenie - Wulkanowy - Známky - Dochádzka - Skúšky - Plán lekcie - Nastavenia - Viac - O aplikácii - Prehliadač protokolov - Prispievatelia - Licencie - Správy - Nová správa - Poznámky a úspechy - Domáce úlohy - Manažér účtov - Vyberte účet - Podrobnosti účtu - Informácie o žiakovi - - Semester %1$d, %2$d/%3$d - - Prihláste sa pomocou študentského alebo rodičovského konta - Zadajte symbol zo stránky denníka - Užívateľské meno - Email - Prihlásenie, číslo PESEL alebo e-mail - Heslo - Variácie denníka UONET+ - Mobile API - Scraper - Hybridné - Token - PIN - Kľúč API - Symbol - Prihlásiť - Toto heslo je príliš krátke - Prihlasovacie údaje sú nesprávne. Uistite sa, že je v poli nižšie vybraná správna variácie denníka UONET+ - Neplatný PIN - Neplatný token - Platnosť tokenu vypršala - Neplatný e-mail - Namiesto e-mailu použite priradené prihlasovacie údaje - Použite priradené prihlasovacie alebo e-mail v @%1$s - Neplatný symbol - Žiak nebol nájdený. Skontrolujte správnosť symbolu a vybrané varianty denníka UONET+ - Toto pole je povinné - Vybraný žiak už je prihlásený - Symbol nájdete na stránke denníka v  Uczeń→ Dostęp Mobilny → Zarejestruj urządzenie mobilne.\n\nUistite sa, že ste na predchádzajúcu obrazovke nastaviť správny variant denníka do poľa Variácie denníka UONET+. Wulkanowy v túto chvíľu nezistí predškolské żaków - Vyberte žiakov, ktorí sa majú do aplikácie prihlásiť - Iné možnosti - V tomto režime nefungujú nasledovné: šťastné číslo, štatistiky triedy, zhrnutie dochádzky, ospravedlnenie neprítomnosti, dokončené lekcie, informácie o škole a prezeranie zoznamu registrovaných zariadení - Tento režim zobrazuje rovnaké dáta, ktoré sa zobrazujú na webových stránkach denníka - Kombinácia najlepších vlastností ostatných dvoch režimov. Funguje rýchlejšie ako scraper a poskytuje funkcie, ktoré nie sú k dispozícii v režime Mobilne API. Je to v experimentálnej fáze - Zásady ochrany osobných údajov - Problémy s prihlásením? Napíšte nám! - Email - Discord - Poslať e-mail - Opíšte podrobnosti problému: - Uistite sa, že ste vybrali správny variant denníka UONET+! - Zabudol som heslo - Obnovte svoj účet - Obnoviť - Žiak je už prihlásený - - Manažér účtov - Prihlásiť sa - Relácia vypršala - Relácia vypršala. Prihláste sa prosím znovu - - Známka - Semester %d - Zmeniť semester - Žiadne známky - Váha - Váha: %s - Komentár - Žiadne nové známky - Počet nových známok %1$d - Priemer: %1$.2f - Body: %s - Bez priemeru - Predpokladaná: %1$s - Konečná: %1$s - Súčet bodov - Konečná známka - Predpokladaná známka - Vypočítaný priemer - Konečný priemer - Zhrnutie - Trieda - Označiť ako prečítané - Čiastočné - Semester - Body - Vysvetlivky - Priemer: %1$s - Trieda - Žiák - - %d známka - %d známky - %d známok - %d známok - - - Nová známka - Nové známky - Nové známky - Nové známky - - - Nová predpokladaná známka - Nové predpokladané známky - Nové predpokladané známky - Nové predpokladané známky - - - Nová konečná známka - Nové konečné známky - Nové konečné známky - Nové konečné známky - - - Máte %1$d novú známku - Máte %1$d nové známky - Máte %1$d nových známok - Máte %1$d nových známok - - - Máte %1$d novú predpokladanú známku - Máte %1$d nové predpokladané známky - Máte %1$d nových predpokladaných známok - Máte %1$d nových predpokladaných známok - - - Máte %1$d novú konečnú známku - Máte %1$d nové konečnej známky - Máte %1$d nových konečných známok - Máte %1$d nových konečných známok - - - Lekcia - Učebňa - Skupina - Hodiny - Zmeny - Žiadne lekcie tento deň - %s min - %s sek - ešte %1$s - za %1$s - Ukončila - Teraz: %s - Za chvíľu: %s - Neskôr: %s - - Dokončené lekcie - Zobraziť dokončené lekcie - Žiadne informácie o dokončených lekciách - Téma - Neprítomnosť - Zdroje - - Ďalší lekcie - Zobraziť ďalšie lekcie - Žiadne informácie o ďalších lekciách - - Zhrnutie dochádzky - Neprítomnosť zo školských dôvodov - Ospravedlnená neprítomnosť - Neospravedlnená neprítomnosť - Oslobodenie - Ospravedlnenie meškanie - Neospravedlnenie meškanie - Prítomnosť - Odstránené - Neznámy - Číslo lekcie - Žiadne položky - - %1$d neprítomnosť - %1$d neprítomnosti - %1$d neprítomnosti - %1$d neprítomnosti - - Dôvod neprítomnosti (voliteľný) - Poslať - Žiadosť o ospravedlnenie neprítomnosti bola úspešne odoslaná! - Musíte vybrať aspoň jednu neprítomnosť! - Ospravedlniť - - Dochádzka - Spoločne - - Tento týždeň žiadne testy - Typ - Dátum vstupu - - Doručená pošta - Odoslané - Kôš - (žiadny predmet) - Žiadne správy - Pri sťahovaní obsahu správy došlo k chybe - Od: - Komu: - Dátum: %s - Odpoveď - Poslať ďalej - Odstrániť - Presunúť do koša - Odstrániť natrvalo - Správa bola úspešne odstránená - Zdieľať - Vytlačiť - Predmet - Obsah - Správa úspešne odoslaná - Správa neexistuje - Musíte vybrať aspoň 1 príjemca - Obsah správy musí mať aspoň 3 znaky - - %d správa - %d správy - %d správ - %d správ - - - Nová správa - Nové správy - Nové správy - Nové správy - - - Máte %1$d novú správu - Máte %1$d nové správy - Máte %1$d nových správ - Máte %1$d nových správ - - - Žiadne informácie o poznámkach - Body - - %d poznámka - %d poznámky - %d poznámok - %d poznámok - - - Nová poznámka - Nové poznámky - Nové poznámky - Nové poznámky - - - Máte %1$d novú poznámku - Máte %1$d nové poznámky - Máte %1$d nových poznámok - Máte %1$d nových poznámok - - - - %d chvála - %d chvály - %d chvál - %d chvál - - - Nová chvála - Nové chvály - Nové chvály - Nové chvály - - - Máte %1$d novú chválu - Máte %1$d nové chvály - Máte %1$d nových chvál - Máte %1$d nových chvál - - - - %d neutrálny poznámka - %d neutrálne poznámky - %d neutrálne poznámky - %d neutrálne poznámky - - - Nová neutrálny poznámka - Nové neutrálne poznámky - Nové neutrálne poznámky - Nové neutrálne poznámky - - - Máte %1$d novú neutrálny poznámku - Máte %1$d nové neutrálne poznámky - Máte %1$d nových neutrálne poznámok - Máte %1$d nových neutrálne poznámok - - - Žiadne informácie o domácich úlohách - Označiť ako hotové - Nevyrobené - Prílohy - - Šťastné číslo - Dnešné šťastné číslo je - Žiadne informácie o šťastnom čísle - Šťastné číslo pre dnešok - Dnes je šťastným číslom: %d - Zobraziť históriu - - História šťastných čísel - Žiadne informácie o šťastných číslach - - Mobilný prístup - Žiadne zariadenia - Zrušiť registráciu - Zariadenie odstránenie - QR kód - Token - Symbol - PIN - - Škola a učitelia - - Škola - Žiadne informácie o škole - Názov školy - Adresa školy - Telefón - Meno riaditeľa - Meno pedagóga - Zobraziť na mape - Volať - - Učitelia - Žiadne informácie o učiteľoch - Žiadny predmet - - Stretnutie - Žiadne informácie o stretnutiach - - Pridať účet - Odhlásiť - Chcete sa odhlásiť z aktívneho žiaka? - Odhlásenie žiakov - Zakov účet - Rodičovský účet - Režim Mobilného API - Hybridný režim - Upraviť dáta - Manažér účtov - Vyberte žiaka - Rodina - Kontakt - Údaje o adresách - Osobné údaje - - Verzia aplikácie - Prispievatelia - Zoznam vývojárov Wulkanového - Nahlásiť chybu - Odoslať správu o chybe e-mailom - FAQ - Prečítajte si často kladené otázky - Server Discord - Pripojte sa ku komunite Wulkanového - Facebooková fanpage - Rovnako ako naše facebooková fanpage - Zásady ochrany osobných údajov - Pravidlá pre zhromažďovanie osobných údajov - Domovská stránka - Navštívte stránku a pomôžte s vývojom aplikácie - Licencie - Licencia knižníc použitých v aplikácii - - Licencia - - Avatar - Zobraziť viac na GitHub - - Žiadne informácie o žiakov alebo rodine žiaka - Meno - Druhé meno - Pohlavie - Poľské občianstvo - Rodinné meno - Mená matky a otca - Telefón - Mobilný telefón - E-mail - Adresa bydliska - Registrovaná adresa - Korešpondenčná adresa - Priezvisko a meno - Stupeň príbuznosti - Adresa - Telefóny - Muž - Žena - Priezvisko - - Prezývka - Pridať prezývku - Vybrať farbu avataru - - Zdieľať protokoly - Obnoviť - - Skontrolovať aktualizácie - Pred hlásením chyby skontrolujte, či je k dispozícii aktualizácia s opravou chýb - - Obsah - Skúsiť znova - Popis - Žiadny popis - Učiteľ - Dátum - Dátum vstupu - Farba - Podrobnosti - Kategória - Zavrieť - Žiadne údaje - Predmet - Vráť - Ďalej - Hľadať - Hledať… - Áno - Nie - Uložiť - - Žiadne lekcie - Vybrať motív - Svetlý - Tmavý - Motív systému - - Vzhľad a správanie aplikácií - Predvolené zobrazenie - Výpočet koncoročního priemeru - Vynútiť priemerný výpočet podľa aplikácie - Zobraziť prítomnosť - Motív - Rozbaliť známky - Označiť aktuálne lekciu - Zobraziť skupiny vedľa predmetov - Zobraziť zoznam grafov v známkach triedy - Zobraziť lekcie pre celú triedu - Zobraziť predmety bez známok - Známky farebnú schému - Triedenie predmetov - Jazyk - Upozornenia - Zobraziť upozornenia - Zobraziť upozornenia o nadchádzajúcej lekciu - Opravte problémy so synchronizáciou a upozornením - Vaše zariadenie môže mať problémy so synchronizáciou dát as upozorneniami.\n\nAk ich chcete opraviť, pridajte Wulkanového do funkcie Autostart a vypnite optimalizáciu/úsporu batérie v nastavení systému telefóne. - Prejsť do nastavení - Zobraziť upozornenia o ladení - Synchronizácia je vypnutá - Synchronizácia - Automatická aktualizácia - Pozastavený počas dovolenky - Interval aktualizácií - Iba Wi-Fi - Synchronizovať teraz - Synchronizovano! - Synchronizácia zlyhala - Prebieha synchronizácia - Hodnota plusu - Hodnota mínusu - Odpovedať s históriou správ - Pokročilé - Vzhľad a správanie - Upozornenia - Synchronizácia - Známky - Dochádzka - Plán lekcie - Známky - Správy - Vzhľad a správanie - Jazyky, motívy, triedenie predmetov - Upozornenia aplikácie, oprava problémov - Upozornenia - Synchronizácia - Automatická aktualizácia, interval aktualizácií - Hodnota plusu a mínusu, výpočet priemeru - Pokročilé - Verzia aplikácie, prispievatelia, sociálne portály, licencie - - Nové položky v denníku - Nové známky - Šťastné číslo - Nové správy - Nové poznámky - Push upozornenia - Nadchádzajúce lekcie - Ladenie - - Koniec podpory - Ukončujeme podporu pre vaše zariadenie. V Wulkanovým už pre neho nebudú žiadne nové funkcie. Kritické opravy však budeme vydávať až do konca roka 2021, aby ste mali čas prejsť na novší model - Nezobrazovať znovu - - Čierny - Červený - Modrý - Zelený - Fialový - Žiadna farba - - Skopírované - Vrátiť - - Sťahovanie aktualizácií začalo… - Aktualizácia bola stiahnutá. - Reštartovať - Aktualizácia zlyhala! Wulkanowy nemusí fungovať správne. Zvážte aktualizáciu - - Žiadne internetové pripojenie - Nedá sa pripojiť ku denníku. Servery môžu byť preťažené. Prosím skúste to znova neskôr - Načítanie údajov zlyhalo. Skúste neskôr prosím - Je vyžadovaná zmena hesla pre denník - Prebieha údržba UONET+ denník. Skúste to neskôr znova - Neznáma chyba dennika UONET+. Prosím skúste to znova neskôr - Neznáma chyba aplikácie. Prosím skúste to znova neskôr - Vyskytla sa neočakávaná chyba - Funkcia je deaktivovaná cez vašou školou - Funkcia nie je k dispozícii. Prihláste sa v inom režime než Mobile API - diff --git a/app/src/main/res/values-uk/preferences_values.xml b/app/src/main/res/values-uk/preferences_values.xml index d0891925..02b6ccf8 100644 --- a/app/src/main/res/values-uk/preferences_values.xml +++ b/app/src/main/res/values-uk/preferences_values.xml @@ -13,7 +13,6 @@ Українська Deutsch Čeština - Slovenčina 15 хвилин diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 2e0b89da..3c4b4436 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -46,7 +46,6 @@ Минув термін дії токену Недійсна адреса електронної пошти Використовуйте призначений логін замість електронної пошти - Використовуйте призначений логін або електронну адресу в @%1$s Неправильний симбвол Студента не знайдено Перевірте символ та обраний варіант реєстру UONET+ Обов\'язкове поле @@ -192,7 +191,7 @@ Причина відсутності (необов’язково) Надіслати - Запит на виправдання відсутності успішно надіслано! + Змінено статус відсутності Оберіть хоча б одну відсутність Змінити статус @@ -314,10 +313,6 @@ Брак інформації о щасливому номері Сьогоднішній щасливий номер Сьогоднішнім щасливим номером є %d - Показати історію - - Історія щасливих чисел - Немає інформації про щасливі номери Мобільні пристрої Брак пристроїв @@ -386,7 +381,7 @@ Аватар Сторінка проекту на GitHub - Немає інформації про учня або сім\'ю учня + Брак інформації про учня Ім\'я Друге ім\'я Стать @@ -409,7 +404,6 @@ Псевдонім Додати псевдонім - Оберіть колір аватара Поділитися логами Оновити @@ -444,21 +438,21 @@ Темна Тема системи - Поява додатка & amp; поведінки + Вигляд Вікно за замовчуванням Спосіб облічування оцінки на кінець року Примусово розрахувати середню оцінку через додаток - Показати присутність - Тема + Показувати присутність у відвідуваності + Тема додатку Більше оцінок - Позначити поточний урок - Показувати групи поруч з темами + Позначити поточний урок у розкладі + Покажіть групи поруч із предметами в розкладі Показувати діаграми в оцінках класу Показати уроки всього класу - Показати предмети без оцінок + Показуйте предмети без оцінок у оцінках Схема кольорів оцінок - Сортування предметів - Мова + Сортування предметів за \"Оцінками\" + Мова додатку Повідомлення Показувати повідомлення Показувати повідомлення о наступних уроках @@ -466,7 +460,6 @@ На вашому пристрої можуть бути помилки з синхронізацією і повідомленнями\n\nЩоб виправити іх, вам необхідно додати Wulkanowy в авто-старт и вимкнути оптимізацію/экономію батареї в налаштуваннях пристрою. Перейти до налаштувань Показувати дебаг-повідомлення - Синхронізація вимкнена Синхронізація Автоматична синхронізація Призупинено на час канікул @@ -476,27 +469,14 @@ Синхронізовано! Синхронізація не вдалася Триває синхронізація + Синхронізація + Ручна синхронізація не оновлює дані в додатку. + \nЩоб побачити оновлені дані, перезавантажте додаток. + + Інші Вартість плюсу Вага мінуса Відповісти з історією повідомлень - Додатково - Вигляд & Поведінка - Повідомлення - Синхронізація - Оцінки - Відвідуваність - Розклад - Класи - Повідомлення - Вигляд & Поведінка - Мови, теми, тема сортування - Сповіщення додатку, виправляти проблеми - Повідомлення - Синхронізація - Автоматичне оновлення, інтервал синхронізації - Плюс і мінус значення, середні обчислення - Додатково - Версія програми, учасники, соціальні портали, ліцензії Нові дані в щоденнику Нові оцінки @@ -506,10 +486,6 @@ Показувати push-повідомлення Наступні уроки Дебаг - - Кінець підтримки - Ми завершуємо підтримку вашого пристрою. Більше нових функцій не з\'явиться у Wulkanowy. Однак ми виробляємо критичні патчі до кінця 2021, тому у вас буде час перейти на новішу модель - Не показувати знову Чорний Червоний diff --git a/app/src/main/res/values-v23/styles.xml b/app/src/main/res/values-v23/styles.xml deleted file mode 100644 index 574e8488..00000000 --- a/app/src/main/res/values-v23/styles.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values-v26/styles.xml b/app/src/main/res/values-v26/styles.xml deleted file mode 100644 index 55413c05..00000000 --- a/app/src/main/res/values-v26/styles.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/app/src/main/res/values-v28/styles.xml b/app/src/main/res/values-v27/styles.xml similarity index 75% rename from app/src/main/res/values-v28/styles.xml rename to app/src/main/res/values-v27/styles.xml index ee77091d..d33f6422 100644 --- a/app/src/main/res/values-v28/styles.xml +++ b/app/src/main/res/values-v27/styles.xml @@ -1,10 +1,9 @@ - \ No newline at end of file + diff --git a/app/src/main/res/values-v29/styles.xml b/app/src/main/res/values-v29/styles.xml deleted file mode 100644 index ee77091d..00000000 --- a/app/src/main/res/values-v29/styles.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/api_hosts.xml b/app/src/main/res/values/api_hosts.xml index 15849047..0a43612d 100644 --- a/app/src/main/res/values/api_hosts.xml +++ b/app/src/main/res/values/api_hosts.xml @@ -14,7 +14,7 @@ Skarżysko-Kamienna - e-Skarżysko Łask - Platforma vEdukacja Powiat łaski - Platforma edukacyjna - Powiat krasnostawski - Platforma oświatowa + Powiat Krasnostawski - Platforma oświatowa Powiat kętrzyński - Platforma e-Usług Gmina Ulan-Majorat - Platforma oświatowa Gmina Ozorków - Platforma edukacyjna diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index b2e0dcef..99456744 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -6,12 +6,6 @@ #ff5722 #e84853 - #2D2D2D - #1E1E1E - - #1C1C1C - #0D0D0D - #ffd54f #ff8f00 diff --git a/app/src/main/res/values/preferences_values.xml b/app/src/main/res/values/preferences_values.xml index 44f54c17..5f2aec4c 100644 --- a/app/src/main/res/values/preferences_values.xml +++ b/app/src/main/res/values/preferences_values.xml @@ -32,7 +32,6 @@ Українська Deutsch Čeština - Slovenčina system @@ -42,7 +41,6 @@ uk de cs - sk diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4109d2b..c21146c9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,7 +50,6 @@ Token expired Invalid email Use the assigned login instead of email - Use the assigned login or email in @%1$s Invalid symbol Student not found. Validate the symbol and the chosen variation of the UONET+ register This field is required @@ -194,7 +193,7 @@ Absence reason (optional) Send - Absence excuse request sent successfully! + Absence excused successfully! You must select at least one absence! Excuse @@ -306,11 +305,6 @@ No info about the lucky number Lucky number for today Today\'s lucky number is: %d - Show history - - - Lucky number history - No info about lucky numbers Mobile devices @@ -424,7 +418,6 @@ Nick Add nick - Choose avatar color @@ -469,21 +462,21 @@ - App appearance & behavior + Appearance Default view Calculation of the end-of-year average Force average calculation by app - Show presence - Theme + Show presence in attendance + Application theme Expand grades - Mark current lesson - Show groups next to subjects + Mark current lesson in timetable + Show groups next to subjects in timetable Show chart list in class grades Show whole class lessons - Show subjects without grades + Show subjects without grades in Grades Grades color scheme - Subjects sorting - Language + Subjects sorting in "Grades" + App language Notifications Show notifications @@ -492,7 +485,6 @@ Your device may have data synchronization issues and with notifications.\n\nTo fix them, you need to add Wulkanowy to the autostart and turn off battery optimization/saving in the phone settings. Go to settings Show debug notifications - Synchronization is disabled Synchronization Automatic update @@ -503,32 +495,17 @@ Synced! Sync failed Sync in progress + Synchronization + + Manual sync doesn\'t refresh app views. + \nTo see the synced data relaunch the app after syncing. + + Other Value of the plus Value of the minus Reply with message history - Advanced - Appearance & Behavior - Notifications - Synchronization - - Grades - Attendance - Timetable - Grades - Messages - - Appearance & Behavior - Languages, themes, subjects sorting - App notifications, fix problems - Notifications - Synchronization - Automatic update, synchronization interval - Plus and minus values, average calculation - Advanced - App version, contributors, social portals, licenses - New entries in register @@ -541,12 +518,6 @@ Debug - - End of support - We are ending support for your device. No more new features will appear for it in Wulkanowy. However, we will be releasing critical patches until the end of 2021 so you have time to switch to a newer model - Don\'t show again - - Black Red @@ -560,7 +531,6 @@ Copied Undo - Download of updates has started… An update has just been downloaded. @@ -579,4 +549,5 @@ An unexpected error occurred Feature disabled by your school Feature not available. Login in a mode other than Mobile API + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 297a4f28..cf587cbf 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -13,7 +13,6 @@ @color/colorSwipeRefresh ?android:textColorPrimary @style/PreferenceThemeOverlay - false -