From 883024018201db26a5cba85b678c15511035f271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= <m.pich@outlook.com> Date: Sun, 1 Nov 2020 16:53:31 +0100 Subject: [PATCH 01/34] Add conferences (#1004) --- .../28.json | 1842 +++++++++++++++++ .../github/wulkanowy/data/RepositoryModule.kt | 4 + .../github/wulkanowy/data/db/AppDatabase.kt | 11 +- .../wulkanowy/data/db/dao/ConferenceDao.kt | 15 + .../wulkanowy/data/db/entities/Conference.kt | 35 + .../data/db/migrations/Migration28.kt | 23 + .../conference/ConferenceLocal.kt | 25 + .../conference/ConferenceRemote.kt | 31 + .../conference/ConferenceRepository.kt | 25 + .../modules/conference/ConferenceAdapter.kt | 36 + .../modules/conference/ConferenceFragment.kt | 102 + .../modules/conference/ConferencePresenter.kt | 96 + .../ui/modules/conference/ConferenceView.kt | 29 + .../wulkanowy/ui/modules/more/MoreFragment.kt | 8 + .../ui/modules/more/MorePresenter.kt | 2 + .../wulkanowy/ui/modules/more/MoreView.kt | 4 + .../main/res/drawable/ic_more_conferences.xml | 9 + .../main/res/layout/fragment_conference.xml | 104 + app/src/main/res/layout/item_conference.xml | 87 + app/src/main/res/values/strings.xml | 5 + 20 files changed, 2491 insertions(+), 2 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt create mode 100644 app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt create mode 100644 app/src/main/res/drawable/ic_more_conferences.xml create mode 100644 app/src/main/res/layout/fragment_conference.xml create mode 100644 app/src/main/res/layout/item_conference.xml diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json new file mode 100644 index 00000000..c7c4c033 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json @@ -0,0 +1,1842 @@ +{ + "formatVersion": 1, + "database": { + "version": 28, + "identityHash": "3a449a55ea73fbfbb7973f1f3f834e10", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scrapperBaseUrl", + "columnName": "scrapper_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mobileBaseUrl", + "columnName": "mobile_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "login_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginMode", + "columnName": "login_mode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificateKey", + "columnName": "certificate_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "privateKey", + "columnName": "private_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isParent", + "columnName": "is_parent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userLoginId", + "columnName": "user_login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userName", + "columnName": "user_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolShortName", + "columnName": "school_short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "className", + "columnName": "class_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "current", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolYear", + "columnName": "school_year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isStudentPlan", + "columnName": "student_plan", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeId", + "columnName": "time_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excusable", + "columnName": "excusable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excuseStatus", + "columnName": "excuse_status", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPredictedGradeNotified", + "columnName": "is_predicted_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isFinalGradeNotified", + "columnName": "is_final_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "predictedGradeLastChange", + "columnName": "predicted_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "finalGradeLastChange", + "columnName": "final_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predicted_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "final_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "proposedPoints", + "columnName": "proposed_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalPoints", + "columnName": "final_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pointsSum", + "columnName": "points_sum", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "average", + "columnName": "average", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `grade` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `is_semester` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "grade", + "columnName": "grade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semester", + "columnName": "is_semester", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesPointsStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "others", + "columnName": "others", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "student", + "columnName": "student", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hasAttachments", + "columnName": "has_attachments", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MessageAttachments", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", + "fields": [ + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "oneDriveId", + "columnName": "one_drive_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filename", + "columnName": "filename", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "real_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categoryType", + "columnName": "category_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPointsShow", + "columnName": "is_points_show", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isDone", + "columnName": "is_done", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MobileDevices", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceId", + "columnName": "device_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Teachers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "School", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contact", + "columnName": "contact", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "headmaster", + "columnName": "headmaster", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pedagogue", + "columnName": "pedagogue", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Conferences", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "agenda", + "columnName": "agenda", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presentOnConference", + "columnName": "present_on_conference", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conferenceId", + "columnName": "conference_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3a449a55ea73fbfbb7973f1f3f834e10')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index 6486cab9..50642ddd 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -154,4 +154,8 @@ internal class RepositoryModule { @Singleton @Provides fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao + + @Singleton + @Provides + fun provideConferenceDao(database: AppDatabase) = database.conferenceDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index ebd5119f..93f22542 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -10,6 +10,7 @@ import androidx.room.migration.Migration import io.github.wulkanowy.data.db.dao.AttendanceDao import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao import io.github.wulkanowy.data.db.dao.CompletedLessonsDao +import io.github.wulkanowy.data.db.dao.ConferenceDao import io.github.wulkanowy.data.db.dao.ExamDao import io.github.wulkanowy.data.db.dao.GradeDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao @@ -32,6 +33,7 @@ import io.github.wulkanowy.data.db.dao.TimetableDao import io.github.wulkanowy.data.db.entities.Attendance import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.db.entities.CompletedLesson +import io.github.wulkanowy.data.db.entities.Conference import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Grade import io.github.wulkanowy.data.db.entities.GradePointsStatistics @@ -70,6 +72,7 @@ import io.github.wulkanowy.data.db.migrations.Migration24 import io.github.wulkanowy.data.db.migrations.Migration25 import io.github.wulkanowy.data.db.migrations.Migration26 import io.github.wulkanowy.data.db.migrations.Migration27 +import io.github.wulkanowy.data.db.migrations.Migration28 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration5 @@ -103,7 +106,8 @@ import javax.inject.Singleton Recipient::class, MobileDevice::class, Teacher::class, - School::class + School::class, + Conference::class, ], version = AppDatabase.VERSION_SCHEMA, exportSchema = true @@ -112,7 +116,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 27 + const val VERSION_SCHEMA = 28 fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> { return arrayOf( @@ -142,6 +146,7 @@ abstract class AppDatabase : RoomDatabase() { Migration25(), Migration26(), Migration27(), + Migration28(), ) } @@ -198,4 +203,6 @@ abstract class AppDatabase : RoomDatabase() { abstract val teacherDao: TeacherDao abstract val schoolDao: SchoolDao + + abstract val conferenceDao: ConferenceDao } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt new file mode 100644 index 00000000..4ed9aecf --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt @@ -0,0 +1,15 @@ +package io.github.wulkanowy.data.db.dao + +import androidx.room.Dao +import androidx.room.Query +import io.github.wulkanowy.data.db.entities.Conference +import kotlinx.coroutines.flow.Flow +import javax.inject.Singleton + +@Dao +@Singleton +interface ConferenceDao : BaseDao<Conference> { + + @Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId") + fun loadAll(diaryId: Int, studentId: Int): Flow<List<Conference>> +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt new file mode 100644 index 00000000..8ddcbbb0 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt @@ -0,0 +1,35 @@ +package io.github.wulkanowy.data.db.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.io.Serializable +import java.time.LocalDateTime + +@Entity(tableName = "Conferences") +data class Conference( + + @ColumnInfo(name = "student_id") + val studentId: Int, + + @ColumnInfo(name = "diary_id") + val diaryId: Int, + + val title: String, + + val subject: String, + + val agenda: String, + + @ColumnInfo(name = "present_on_conference") + val presentOnConference: String, + + @ColumnInfo(name = "conference_id") + val conferenceId: Int, + + val date: LocalDateTime +) : Serializable { + + @PrimaryKey(autoGenerate = true) + var id: Long = 0 +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt new file mode 100644 index 00000000..51e7628b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt @@ -0,0 +1,23 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration28 : Migration(27, 28) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL(""" + CREATE TABLE IF NOT EXISTS Conferences ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + student_id INTEGER NOT NULL, + diary_id INTEGER NOT NULL, + title TEXT NOT NULL, + subject TEXT NOT NULL, + agenda TEXT NOT NULL, + present_on_conference TEXT NOT NULL, + conference_id INTEGER NOT NULL, + date INTEGER NOT NULL + ) + """) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt new file mode 100644 index 00000000..9f56641f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceLocal.kt @@ -0,0 +1,25 @@ +package io.github.wulkanowy.data.repositories.conference + +import io.github.wulkanowy.data.db.dao.ConferenceDao +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ConferenceLocal @Inject constructor(private val conferenceDb: ConferenceDao) { + + fun getConferences(student: Student, semester: Semester): Flow<List<Conference>> { + return conferenceDb.loadAll(semester.diaryId, student.studentId) + } + + suspend fun saveConferences(items: List<Conference>) { + conferenceDb.insertAll(items) + } + + suspend fun deleteConferences(items: List<Conference>) { + conferenceDb.deleteAll(items) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt new file mode 100644 index 00000000..50e869a9 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRemote.kt @@ -0,0 +1,31 @@ +package io.github.wulkanowy.data.repositories.conference + +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.sdk.Sdk +import io.github.wulkanowy.utils.init +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ConferenceRemote @Inject constructor(private val sdk: Sdk) { + + suspend fun getConferences(student: Student, semester: Semester): List<Conference> { + return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getConferences() + .map { + it.agenda + Conference( + studentId = student.studentId, + diaryId = semester.diaryId, + agenda = it.agenda, + conferenceId = it.id, + date = it.date, + presentOnConference = it.presentOnConference, + subject = it.subject, + title = it.title + ) + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt new file mode 100644 index 00000000..187ecf58 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/conference/ConferenceRepository.kt @@ -0,0 +1,25 @@ +package io.github.wulkanowy.data.repositories.conference + +import io.github.wulkanowy.data.db.entities.Semester +import io.github.wulkanowy.data.db.entities.Student +import io.github.wulkanowy.utils.networkBoundResource +import io.github.wulkanowy.utils.uniqueSubtract +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ConferenceRepository @Inject constructor( + private val local: ConferenceLocal, + private val remote: ConferenceRemote +) { + + fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh }, + query = { local.getConferences(student, semester) }, + fetch = { remote.getConferences(student, semester) }, + saveFetchResult = { old, new -> + local.deleteConferences(old uniqueSubtract new) + local.saveConferences(new uniqueSubtract old) + } + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt new file mode 100644 index 00000000..c8728614 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceAdapter.kt @@ -0,0 +1,36 @@ +package io.github.wulkanowy.ui.modules.conference + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.databinding.ItemConferenceBinding +import io.github.wulkanowy.utils.toFormattedString +import javax.inject.Inject + +class ConferenceAdapter @Inject constructor() : + RecyclerView.Adapter<ConferenceAdapter.ItemViewHolder>() { + + var items = emptyList<Conference>() + + override fun getItemCount() = items.size + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( + ItemConferenceBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val item = items[position] + with(holder.binding) { + conferenceItemDate.text = item.date.toFormattedString("dd.MM.yyyy HH:mm") + conferenceItemName.text = item.presentOnConference + conferenceItemTitle.text = item.title + conferenceItemSubject.text = item.subject + conferenceItemContent.text = item.agenda + conferenceItemContent.visibility = if (item.agenda.isBlank()) View.GONE else View.VISIBLE + } + } + + class ItemViewHolder(val binding: ItemConferenceBinding) : RecyclerView.ViewHolder(binding.root) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt new file mode 100644 index 00000000..74d93897 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceFragment.kt @@ -0,0 +1,102 @@ +package io.github.wulkanowy.ui.modules.conference + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import dagger.hilt.android.AndroidEntryPoint +import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.databinding.FragmentConferenceBinding +import io.github.wulkanowy.ui.base.BaseFragment +import io.github.wulkanowy.ui.modules.main.MainView +import io.github.wulkanowy.ui.widgets.DividerItemDecoration +import javax.inject.Inject + +@AndroidEntryPoint +class ConferenceFragment : BaseFragment<FragmentConferenceBinding>(R.layout.fragment_conference), + ConferenceView, MainView.TitledView { + + @Inject + lateinit var presenter: ConferencePresenter + + @Inject + lateinit var conferencesAdapter: ConferenceAdapter + + companion object { + fun newInstance() = ConferenceFragment() + } + + override val isViewEmpty: Boolean + get() = conferencesAdapter.items.isEmpty() + + override val titleStringId: Int + get() = R.string.conferences_title + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding = FragmentConferenceBinding.bind(view) + messageContainer = binding.conferenceRecycler + presenter.onAttachView(this) + } + + override fun initView() { + with(binding.conferenceRecycler) { + layoutManager = LinearLayoutManager(context) + adapter = conferencesAdapter + addItemDecoration(DividerItemDecoration(context)) + } + + with(binding) { + conferenceSwipe.setOnRefreshListener { presenter.onSwipeRefresh() } + conferenceErrorRetry.setOnClickListener { presenter.onRetry() } + conferenceErrorDetails.setOnClickListener { presenter.onDetailsClick() } + } + } + + override fun updateData(data: List<Conference>) { + with(conferencesAdapter) { + items = data + notifyDataSetChanged() + } + } + + override fun clearData() { + with(conferencesAdapter) { + items = emptyList() + notifyDataSetChanged() + } + } + + override fun hideRefresh() { + binding.conferenceSwipe.isRefreshing = false + } + + override fun showProgress(show: Boolean) { + binding.conferenceProgress.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showEmpty(show: Boolean) { + binding.conferenceEmpty.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun showErrorView(show: Boolean) { + binding.conferenceError.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun setErrorDetails(message: String) { + binding.conferenceErrorMessage.text = message + } + + override fun enableSwipe(enable: Boolean) { + binding.conferenceSwipe.isEnabled = enable + } + + override fun showContent(show: Boolean) { + binding.conferenceRecycler.visibility = if (show) View.VISIBLE else View.GONE + } + + override fun onDestroyView() { + presenter.onDetachView() + super.onDestroyView() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt new file mode 100644 index 00000000..71b412da --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferencePresenter.kt @@ -0,0 +1,96 @@ +package io.github.wulkanowy.ui.modules.conference + +import io.github.wulkanowy.data.Status +import io.github.wulkanowy.data.repositories.conference.ConferenceRepository +import io.github.wulkanowy.data.repositories.semester.SemesterRepository +import io.github.wulkanowy.data.repositories.student.StudentRepository +import io.github.wulkanowy.ui.base.BasePresenter +import io.github.wulkanowy.ui.base.ErrorHandler +import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.afterLoading +import io.github.wulkanowy.utils.flowWithResourceIn +import kotlinx.coroutines.flow.onEach +import timber.log.Timber +import javax.inject.Inject + +class ConferencePresenter @Inject constructor( + errorHandler: ErrorHandler, + studentRepository: StudentRepository, + private val semesterRepository: SemesterRepository, + private val conferenceRepository: ConferenceRepository, + private val analytics: AnalyticsHelper +) : BasePresenter<ConferenceView>(errorHandler, studentRepository) { + + private lateinit var lastError: Throwable + + override fun onAttachView(view: ConferenceView) { + super.onAttachView(view) + view.initView() + Timber.i("Conferences view was initialized") + errorHandler.showErrorMessage = ::showErrorViewOnError + loadData() + } + + fun onSwipeRefresh() { + loadData(true) + } + + fun onRetry() { + view?.run { + showErrorView(false) + showProgress(true) + } + loadData(true) + } + + fun onDetailsClick() { + view?.showErrorDetailsDialog(lastError) + } + + private fun showErrorViewOnError(message: String, error: Throwable) { + view?.run { + if (isViewEmpty) { + lastError = error + setErrorDetails(message) + showErrorView(true) + showEmpty(false) + } else showError(message, error) + } + } + + private fun loadData(forceRefresh: Boolean = false) { + flowWithResourceIn { + val student = studentRepository.getCurrentStudent() + val semester = semesterRepository.getCurrentSemester(student) + conferenceRepository.getConferences(student, semester, forceRefresh) + }.onEach { + when (it.status) { + Status.LOADING -> Timber.i("Loading conference data started") + Status.SUCCESS -> { + Timber.i("Loading conference result: Success") + view?.run { + updateData(it.data!!.sortedByDescending { conference -> conference.date }) + showContent(it.data.isNotEmpty()) + showEmpty(it.data.isEmpty()) + showErrorView(false) + } + analytics.logEvent( + "load_data", + "type" to "conferences", + "items" to it.data!!.size + ) + } + Status.ERROR -> { + Timber.i("Loading conference result: An exception occurred") + errorHandler.dispatch(it.error!!) + } + } + }.afterLoading { + view?.run { + hideRefresh() + showProgress(false) + enableSwipe(true) + } + }.launch() + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt new file mode 100644 index 00000000..37845a6f --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/conference/ConferenceView.kt @@ -0,0 +1,29 @@ +package io.github.wulkanowy.ui.modules.conference + +import io.github.wulkanowy.data.db.entities.Conference +import io.github.wulkanowy.ui.base.BaseView + +interface ConferenceView : BaseView { + + val isViewEmpty: Boolean + + fun initView() + + fun updateData(data: List<Conference>) + + fun clearData() + + fun hideRefresh() + + fun showEmpty(show: Boolean) + + fun showErrorView(show: Boolean) + + fun setErrorDetails(message: String) + + fun showProgress(show: Boolean) + + fun enableSwipe(enable: Boolean) + + fun showContent(show: Boolean) +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt index 1bdcc26f..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 @@ -9,6 +9,7 @@ import io.github.wulkanowy.R import io.github.wulkanowy.databinding.FragmentMoreBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.about.AboutFragment +import io.github.wulkanowy.ui.modules.conference.ConferenceFragment import io.github.wulkanowy.ui.modules.homework.HomeworkFragment import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment import io.github.wulkanowy.ui.modules.main.MainActivity @@ -53,6 +54,9 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more), override val mobileDevicesRes: Pair<String, Drawable?>? get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) } + override val conferencesRes: Pair<String, Drawable?>? + get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) } + override val schoolAndTeachersRes: Pair<String, Drawable?>? get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) } @@ -108,6 +112,10 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more), (activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance()) } + override fun openConferencesView() { + (activity as? MainActivity)?.pushView(ConferenceFragment.newInstance()) + } + override fun openSchoolAndTeachersView() { (activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance()) } 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 6d80f418..d083c981 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 @@ -27,6 +27,7 @@ class MorePresenter @Inject constructor( noteRes?.first -> openNoteView() luckyNumberRes?.first -> openLuckyNumberView() mobileDevicesRes?.first -> openMobileDevicesView() + conferencesRes?.first -> openConferencesView() schoolAndTeachersRes?.first -> openSchoolAndTeachersView() settingsRes?.first -> openSettingsView() aboutRes?.first -> openAboutView() @@ -48,6 +49,7 @@ class MorePresenter @Inject constructor( noteRes, luckyNumberRes, mobileDevicesRes, + conferencesRes, schoolAndTeachersRes, settingsRes, aboutRes diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreView.kt index 922afdfd..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 @@ -15,6 +15,8 @@ interface MoreView : BaseView { val mobileDevicesRes: Pair<String, Drawable?>? + val conferencesRes: Pair<String, Drawable?>? + val schoolAndTeachersRes: Pair<String, Drawable?>? val settingsRes: Pair<String, Drawable?>? @@ -41,5 +43,7 @@ interface MoreView : BaseView { fun openMobileDevicesView() + fun openConferencesView() + fun openSchoolAndTeachersView() } diff --git a/app/src/main/res/drawable/ic_more_conferences.xml b/app/src/main/res/drawable/ic_more_conferences.xml new file mode 100644 index 00000000..87be8e05 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_conferences.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="M9,13.75c-2.34,0 -7,1.17 -7,3.5L2,19h14v-1.75c0,-2.33 -4.66,-3.5 -7,-3.5zM4.34,17c0.84,-0.58 2.87,-1.25 4.66,-1.25s3.82,0.67 4.66,1.25L4.34,17zM9,12c1.93,0 3.5,-1.57 3.5,-3.5S10.93,5 9,5 5.5,6.57 5.5,8.5 7.07,12 9,12zM9,7c0.83,0 1.5,0.67 1.5,1.5S9.83,10 9,10s-1.5,-0.67 -1.5,-1.5S8.17,7 9,7zM16.04,13.81c1.16,0.84 1.96,1.96 1.96,3.44L18,19h4v-1.75c0,-2.02 -3.5,-3.17 -5.96,-3.44zM15,12c1.93,0 3.5,-1.57 3.5,-3.5S16.93,5 15,5c-0.54,0 -1.04,0.13 -1.5,0.35 0.63,0.89 1,1.98 1,3.15s-0.37,2.26 -1,3.15c0.46,0.22 0.96,0.35 1.5,0.35z" /> +</vector> diff --git a/app/src/main/res/layout/fragment_conference.xml b/app/src/main/res/layout/fragment_conference.xml new file mode 100644 index 00000000..d7cac878 --- /dev/null +++ b/app/src/main/res/layout/fragment_conference.xml @@ -0,0 +1,104 @@ +<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.modules.conference.ConferenceFragment"> + + <me.zhanghai.android.materialprogressbar.MaterialProgressBar + android:id="@+id/conferenceProgress" + style="@style/Widget.MaterialProgressBar.ProgressBar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:indeterminate="true" /> + + <androidx.swiperefreshlayout.widget.SwipeRefreshLayout + android:id="@+id/conferenceSwipe" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/conferenceRecycler" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:listitem="@layout/item_conference" /> + </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> + + <LinearLayout + android:id="@+id/conferenceEmpty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="vertical" + android:padding="10dp" + android:visibility="gone" + tools:ignore="UseCompoundDrawables"> + + <ImageView + android:layout_width="100dp" + android:layout_height="100dp" + app:srcCompat="@drawable/ic_more_conferences" + app:tint="?colorOnBackground" + tools:ignore="contentDescription" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:gravity="center" + android:text="@string/conference_no_items" + android:textSize="20sp" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/conferenceError" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="vertical" + android:visibility="invisible" + tools:ignore="UseCompoundDrawables" + tools:visibility="invisible"> + + <ImageView + android:layout_width="100dp" + android:layout_height="100dp" + app:srcCompat="@drawable/ic_error" + app:tint="?colorOnBackground" + tools:ignore="contentDescription" /> + + <TextView + android:id="@+id/conferenceErrorMessage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:gravity="center" + android:padding="8dp" + android:text="@string/error_unknown" + android:textSize="20sp" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:gravity="center" + android:orientation="horizontal"> + + <com.google.android.material.button.MaterialButton + android:id="@+id/conferenceErrorDetails" + style="@style/Widget.MaterialComponents.Button.OutlinedButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:layout_marginRight="8dp" + android:text="@string/all_details" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/conferenceErrorRetry" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/all_retry" /> + </LinearLayout> + </LinearLayout> +</androidx.coordinatorlayout.widget.CoordinatorLayout> diff --git a/app/src/main/res/layout/item_conference.xml b/app/src/main/res/layout/item_conference.xml new file mode 100644 index 00000000..4c881f34 --- /dev/null +++ b/app/src/main/res/layout/item_conference.xml @@ -0,0 +1,87 @@ +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/conference_item_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?selectableItemBackground" + tools:context=".ui.modules.conference.ConferenceAdapter"> + + <TextView + android:id="@+id/conferenceItemDate" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="15dp" + android:layout_marginTop="10dp" + android:textColor="?android:textColorSecondary" + android:textSize="15sp" + app:layout_constraintRight_toLeftOf="@+id/conferenceItemName" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="@tools:sample/date/ddmmyy" /> + + <TextView + android:id="@+id/conferenceItemName" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="15dp" + android:ellipsize="end" + android:gravity="end" + android:singleLine="true" + android:textSize="13sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/conferenceItemDate" + app:layout_constraintTop_toTopOf="parent" + tools:text="@tools:sample/full_names" /> + + <TextView + android:id="@+id/conferenceItemTitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp" + android:ellipsize="end" + android:maxLines="2" + android:textSize="16sp" + app:layout_constraintEnd_toEndOf="@id/conferenceItemName" + app:layout_constraintStart_toStartOf="@id/conferenceItemDate" + app:layout_constraintTop_toBottomOf="@id/conferenceItemDate" + app:layout_goneMarginEnd="0dp" + tools:text="@tools:sample/lorem" /> + + <TextView + android:id="@+id/conferenceItemSubject" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp" + android:ellipsize="end" + android:maxLines="2" + android:textSize="16sp" + app:layout_constraintBottom_toTopOf="@id/conferenceItemContent" + app:layout_constraintEnd_toEndOf="@id/conferenceItemTitle" + app:layout_constraintStart_toStartOf="@id/conferenceItemTitle" + app:layout_constraintTop_toBottomOf="@id/conferenceItemTitle" + app:layout_goneMarginBottom="15dp" + app:layout_goneMarginEnd="0dp" + tools:text="@tools:sample/lorem" /> + + <TextView + android:id="@+id/conferenceItemContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="15dp" + android:ellipsize="end" + android:lineSpacingMultiplier="1.2" + android:maxLines="2" + android:textSize="14sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="@+id/conferenceItemName" + app:layout_constraintStart_toStartOf="@id/conferenceItemDate" + app:layout_constraintTop_toBottomOf="@id/conferenceItemSubject" + tools:text="@tools:sample/lorem/random" + tools:visibility="visible" /> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e849573..cea6a83d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -325,6 +325,11 @@ <string name="teacher_no_subject">No subject</string> + <!--Conference--> + <string name="conferences_title">Conferences</string> + <string name="conference_no_items">No info about conferences</string> + + <!--Account--> <string name="account_add_new">Add account</string> <string name="account_logout">Logout</string> From 83d1d860a61a3efbf256e9f7e7224bcc07479463 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 15:55:36 +0000 Subject: [PATCH 02/34] Bump coil from 1.0.0-rc3 to 1.0.0 (#1006) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 541aff36..dd71b0db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -194,7 +194,7 @@ dependencies { implementation "fr.bipi.treessence:treessence:0.3.2" implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation 'com.wdullaer:materialdatetimepicker:4.2.3' - implementation "io.coil-kt:coil:1.0.0-rc3" + implementation "io.coil-kt:coil:1.0.0" implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' From 6af8263952b580c28af72134f4b2ca409e362a1b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 15:55:51 +0000 Subject: [PATCH 03/34] Bump firebase-inappmessaging-ktx from 19.1.1 to 19.1.2 (#1010) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index dd71b0db..c2a4ebcf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -200,7 +200,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-analytics:17.6.0' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' - playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.1" + playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" playImplementation 'com.google.firebase:firebase-messaging:20.3.0' playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' playImplementation 'com.google.android.play:core-ktx:1.8.1' From 7c9e85793b19a4e1d003445226dd27aba295eeca Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 16:15:17 +0000 Subject: [PATCH 04/34] Bump firebase-inappmessaging-display-ktx from 19.1.1 to 19.1.2 (#1007) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c2a4ebcf..5e351315 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -199,7 +199,7 @@ dependencies { implementation 'me.xdrop:fuzzywuzzy:1.3.1' playImplementation 'com.google.firebase:firebase-analytics:17.6.0' - playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.1' + playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" playImplementation 'com.google.firebase:firebase-messaging:20.3.0' playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' From 9ba999feb05e30cd7568c7564ec728c95a965401 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 16:28:32 +0000 Subject: [PATCH 05/34] Bump about_libraries from 8.4.2 to 8.4.3 (#1011) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index daec6806..051fce64 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.10' - about_libraries = '8.4.2' + about_libraries = '8.4.3' hilt_version = "2.29.1-alpha" } repositories { From b3109aed0ba98fc24b75b17cdd13a94f426de960 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 16:40:39 +0000 Subject: [PATCH 06/34] Bump firebase-messaging from 20.3.0 to 21.0.0 (#1008) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5e351315..c1248afd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -201,7 +201,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-analytics:17.6.0' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" - playImplementation 'com.google.firebase:firebase-messaging:20.3.0' + playImplementation 'com.google.firebase:firebase-messaging:21.0.0' playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' playImplementation 'com.google.android.play:core-ktx:1.8.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' From 20644a7a677063210cf32f1150ccf0d307998faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Sun, 1 Nov 2020 19:05:05 +0100 Subject: [PATCH 07/34] Update english strings (#1014) --- .../main/res/values/preferences_values.xml | 2 +- app/src/main/res/values/strings.xml | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/values/preferences_values.xml b/app/src/main/res/values/preferences_values.xml index d994213c..5f2aec4c 100644 --- a/app/src/main/res/values/preferences_values.xml +++ b/app/src/main/res/values/preferences_values.xml @@ -78,7 +78,7 @@ </string-array> <string-array name="grade_sorting_mode_entries"> - <item>Alphabetic</item> + <item>Alphabetically</item> <item>By date</item> </string-array> <string-array name="grade_sorting_mode_values" translatable="false"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cea6a83d..cc3dbe3c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,12 +26,12 @@ <!--Login--> <string name="login_header_default">Sign in with the student or parent account</string> - <string name="login_header_symbol">Enter the symbol</string> + <string name="login_header_symbol">Enter the symbol from the register page</string> <string name="login_nickname_hint">Username</string> <string name="login_email_hint">Email</string> <string name="login_login_pesel_email_hint">Login, PESEL or e-mail</string> <string name="login_password_hint">Password</string> - <string name="login_host_hint">UONET+ Register</string> + <string name="login_host_hint">UONET+ register variant</string> <string name="login_type_api">Mobile API</string> <string name="login_type_scrapper">Scraper</string> <string name="login_type_hybrid">Hybrid</string> @@ -41,17 +41,17 @@ <string name="login_symbol_hint">Symbol</string> <string name="login_sign_in">Sign in</string> <string name="login_invalid_password">Password too short</string> - <string name="login_incorrect_password">Login details are incorrect. Make sure the correct UONET+ register is selected</string> + <string name="login_incorrect_password">Login details are incorrect. Make sure the correct UONET+ register variation is selected in the field below</string> <string name="login_invalid_pin">Invalid PIN</string> <string name="login_invalid_token">Invalid token</string> <string name="login_expired_token">Token expired</string> <string name="login_invalid_email">Invalid email</string> - <string name="login_invalid_login">Invalid login</string> + <string name="login_invalid_login">Use the assigned login instead of email</string> <string name="login_invalid_symbol">Invalid symbol</string> - <string name="login_incorrect_symbol">Student not found. Check the symbol</string> + <string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string> <string name="login_field_required">This field is required</string> <string name="login_duplicate_student">Selected student is already logged in</string> - <string name="login_symbol_helper">The symbol can be found on the register page in <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b></string> + <string name="login_symbol_helper">The symbol can be found on the register page in <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the previous screen. Wulkanowy does not detect pre-school students at the moment</string> <string name="login_select_student">Select students to log in to the application</string> <string name="login_advanced">Other options</string> <string name="login_advanced_warning_mobile_api">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</string> @@ -65,7 +65,7 @@ <string name="login_email_details">Describe details of problem:</string> <string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string> <string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\nDodatkowe informacje: %4$s\nOstatni błąd: %5$s\n\nOpis problemu: </string> - <string name="login_recover_warning">Make sure the correct UONET+ register is selected!</string> + <string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string> <string name="login_recover_button">I forgot my password</string> <string name="login_recover_title">Recover your account</string> <string name="login_recover">Recover</string> @@ -486,12 +486,12 @@ <!--Errors--> <string name="error_no_internet">No internet connection</string> - <string name="error_timeout">Connection to the register timed out</string> - <string name="error_login_failed">Login failed. Try again</string> - <string name="error_password_change_required">Password change required</string> + <string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string> + <string name="error_login_failed">Loading data failed. Please try again later</string> + <string name="error_password_change_required">Register password change required</string> <string name="error_service_unavailable">Maintenance underway UONET + register. Try again later</string> <string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string> - <string name="error_unknown_app">Unknown application error</string> + <string name="error_unknown_app">Unknown application error. Please try again later</string> <string name="error_unknown">An unexpected error occurred</string> <string name="error_feature_disabled">Feature disabled by your school</string> <string name="error_feature_not_available">Feature not available. Login in a mode other than Mobile API</string> From 57e760844f3aba5a6528e6ea0e4ded7ba8ba5163 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 18:15:52 +0000 Subject: [PATCH 08/34] Bump kotlinx-coroutines-test from 1.3.9 to 1.4.0 (#1012) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c1248afd..c4bb798c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -216,7 +216,7 @@ dependencies { testImplementation "junit:junit:4.13.1" testImplementation "io.mockk:mockk:$mockk" - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.9' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.0' androidTestImplementation "androidx.test:core:1.3.0" androidTestImplementation "androidx.test:runner:1.3.0" From 9eb091fbf4cdb0b1d00445ffa0c8914d1d1ae2ee Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 18:16:21 +0000 Subject: [PATCH 09/34] Bump kotlinx-coroutines-android from 1.3.9 to 1.4.0 (#1005) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c4bb798c..d1727551 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,7 +147,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0' implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.activity:activity-ktx:1.1.0" From fe191bb0df19c1fe2f28b64efcf8bbf68cedc7e8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2020 18:36:55 +0000 Subject: [PATCH 10/34] Bump firebase-analytics from 17.6.0 to 18.0.0 (#1009) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d1727551..ddb63d47 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -198,7 +198,7 @@ dependencies { implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' - playImplementation 'com.google.firebase:firebase-analytics:17.6.0' + playImplementation 'com.google.firebase:firebase-analytics:18.0.0' playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" playImplementation 'com.google.firebase:firebase-messaging:21.0.0' From ada5854d10bac7d6e9490e149182b31197d04c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Mon, 2 Nov 2020 17:54:02 +0100 Subject: [PATCH 11/34] New Crowdin updates (#1013) --- app/src/main/res/values-cs-rCZ/strings.xml | 25 ++-- .../main/res/values-de/preferences_values.xml | 4 +- app/src/main/res/values-de/strings.xml | 69 ++++----- app/src/main/res/values-pl/strings.xml | 9 +- app/src/main/res/values-ru/strings.xml | 35 +++-- .../main/res/values-uk/preferences_values.xml | 8 +- app/src/main/res/values-uk/strings.xml | 137 +++++++++--------- 7 files changed, 151 insertions(+), 136 deletions(-) diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 67babcd5..dd474aec 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -22,12 +22,12 @@ <string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string> <!--Login--> <string name="login_header_default">Přihlaste se pomocí studentského nebo nadřazeného účtu</string> - <string name="login_header_symbol">Zadejte symbol</string> + <string name="login_header_symbol">Zadejte symbol ze stránky deníku</string> <string name="login_nickname_hint">Uživatelské jméno</string> <string name="login_email_hint">Email</string> <string name="login_login_pesel_email_hint">Přihlášení, číslo PESEL nebo e-mail</string> <string name="login_password_hint">Heslo</string> - <string name="login_host_hint">Deník UONET+</string> + <string name="login_host_hint">Variace deníku UONET+</string> <string name="login_type_api">Mobile API</string> <string name="login_type_scrapper">Scraper</string> <string name="login_type_hybrid">Hybridní</string> @@ -37,17 +37,17 @@ <string name="login_symbol_hint">Symbol</string> <string name="login_sign_in">Přihlásit</string> <string name="login_invalid_password">Toto heslo je příliš krátké</string> - <string name="login_incorrect_password">Přihlašovací údaje jsou nesprávné. Zkontrolujte, zda je v poli níže vybrán správný deník UONET+</string> + <string name="login_incorrect_password">Přihlašovací údaje jsou nesprávné. Ujistěte se, že je v poli níže vybrána správná variace deníku UONET+</string> <string name="login_invalid_pin">Neplatný PIN</string> <string name="login_invalid_token">Neplatný token</string> <string name="login_expired_token">Platnost tokenu vypršela</string> <string name="login_invalid_email">Nesprávná e-mailová adresa</string> - <string name="login_invalid_login">Neplatné přihlášení</string> + <string name="login_invalid_login">Místo e-mailu použijte přiřazené přihlašovací údaje</string> <string name="login_invalid_symbol">Neplatný symbol</string> - <string name="login_incorrect_symbol">Student nebyl nalezen. Zkontrolujte symbol</string> + <string name="login_incorrect_symbol">Student nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+</string> <string name="login_field_required">Toto pole je povinné</string> <string name="login_duplicate_student">Vybraný student je již přihlášen</string> - <string name="login_symbol_helper">Symbol najdete na stránce deníku v <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b></string> + <string name="login_symbol_helper">Symbol najdete na stránce deníku v  <b>Uczeń</b> →  <b>Dostęp Mobilny</b> →  <b>Zarejestruj urządzenie mobilne</b>.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole <b>Variace deníku UONET+</b>. Wulkanowy v tuto chvíli nezjistí předškolní studenty</string> <string name="login_select_student">Vyberte studenty k přihlášení do aplikace</string> <string name="login_advanced">Jiné možnosti</string> <string name="login_advanced_warning_mobile_api">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í</string> @@ -59,7 +59,7 @@ <string name="login_contact_discord">Discord</string> <string name="login_email_intent_title">Poslat e-mail</string> <string name="login_email_details">Popište podrobnosti problému:</string> - <string name="login_recover_warning">Ujistěte se, že je vybrán správný UONET+ deník!</string> + <string name="login_recover_warning">Ujistěte se, že jste vybrali správnou variantu deníku UONET+!</string> <string name="login_recover_button">Zapomněl jsem své heslo</string> <string name="login_recover_title">Obnovte svůj účet</string> <string name="login_recover">Obnovit</string> @@ -326,6 +326,9 @@ <string name="teachers_title">Učitelé</string> <string name="teacher_no_items">Žádné informace o učitelích</string> <string name="teacher_no_subject">Žádný předmět</string> + <!--Conference--> + <string name="conferences_title">Setkání</string> + <string name="conference_no_items">Žádné informace o setkání</string> <!--Account--> <string name="account_add_new">Přidat účet</string> <string name="account_logout">Odhlásit se</string> @@ -452,12 +455,12 @@ <string name="update_failed">Aktualizace selhala! Wulkanowy nemusí fungovat správně. Zvažte aktualizaci</string> <!--Errors--> <string name="error_no_internet">Žádné internetové připojení</string> - <string name="error_timeout">Vypršel časový limit připojení k denik</string> - <string name="error_login_failed">Přihlášení selhalo. Zkus to znovu</string> - <string name="error_password_change_required">Je vyžadována změna hesla</string> + <string name="error_timeout">Nelze se připojit ke deníku. Servery mohou být přetíženy. Prosím zkuste to znovu později</string> + <string name="error_login_failed">Načítání dat se nezdařilo. Prosím zkuste to znovu později</string> + <string name="error_password_change_required">Je vyžadována změna hesla pro deník</string> <string name="error_service_unavailable">Probíhá údržba UONET+ deník. Zkuste to později znovu</string> <string name="error_unknown_uonet">Neznámá chyba denika UONET+. Prosím zkuste to znovu později</string> - <string name="error_unknown_app">Neznámá chyba aplikace</string> + <string name="error_unknown_app">Neznámá chyba aplikace. Prosím zkuste to znovu později</string> <string name="error_unknown">Došlo k neočekávané chybě</string> <string name="error_feature_disabled">Funkce deaktivována vaší školou</string> <string name="error_feature_not_available">Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API</string> diff --git a/app/src/main/res/values-de/preferences_values.xml b/app/src/main/res/values-de/preferences_values.xml index 2ee70f62..7226ff2d 100644 --- a/app/src/main/res/values-de/preferences_values.xml +++ b/app/src/main/res/values-de/preferences_values.xml @@ -31,8 +31,8 @@ <item>0,75</item> </string-array> <string-array name="grade_sorting_mode_entries"> - <item>Alphabetic</item> - <item>By date</item> + <item>Alphabetisch</item> + <item>Nach Datum</item> </string-array> <string-array name="grade_color_scheme_entries"> <item>Dzienniczek+</item> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 89af346c..d885261c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -22,12 +22,12 @@ <string name="grade_subtitle">Semester %1$d, %2$d/%3$d</string> <!--Login--> <string name="login_header_default">Melden Sie sich mit dem Studenten- oder Elternkonto an</string> - <string name="login_header_symbol">Geben Sie das Symbol</string> + <string name="login_header_symbol">Geben Sie das Symbol von der Registerseite ein</string> <string name="login_nickname_hint">Benutzername</string> <string name="login_email_hint">Email</string> <string name="login_login_pesel_email_hint">Anmeldung, PESEL oder e-mail</string> <string name="login_password_hint">Passwort</string> - <string name="login_host_hint">UONET+ Klassenbuch</string> + <string name="login_host_hint">UONET+ Registervariante</string> <string name="login_type_api">Mobile API</string> <string name="login_type_scrapper">Scraper</string> <string name="login_type_hybrid">Hybride</string> @@ -37,17 +37,17 @@ <string name="login_symbol_hint">Symbol</string> <string name="login_sign_in">Anmelden</string> <string name="login_invalid_password">Passwort ist zu kurz</string> - <string name="login_incorrect_password">Anmeldedaten sind falsch. Stellen Sie sicher, dass das richtige UONET+-Register ausgewählt ist</string> + <string name="login_incorrect_password">Anmeldedaten sind falsch. Stellen Sie sicher, dass die richtige UONET+ Registervariation im unteren Feld ausgewählt ist</string> <string name="login_invalid_pin">Ungültige PIN</string> <string name="login_invalid_token">Ungültige token</string> <string name="login_expired_token">Token ist nicht mehr gültig</string> <string name="login_invalid_email">Ungültige email</string> - <string name="login_invalid_login">Ungültige login</string> + <string name="login_invalid_login">Den zugewiesenen Login anstelle von email verwenden</string> <string name="login_invalid_symbol">Ungültige symbol</string> - <string name="login_incorrect_symbol">Student nicht gefunden. Überprüfen Sie das Symbol</string> + <string name="login_incorrect_symbol">Schüler nicht gefunden. Überprüfen Sie das Symbol und die gewählte Variation des UONET+ Registers</string> <string name="login_field_required">Dieses Datenfeld ist erforderlich</string> <string name="login_duplicate_student">Ausgewählter Student ist bereits angemeldet.</string> - <string name="login_symbol_helper">Das Symbol finden Sie auf der Registerseite unter <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b></string> + <string name="login_symbol_helper">Das Symbol kann auf der Registerseite in <b>Uczeń</b>→ <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>gefunden werden.\n\nStellen Sie sicher, dass Sie die entsprechende Registervariante im Feld <b>UONET+ Registervariante</b> auf dem vorherigen Bildschirm festgelegt haben. Wulkanowy erkennt zur Zeit keine Vorschulstudenten</string> <string name="login_select_student">Wählen Sie die Studenten aus, die sich bei der Anwendung anmelden sollen.</string> <string name="login_advanced">Andere Optionen</string> <string name="login_advanced_warning_mobile_api">In diesem Modus funktioniert eine Glücknummer, eine Klassenstatistik, eine Zusammenfassung der Anwesenheit, eine Entschuldigung für die Abwesenheit, abgeschlossene Lektionen, Schulinformationen und eine Vorschau der Liste der registrierten Geräte nicht</string> @@ -59,7 +59,7 @@ <string name="login_contact_discord">Discord</string> <string name="login_email_intent_title">email senden</string> <string name="login_email_details">Beschreiben Sie die Details des Problems:</string> - <string name="login_recover_warning">Stellen Sie sicher, dass das richtige UONET + Klassenbuch ausgewählt ist!</string> + <string name="login_recover_warning">Stellen Sie sicher, dass Sie die richtige UONET+ Registervariation wählen!</string> <string name="login_recover_button">Ich habe mein Passwort vergessen.</string> <string name="login_recover_title">Ihr Konto wiederherstellen</string> <string name="login_recover">Wiederherstellen</string> @@ -154,8 +154,8 @@ <string name="attendance_excused_lateness">Entschuldigte Verspätung</string> <string name="attendance_unexcused_lateness">Unentschuldigte Verspätung</string> <string name="attendance_present">Anwesend</string> - <string name="attendance_deleted">Deleted</string> - <string name="attendance_unknown">Unknown</string> + <string name="attendance_deleted">Entfernt</string> + <string name="attendance_unknown">Unbekannt</string> <string name="attendance_number">Lektion Nummer</string> <string name="attendance_no_items">Keine Einträgen</string> <plurals name="attendance_number_absences"> @@ -226,29 +226,29 @@ </plurals> <!--Praise--> <plurals name="praise_number_item"> - <item quantity="one">%d praise</item> - <item quantity="other">%d praises</item> + <item quantity="one">%d Lob</item> + <item quantity="other">%d Lob</item> </plurals> <plurals name="praise_new_items"> - <item quantity="one">New praise</item> - <item quantity="other">New praises</item> + <item quantity="one">Neues Lob</item> + <item quantity="other">Neues Lob</item> </plurals> <plurals name="praise_notify_new_items"> - <item quantity="one">You received %1$d praise</item> - <item quantity="other">You received %1$d praises</item> + <item quantity="one">Du hast %1$d Lob erhalten</item> + <item quantity="other">Du hast %1$d Lob erhalten</item> </plurals> <!--Neutral notes--> <plurals name="neutral_note_number_item"> - <item quantity="one">%d neutral note</item> - <item quantity="other">%d neutral notes</item> + <item quantity="one">%d neutrale Notiz</item> + <item quantity="other">%d neutrale Notizen</item> </plurals> <plurals name="neutral_note_new_items"> - <item quantity="one">New neutral note</item> - <item quantity="other">New neutral notes</item> + <item quantity="one">Neue neutrale Notiz</item> + <item quantity="other">Neue neutrale Notizen</item> </plurals> <plurals name="neutral_note_notify_new_items"> - <item quantity="one">You received %1$d neutral note</item> - <item quantity="other">You received %1$d neutral notes</item> + <item quantity="one">Du hast %1$d neutrale Notiz erhalten</item> + <item quantity="other">Du hast %1$d neutrale Notizen erhalten</item> </plurals> <!--Homework--> <string name="homework_no_items">Keine Informationen über Hausaufgaben</string> @@ -286,6 +286,9 @@ <string name="teachers_title">Lehrerinnen und Lehrer</string> <string name="teacher_no_items">Keine Informationen über Lehrer</string> <string name="teacher_no_subject">Kein Thema</string> + <!--Conference--> + <string name="conferences_title">Sitzungen</string> + <string name="conference_no_items">Keine Informationen über Sitzungen</string> <!--Account--> <string name="account_add_new">Konto hinzufügen</string> <string name="account_logout">Abmelden</string> @@ -355,12 +358,12 @@ <string name="pref_view_app_theme">Thema der Anwendung</string> <string name="pref_view_expand_grade">Noten erweitern</string> <string name="pref_view_timetable_show_timers">Aktuelle Lektion im Stundenplan markieren</string> - <string name="pref_view_timetable_show_groups">Show groups next to subjects in timetable</string> + <string name="pref_view_timetable_show_groups">Zeige Gruppen neben Themen im Zeitplan</string> <string name="pref_view_grade_statistics_list">Liste der Diagramme in Klassenbewertungen anzeigen</string> <string name="pref_view_timetable_show_whole_class">Unterricht der ganzen Klasse anzeigen</string> - <string name="pref_view_subjects_without_grades">Show subjects without grades in Grades</string> + <string name="pref_view_subjects_without_grades">Zeigen Sie Themen ohne Noten in Noten</string> <string name="pref_view_grade_color_scheme">Farbschema der Noten</string> - <string name="pref_view_grade_sorting_mode">Subjects sorting in \"Grades\"</string> + <string name="pref_view_grade_sorting_mode">Themen sortieren in \"Noten\"</string> <string name="pref_view_app_language">App Sprache</string> <string name="pref_notify_header">Benachrichtigungen</string> <string name="pref_notify_switch">Benachrichtigungen anzeigen</string> @@ -406,18 +409,18 @@ <string name="all_copied">Kopiert</string> <string name="all_undo">lösen</string> <!--Update helper--> - <string name="update_download_started">Download of updates has started…</string> - <string name="update_download_success">An update has just been downloaded.</string> - <string name="update_download_success_button">Restart</string> - <string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string> + <string name="update_download_started">Download der Updates wurde gestartet…</string> + <string name="update_download_success">Ein Update wurde gerade heruntergeladen.</string> + <string name="update_download_success_button">Neustart</string> + <string name="update_failed">Update fehlgeschlagen! Wulkanowy funktioniert möglicherweise nicht richtig. Überlegen Sie die Aktualisierung</string> <!--Errors--> <string name="error_no_internet">Keine Internetverbindung</string> - <string name="error_timeout">Das Zeitlimit für die Verbindung zum Klassenbuch ist abgelaufen</string> - <string name="error_login_failed">Login failed. Try again</string> - <string name="error_password_change_required">Passwortänderung erforderlich</string> + <string name="error_timeout">Registrierungsverbindung fehlgeschlagen. Server können überlastet sein. Bitte versuchen Sie es später noch einmal</string> + <string name="error_login_failed">Das Laden der Daten ist fehlgeschlagen. Bitte versuchen Sie es später noch einmal</string> + <string name="error_password_change_required">Passwortänderung für Registrierung erforderlich</string> <string name="error_service_unavailable">Wartung im Gange UONET + Klassenbuch. Versuchen Sie es später noch einmal</string> - <string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string> - <string name="error_unknown_app">Unknown application error</string> + <string name="error_unknown_uonet">Unbekannter UONET + Registerfehler. Versuchen Sie es später erneut</string> + <string name="error_unknown_app">Unbekannter Anwendungsfehler. Bitte versuchen Sie es später noch einmal</string> <string name="error_unknown">Ein unerwarteter Fehler ist aufgetreten</string> <string name="error_feature_disabled">Funktion, die von Ihrer Schule deaktiviert wurde</string> <string name="error_feature_not_available">Feature in diesem Modus nicht verfügbar</string> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 99fd05db..67f8bd1b 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -168,7 +168,7 @@ <string name="attendance_excused_lateness">Spóźnienie usprawiedliwione</string> <string name="attendance_unexcused_lateness">Spóźnienie nieusprawiedliwione</string> <string name="attendance_present">Obecność</string> - <string name="attendance_deleted">Usunięty</string> + <string name="attendance_deleted">Usunięto</string> <string name="attendance_unknown">Nieznany</string> <string name="attendance_number">Numer lekcji</string> <string name="attendance_no_items">Brak wpisów</string> @@ -326,6 +326,9 @@ <string name="teachers_title">Nauczyciele</string> <string name="teacher_no_items">Brak informacji o nauczycielach</string> <string name="teacher_no_subject">Brak przedmiotu</string> + <!--Conference--> + <string name="conferences_title">Zebrania</string> + <string name="conference_no_items">Brak informacji o zebraniach</string> <!--Account--> <string name="account_add_new">Dodaj konto</string> <string name="account_logout">Wyloguj</string> @@ -398,9 +401,9 @@ <string name="pref_view_timetable_show_groups">Pokazuj grupę obok przedmiotu na planie</string> <string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string> <string name="pref_view_timetable_show_whole_class">Pokazuj lekcje całej klasy</string> - <string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen w Oceny</string> + <string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen w Ocenach</string> <string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string> - <string name="pref_view_grade_sorting_mode">Sortowanie przedmiotów w \"Oceny\"</string> + <string name="pref_view_grade_sorting_mode">Sortowanie przedmiotów w Ocenach</string> <string name="pref_view_app_language">Język aplikacji</string> <string name="pref_notify_header">Powiadomienia</string> <string name="pref_notify_switch">Pokazuj powiadomienia</string> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7a10553d..5e260d99 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -22,12 +22,12 @@ <string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string> <!--Login--> <string name="login_header_default">Авторизируйтесь при помощи аккаунта ученика или родителя</string> - <string name="login_header_symbol">Впишите \"symbol\"</string> + <string name="login_header_symbol">Введите символ со страницы регистрации</string> <string name="login_nickname_hint">Имя пользователя</string> <string name="login_email_hint">Электронная почта</string> <string name="login_login_pesel_email_hint">Логин, PESEL или электронная почта</string> <string name="login_password_hint">Пароль</string> - <string name="login_host_hint">Дневник UONET+</string> + <string name="login_host_hint">Разновидностью бревна UONET+</string> <string name="login_type_api">Mobile API</string> <string name="login_type_scrapper">Scraper</string> <string name="login_type_hybrid">Hybrid</string> @@ -37,17 +37,17 @@ <string name="login_symbol_hint">Symbol</string> <string name="login_sign_in">Войти</string> <string name="login_invalid_password">Слишком короткий пароль</string> - <string name="login_incorrect_password">Указаны неверные данные. Убедитесь, что вы выбрали нужный дневник</string> + <string name="login_incorrect_password">Данные для входа неверны. Убедитесь, что в поле ниже выбран правильный вариант регистра UONET+</string> <string name="login_invalid_pin">Неправильный PIN</string> <string name="login_invalid_token">Неправильный token</string> <string name="login_expired_token">Токен просрочен</string> <string name="login_invalid_email">Неверный адрес электронной почты</string> - <string name="login_invalid_login">Неправильный логин</string> + <string name="login_invalid_login">Используйте назначенный логин вместо электронной почты</string> <string name="login_invalid_symbol">Неправильный symbol</string> - <string name="login_incorrect_symbol">Не удалось найти ученика. Проверьте \"symbol\"</string> + <string name="login_incorrect_symbol">Студент не найден. Подтвердите символ и выбранный вариант регистра UONET+</string> <string name="login_field_required">Обязательное поле</string> <string name="login_duplicate_student">Данный ученик уже авторизован</string> - <string name="login_symbol_helper">Вы можете найти \"symbol\" на странице VULCAN по пути <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b></string> + <string name="login_symbol_helper">Этот символ можно найти на странице регистрации в  <b>Uczeń</b> →  <b>Dostęp Mobilny</b> →  <b>Zarejestruj urządzenie mobilne</b>.\n\nУбедитесь, что вы установили соответствующий вариант регистра в поле <b>Разновидностью бревна UONET+</b> на предыдущем экране. Wulkanowy на данный момент не обнаруживает дошкольников</string> <string name="login_select_student">Выберите учеников для авторизации в приложении</string> <string name="login_advanced">Другие варианты</string> <string name="login_advanced_warning_mobile_api">В этом режиме не работают: счастливый номер, статистика класса по оценкам, статистика посещаемости и уроков, информация о школе и список зарегистрированных устройств</string> @@ -59,7 +59,7 @@ <string name="login_contact_discord">Discord</string> <string name="login_email_intent_title">Отправить письмо</string> <string name="login_email_details">Опишите детали проблемы:</string> - <string name="login_recover_warning">Убедитесь, что выбран нужный дневник!</string> + <string name="login_recover_warning">Убедитесь, что вы выбрали правильный вариант регистра UONET+!</string> <string name="login_recover_button">Забыли пароль?</string> <string name="login_recover_title">Восстановите свой аккаунт</string> <string name="login_recover">Восстановить</string> @@ -326,6 +326,9 @@ <string name="teachers_title">Учителя</string> <string name="teacher_no_items">Нет информации о учителях</string> <string name="teacher_no_subject">Нет предмета</string> + <!--Conference--> + <string name="conferences_title">Встречи</string> + <string name="conference_no_items">Нет информации о встречах</string> <!--Account--> <string name="account_add_new">Добавить аккаунт</string> <string name="account_logout">Выйти</string> @@ -446,18 +449,18 @@ <string name="all_copied">Скопировано</string> <string name="all_undo">Отменить</string> <!--Update helper--> - <string name="update_download_started">Download of updates has started…</string> - <string name="update_download_success">An update has just been downloaded.</string> - <string name="update_download_success_button">Restart</string> - <string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string> + <string name="update_download_started">Загрузка обновлений началась…</string> + <string name="update_download_success">Только что было скачано обновление.</string> + <string name="update_download_success_button">Перезапустить</string> + <string name="update_failed">Не удалось обновить! Wulkanowy может работать некорректно. Рассмотрите возможность обновления</string> <!--Errors--> <string name="error_no_internet">Нет интернет-подключения</string> - <string name="error_timeout">Слишком долгое ожидание соединения с дневником</string> - <string name="error_login_failed">Login failed. Try again</string> - <string name="error_password_change_required">Требуется смена пароля</string> + <string name="error_timeout">Не удалось подключиться к регистрации. Серверы могут быть перегружены. Пожалуйста, повторите попытку позже</string> + <string name="error_login_failed">Не удалось загрузить данные. Пожалуйста, повторите попытку позже</string> + <string name="error_password_change_required">Необходимо изменить пароль реестра</string> <string name="error_service_unavailable">Технический перерыв в журнале UONET + продолжается. Попробуйте позже</string> - <string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string> - <string name="error_unknown_app">Unknown application error</string> + <string name="error_unknown_uonet">Неизвестная ошибка UONET + регистр. Попробуйте позже</string> + <string name="error_unknown_app">Неизвестная ошибка приложения. Пожалуйста, повторите попытку позже</string> <string name="error_unknown">Произошла неожиданная ошибка</string> <string name="error_feature_disabled">Функция была выключена школой</string> <string name="error_feature_not_available">Функция не доступна в этом режиме</string> diff --git a/app/src/main/res/values-uk/preferences_values.xml b/app/src/main/res/values-uk/preferences_values.xml index 0ff8bfd0..02b6ccf8 100644 --- a/app/src/main/res/values-uk/preferences_values.xml +++ b/app/src/main/res/values-uk/preferences_values.xml @@ -31,8 +31,8 @@ <item>0,75</item> </string-array> <string-array name="grade_sorting_mode_entries"> - <item>Alphabetic</item> - <item>By date</item> + <item>За алфавітом</item> + <item>За датою</item> </string-array> <string-array name="grade_color_scheme_entries"> <item>Dzienniczek+</item> @@ -41,8 +41,8 @@ </string-array> <string-array name="grade_average_mode_entries"> <item>Середня оцінка з 2 семестру</item> - <item>Average of grades from both semesters</item> - <item>Average of grades from the whole year</item> + <item>Середнє оцінювання за обидва семестри</item> + <item>Середнє оцінювання за весь рік</item> </string-array> <string-array name="timetable_show_whole_class_entries"> <item>Не показувати</item> diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4a15db9f..48da2784 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -22,12 +22,12 @@ <string name="grade_subtitle">%1$d семестр, %2$d/%3$d</string> <!--Login--> <string name="login_header_default">Авторизуйтеся за допомогою аккаунта учня або батька</string> - <string name="login_header_symbol">Впишіть \"symbol\"</string> + <string name="login_header_symbol">Введіть символ зі сторінки реєстру</string> <string name="login_nickname_hint">Ім\'я користувача</string> <string name="login_email_hint">Електронна пошта</string> <string name="login_login_pesel_email_hint">Логін, PESEL або електронна пошта</string> <string name="login_password_hint">Пароль</string> - <string name="login_host_hint">Щоденник</string> + <string name="login_host_hint">UONET + варіант реєстрації</string> <string name="login_type_api">Мobile API</string> <string name="login_type_scrapper">Scraper</string> <string name="login_type_hybrid">Hybrid</string> @@ -37,17 +37,17 @@ <string name="login_symbol_hint">Symbol</string> <string name="login_sign_in">Увійти</string> <string name="login_invalid_password">Занадто короткий пароль</string> - <string name="login_incorrect_password">Вказані невірні дані. Впевніться, що ви увібрали потрібний щоденник</string> + <string name="login_incorrect_password">Дані для входу неправильні. Переконайтеся, що у полі нижче вказано правильний варіант реєстрації UONET+</string> <string name="login_invalid_pin">Неправильний PIN</string> <string name="login_invalid_token">Неправильний token</string> <string name="login_expired_token">Минув термін дії токену</string> <string name="login_invalid_email">Недійсна адреса електронної пошти</string> - <string name="login_invalid_login">Неправильний логін</string> + <string name="login_invalid_login">Використовуйте призначений логін замість електронної пошти</string> <string name="login_invalid_symbol">Неправильний symbol</string> - <string name="login_incorrect_symbol">Не вдалося знайти учня. Будь ласка, перевірте \"symbol\"</string> + <string name="login_incorrect_symbol">Студента не знайдено Перевірте символ та обраний варіант реєстру UONET+</string> <string name="login_field_required">Обов\'язкове поле</string> <string name="login_duplicate_student">Даного учня вже авторизовано</string> - <string name="login_symbol_helper">Ви можете знайти \"symbol\" на сторінцi VULCAN стежкою <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b></string> + <string name="login_symbol_helper">Символ можна знайти на сторінці реєстру в   <b> Uczeń </b> →   <b> Dostęp Mobilny </b> →   <b> Zarejestruj urządzenie mobilne </b>.\n\nПереконайтесь, що ви встановили відповідний варіант реєстру в полі <b> UONET + варіант реєстрації </b> на попередньому екрані. На даний момент Wulkanowy не виявляє учнів дошкільних закладів</string> <string name="login_select_student">Виберіть учнів для авторизації в додатку</string> <string name="login_advanced">Інші варіанти</string> <string name="login_advanced_warning_mobile_api">У цьому режимі не працюють: щасливий номер, статистика класу по оцінкам, статистика відвідуваності і уроків, інформація про школу і список зареєстрованних пристроїв</string> @@ -59,7 +59,7 @@ <string name="login_contact_discord">Discord</string> <string name="login_email_intent_title">Відправити лист</string> <string name="login_email_details">Опишіть деталі помилки:</string> - <string name="login_recover_warning">Переконайтесь, що обрано потрібний щоденник!</string> + <string name="login_recover_warning">Переконайтеся, що ви вибрали правильний варіант реєстрації UONET+!</string> <string name="login_recover_button">Забули пароль?</string> <string name="login_recover_title">Відновіть свій аккаунт</string> <string name="login_recover">Відновити</string> @@ -108,16 +108,16 @@ <item quantity="other">Нові оцінки</item> </plurals> <plurals name="grade_new_items_predicted"> - <item quantity="one">New predicted grade</item> - <item quantity="few">New predicted grades</item> - <item quantity="many">New predicted grades</item> - <item quantity="other">New predicted grades</item> + <item quantity="one">Нова прогнозована оцінка</item> + <item quantity="few">Нові прогнозовані оцінки</item> + <item quantity="many">Нові прогнозовані оцінки</item> + <item quantity="other">Нові прогнозовані оцінки</item> </plurals> <plurals name="grade_new_items_final"> - <item quantity="one">New final grade</item> - <item quantity="few">New final grades</item> - <item quantity="many">New final grades</item> - <item quantity="other">New final grades</item> + <item quantity="one">Нова підсумкова оцінка</item> + <item quantity="few">Нові підсумкові оцінки</item> + <item quantity="many">Нові підсумкові оцінки</item> + <item quantity="other">Нові підсумкові оцінки</item> </plurals> <plurals name="grade_notify_new_items"> <item quantity="one">Ви отримали %1$d оцінку</item> @@ -126,16 +126,16 @@ <item quantity="other">Ви отримали %1$d оцінок</item> </plurals> <plurals name="grade_notify_new_items_predicted"> - <item quantity="one">You received %1$d predicted grade</item> - <item quantity="few">You received %1$d predicted grades</item> - <item quantity="many">You received %1$d predicted grades</item> - <item quantity="other">You received %1$d predicted grades</item> + <item quantity="one">Ви отримали %1$d нову прогнозовану оцінку</item> + <item quantity="few">Ви отримали %1$d нові прогнозовані оцінки</item> + <item quantity="many">Ви отримали %1$d нових прогнозованих оцінок</item> + <item quantity="other">Ви отримали %1$d нових прогнозованих оцінок</item> </plurals> <plurals name="grade_notify_new_items_final"> - <item quantity="one">You received %1$d final grade</item> - <item quantity="few">You received %1$d final grades</item> - <item quantity="many">You received %1$d final grades</item> - <item quantity="other">You received %1$d final grades</item> + <item quantity="one">Ви отримали %1$d нову підсумкову оцінку</item> + <item quantity="few">Ви отримали %1$d нові підсумкові оцінки</item> + <item quantity="many">Ви отримали %1$d нових підсумкових оцінок</item> + <item quantity="other">Ви отримали %1$d нових підсумкових оцінок</item> </plurals> <!--Timetable--> <string name="timetable_lesson">Урок</string> @@ -168,8 +168,8 @@ <string name="attendance_excused_lateness">Спізнення з поважних причин</string> <string name="attendance_unexcused_lateness">Спізнення з не поважних причин</string> <string name="attendance_present">Присутність</string> - <string name="attendance_deleted">Deleted</string> - <string name="attendance_unknown">Unknown</string> + <string name="attendance_deleted">Вилучено</string> + <string name="attendance_unknown">Невідомо</string> <string name="attendance_number">Номер уроку</string> <string name="attendance_no_items">Брак записів</string> <plurals name="attendance_number_absences"> @@ -206,8 +206,8 @@ <string name="message_move_to_bin">Перемістити у кошик</string> <string name="message_delete_forever">Видалити назавжди</string> <string name="message_delete_success">Повідомлення було успішно видалено</string> - <string name="message_share">Share</string> - <string name="message_print">Print</string> + <string name="message_share">Поділіться</string> + <string name="message_print">Друк</string> <string name="message_subject">Тема</string> <string name="message_content">Зміст</string> <string name="message_send_successful">Повідомлення було успішно відправлено</string> @@ -254,41 +254,41 @@ </plurals> <!--Praise--> <plurals name="praise_number_item"> - <item quantity="one">%d praise</item> - <item quantity="few">%d praises</item> - <item quantity="many">%d praises</item> - <item quantity="other">%d praises</item> + <item quantity="one">%d похвалили</item> + <item quantity="few">%d похвали</item> + <item quantity="many">%d похвал</item> + <item quantity="other">%d похвал</item> </plurals> <plurals name="praise_new_items"> - <item quantity="one">New praise</item> - <item quantity="few">New praises</item> - <item quantity="many">New praises</item> - <item quantity="other">New praises</item> + <item quantity="one">Нова похвала</item> + <item quantity="few">Нові похвали</item> + <item quantity="many">Нові похвали</item> + <item quantity="other">Нові похвали</item> </plurals> <plurals name="praise_notify_new_items"> - <item quantity="one">You received %1$d praise</item> - <item quantity="few">You received %1$d praises</item> - <item quantity="many">You received %1$d praises</item> - <item quantity="other">You received %1$d praises</item> + <item quantity="one">Ви отримали %1$d нову похвалу</item> + <item quantity="few">Ви отримали %1$d нові похвали</item> + <item quantity="many">Ви отримали %1$d нових похвал</item> + <item quantity="other">Ви отримали %1$d нових похвал</item> </plurals> <!--Neutral notes--> <plurals name="neutral_note_number_item"> - <item quantity="one">%d neutral note</item> - <item quantity="few">%d neutral notes</item> - <item quantity="many">%d neutral notes</item> - <item quantity="other">%d neutral notes</item> + <item quantity="one">%d нейтральна нота</item> + <item quantity="few">%d нейтральні ноти</item> + <item quantity="many">%d нейтральних нот</item> + <item quantity="other">%d нейтральних нот</item> </plurals> <plurals name="neutral_note_new_items"> - <item quantity="one">New neutral note</item> - <item quantity="few">New neutral notes</item> - <item quantity="many">New neutral notes</item> - <item quantity="other">New neutral notes</item> + <item quantity="one">Нова нейтральна нота</item> + <item quantity="few">Нова нейтральна нота</item> + <item quantity="many">Нова нейтральна нота</item> + <item quantity="other">Нові нейтральні ноти</item> </plurals> <plurals name="neutral_note_notify_new_items"> - <item quantity="one">You received %1$d neutral note</item> - <item quantity="few">You received %1$d neutral notes</item> - <item quantity="many">You received %1$d neutral notes</item> - <item quantity="other">You received %1$d neutral notes</item> + <item quantity="one">Ви отримали %1$d нову нейтральну ноту</item> + <item quantity="few">Ви отримали %1$d нові нейтральні ноти</item> + <item quantity="many">Ви отримали %1$d нових нейтральних нот</item> + <item quantity="other">Ви отримали %1$d нових нейтральних нот</item> </plurals> <!--Homework--> <string name="homework_no_items">Брак домашніх завдань</string> @@ -326,15 +326,18 @@ <string name="teachers_title">Вчителі</string> <string name="teacher_no_items">Брак інформації про вчителів</string> <string name="teacher_no_subject">Брак предмету</string> + <!--Conference--> + <string name="conferences_title">Зустрічі</string> + <string name="conference_no_items">Немає інформації про зустрічі</string> <!--Account--> <string name="account_add_new">Додати аккаунт</string> <string name="account_logout">Вийти</string> <string name="account_confirm">Ви впевнені, що хочете вийти з цього аккаунту?</string> <string name="account_logout_student">Вийти з аккаунту учня</string> - <string name="account_type_student">Student account</string> - <string name="account_type_parent">Parent account</string> - <string name="account_login_mobile_api">Mobile API mode</string> - <string name="account_login_hybrid">Hybrid mode</string> + <string name="account_type_student">Студентський рахунок</string> + <string name="account_type_parent">Головний рахунок</string> + <string name="account_login_mobile_api">Режим мобільного API</string> + <string name="account_login_hybrid">Гібридний режим</string> <!--About--> <string name="about_version">Версія додатка</string> <string name="about_contributor">Розробники</string> @@ -395,12 +398,12 @@ <string name="pref_view_app_theme">Тема додатку</string> <string name="pref_view_expand_grade">Більше оцінок</string> <string name="pref_view_timetable_show_timers">Позначити поточний урок у розкладі</string> - <string name="pref_view_timetable_show_groups">Show groups next to subjects in timetable</string> + <string name="pref_view_timetable_show_groups">Покажіть групи поруч із предметами в розкладі</string> <string name="pref_view_grade_statistics_list">Показувати діаграми в оцінках класу</string> <string name="pref_view_timetable_show_whole_class">Показати уроки всього класу</string> - <string name="pref_view_subjects_without_grades">Show subjects without grades in Grades</string> + <string name="pref_view_subjects_without_grades">Показуйте предмети без оцінок у оцінках</string> <string name="pref_view_grade_color_scheme">Схема кольорів оцінок</string> - <string name="pref_view_grade_sorting_mode">Subjects sorting in \"Grades\"</string> + <string name="pref_view_grade_sorting_mode">Сортування предметів за \"Оцінками\"</string> <string name="pref_view_app_language">Мова додатку</string> <string name="pref_notify_header">Повідомлення</string> <string name="pref_notify_switch">Показувати повідомлення</string> @@ -446,18 +449,18 @@ <string name="all_copied">Скопійовано</string> <string name="all_undo">Відмінити</string> <!--Update helper--> - <string name="update_download_started">Download of updates has started…</string> - <string name="update_download_success">An update has just been downloaded.</string> - <string name="update_download_success_button">Restart</string> - <string name="update_failed">Update failed! Wulkanowy may not function properly. Consider updating</string> + <string name="update_download_started">Завантаження оновлень розпочато…</string> + <string name="update_download_success">Щойно завантажено оновлення.</string> + <string name="update_download_success_button">Перезапустити</string> + <string name="update_failed">Помилка оновлення! Wulkanowy може не працювати належним чином. Подумайте про оновлення</string> <!--Errors--> <string name="error_no_internet">Брак з\'єднання з інтернетом</string> - <string name="error_timeout">Занадто довге очікування з\'єднання з щоденником</string> - <string name="error_login_failed">Login failed. Try again</string> - <string name="error_password_change_required">Потрібно змінити пароль</string> + <string name="error_timeout">Помилка підключення до реєстрації. Сервери можуть бути перевантажені. Будь-ласка спробуйте пізніше</string> + <string name="error_login_failed">Помилка завантаження даних. Будь-ласка спробуйте пізніше</string> + <string name="error_password_change_required">Потрібна реєстрація зміни пароля</string> <string name="error_service_unavailable">Технічна перерва в журналі UONET + продовжується. Спробуйте пізніше</string> - <string name="error_unknown_uonet">Unknown UONET + register error. Try again later</string> - <string name="error_unknown_app">Unknown application error</string> + <string name="error_unknown_uonet">Невідома помилка реєстру UONET+. Спробуйте ще раз пізніше</string> + <string name="error_unknown_app">Невідома помилка програми. Будь-ласка спробуйте пізніше</string> <string name="error_unknown">Відбулася несподівана помилка</string> <string name="error_feature_disabled">Функція вимкнена школою</string> <string name="error_feature_not_available">Функція не доступна в цьому режимі</string> From a1ebf6c6ad806960504265f9e7095a3ec0c73a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= <m.pich@outlook.com> Date: Wed, 11 Nov 2020 16:03:52 +0100 Subject: [PATCH 12/34] Add average in class grades statistics (#1017) --- app/build.gradle | 2 +- .../29.json | 1898 +++++++++++++++++ .../GradeStatisticsLocalTest.kt | 30 +- .../github/wulkanowy/utils/CrashLogUtils.kt | 2 +- .../github/wulkanowy/data/RepositoryModule.kt | 8 +- .../github/wulkanowy/data/db/AppDatabase.kt | 19 +- .../data/db/dao/GradePartialStatisticsDao.kt | 13 + .../data/db/dao/GradeSemesterStatisticsDao.kt | 13 + .../data/db/dao/GradeStatisticsDao.kt | 18 - .../db/entities/GradePartialStatistics.kt | 33 + ...atistics.kt => GradeSemesterStatistics.kt} | 15 +- .../data/db/migrations/Migration29.kt | 33 + .../data/pojos/GradeStatisticsItem.kt | 9 +- .../gradestatistics/GradeStatisticsLocal.kt | 52 +- .../gradestatistics/GradeStatisticsRemote.kt | 49 +- .../GradeStatisticsRepository.kt | 116 +- .../sync/works/GradeStatisticsWork.kt | 4 +- .../statistics/GradeStatisticsAdapter.kt | 58 +- .../statistics/GradeStatisticsPresenter.kt | 15 +- .../GradeStatisticsRemoteTest.kt | 28 +- 20 files changed, 2270 insertions(+), 145 deletions(-) create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt delete mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt rename app/src/main/java/io/github/wulkanowy/data/db/entities/{GradeStatistics.kt => GradeSemesterStatistics.kt} (61%) create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt diff --git a/app/build.gradle b/app/build.gradle index ddb63d47..0afaab01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,7 +142,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:0.22.2" + implementation "io.github.wulkanowy:sdk:bcf6b53" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json new file mode 100644 index 00000000..3e863c57 --- /dev/null +++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/29.json @@ -0,0 +1,1898 @@ +{ + "formatVersion": 1, + "database": { + "version": 29, + "identityHash": "30e4647c7dd84a6ac9b2f9f3ef7d3264", + "entities": [ + { + "tableName": "Students", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scrapperBaseUrl", + "columnName": "scrapper_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mobileBaseUrl", + "columnName": "mobile_base_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginType", + "columnName": "login_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginMode", + "columnName": "login_mode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificateKey", + "columnName": "certificate_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "privateKey", + "columnName": "private_key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isParent", + "columnName": "is_parent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userLoginId", + "columnName": "user_login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userName", + "columnName": "user_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentName", + "columnName": "student_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolSymbol", + "columnName": "school_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolShortName", + "columnName": "school_short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolName", + "columnName": "school_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "className", + "columnName": "class_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCurrent", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "registrationDate", + "columnName": "registration_date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Students_email_symbol_student_id_school_id_class_id", + "unique": true, + "columnNames": [ + "email", + "symbol", + "student_id", + "school_id", + "class_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Semesters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "current", + "columnName": "is_current", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryName", + "columnName": "diary_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "schoolYear", + "columnName": "school_year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterName", + "columnName": "semester_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_Semesters_student_id_diary_id_semester_id", + "unique": true, + "columnNames": [ + "student_id", + "diary_id", + "semester_id" + ], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `semester_id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "Exams", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Timetable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subjectOld", + "columnName": "subjectOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "room", + "columnName": "room", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roomOld", + "columnName": "roomOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherOld", + "columnName": "teacherOld", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "info", + "columnName": "info", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isStudentPlan", + "columnName": "student_plan", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "changes", + "columnName": "changes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canceled", + "columnName": "canceled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Attendance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timeId", + "columnName": "time_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excused", + "columnName": "excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excusable", + "columnName": "excusable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "excuseStatus", + "columnName": "excuse_status", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "AttendanceSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subjectId", + "columnName": "subject_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "month", + "columnName": "month", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "presence", + "columnName": "presence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceExcused", + "columnName": "absence_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "absenceForSchoolReasons", + "columnName": "absence_for_school_reasons", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lateness", + "columnName": "lateness", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latenessExcused", + "columnName": "lateness_excused", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exemption", + "columnName": "exemption", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Grades", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entry", + "columnName": "entry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "modifier", + "columnName": "modifier", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gradeSymbol", + "columnName": "grade_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weightValue", + "columnName": "weightValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesSummary", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPredictedGradeNotified", + "columnName": "is_predicted_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isFinalGradeNotified", + "columnName": "is_final_grade_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "predictedGradeLastChange", + "columnName": "predicted_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "finalGradeLastChange", + "columnName": "final_grade_last_change", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "predictedGrade", + "columnName": "predicted_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalGrade", + "columnName": "final_grade", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "proposedPoints", + "columnName": "proposed_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "finalPoints", + "columnName": "final_points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pointsSum", + "columnName": "points_sum", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "average", + "columnName": "average", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradePartialStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classAverage", + "columnName": "class_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAverage", + "columnName": "student_average", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "classAmounts", + "columnName": "class_amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentAmounts", + "columnName": "student_amounts", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradesPointsStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "others", + "columnName": "others", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "student", + "columnName": "student", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "GradeSemesterStatistics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "amounts", + "columnName": "amounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentGrade", + "columnName": "student_grade", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Messages", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `unread_by` INTEGER NOT NULL, `read_by` INTEGER NOT NULL, `content` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `recipient_name` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `removed` INTEGER NOT NULL, `has_attachments` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadBy", + "columnName": "unread_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "readBy", + "columnName": "read_by", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipient", + "columnName": "recipient_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folderId", + "columnName": "folder_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "removed", + "columnName": "removed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hasAttachments", + "columnName": "has_attachments", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MessageAttachments", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_id` INTEGER NOT NULL, `one_drive_id` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))", + "fields": [ + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "messageId", + "columnName": "message_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "oneDriveId", + "columnName": "one_drive_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filename", + "columnName": "filename", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "real_id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Notes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isRead", + "columnName": "is_read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "categoryType", + "columnName": "category_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPointsShow", + "columnName": "is_points_show", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Homework", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isDone", + "columnName": "is_done", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "semesterId", + "columnName": "semester_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "entryDate", + "columnName": "entry_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Subjects", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LuckyNumbers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isNotified", + "columnName": "is_notified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "luckyNumber", + "columnName": "lucky_number", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CompletedLesson", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacher", + "columnName": "teacher", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "teacherSymbol", + "columnName": "teacher_symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "substitution", + "columnName": "substitution", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "absence", + "columnName": "absence", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "resources", + "columnName": "resources", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ReportingUnits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `short` TEXT NOT NULL, `sender_id` INTEGER NOT NULL, `sender_name` TEXT NOT NULL, `roles` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "sender_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "senderName", + "columnName": "sender_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Recipients", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `real_id` TEXT NOT NULL, `name` TEXT NOT NULL, `real_name` TEXT NOT NULL, `login_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `role` INTEGER NOT NULL, `hash` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "realId", + "columnName": "real_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "realName", + "columnName": "real_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "loginId", + "columnName": "login_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unitId", + "columnName": "unit_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MobileDevices", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deviceId", + "columnName": "device_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Teachers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortName", + "columnName": "short_name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "School", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "classId", + "columnName": "class_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contact", + "columnName": "contact", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "headmaster", + "columnName": "headmaster", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pedagogue", + "columnName": "pedagogue", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Conferences", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "studentId", + "columnName": "student_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "diaryId", + "columnName": "diary_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "agenda", + "columnName": "agenda", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "presentOnConference", + "columnName": "present_on_conference", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "conferenceId", + "columnName": "conference_id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '30e4647c7dd84a6ac9b2f9f3ef7d3264')" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt index 197d2d0e..db083432 100644 --- a/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt +++ b/app/src/androidTest/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocalTest.kt @@ -4,8 +4,8 @@ import androidx.room.Room import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import io.github.wulkanowy.data.db.AppDatabase +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics import io.github.wulkanowy.data.db.entities.Semester import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking @@ -27,7 +27,7 @@ class GradeStatisticsLocalTest { fun createDb() { testDb = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java) .build() - gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradeStatistics, testDb.gradePointsStatistics) + gradeStatisticsLocal = GradeStatisticsLocal(testDb.gradePartialStatisticsDao, testDb.gradePointsStatisticsDao, testDb.gradeSemesterStatisticsDao) } @After @@ -41,9 +41,9 @@ class GradeStatisticsLocalTest { getGradeStatistics("Matematyka", 2, 1), getGradeStatistics("Fizyka", 1, 2) ) - runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) } + runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) } - val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() } + val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() } assertEquals(1, stats.size) assertEquals(stats[0].subject, "Matematyka") } @@ -55,12 +55,10 @@ class GradeStatisticsLocalTest { getGradeStatistics("Chemia", 2, 1), getGradeStatistics("Fizyka", 1, 2) ) - runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) } + runBlocking { gradeStatisticsLocal.saveGradePartialStatistics(list) } - val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() } + val stats = runBlocking { gradeStatisticsLocal.getGradePartialStatistics(getSemester()).first() } assertEquals(2, stats.size) -// assertEquals(3, stats.size) -// assertEquals(stats[0].subject, "Wszystkie") // now in main repo assertEquals(stats[0].subject, "Matematyka") assertEquals(stats[1].subject, "Chemia") } @@ -72,9 +70,9 @@ class GradeStatisticsLocalTest { getGradePointsStatistics("Chemia", 2, 1), getGradePointsStatistics("Fizyka", 1, 2) ) - runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) } + runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(list) } - val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } + val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } with(stats[0]) { assertEquals(subject, "Matematyka") assertEquals(others, 5.0) @@ -84,17 +82,17 @@ class GradeStatisticsLocalTest { @Test fun saveAndRead_subjectEmpty() { - runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) } + runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) } - val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } + val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } assertEquals(emptyList(), stats) } @Test fun saveAndRead_allEmpty() { - runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) } + runBlocking { gradeStatisticsLocal.saveGradePointsStatistics(listOf()) } - val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() } + val stats = runBlocking { gradeStatisticsLocal.getGradePointsStatistics(getSemester()).first() } assertEquals(emptyList(), stats) } @@ -102,8 +100,8 @@ class GradeStatisticsLocalTest { return Semester(2, 2, "", 2019, 1, 2, now(), now(), 1, 1) } - private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradeStatistics { - return GradeStatistics(studentId, semesterId, subject, 5, 5, false) + private fun getGradeStatistics(subject: String, studentId: Int, semesterId: Int): GradePartialStatistics { + return GradePartialStatistics(studentId, semesterId, subject, "", "", listOf(5), listOf(5)) } private fun getGradePointsStatistics(subject: String, studentId: Int, semesterId: Int): GradePointsStatistics { diff --git a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt index 7f4bedae..8adf2b29 100644 --- a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt +++ b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt @@ -42,7 +42,7 @@ class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) { connectCrash.setCustomKey("priority", priority) connectCrash.setCustomKey("tag", tag.orEmpty()) connectCrash.setCustomKey("message", message) - connectCrash.log(priority, t?.stackTraceToString()) + if (t != null) { connectCrash.log(priority, t.stackTraceToString()) } else { diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index 50642ddd..5efe7773 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -85,11 +85,15 @@ internal class RepositoryModule { @Singleton @Provides - fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics + fun provideGradePartialStatisticsDao(database: AppDatabase) = database.gradePartialStatisticsDao @Singleton @Provides - fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics + fun provideGradeSemesterStatisticsDao(database: AppDatabase) = database.gradeSemesterStatisticsDao + + @Singleton + @Provides + fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatisticsDao @Singleton @Provides diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt index 93f22542..57160a2b 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt @@ -13,8 +13,9 @@ import io.github.wulkanowy.data.db.dao.CompletedLessonsDao import io.github.wulkanowy.data.db.dao.ConferenceDao import io.github.wulkanowy.data.db.dao.ExamDao import io.github.wulkanowy.data.db.dao.GradeDao +import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeStatisticsDao +import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao import io.github.wulkanowy.data.db.dao.GradeSummaryDao import io.github.wulkanowy.data.db.dao.HomeworkDao import io.github.wulkanowy.data.db.dao.LuckyNumberDao @@ -36,8 +37,9 @@ import io.github.wulkanowy.data.db.entities.CompletedLesson import io.github.wulkanowy.data.db.entities.Conference import io.github.wulkanowy.data.db.entities.Exam import io.github.wulkanowy.data.db.entities.Grade +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.GradeSummary import io.github.wulkanowy.data.db.entities.Homework import io.github.wulkanowy.data.db.entities.LuckyNumber @@ -73,6 +75,7 @@ import io.github.wulkanowy.data.db.migrations.Migration25 import io.github.wulkanowy.data.db.migrations.Migration26 import io.github.wulkanowy.data.db.migrations.Migration27 import io.github.wulkanowy.data.db.migrations.Migration28 +import io.github.wulkanowy.data.db.migrations.Migration29 import io.github.wulkanowy.data.db.migrations.Migration3 import io.github.wulkanowy.data.db.migrations.Migration4 import io.github.wulkanowy.data.db.migrations.Migration5 @@ -93,8 +96,9 @@ import javax.inject.Singleton AttendanceSummary::class, Grade::class, GradeSummary::class, - GradeStatistics::class, + GradePartialStatistics::class, GradePointsStatistics::class, + GradeSemesterStatistics::class, Message::class, MessageAttachment::class, Note::class, @@ -116,7 +120,7 @@ import javax.inject.Singleton abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION_SCHEMA = 28 + const val VERSION_SCHEMA = 29 fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> { return arrayOf( @@ -147,6 +151,7 @@ abstract class AppDatabase : RoomDatabase() { Migration26(), Migration27(), Migration28(), + Migration29() ) } @@ -176,9 +181,11 @@ abstract class AppDatabase : RoomDatabase() { abstract val gradeSummaryDao: GradeSummaryDao - abstract val gradeStatistics: GradeStatisticsDao + abstract val gradePartialStatisticsDao: GradePartialStatisticsDao - abstract val gradePointsStatistics: GradePointsStatisticsDao + abstract val gradePointsStatisticsDao: GradePointsStatisticsDao + + abstract val gradeSemesterStatisticsDao: GradeSemesterStatisticsDao abstract val messagesDao: MessagesDao diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt new file mode 100644 index 00000000..bce6ce57 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt @@ -0,0 +1,13 @@ +package io.github.wulkanowy.data.db.dao + +import androidx.room.Dao +import androidx.room.Query +import io.github.wulkanowy.data.db.entities.GradePartialStatistics +import kotlinx.coroutines.flow.Flow + +@Dao +interface GradePartialStatisticsDao : BaseDao<GradePartialStatistics> { + + @Query("SELECT * FROM GradePartialStatistics WHERE student_id = :studentId AND semester_id = :semesterId") + fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradePartialStatistics>> +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt new file mode 100644 index 00000000..09ae8171 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt @@ -0,0 +1,13 @@ +package io.github.wulkanowy.data.db.dao + +import androidx.room.Dao +import androidx.room.Query +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics +import kotlinx.coroutines.flow.Flow + +@Dao +interface GradeSemesterStatisticsDao : BaseDao<GradeSemesterStatistics> { + + @Query("SELECT * FROM GradeSemesterStatistics WHERE student_id = :studentId AND semester_id = :semesterId") + fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradeSemesterStatistics>> +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt deleted file mode 100644 index b462ad5d..00000000 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.wulkanowy.data.db.dao - -import androidx.room.Dao -import androidx.room.Query -import io.github.wulkanowy.data.db.entities.GradeStatistics -import kotlinx.coroutines.flow.Flow -import javax.inject.Singleton - -@Singleton -@Dao -interface GradeStatisticsDao : BaseDao<GradeStatistics> { - - @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester") - fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Flow<List<GradeStatistics>> - - @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester") - fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Flow<List<GradeStatistics>> -} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt new file mode 100644 index 00000000..db164afd --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt @@ -0,0 +1,33 @@ +package io.github.wulkanowy.data.db.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "GradePartialStatistics") +data class GradePartialStatistics( + + @ColumnInfo(name = "student_id") + val studentId: Int, + + @ColumnInfo(name = "semester_id") + val semesterId: Int, + + val subject: String, + + @ColumnInfo(name = "class_average") + val classAverage: String, + + @ColumnInfo(name = "student_average") + val studentAverage: String, + + @ColumnInfo(name = "class_amounts") + val classAmounts: List<Int>, + + @ColumnInfo(name = "student_amounts") + val studentAmounts: List<Int> + +) { + @PrimaryKey(autoGenerate = true) + var id: Long = 0 +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt similarity index 61% rename from app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt rename to app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt index 8ad8b8b8..e747271c 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt @@ -4,8 +4,8 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -@Entity(tableName = "GradesStatistics") -data class GradeStatistics( +@Entity(tableName = "GradeSemesterStatistics") +data class GradeSemesterStatistics( @ColumnInfo(name = "student_id") val studentId: Int, @@ -15,13 +15,14 @@ data class GradeStatistics( val subject: String, - val grade: Int, + val amounts: List<Int>, - val amount: Int, - - @ColumnInfo(name = "is_semester") - val semester: Boolean + @ColumnInfo(name = "student_grade") + val studentGrade: Int ) { @PrimaryKey(autoGenerate = true) var id: Long = 0 + + @Transient + var average: String = "" } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt new file mode 100644 index 00000000..327552d7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt @@ -0,0 +1,33 @@ +package io.github.wulkanowy.data.db.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration29 : Migration(28, 29) { + + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE IF EXISTS GradesStatistics") + database.execSQL(""" + CREATE TABLE IF NOT EXISTS GradeSemesterStatistics ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + student_id INTEGER NOT NULL, + semester_id INTEGER NOT NULL, + subject TEXT NOT NULL, + amounts TEXT NOT NULL, + student_grade INTEGER NOT NULL + ) + """) + database.execSQL(""" + CREATE TABLE IF NOT EXISTS GradePartialStatistics ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + student_id INTEGER NOT NULL, + semester_id INTEGER NOT NULL, + subject TEXT NOT NULL, + class_average TEXT NOT NULL, + student_average TEXT NOT NULL, + class_amounts TEXT NOT NULL, + student_amounts TEXT NOT NULL + ) + """) + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt b/app/src/main/java/io/github/wulkanowy/data/pojos/GradeStatisticsItem.kt index 34b62abd..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 @@ -1,14 +1,19 @@ package io.github.wulkanowy.data.pojos +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.ui.modules.grade.statistics.ViewType data class GradeStatisticsItem( val type: ViewType, - val partial: List<GradeStatistics>, + val average: String, + + val partial: GradePartialStatistics?, + + val semester: GradeSemesterStatistics?, val points: GradePointsStatistics? ) diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt index e0e2cd4d..3e3c819f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsLocal.kt @@ -1,9 +1,11 @@ package io.github.wulkanowy.data.repositories.gradestatistics +import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao -import io.github.wulkanowy.data.db.dao.GradeStatisticsDao +import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.Semester import kotlinx.coroutines.flow.Flow import javax.inject.Inject @@ -11,31 +13,47 @@ import javax.inject.Singleton @Singleton class GradeStatisticsLocal @Inject constructor( - private val gradeStatisticsDb: GradeStatisticsDao, - private val gradePointsStatisticsDb: GradePointsStatisticsDao + private val gradePartialStatisticsDb: GradePartialStatisticsDao, + private val gradePointsStatisticsDb: GradePointsStatisticsDao, + private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao ) { - fun getGradesStatistics(semester: Semester, isSemester: Boolean): Flow<List<GradeStatistics>> { - return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester) + // partial + fun getGradePartialStatistics(semester: Semester): Flow<List<GradePartialStatistics>> { + return gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) } - fun getGradesPointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> { + suspend fun saveGradePartialStatistics(items: List<GradePartialStatistics>) { + gradePartialStatisticsDb.insertAll(items) + } + + suspend fun deleteGradePartialStatistics(items: List<GradePartialStatistics>) { + gradePartialStatisticsDb.deleteAll(items) + } + + // points + fun getGradePointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> { return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) } - suspend fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) { - gradeStatisticsDb.insertAll(gradesStatistics) - } - - suspend fun saveGradesPointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) { + suspend fun saveGradePointsStatistics(gradePointsStatistics: List<GradePointsStatistics>) { gradePointsStatisticsDb.insertAll(gradePointsStatistics) } - suspend fun deleteGradesStatistics(gradesStatistics: List<GradeStatistics>) { - gradeStatisticsDb.deleteAll(gradesStatistics) - } - - suspend fun deleteGradesPointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) { + suspend fun deleteGradePointsStatistics(gradesPointsStatistics: List<GradePointsStatistics>) { gradePointsStatisticsDb.deleteAll(gradesPointsStatistics) } + + // semester + fun getGradeSemesterStatistics(semester: Semester): Flow<List<GradeSemesterStatistics>> { + return gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) + } + + suspend fun saveGradeSemesterStatistics(items: List<GradeSemesterStatistics>) { + gradeSemesterStatisticsDb.insertAll(items) + } + + suspend fun deleteGradeSemesterStatistics(items: List<GradeSemesterStatistics>) { + gradeSemesterStatisticsDb.deleteAll(items) + } } diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt index 1ff8132f..144df8a0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemote.kt @@ -1,7 +1,8 @@ package io.github.wulkanowy.data.repositories.gradestatistics +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.sdk.Sdk @@ -12,20 +13,38 @@ import javax.inject.Singleton @Singleton class GradeStatisticsRemote @Inject constructor(private val sdk: Sdk) { - suspend fun getGradeStatistics(student: Student, semester: Semester, isSemester: Boolean): List<GradeStatistics> { - return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).let { - if (isSemester) it.getGradesAnnualStatistics(semester.semesterId) - else it.getGradesPartialStatistics(semester.semesterId) - }.map { - GradeStatistics( - semesterId = semester.semesterId, - studentId = semester.studentId, - subject = it.subject, - grade = it.gradeValue, - amount = it.amount, - semester = isSemester - ) - } + suspend fun getGradePartialStatistics(student: Student, semester: Semester): List<GradePartialStatistics> { + return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getGradesPartialStatistics(semester.semesterId) + .map { + GradePartialStatistics( + semesterId = semester.semesterId, + studentId = student.studentId, + subject = it.subject, + classAverage = it.classAverage, + studentAverage = it.studentAverage, + classAmounts = it.classItems + .sortedBy { item -> item.grade } + .map { item -> item.amount }, + studentAmounts = it.studentItems.map { item -> item.amount } + ) + } + } + + suspend fun getGradeSemesterStatistics(student: Student, semester: Semester): List<GradeSemesterStatistics> { + return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) + .getGradesSemesterStatistics(semester.semesterId) + .map { + GradeSemesterStatistics( + semesterId = semester.semesterId, + studentId = semester.studentId, + subject = it.subject, + amounts = it.items + .sortedBy { item -> item.grade } + .map { item -> item.amount }, + studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0 + ) + } } suspend fun getGradePointsStatistics(student: Student, semester: Semester): List<GradePointsStatistics> { diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt index 52ca705f..ca0f6ffb 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRepository.kt @@ -1,13 +1,15 @@ package io.github.wulkanowy.data.repositories.gradestatistics +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.pojos.GradeStatisticsItem import io.github.wulkanowy.ui.modules.grade.statistics.ViewType import io.github.wulkanowy.utils.networkBoundResource import io.github.wulkanowy.utils.uniqueSubtract +import java.util.Locale import javax.inject.Inject import javax.inject.Singleton @@ -17,55 +19,125 @@ class GradeStatisticsRepository @Inject constructor( private val remote: GradeStatisticsRemote ) { - fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean) = networkBoundResource( + fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getGradesStatistics(semester, isSemester) }, - fetch = { remote.getGradeStatistics(student, semester, isSemester) }, + query = { local.getGradePartialStatistics(semester) }, + fetch = { remote.getGradePartialStatistics(student, semester) }, saveFetchResult = { old, new -> - local.deleteGradesStatistics(old uniqueSubtract new) - local.saveGradesStatistics(new uniqueSubtract old) + local.deleteGradePartialStatistics(old uniqueSubtract new) + local.saveGradePartialStatistics(new uniqueSubtract old) }, mapResult = { items -> when (subjectName) { - "Wszystkie" -> items.groupBy { it.grade }.map { - GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key, - it.value.fold(0) { acc, e -> acc + e.amount }, false) - } + items + "Wszystkie" -> { + val numerator = items.map { + it.classAverage.replace(",", ".").toDoubleOrNull() ?: .0 + }.filterNot { it == .0 } + (items.reversed() + GradePartialStatistics( + studentId = semester.studentId, + semesterId = semester.semesterId, + subject = subjectName, + classAverage = if (numerator.isEmpty()) "" else numerator.average().let { + "%.2f".format(Locale.FRANCE, it) + }, + studentAverage = "", + classAmounts = items.map { it.classAmounts }.sumGradeAmounts(), + studentAmounts = items.map { it.studentAmounts }.sumGradeAmounts() + )).reversed() + } else -> items.filter { it.subject == subjectName } - }.mapToStatisticItems() + }.mapPartialToStatisticItems() + } + ) + + fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( + shouldFetch = { it.isEmpty() || forceRefresh }, + query = { local.getGradeSemesterStatistics(semester) }, + fetch = { remote.getGradeSemesterStatistics(student, semester) }, + saveFetchResult = { old, new -> + local.deleteGradeSemesterStatistics(old uniqueSubtract new) + local.saveGradeSemesterStatistics(new uniqueSubtract old) + }, + mapResult = { items -> + val itemsWithAverage = items.map { item -> + item.copy().apply { + val denominator = item.amounts.sum() + average = if (denominator == 0) "" else (item.amounts.mapIndexed { gradeValue, amount -> + (gradeValue + 1) * amount + }.sum().toDouble() / denominator).let { + "%.2f".format(Locale.FRANCE, it) + } + } + } + when (subjectName) { + "Wszystkie" -> (itemsWithAverage.reversed() + GradeSemesterStatistics( + studentId = semester.studentId, + semesterId = semester.semesterId, + subject = subjectName, + amounts = itemsWithAverage.map { it.amounts }.sumGradeAmounts(), + studentGrade = 0 + ).apply { + average = itemsWithAverage.mapNotNull { it.average.replace(",", ".").toDoubleOrNull() }.average().let { + "%.2f".format(Locale.FRANCE, it) + } + }).reversed() + else -> itemsWithAverage.filter { it.subject == subjectName } + }.mapSemesterToStatisticItems() } ) fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource( shouldFetch = { it.isEmpty() || forceRefresh }, - query = { local.getGradesPointsStatistics(semester) }, + query = { local.getGradePointsStatistics(semester) }, fetch = { remote.getGradePointsStatistics(student, semester) }, saveFetchResult = { old, new -> - local.deleteGradesPointsStatistics(old uniqueSubtract new) - local.saveGradesPointsStatistics(new uniqueSubtract old) + local.deleteGradePointsStatistics(old uniqueSubtract new) + local.saveGradePointsStatistics(new uniqueSubtract old) }, mapResult = { items -> when (subjectName) { "Wszystkie" -> items else -> items.filter { it.subject == subjectName } - }.mapToStatisticsItem() + }.mapPointsToStatisticsItems() } ) - private fun List<GradeStatistics>.mapToStatisticItems() = groupBy { it.subject }.map { + private fun List<List<Int>>.sumGradeAmounts(): List<Int> { + val result = mutableListOf(0, 0, 0, 0, 0, 0) + forEach { + it.forEachIndexed { grade, amount -> + result[grade] += amount + } + } + return result + } + + private fun List<GradePartialStatistics>.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map { GradeStatisticsItem( type = ViewType.PARTIAL, - partial = it.value - .sortedByDescending { item -> item.grade } - .filter { item -> item.amount != 0 }, - points = null + average = it.classAverage, + partial = it, + points = null, + semester = null ) } - private fun List<GradePointsStatistics>.mapToStatisticsItem() = map { + private fun List<GradeSemesterStatistics>.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map { + GradeStatisticsItem( + type = ViewType.SEMESTER, + partial = null, + points = null, + average = "", + semester = it + ) + } + + private fun List<GradePointsStatistics>.mapPointsToStatisticsItems() = map { GradeStatisticsItem( type = ViewType.POINTS, - partial = emptyList(), + partial = null, + semester = null, + average = "", points = it ) } diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt index 3d61a423..461836b8 100644 --- a/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt +++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/GradeStatisticsWork.kt @@ -12,8 +12,8 @@ class GradeStatisticsWork @Inject constructor( override suspend fun doWork(student: Student, semester: Semester) { with(gradeStatisticsRepository) { - getGradesStatistics(student, semester, "Wszystkie", isSemester = true, forceRefresh = true).waitForResult() - getGradesStatistics(student, semester, "Wszystkie", isSemester = false, forceRefresh = true).waitForResult() + getGradesPartialStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult() + getGradesSemesterStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult() getGradesPointsStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult() } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt index dbb60910..cbcb444a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsAdapter.kt @@ -17,8 +17,9 @@ import com.github.mikephil.charting.data.PieDataSet import com.github.mikephil.charting.data.PieEntry import com.github.mikephil.charting.formatter.ValueFormatter import io.github.wulkanowy.R +import io.github.wulkanowy.data.db.entities.GradePartialStatistics import io.github.wulkanowy.data.db.entities.GradePointsStatistics -import io.github.wulkanowy.data.db.entities.GradeStatistics +import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics import io.github.wulkanowy.data.pojos.GradeStatisticsItem import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding @@ -68,22 +69,32 @@ class GradeStatisticsAdapter @Inject constructor() : override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return when (viewType) { - ViewType.PARTIAL.id, ViewType.SEMESTER.id -> PieViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) - ViewType.POINTS.id -> BarViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)) + ViewType.PARTIAL.id -> PartialViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) + ViewType.SEMESTER.id -> SemesterViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)) + ViewType.POINTS.id -> PointsViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)) else -> throw IllegalStateException() } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { - is PieViewHolder -> bindPieChart(holder, items[position].partial) - is BarViewHolder -> bindBarChart(holder, items[position].points!!) + is PartialViewHolder -> bindPartialChart(holder, items[position].partial!!) + is SemesterViewHolder -> bindSemesterChart(holder, items[position].semester!!) + is PointsViewHolder -> bindBarChart(holder, items[position].points!!) } } - private fun bindPieChart(holder: PieViewHolder, partials: List<GradeStatistics>) { - with(holder.binding.gradeStatisticsPieTitle) { - text = partials.firstOrNull()?.subject + private fun bindPartialChart(holder: PartialViewHolder, partials: GradePartialStatistics) { + bindPieChart(holder.binding, partials.subject, partials.classAverage, partials.classAmounts) + } + + private fun bindSemesterChart(holder: SemesterViewHolder, semester: GradeSemesterStatistics) { + bindPieChart(holder.binding, semester.subject, semester.average, semester.amounts) + } + + private fun bindPieChart(binding: ItemGradeStatisticsPieBinding, subject: String, average: String, amounts: List<Int>) { + with(binding.gradeStatisticsPieTitle) { + text = subject visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE } @@ -92,22 +103,23 @@ class GradeStatisticsAdapter @Inject constructor() : else -> materialGradeColors } - val dataset = PieDataSet(partials.map { - PieEntry(it.amount.toFloat(), it.grade.toString()) - }, "Legenda") + val dataset = PieDataSet(amounts.mapIndexed { grade, amount -> + PieEntry(amount.toFloat(), (grade + 1).toString()) + }.reversed().filterNot { it.value == 0f }, "Legenda") with(dataset) { valueTextSize = 12f sliceSpace = 1f valueTextColor = Color.WHITE - setColors(partials.map { - gradeColors.single { color -> color.first == it.grade }.second - }.toIntArray(), holder.binding.root.context) + val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }.filterNot { it.second == 0 } + setColors(grades.reversed().map { (grade, _) -> + gradeColors.single { color -> color.first == grade }.second + }.toIntArray(), binding.root.context) } - with(holder.binding.gradeStatisticsPie) { + with(binding.gradeStatisticsPie) { setTouchEnabled(false) - if (partials.size == 1) animateXY(1000, 1000) + if (amounts.size == 1) animateXY(1000, 1000) data = PieData(dataset).apply { setValueFormatter(object : ValueFormatter() { override fun getPieLabel(value: Float, pieEntry: PieEntry): String { @@ -128,8 +140,9 @@ class GradeStatisticsAdapter @Inject constructor() : minAngleForSlices = 25f description.isEnabled = false - centerText = partials.fold(0) { acc, it -> acc + it.amount } - .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } + centerText = amounts.fold(0) { acc, it -> acc + it } + .let { resources.getQuantityString(R.plurals.grade_number_item, it, it) } + + ("\n\nŚrednia: $average").takeIf { average.isNotBlank() }.orEmpty() setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground)) setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary)) @@ -137,7 +150,7 @@ class GradeStatisticsAdapter @Inject constructor() : } } - private fun bindBarChart(holder: BarViewHolder, points: GradePointsStatistics) { + private fun bindBarChart(holder: PointsViewHolder, points: GradePointsStatistics) { with(holder.binding.gradeStatisticsBarTitle) { text = points.subject visibility = if (items.size == 1) GONE else VISIBLE @@ -200,9 +213,12 @@ class GradeStatisticsAdapter @Inject constructor() : } } - private class PieViewHolder(val binding: ItemGradeStatisticsPieBinding) : + private class PartialViewHolder(val binding: ItemGradeStatisticsPieBinding) : RecyclerView.ViewHolder(binding.root) - private class BarViewHolder(val binding: ItemGradeStatisticsBarBinding) : + private class SemesterViewHolder(val binding: ItemGradeStatisticsPieBinding) : + RecyclerView.ViewHolder(binding.root) + + private class PointsViewHolder(val binding: ItemGradeStatisticsBarBinding) : RecyclerView.ViewHolder(binding.root) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/grade/statistics/GradeStatisticsPresenter.kt index 2f46d21d..aca3ec96 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 @@ -153,8 +153,8 @@ class GradeStatisticsPresenter @Inject constructor( with(gradeStatisticsRepository) { when (type) { - ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh) - ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, forceRefresh) + ViewType.PARTIAL -> getGradesPartialStatistics(student, semester, currentSubjectName, forceRefresh) + ViewType.SEMESTER -> getGradesSemesterStatistics(student, semester, currentSubjectName, forceRefresh) ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh) } } @@ -164,8 +164,15 @@ class GradeStatisticsPresenter @Inject constructor( Status.SUCCESS -> { Timber.i("Loading grade stats result: Success") view?.run { - showEmpty(it.data!!.isEmpty() || it.data.first().partial.isEmpty()) - showContent(it.data.isNotEmpty() && it.data.first().partial.isNotEmpty()) + val isNoContent = it.data!!.isEmpty() || when (type) { + ViewType.SEMESTER -> it.data.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0 + ViewType.PARTIAL -> it.data.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0 + ViewType.POINTS -> it.data.firstOrNull()?.points?.let { points -> + points.student == .0 && points.others == .0 + } ?: false + } + showEmpty(isNoContent) + showContent(!isNoContent) showErrorView(false) updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList) showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList) diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt index cd2a3070..6d3d63a7 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/gradestatistics/GradeStatisticsRemoteTest.kt @@ -4,7 +4,8 @@ import io.github.wulkanowy.data.db.entities.Semester import io.github.wulkanowy.getStudentEntity import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.pojo.GradePointsStatistics -import io.github.wulkanowy.sdk.pojo.GradeStatistics +import io.github.wulkanowy.sdk.pojo.GradeStatisticsItem +import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject import io.github.wulkanowy.utils.init import io.mockk.MockKAnnotations import io.mockk.coEvery @@ -35,8 +36,8 @@ class GradeStatisticsRemoteTest { @Test fun getGradeStatisticsTest() { coEvery { mockSdk.getGradesPartialStatistics(1) } returns listOf( - getGradeStatistics("Fizyka"), - getGradeStatistics("Matematyka") + getGradeStatisticsPartialSubject("Fizyka"), + getGradeStatisticsPartialSubject("Matematyka") ) every { semesterMock.studentId } returns 1 @@ -45,7 +46,7 @@ class GradeStatisticsRemoteTest { every { semesterMock.semesterId } returns 1 every { mockSdk.switchDiary(any(), any()) } returns mockSdk - val stats = runBlocking { GradeStatisticsRemote(mockSdk).getGradeStatistics(student, semesterMock, false) } + val stats = runBlocking { GradeStatisticsRemote(mockSdk).getGradePartialStatistics(student, semesterMock) } assertEquals(2, stats.size) } @@ -66,19 +67,24 @@ class GradeStatisticsRemoteTest { assertEquals(2, stats.size) } - private fun getGradeStatistics(subjectName: String): GradeStatistics { - return GradeStatistics( + private fun getGradeStatisticsPartialSubject(subjectName: String): GradeStatisticsSubject { + return GradeStatisticsSubject( subject = subjectName, - gradeValue = 5, - amount = 10, - grade = "", - semesterId = 1 + studentAverage = "", + classAverage = "", + classItems = listOf( + GradeStatisticsItem( + subject = subjectName, + grade = 0, + amount = 0 + ) + ), + studentItems = listOf() ) } private fun getGradePointsStatistics(subjectName: String): GradePointsStatistics { return GradePointsStatistics( - semesterId = 1, subject = subjectName, student = 0.80, others = 0.40 From 8a00ae95b899a41344fa9b3b932bce7dbf9e4b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Jelnicki?= <s.jelnicki@gmail.com> Date: Fri, 13 Nov 2020 23:59:45 +0100 Subject: [PATCH 13/34] Update contributor's username (#1020) --- app/src/main/assets/contributors.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json index 40aff4c4..54b47350 100644 --- a/app/src/main/assets/contributors.json +++ b/app/src/main/assets/contributors.json @@ -33,6 +33,6 @@ }, { "displayName": "Mateusz Idziejczak", - "githubUsername": "PanTajemnic" + "githubUsername": "Luncenok" } ] From c7fdcc2bbdbf4f533688b56702cd313b18745778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Tue, 17 Nov 2020 16:58:24 +0100 Subject: [PATCH 14/34] Add facebook link to about (#1021) --- .../github/wulkanowy/ui/modules/about/AboutFragment.kt | 9 +++++++++ .../wulkanowy/ui/modules/about/AboutPresenter.kt | 8 +++++++- .../io/github/wulkanowy/ui/modules/about/AboutView.kt | 4 ++++ app/src/main/res/drawable/ic_about_facebook.xml | 10 ++++++++++ app/src/main/res/values/strings.xml | 2 ++ build.gradle | 2 +- 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/ic_about_facebook.xml diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt index 5ec1a66e..0730033f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutFragment.kt @@ -58,6 +58,11 @@ class AboutFragment : BaseFragment<FragmentAboutBinding>(R.layout.fragment_about Triple(getString(R.string.about_discord), getString(R.string.about_discord_summary), getCompatDrawable(R.drawable.ic_about_discord)) } + override val facebookRes: Triple<String, String, Drawable?>? + get() = context?.run { + Triple(getString(R.string.about_facebook), getString(R.string.about_facebook_summary), getCompatDrawable(R.drawable.ic_about_facebook)) + } + override val homepageRes: Triple<String, String, Drawable?>? get() = context?.run { Triple(getString(R.string.about_homepage), getString(R.string.about_homepage_summary), getCompatDrawable(R.drawable.ic_about_homepage)) @@ -113,6 +118,10 @@ class AboutFragment : BaseFragment<FragmentAboutBinding>(R.layout.fragment_about context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage) } + override fun openFacebookPage() { + context?.openInternetBrowser("https://www.facebook.com/wulkanowy", ::showMessage) + } + override fun openHomepage() { context?.openInternetBrowser("https://wulkanowy.github.io/", ::showMessage) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt index cd08b67e..76ba8212 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutPresenter.kt @@ -3,8 +3,8 @@ package io.github.wulkanowy.ui.modules.about import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.ErrorHandler -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.AppInfo import timber.log.Timber import javax.inject.Inject @@ -46,6 +46,11 @@ class AboutPresenter @Inject constructor( openDiscordInvite() analytics.logEvent("about_open", "name" to "discord") } + facebookRes?.first -> { + Timber.i("Opening facebook") + openFacebookPage() + analytics.logEvent("about_open", "name" to "facebook") + } homepageRes?.first -> { Timber.i("Opening homepage") openHomepage() @@ -78,6 +83,7 @@ class AboutPresenter @Inject constructor( feedbackRes, faqRes, discordRes, + facebookRes, homepageRes, licensesRes, privacyRes diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt index 4c4b002f..54882b30 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/about/AboutView.kt @@ -15,6 +15,8 @@ interface AboutView : BaseView { val discordRes: Triple<String, String, Drawable?>? + val facebookRes: Triple<String, String, Drawable?>? + val homepageRes: Triple<String, String, Drawable?>? val licensesRes: Triple<String, String, Drawable?>? @@ -31,6 +33,8 @@ interface AboutView : BaseView { fun openDiscordInvite() + fun openFacebookPage() + fun openEmailClient() fun openFaqPage() diff --git a/app/src/main/res/drawable/ic_about_facebook.xml b/app/src/main/res/drawable/ic_about_facebook.xml new file mode 100644 index 00000000..a1b7b46e --- /dev/null +++ b/app/src/main/res/drawable/ic_about_facebook.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FFF" + android:fillType="nonZero" + android:pathData="M12,2C6.4883,2 2,6.4883 2,12C2,17.5117 6.4883,22 12,22C17.5117,22 22,17.5117 22,12C22,6.4883 17.5117,2 12,2ZM12,4C16.4297,4 20,7.5703 20,12C20,16.0156 17.0664,19.3125 13.2188,19.8984L13.2188,14.3828L15.5469,14.3828L15.9102,12.0195L13.2188,12.0195L13.2188,10.7266C13.2188,9.7422 13.5391,8.8711 14.457,8.8711L15.9336,8.8711L15.9336,6.8047C15.6758,6.7734 15.125,6.6953 14.0898,6.6953C11.9258,6.6953 10.6523,7.8398 10.6523,10.4453L10.6523,12.0195L8.4258,12.0195L8.4258,14.3828L10.6523,14.3828L10.6523,19.8789C6.8711,19.2422 4,15.9688 4,12C4,7.5703 7.5703,4 12,4ZM12,4" /> +</vector> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cc3dbe3c..7c77b735 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -351,6 +351,8 @@ <string name="about_faq_summary">Read Frequently Asked Questions</string> <string name="about_discord">Discord server</string> <string name="about_discord_summary">Join the Wulkanowy community</string> + <string name="about_facebook">Facebook fanpage</string> + <string name="about_facebook_summary">Like our facebook fanpage</string> <string name="about_privacy">Privacy policy</string> <string name="about_privacy_summary">Rules for collecting personal data</string> <string name="about_homepage">Homepage</string> diff --git a/build.gradle b/build.gradle index 051fce64..c6a6da0b 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.1' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.4' classpath 'com.huawei.agconnect:agcp:1.4.1.300' From 5e9853b04335b7fd98f781b8054fbd89c62ab911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Sat, 21 Nov 2020 15:50:18 +0100 Subject: [PATCH 15/34] New Crowdin updates (#1022) --- app/src/main/res/values-cs-rCZ/strings.xml | 2 ++ app/src/main/res/values-de/strings.xml | 2 ++ app/src/main/res/values-pl/strings.xml | 2 ++ app/src/main/res/values-ru/strings.xml | 2 ++ app/src/main/res/values-uk/strings.xml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index dd474aec..44a03e3d 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -348,6 +348,8 @@ <string name="about_faq_summary">Přečtěte si často kladené otázky</string> <string name="about_discord">Server Discord</string> <string name="about_discord_summary">Připojte se ke komunitě Wulkanowy</string> + <string name="about_facebook">Facebooková fanpage</string> + <string name="about_facebook_summary">Stejně jako naše facebooková fanpage</string> <string name="about_privacy">Zásady ochrany osobních údajů</string> <string name="about_privacy_summary">Pravidla pro shromažďování osobních údajů</string> <string name="about_homepage">Domovská stránka</string> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d885261c..a16b18e5 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -308,6 +308,8 @@ <string name="about_faq_summary">Lesen Sie Häufig gestellte Fragen</string> <string name="about_discord">Discord server</string> <string name="about_discord_summary">Treten Sie der Wulkanowy-Gemeinschaft bei</string> + <string name="about_facebook">Facebook fanpage</string> + <string name="about_facebook_summary">Gefällt unsere Facebook-Fanpage</string> <string name="about_privacy">Datenschutzerklärung</string> <string name="about_privacy_summary">Regeln für die Sammlung persönlicher Daten</string> <string name="about_homepage">Startseite</string> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 67f8bd1b..dc877eaf 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -348,6 +348,8 @@ <string name="about_faq_summary">Zobacz Najczęściej Zadawane Pytania</string> <string name="about_discord">Serwer Discord</string> <string name="about_discord_summary">Dołącz do społeczności Wulkanowego</string> + <string name="about_facebook">Fanpage na Facebooku</string> + <string name="about_facebook_summary">Polub nasz fanpage na Facebooku</string> <string name="about_privacy">Polityka prywatności</string> <string name="about_privacy_summary">Zasady zbierania danych osobowych</string> <string name="about_homepage">Strona domowa</string> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5e260d99..e2620b60 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -348,6 +348,8 @@ <string name="about_faq_summary">Часто задаваемые вопросы</string> <string name="about_discord">Сервер Discord</string> <string name="about_discord_summary">Присоединиться к сообществу приложения</string> + <string name="about_facebook">Facebook фан-страница</string> + <string name="about_facebook_summary">Поставьте лайк на нашей странице в Facebook</string> <string name="about_privacy">Политика приватности</string> <string name="about_privacy_summary">Правила хранения личных данных</string> <string name="about_homepage">Домашняя страница</string> diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 48da2784..cc26b24f 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -348,6 +348,8 @@ <string name="about_faq_summary">Запитання, які часто задають</string> <string name="about_discord">Сервер Discord</string> <string name="about_discord_summary">Приєднатися до спільноти додатка</string> + <string name="about_facebook">Фен-сторінка Facebook</string> + <string name="about_facebook_summary">Вподобати нашу фансторінку у Facebook</string> <string name="about_privacy">Політика конфіденційності</string> <string name="about_privacy_summary">Правила зберігання особистих даних</string> <string name="about_homepage">Домашня сторінка</string> From c675dc8b848991836b4e72c2b24c05426f200c21 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:27:47 +0000 Subject: [PATCH 16/34] Bump kotlin_version from 1.4.10 to 1.4.20 (#1026) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c6a6da0b..92f4e448 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlin_version = '1.4.10' + kotlin_version = '1.4.20' about_libraries = '8.4.3' hilt_version = "2.29.1-alpha" } From c42333cd35854639dd77a6ef90434744071058e4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:28:10 +0000 Subject: [PATCH 17/34] Bump firebase-crashlytics-gradle from 2.3.0 to 2.4.1 (#1029) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 92f4e448..cbc06193 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.4' classpath 'com.huawei.agconnect:agcp:1.4.1.300' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' classpath "com.github.triplet.gradle:play-publisher:2.8.0" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0" classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0" From 3c0dda9a82c13af9f94db34766fe0212b3e725cb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:29:49 +0000 Subject: [PATCH 18/34] Bump hianalytics from 5.0.4.301 to 5.0.5.301 (#1023) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 0afaab01..6944276a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -206,7 +206,7 @@ dependencies { playImplementation 'com.google.android.play:core-ktx:1.8.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - hmsImplementation 'com.huawei.hms:hianalytics:5.0.4.301' + hmsImplementation 'com.huawei.hms:hianalytics:5.0.5.301' hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.1.300' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" From 13906a7d62c9071e67cd7a65379adde1cae0637c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:47:26 +0000 Subject: [PATCH 19/34] Bump about_libraries from 8.4.3 to 8.6.2 (#1025) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cbc06193..d0479a63 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.20' - about_libraries = '8.4.3' + about_libraries = '8.6.2' hilt_version = "2.29.1-alpha" } repositories { From 0fc828f006bbd2a51554cab88b39d834bf215e1c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:48:25 +0000 Subject: [PATCH 20/34] Bump agcp from 1.4.1.300 to 1.4.2.301 (#1024) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d0479a63..6aa3d6f2 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { classpath 'com.android.tools.build:gradle:4.1.1' classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.google.gms:google-services:4.3.4' - classpath 'com.huawei.agconnect:agcp:1.4.1.300' + classpath 'com.huawei.agconnect:agcp:1.4.2.301' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' classpath "com.github.triplet.gradle:play-publisher:2.8.0" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0" From 1428887204f286ccb99fda0a6e5fadad636bad67 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 13:57:37 +0000 Subject: [PATCH 21/34] Bump agconnect-crash from 1.4.1.300 to 1.4.2.301 (#1030) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 6944276a..2d35af50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -207,7 +207,7 @@ dependencies { playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' hmsImplementation 'com.huawei.hms:hianalytics:5.0.5.301' - hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.1.300' + hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.4.2.301' releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker" From 7ed478749644e9514a6623e5a752aa4912c416ed Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 3 Dec 2020 14:19:21 +0000 Subject: [PATCH 22/34] Bump chucker from 3.3.0 to 3.4.0 (#1027) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 2d35af50..5957bd6a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,7 +132,7 @@ play { ext { work_manager = "2.4.0" room = "2.2.5" - chucker = "3.3.0" + chucker = "3.4.0" mockk = "1.10.2" moshi = "1.11.0" } From f263b5534a5c57644738c4cae7bd9578e08bd3aa Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:08:26 +0000 Subject: [PATCH 23/34] Bump mockk from 1.10.2 to 1.10.3-jdk8 (#1034) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5957bd6a..a8ee923f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -133,7 +133,7 @@ ext { work_manager = "2.4.0" room = "2.2.5" chucker = "3.4.0" - mockk = "1.10.2" + mockk = "1.10.3-jdk8" moshi = "1.11.0" } From 41dbd2d25f0a32ac4d435d7e7e38deece2806d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Sun, 6 Dec 2020 15:14:58 +0100 Subject: [PATCH 24/34] New Crowdin updates (#1033) --- app/src/main/res/values-cs-rCZ/strings.xml | 100 ++++++++++----------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 44a03e3d..3769b851 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <!--Activity/Fragment title--> - <string name="login_title">Přihlásit se</string> + <string name="login_title">Přihlášení</string> <string name="main_title">Wulkanowy</string> <string name="grade_title">Známky</string> - <string name="attendance_title">Prezence</string> + <string name="attendance_title">Docházka</string> <string name="exam_title">Zkoušky</string> <string name="timetable_title">Plán lekce</string> <string name="settings_title">Nastavení</string> @@ -16,12 +16,12 @@ <string name="message_title">Zprávy</string> <string name="send_message_title">Nová zpráva</string> <string name="note_title">Poznámky a úspěchy</string> - <string name="homework_title">Domácí práce</string> + <string name="homework_title">Domácí úkoly</string> <string name="account_title">Vyberte účet</string> <!--Subtitles--> <string name="grade_subtitle">Semestr %1$d, %2$d/%3$d</string> <!--Login--> - <string name="login_header_default">Přihlaste se pomocí studentského nebo nadřazeného účtu</string> + <string name="login_header_default">Přihlaste se pomocí studentského nebo rodičovského účtu</string> <string name="login_header_symbol">Zadejte symbol ze stránky deníku</string> <string name="login_nickname_hint">Uživatelské jméno</string> <string name="login_email_hint">Email</string> @@ -41,14 +41,14 @@ <string name="login_invalid_pin">Neplatný PIN</string> <string name="login_invalid_token">Neplatný token</string> <string name="login_expired_token">Platnost tokenu vypršela</string> - <string name="login_invalid_email">Nesprávná e-mailová adresa</string> + <string name="login_invalid_email">Neplatný e-mail</string> <string name="login_invalid_login">Místo e-mailu použijte přiřazené přihlašovací údaje</string> <string name="login_invalid_symbol">Neplatný symbol</string> <string name="login_incorrect_symbol">Student nebyl nalezen. Zkontrolujte správnost symbolu a vybrané varianty deníku UONET+</string> <string name="login_field_required">Toto pole je povinné</string> <string name="login_duplicate_student">Vybraný student je již přihlášen</string> <string name="login_symbol_helper">Symbol najdete na stránce deníku v  <b>Uczeń</b> →  <b>Dostęp Mobilny</b> →  <b>Zarejestruj urządzenie mobilne</b>.\n\nUjistěte se, že jste na předchozí obrazovce nastavili správnou variantu deníku do pole <b>Variace deníku UONET+</b>. Wulkanowy v tuto chvíli nezjistí předškolní studenty</string> - <string name="login_select_student">Vyberte studenty k přihlášení do aplikace</string> + <string name="login_select_student">Vyberte studenty, kteří se mají do aplikace přihlásit</string> <string name="login_advanced">Jiné možnosti</string> <string name="login_advanced_warning_mobile_api">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í</string> <string name="login_advanced_warning_scraper">Tento režim zobrazuje stejná data, která se zobrazují na webových stránkách deníka</string> @@ -65,7 +65,7 @@ <string name="login_recover">Obnovit</string> <string name="login_signed_in">Student je již přihlášen</string> <!--Main--> - <string name="main_account_picker">Správce účtu</string> + <string name="main_account_picker">Manažer účtů</string> <string name="main_log_in">Přihlásit se</string> <string name="main_session_expired">Platnost relace vypršela</string> <string name="main_session_relogin">Vaše relace vypršela, přihlaste se prosím znovu</string> @@ -79,9 +79,9 @@ <string name="grade_comment">Komentář</string> <string name="grade_no_new_items">Žádné nové známky</string> <string name="grade_number_new_items">Počet nových známek: %1$d</string> - <string name="grade_average">Průměrný: %1$.2f</string> + <string name="grade_average">Průměr: %1$.2f</string> <string name="grade_points_sum">Body: %s</string> - <string name="grade_no_average">Žádný průměr</string> + <string name="grade_no_average">Bez průměru</string> <string name="grade_predicted">Předpovězeno: %1$s</string> <string name="grade_final">Konečná: %1$s</string> <string name="grade_summary_points">Celkem bodů</string> @@ -126,10 +126,10 @@ <item quantity="other">Máte %1$d nové známky</item> </plurals> <plurals name="grade_notify_new_items_predicted"> - <item quantity="one">Máte %1$d novou konečnou známku</item> - <item quantity="few">Máte %1$d nové konečné známky</item> - <item quantity="many">Máte %1$d nové konečné známky</item> - <item quantity="other">Máte %1$d nové konečné známky</item> + <item quantity="one">Máte %1$d novou předpokládanou známku</item> + <item quantity="few">Máte %1$d nové předpokládané známky</item> + <item quantity="many">Máte %1$d nové předpokládané známky</item> + <item quantity="other">Máte %1$d nové předpokládané známky</item> </plurals> <plurals name="grade_notify_new_items_final"> <item quantity="one">Máte %1$d novou konečnou známku</item> @@ -143,7 +143,7 @@ <string name="timetable_group">Skupina</string> <string name="timetable_time">Hodiny</string> <string name="timetable_changes">Změny</string> - <string name="timetable_no_items">Dnes žádné lekce</string> + <string name="timetable_no_items">Žádné lekce tento den</string> <string name="timetable_minutes">%s min</string> <string name="timetable_seconds">%s sek</string> <string name="timetable_time_left">dosud %1$s</string> @@ -155,32 +155,32 @@ <!--Completed lessons--> <string name="completed_lessons_title">Dokončené lekce</string> <string name="completed_lessons_button">Zobrazit dokončené lekce</string> - <string name="completed_lessons_no_items">Žádné informace o absolvovaných lekcích</string> + <string name="completed_lessons_no_items">Žádné informace o dokončených lekcích</string> <string name="completed_lessons_topic">Téma</string> - <string name="completed_lessons_absence">Absence</string> + <string name="completed_lessons_absence">Nepřítomnost</string> <string name="completed_lessons_resources">Zdroje</string> <!--Attendance--> <string name="attendance_summary_button">Souhrn docházky</string> <string name="attendance_absence_school">Nepřítomen ze školních důvodů</string> - <string name="attendance_absence_excused">Omluvená absence</string> + <string name="attendance_absence_excused">Omluvená nepřítomnost</string> <string name="attendance_absence_unexcused">Neomluvená absence</string> <string name="attendance_exemption">Osvobození</string> - <string name="attendance_excused_lateness">Oprávněné zpoždění</string> - <string name="attendance_unexcused_lateness">Neomluvená zpoždění</string> + <string name="attendance_excused_lateness">Omluvené zpoždění</string> + <string name="attendance_unexcused_lateness">Neomluvené zpoždění</string> <string name="attendance_present">Přítomnost</string> <string name="attendance_deleted">Smazáno</string> <string name="attendance_unknown">Neznámý</string> <string name="attendance_number">Číslo lekce</string> <string name="attendance_no_items">Žádné položky</string> <plurals name="attendance_number_absences"> - <item quantity="one">%1$d absence</item> - <item quantity="few">%1$d absence</item> - <item quantity="many">%1$d absence</item> - <item quantity="other">%1$d absence</item> + <item quantity="one">%1$d nepřítomnost</item> + <item quantity="few">%1$d nepřítomnosti</item> + <item quantity="many">%1$d nepřítomnosti</item> + <item quantity="other">%1$d nepřítomnosti</item> </plurals> - <string name="attendance_excuse_dialog_reason">Důvod absence (volitelný)</string> + <string name="attendance_excuse_dialog_reason">Důvod nepřítomnosti (volitelný)</string> <string name="attendance_excuse_dialog_submit">Poslat</string> - <string name="attendance_excuse_success">Absence úspěšně omluvena!</string> + <string name="attendance_excuse_success">Nepřítomnost úspěšně omluvena!</string> <string name="attendance_excuse_no_selection">Musíte vybrat alespoň jednu nepřítomnost!</string> <string name="attendance_excuse_title">Ospravedlnit</string> <!--Attendance summary--> @@ -198,7 +198,7 @@ <string name="message_no_items">Žádné zprávy</string> <string name="message_preview_error">Při stahování obsahu zprávy došlo k chybě</string> <string name="message_from">Od:</string> - <string name="message_to">Do:</string> + <string name="message_to">Komu:</string> <string name="message_date">Datum: %s</string> <string name="message_reply">Odpověď</string> <string name="message_forward">Poslat dále</string> @@ -226,10 +226,10 @@ <item quantity="other">Nové zprávy</item> </plurals> <plurals name="message_notify_new_items"> - <item quantity="one">Obdrželi jste %1$d zprávu</item> - <item quantity="few">Obdrželi jste %1$d zpráv</item> - <item quantity="many">Obdrželi jste %1$d zpráv</item> - <item quantity="other">Obdrželi jste %1$d zpráv</item> + <item quantity="one">Máte %1$d novou zprávu</item> + <item quantity="few">Máte %1$d nové zprávy</item> + <item quantity="many">Máte %1$d nové zprávy</item> + <item quantity="other">Máte %1$d nové zprávy</item> </plurals> <!--Note--> <string name="note_no_items">Žádné informace o poznámkách</string> @@ -286,12 +286,12 @@ </plurals> <plurals name="neutral_note_notify_new_items"> <item quantity="one">Máte %1$d novou neutrální pozornost</item> - <item quantity="few">Máte %1$d nové neutrální komentáře</item> - <item quantity="many">Máte %1$d nové neutrální komentáře</item> - <item quantity="other">Máte %1$d nové neutrální komentáře</item> + <item quantity="few">Máte %1$d nové neutrální pozornosti</item> + <item quantity="many">Máte %1$d nové neutrální pozornosti</item> + <item quantity="other">Máte %1$d nové neutrální pozornosti</item> </plurals> <!--Homework--> - <string name="homework_no_items">Žádný domácí úkol</string> + <string name="homework_no_items">Žádné informace o domácím úkolu</string> <string name="homework_mark_as_done">Označit jako hotové</string> <string name="homework_mark_as_undone">Neudělané</string> <string name="homework_attachments">Přílohy</string> @@ -315,7 +315,7 @@ <!--School--> <string name="school_title">Škola</string> <string name="school_no_info">Žádné informace o škole</string> - <string name="school_name">Školní jméno</string> + <string name="school_name">Název školy</string> <string name="school_address">Adresa školy</string> <string name="school_telephone">Telefon</string> <string name="school_headmaster">Jméno ředitele</string> @@ -336,14 +336,14 @@ <string name="account_logout_student">Odhlášení studentů</string> <string name="account_type_student">Studentský účet</string> <string name="account_type_parent">Rodičovský účet</string> - <string name="account_login_mobile_api">Režimu Mobíle API</string> + <string name="account_login_mobile_api">Režim Mobilního API</string> <string name="account_login_hybrid">Hybridní režim</string> <!--About--> <string name="about_version">Verze aplikace</string> <string name="about_contributor">Tvůrci</string> <string name="about_contributor_summary">Seznam vývojářů Wulkanowy</string> <string name="about_feedback">Nahlásit chybu</string> - <string name="about_feedback_summary">Pošlete hlášení o chybě e-mailem</string> + <string name="about_feedback_summary">Odeslat zprávu o chybě e-mailem</string> <string name="about_faq">FAQ</string> <string name="about_faq_summary">Přečtěte si často kladené otázky</string> <string name="about_discord">Server Discord</string> @@ -365,8 +365,8 @@ <string name="logviewer_share">Sdílejte protokoly</string> <string name="logviewer_refresh">Obnovit</string> <!--Error dialog--> - <string name="dialog_error_check_update">Kontrola aktualizací</string> - <string name="dialog_error_check_update_message">Před nahlášením chyby nejprve zkontrolujte, zda je k dispozici aktualizace s opravou chyby</string> + <string name="dialog_error_check_update">Zkontrolovat aktualizace</string> + <string name="dialog_error_check_update_message">Před hlášením chyby zkontrolujte, zda je k dispozici aktualizace s opravou chyb</string> <!--Generic--> <string name="all_content">Obsah</string> <string name="all_retry">Zkuste to znovu</string> @@ -383,21 +383,21 @@ <string name="all_subject">Předmět</string> <string name="all_prev">Předchozí</string> <string name="all_next">Další</string> - <string name="all_search">Vyhledávání</string> - <string name="all_search_hint">Vyhledávání…</string> + <string name="all_search">Hledat</string> + <string name="all_search_hint">Hledat…</string> <!--Timetable Widget--> <string name="widget_timetable_no_items">Žádné lekce</string> - <string name="widget_timetable_theme_title">Vyberte téma</string> + <string name="widget_timetable_theme_title">Vybrat motiv</string> <string name="widget_timetable_theme_light">Světlý</string> <string name="widget_timetable_theme_dark">Tmavý</string> - <string name="widget_timetable_theme_system">Téma systému</string> + <string name="widget_timetable_theme_system">Motiv systému</string> <!--Preferences--> <string name="pref_view_header">Vzhled</string> <string name="pref_view_list">Výchozí zobrazení</string> <string name="pref_view_grade_average_mode">Výpočet koncoročního průměru</string> <string name="pref_view_grade_average_force_calc">Vynutit průměrný výpočet podle aplikace</string> <string name="pref_view_present">Zobrazit přítomnost v účasti</string> - <string name="pref_view_app_theme">Téma aplikace</string> + <string name="pref_view_app_theme">Motiv aplikace</string> <string name="pref_view_expand_grade">Rozbalit známky</string> <string name="pref_view_timetable_show_timers">Označte aktuální lekci v plánu lekce</string> <string name="pref_view_timetable_show_groups">Ukázat skupiny vedle předmětů v plánu lekce</string> @@ -412,22 +412,22 @@ <string name="pref_notify_upcoming_lessons_switch">Ukázat nadcházející oznámení o lekci</string> <string name="pref_notify_fix_sync_issues">Opravte problémy se synchronizací a upozorněním</string> <string name="pref_notify_fix_sync_issues_message">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.</string> - <string name="pref_notify_fix_sync_issues_settings_button">Jdi do nastavení</string> + <string name="pref_notify_fix_sync_issues_settings_button">Přejít do nastavení</string> <string name="pref_notify_debug_switch">Ukázat oznámení o ladění</string> <string name="pref_services_header">Synchronizace</string> <string name="pref_services_switch">Automatická aktualizace</string> <string name="pref_services_suspended">Pozastaveno na dovolené</string> <string name="pref_services_interval">Interval aktualizací</string> <string name="pref_services_wifi">Pouze Wi-Fi</string> - <string name="pref_services_force_sync">Nyní synchronizovat</string> + <string name="pref_services_force_sync">Synchronizovat nyní</string> <string name="pref_services_message_sync_success">Synchronizováno!</string> - <string name="pref_services_message_sync_failed">Synchronizace se nezdařila</string> + <string name="pref_services_message_sync_failed">Synchronizace selhala</string> <string name="pref_services_sync_in_progress">Probíhá synchronizace</string> <string name="pref_services_dialog_force_sync_title">Synchronizace</string> <string name="pref_services_dialog_force_sync_summary"> Ruční synchronizace neobnoví zobrazení aplikace. \nChcete-li zobrazit synchronizovaná data, restartujte aplikaci po synchronizaci. </string> - <string name="pref_other_header">Jiný</string> + <string name="pref_other_header">Jiné</string> <string name="pref_other_grade_modifier_plus">Hodnota plusu</string> <string name="pref_other_grade_modifier_minus">Hodnota mínusu</string> <string name="pref_other_fill_message_content">Odpovědět s historií zpráv</string> @@ -437,9 +437,9 @@ <string name="channel_lucky_number">Šťastné číslo</string> <string name="channel_new_message">Nové zprávy</string> <string name="channel_new_notes">Nové poznámky</string> - <string name="channel_push">Oznámení push</string> + <string name="channel_push">Push oznámení</string> <string name="channel_upcoming_lessons">Nadcházející lekce</string> - <string name="channel_debug">Ladění</string> + <string name="channel_debug">Debug</string> <!--Colors--> <string name="all_black">Černý</string> <string name="all_red">Červený</string> From 40ec5bbe867846d611e495301ac832ec0e03be21 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:29:32 +0000 Subject: [PATCH 25/34] Bump kotlinx-coroutines-android from 1.4.0 to 1.4.2-native-mt (#1032) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index a8ee923f..02c121f9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,7 +147,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.activity:activity-ktx:1.1.0" From bf342ed28947e5b5702b515eba9adaa089e52dbd Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:32:08 +0000 Subject: [PATCH 26/34] Bump kotlinx-coroutines-test from 1.4.0 to 1.4.2-native-mt (#1031) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 02c121f9..22d24083 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -216,7 +216,7 @@ dependencies { testImplementation "junit:junit:4.13.1" testImplementation "io.mockk:mockk:$mockk" - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.0' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2' androidTestImplementation "androidx.test:core:1.3.0" androidTestImplementation "androidx.test:runner:1.3.0" From ce802cc737088ffd3013854f18a387e3940f7aac Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:43:48 +0000 Subject: [PATCH 27/34] Bump about_libraries from 8.6.2 to 8.6.3 (#1037) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6aa3d6f2..84d1d236 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = '1.4.20' - about_libraries = '8.6.2' + about_libraries = '8.6.3' hilt_version = "2.29.1-alpha" } repositories { From e637896ad3c971ea552619bafd3b5a6829d15786 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:50:57 +0000 Subject: [PATCH 28/34] Bump firebase-crashlytics from 17.2.2 to 17.3.0 (#1038) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 22d24083..3e4bbfe0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -202,7 +202,7 @@ dependencies { playImplementation 'com.google.firebase:firebase-inappmessaging-display-ktx:19.1.2' playImplementation "com.google.firebase:firebase-inappmessaging-ktx:19.1.2" playImplementation 'com.google.firebase:firebase-messaging:21.0.0' - playImplementation 'com.google.firebase:firebase-crashlytics:17.2.2' + playImplementation 'com.google.firebase:firebase-crashlytics:17.3.0' playImplementation 'com.google.android.play:core-ktx:1.8.1' playImplementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' From d115372c3bc9c197aeec882139426302686249a1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 14:57:50 +0000 Subject: [PATCH 29/34] Bump coil from 1.0.0 to 1.1.0 (#1040) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3e4bbfe0..cd7a1bcb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -194,7 +194,7 @@ dependencies { implementation "fr.bipi.treessence:treessence:0.3.2" implementation "com.mikepenz:aboutlibraries-core:$about_libraries" implementation 'com.wdullaer:materialdatetimepicker:4.2.3' - implementation "io.coil-kt:coil:1.0.0" + implementation "io.coil-kt:coil:1.1.0" implementation "io.github.wulkanowy:AppKillerManager:3.0.0" implementation 'me.xdrop:fuzzywuzzy:1.3.1' From 33d540e1c9b6af3953cbba00af95c3d9fcba61e6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 15:04:43 +0000 Subject: [PATCH 30/34] Bump desugar_jdk_libs from 1.0.10 to 1.1.1 (#1039) --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cd7a1bcb..c85af3c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -144,7 +144,7 @@ configurations.all { dependencies { implementation "io.github.wulkanowy:sdk:bcf6b53" - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' From 05a597313b4898c8953a5f2ab9e9caea2b95a439 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 17:54:09 +0000 Subject: [PATCH 31/34] Bump hilt_version from 2.29.1-alpha to 2.30.1-alpha (#1035) --- .../main/java/io/github/wulkanowy/data/RepositoryModule.kt | 4 ++-- app/src/main/java/io/github/wulkanowy/di/AppModule.kt | 4 ++-- .../main/java/io/github/wulkanowy/services/ServicesModule.kt | 4 ++-- build.gradle | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt index 5efe7773..e8a3fa48 100644 --- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt +++ b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt @@ -11,8 +11,8 @@ import com.chuckerteam.chucker.api.RetentionManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ApplicationComponent import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent import io.github.wulkanowy.data.db.AppDatabase import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository @@ -21,7 +21,7 @@ import timber.log.Timber import javax.inject.Singleton @Module -@InstallIn(ApplicationComponent::class) +@InstallIn(SingletonComponent::class) internal class RepositoryModule { @Singleton diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt index 9133c34e..4efb4d84 100644 --- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt +++ b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt @@ -6,13 +6,13 @@ import com.yariksoffice.lingver.Lingver import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ApplicationComponent import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent import io.github.wulkanowy.utils.DispatchersProvider import javax.inject.Singleton @Module -@InstallIn(ApplicationComponent::class) +@InstallIn(SingletonComponent::class) internal class AppModule { @Singleton diff --git a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt index ac5a84e8..891f07da 100644 --- a/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt +++ b/app/src/main/java/io/github/wulkanowy/services/ServicesModule.kt @@ -9,8 +9,8 @@ import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ApplicationComponent import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent import dagger.multibindings.IntoSet import io.github.wulkanowy.services.sync.channels.Channel import io.github.wulkanowy.services.sync.channels.DebugChannel @@ -38,7 +38,7 @@ import javax.inject.Singleton @Suppress("unused") @Module -@InstallIn(ApplicationComponent::class) +@InstallIn(SingletonComponent::class) abstract class ServicesModule { companion object { diff --git a/build.gradle b/build.gradle index 84d1d236..a68efccd 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { kotlin_version = '1.4.20' about_libraries = '8.6.3' - hilt_version = "2.29.1-alpha" + hilt_version = "2.30.1-alpha" } repositories { mavenCentral() From 6ca5e11371e65b27d16effd6582cce4c1aa4d64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= <RafalBO99@outlook.com> Date: Sun, 6 Dec 2020 19:31:35 +0100 Subject: [PATCH 32/34] Fix HMS analytics and crashlytics (#1042) --- .../io/github/wulkanowy/utils/AnalyticsHelper.kt | 4 ++++ .../io/github/wulkanowy/utils/AnalyticsHelper.kt | 9 +++++---- .../io/github/wulkanowy/utils/CrashLogUtils.kt | 4 ++-- .../wulkanowy/ui/base/BaseDialogFragment.kt | 15 +++++++++++++++ .../wulkanowy/ui/modules/main/MainActivity.kt | 14 ++++++++------ .../wulkanowy/ui/modules/main/MainPresenter.kt | 3 +-- .../github/wulkanowy/ui/modules/main/MainView.kt | 2 -- .../io/github/wulkanowy/utils/AnalyticsHelper.kt | 4 ++++ 8 files changed, 39 insertions(+), 16 deletions(-) diff --git a/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt b/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt index 0cd9a52e..3bf7e169 100644 --- a/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt +++ b/app/src/fdroid/java/io/github/wulkanowy/utils/AnalyticsHelper.kt @@ -15,4 +15,8 @@ class AnalyticsHelper @Inject constructor() { fun setCurrentScreen(activity: Activity, name: String?) { // do nothing } + + fun popCurrentScreen(name: String?) { + // do nothing + } } diff --git a/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt index b3cecf24..5d33825f 100644 --- a/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt +++ b/app/src/hms/java/io/github/wulkanowy/utils/AnalyticsHelper.kt @@ -30,9 +30,10 @@ class AnalyticsHelper @Inject constructor( } fun setCurrentScreen(activity: Activity, name: String?) { - analytics.onEvent("screen_view", Bundle().apply { - putString("screen_name", name) - putString("screen_class", activity::class.simpleName) - }) + analytics.pageStart(name, activity::class.simpleName) + } + + fun popCurrentScreen(name: String?) { + analytics.pageEnd(name) } } diff --git a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt index 8adf2b29..60588f63 100644 --- a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt +++ b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt @@ -44,9 +44,9 @@ class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR) { connectCrash.setCustomKey("message", message) if (t != null) { - connectCrash.log(priority, t.stackTraceToString()) + connectCrash.recordException(t) } else { - connectCrash.log(priority, StackTraceRecorder(format(priority, tag, message)).stackTraceToString()) + connectCrash.recordException(StackTraceRecorder(format(priority, tag, message))) } } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt index 18cd58b4..1c31976e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BaseDialogFragment.kt @@ -3,10 +3,15 @@ package io.github.wulkanowy.ui.base import android.widget.Toast import androidx.fragment.app.DialogFragment import androidx.viewbinding.ViewBinding +import io.github.wulkanowy.utils.AnalyticsHelper import io.github.wulkanowy.utils.lifecycleAwareVariable +import javax.inject.Inject abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView { + @Inject + lateinit var analyticsHelper: AnalyticsHelper + protected var binding: VB by lifecycleAwareVariable() override fun showError(text: String, error: Throwable) { @@ -28,4 +33,14 @@ abstract class BaseDialogFragment<VB : ViewBinding> : DialogFragment(), BaseView override fun showErrorDetailsDialog(error: Throwable) { ErrorDialog.newInstance(error).show(childFragmentManager, error.toString()) } + + override fun onResume() { + super.onResume() + analyticsHelper.setCurrentScreen(requireActivity(), this::class.simpleName) + } + + override fun onPause() { + super.onPause() + analyticsHelper.popCurrentScreen(this::class.simpleName) + } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt index 245f3b16..25b41aab 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainActivity.kt @@ -38,8 +38,8 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.more.MoreFragment import io.github.wulkanowy.ui.modules.note.NoteFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment -import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.AnalyticsHelper +import io.github.wulkanowy.utils.AppInfo import io.github.wulkanowy.utils.UpdateHelper import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.getThemeAttrColor @@ -182,7 +182,10 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie } with(navController) { - setOnViewChangeListener(presenter::onViewChange) + setOnViewChangeListener { section, name -> + analytics.setCurrentScreen(this@MainActivity, name) + presenter.onViewChange(section) + } fragmentHideStrategy = HIDE rootFragments = listOf( GradeFragment.newInstance(), @@ -194,10 +197,6 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie } } - override fun setCurrentScreen(name: String?) { - analytics.setCurrentScreen(this, name) - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { return if (item.itemId == R.id.mainMenuAccount) presenter.onAccountManagerSelected() else false @@ -208,6 +207,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie } override fun switchMenuView(position: Int) { + analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.switchTab(position) } @@ -245,10 +245,12 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie } fun pushView(fragment: Fragment) { + analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.pushFragment(fragment) } override fun popView(depth: Int) { + analytics.popCurrentScreen(navController.currentFrag!!::class.simpleName) navController.safelyPopFragments(depth) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainPresenter.kt index 7ea8197e..cc525c29 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 @@ -35,9 +35,8 @@ class MainPresenter @Inject constructor( analytics.logEvent("app_open", "destination" to initMenu?.name) } - fun onViewChange(section: MainView.Section?, name: String?) { + fun onViewChange(section: MainView.Section?) { view?.apply { - setCurrentScreen(name) showActionBarElevation(section != GRADE && section != MESSAGE && section != SCHOOL) currentViewTitle?.let { setViewTitle(it) } currentViewSubtitle?.let { setViewSubTitle(it.ifBlank { null }) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt index 7e583147..97b556e3 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/main/MainView.kt @@ -24,8 +24,6 @@ interface MainView : BaseView { fun showAccountPicker() - fun setCurrentScreen(name: String?) - fun showActionBarElevation(show: Boolean) fun notifyMenuViewReselected() diff --git a/app/src/play/java/io/github/wulkanowy/utils/AnalyticsHelper.kt b/app/src/play/java/io/github/wulkanowy/utils/AnalyticsHelper.kt index 8897f180..ba29e1cb 100644 --- a/app/src/play/java/io/github/wulkanowy/utils/AnalyticsHelper.kt +++ b/app/src/play/java/io/github/wulkanowy/utils/AnalyticsHelper.kt @@ -35,4 +35,8 @@ class AnalyticsHelper @Inject constructor( putString(FirebaseAnalytics.Param.SCREEN_CLASS, activity::class.simpleName) }) } + + @Suppress("UNUSED_PARAMETER") + fun popCurrentScreen(name: String?) { + } } From 67cef0f6d9062129bfd3410f051c29c21a846001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= <m.pich@outlook.com> Date: Sun, 6 Dec 2020 21:23:02 +0100 Subject: [PATCH 33/34] Add register variant auto-matching based on email (#1041) --- app/build.gradle | 2 +- .../repositories/timetable/TimetableRemote.kt | 2 +- .../modules/login/form/LoginFormFragment.kt | 8 ++++++ .../modules/login/form/LoginFormPresenter.kt | 17 +++++++++--- .../ui/modules/login/form/LoginFormView.kt | 4 +++ app/src/main/res/values/api_hosts.xml | 26 +++++++++---------- .../timetable/TimetableRemoteTest.kt | 4 +-- 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c85af3c7..8dde9e7c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,7 +142,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:bcf6b53" + implementation "io.github.wulkanowy:sdk:50c049ef" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt index eef8729e..9fb80e77 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemote.kt @@ -14,7 +14,7 @@ class TimetableRemote @Inject constructor(private val sdk: Sdk) { suspend fun getTimetable(student: Student, semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Timetable> { return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear) - .getTimetable(startDate, endDate) + .getTimetable(startDate, endDate).first .map { Timetable( studentId = semester.studentId, 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 41345686..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 @@ -89,6 +89,8 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme } } + override fun getHostsValues(): List<String> = hostValues.toList() + override fun setCredentials(username: String, pass: String) { with(binding) { loginFormUsername.setText(username) @@ -96,6 +98,12 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme } } + override fun setHost(host: String) { + binding.loginFormHost.setText( + hostKeys.getOrNull(hostValues.indexOf(host)).orEmpty() + ) + } + override fun setUsernameLabel(label: String) { binding.loginFormUsernameLayout.hint = label } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt index 3e77cd77..35c79bb5 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormPresenter.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.ui.modules.login.form +import androidx.core.net.toUri import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.repositories.student.StudentRepository import io.github.wulkanowy.ui.base.BasePresenter @@ -56,7 +57,7 @@ class LoginFormPresenter @Inject constructor( fun updateUsernameLabel() { view?.run { - setUsernameLabel(if ("standard" in formHostValue) emailLabel else nicknameLabel) + setUsernameLabel(if ("login" in formHostValue) nicknameLabel else emailLabel) } } @@ -66,6 +67,16 @@ class LoginFormPresenter @Inject constructor( fun onUsernameTextChanged() { view?.clearUsernameError() + + val username = view?.formUsernameValue.orEmpty().trim() + if ("@" in username && "@vulcan" !in username) { + val hosts = view?.getHostsValues().orEmpty().map { it.toUri().host to it }.toMap() + val usernameHost = username.substringAfter("@") + + hosts[usernameHost]?.let { + view?.setHost(it) + } + } } fun onSignInClick() { @@ -135,12 +146,12 @@ class LoginFormPresenter @Inject constructor( view?.setErrorUsernameRequired() isCorrect = false } else { - if ("@" in login && "standard" !in host) { + if ("@" in login && "login" in host) { view?.setErrorLoginRequired() isCorrect = false } - if ("@" !in login && "standard" in host) { + if ("@" !in login && "email" in host) { view?.setErrorEmailRequired() isCorrect = false } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/login/form/LoginFormView.kt index 77e66538..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 @@ -19,8 +19,12 @@ interface LoginFormView : BaseView { val emailLabel: String + fun getHostsValues(): List<String> + fun setCredentials(username: String, pass: String) + fun setHost(host: String) + fun setUsernameLabel(label: String) fun setErrorUsernameRequired() diff --git a/app/src/main/res/values/api_hosts.xml b/app/src/main/res/values/api_hosts.xml index 29434602..0a43612d 100644 --- a/app/src/main/res/values/api_hosts.xml +++ b/app/src/main/res/values/api_hosts.xml @@ -22,25 +22,25 @@ <item>Fakelog</item> </string-array> <string-array name="hosts_values"> - <item>https://vulcan.net.pl/?standard</item> + <item>https://vulcan.net.pl/?email</item> <item>https://eszkola.opolskie.pl</item> <item>https://edu.gdansk.pl</item> <item>https://edu.lublin.eu</item> <item>https://umt.tarnow.pl</item> <item>https://resman.pl</item> <item>https://eduportal.koszalin.pl</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>https://vulcan.net.pl/</item> - <item>http://fakelog.tk/?standard</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>https://vulcan.net.pl/?login</item> + <item>http://fakelog.cf/?email</item> </string-array> <string-array name="hosts_symbols"> <item>Default</item> diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt index c948ba31..a333e0d7 100644 --- a/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt +++ b/app/src/test/java/io/github/wulkanowy/data/repositories/timetable/TimetableRemoteTest.kt @@ -39,10 +39,10 @@ class TimetableRemoteTest { of(2018, 9, 10), of(2018, 9, 15) ) - } returns listOf( + } returns (listOf( getTimetable(of(2018, 9, 10)), getTimetable(of(2018, 9, 17)) - ) + ) to emptyList()) every { semesterMock.studentId } returns 1 every { semesterMock.diaryId } returns 1 From 73a92497ede9b1c32a7fd059655539b7e6cf1167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= <m.pich@outlook.com> Date: Sun, 6 Dec 2020 22:12:18 +0100 Subject: [PATCH 34/34] Version 0.23.0 --- .travis.yml | 2 +- app/build.gradle | 8 ++++---- app/src/main/play/release-notes/pl-PL/default.txt | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26abd202..1fb3df0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: branches: only: - develop - - 0.22.2 + - 0.23.0 android: licenses: diff --git a/app/build.gradle b/app/build.gradle index 8dde9e7c..e5cfdcb2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 17 targetSdkVersion 30 - versionCode 75 - versionName "0.22.2" + versionCode 76 + versionName "0.23.0" multiDexEnabled true resValue "string", "app_name", "Wulkanowy" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -126,7 +126,7 @@ play { serviceAccountCredentials = file('key.p12') defaultToAppBundles = false track = 'alpha' - updatePriority = 1 + updatePriority = 3 } ext { @@ -142,7 +142,7 @@ configurations.all { } dependencies { - implementation "io.github.wulkanowy:sdk:50c049ef" + implementation "io.github.wulkanowy:sdk:0.23.0" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' 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 23fd77bc..32bce4a9 100644 --- a/app/src/main/play/release-notes/pl-PL/default.txt +++ b/app/src/main/play/release-notes/pl-PL/default.txt @@ -1,6 +1,7 @@ -Wersja 0.22.2 -- naprawiliśmy problem z wyświetlaniem pozycji na liście ocen -- zmieniliśmy komunikaty o błędach, które powinny być teraz czytelniejsze dla większej liczby użytkowników -- zwiększyliśmy maksymalny czas, przez który aplikacja będzie próbowała łączyć się z dziennikiem do 1 minuty +Wersja 0.23.0 +- naprawiliśmy logowanie do dziennika Gdańskiej i Koszalińskiej Platformy Edukacyjnej +- przy logowaniu odpowiednia odmiana dziennika jest ustawiana automatycznie na podstawie wpisanego adresu email +- dodaliśmy wyświetlanie średniej w ocenach klasy (jeśli włączone przez szkołę) +- dodaliśmy wyświetlanie zebrań Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases