From 7a4032dda4e3061a09ecffd69712b3598e82e414 Mon Sep 17 00:00:00 2001
From: JestemKamil <84380834+JestemKamil@users.noreply.github.com>
Date: Thu, 29 Feb 2024 21:30:02 +0100
Subject: [PATCH 1/3] Add mute message senders (#2415)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Mikołaj Pich
---
.../60.json | 2527 +++++++++++++++++
app/src/main/assets/contributors.json | 4 +
.../io/github/wulkanowy/data/DataModule.kt | 4 +
.../github/wulkanowy/data/db/AppDatabase.kt | 8 +-
.../wulkanowy/data/db/dao/MessagesDao.kt | 10 +-
.../data/db/dao/MutedMessageSendersDao.kt | 20 +
.../data/db/entities/MessageWithAttachment.kt | 8 +-
.../db/entities/MessageWithMutedAuthor.kt | 12 +
.../data/db/entities/MutedMessageSender.kt | 15 +
.../data/repositories/MessageRepository.kt | 35 +-
.../modules/dashboard/DashboardPresenter.kt | 1 +
.../message/preview/MessagePreviewAdapter.kt | 6 +
.../message/preview/MessagePreviewFragment.kt | 18 +-
.../preview/MessagePreviewPresenter.kt | 106 +-
.../message/preview/MessagePreviewView.kt | 6 +
.../modules/message/tab/MessageTabAdapter.kt | 16 +-
.../modules/message/tab/MessageTabDataItem.kt | 1 +
.../message/tab/MessageTabPresenter.kt | 38 +-
.../res/drawable/ic_circle_notification.xml | 10 +
.../res/drawable/ic_notifications_off.xml | 5 +
app/src/main/res/layout/item_message.xml | 6 +-
.../res/menu/action_menu_message_preview.xml | 7 +
app/src/main/res/values/strings.xml | 6 +
.../repositories/MessageRepositoryTest.kt | 47 +-
24 files changed, 2827 insertions(+), 89 deletions(-)
create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt
create mode 100644 app/src/main/res/drawable/ic_circle_notification.xml
create mode 100644 app/src/main/res/drawable/ic_notifications_off.xml
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json
new file mode 100644
index 00000000..20eacad1
--- /dev/null
+++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/60.json
@@ -0,0 +1,2527 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 60,
+ "identityHash": "3672d3f4d5e6b874e5a22d2bb458dc65",
+ "entities": [
+ {
+ "tableName": "Students",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `scrapper_domain_suffix` TEXT NOT NULL DEFAULT '', `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nick` TEXT NOT NULL, `avatar_color` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "scrapperBaseUrl",
+ "columnName": "scrapper_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "scrapperDomainSuffix",
+ "columnName": "scrapper_domain_suffix",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "mobileBaseUrl",
+ "columnName": "mobile_base_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginType",
+ "columnName": "login_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "loginMode",
+ "columnName": "login_mode",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "certificateKey",
+ "columnName": "certificate_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "privateKey",
+ "columnName": "private_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isParent",
+ "columnName": "is_parent",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "symbol",
+ "columnName": "symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "user_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentName",
+ "columnName": "student_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolSymbol",
+ "columnName": "school_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolShortName",
+ "columnName": "school_short",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolName",
+ "columnName": "school_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "className",
+ "columnName": "class_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isCurrent",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "registrationDate",
+ "columnName": "registration_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "nick",
+ "columnName": "nick",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "avatarColor",
+ "columnName": "avatar_color",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_Students_email_symbol_student_id_school_id_class_id",
+ "unique": true,
+ "columnNames": [
+ "email",
+ "symbol",
+ "student_id",
+ "school_id",
+ "class_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Students_email_symbol_student_id_school_id_class_id` ON `${TABLE_NAME}` (`email`, `symbol`, `student_id`, `school_id`, `class_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Semesters",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `kindergarten_diary_id` INTEGER NOT NULL DEFAULT 0, `diary_name` TEXT NOT NULL, `school_year` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `semester_name` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `unit_id` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_current` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "kindergartenDiaryId",
+ "columnName": "kindergarten_diary_id",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "diaryName",
+ "columnName": "diary_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolYear",
+ "columnName": "school_year",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterName",
+ "columnName": "semester_name",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unitId",
+ "columnName": "unit_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "current",
+ "columnName": "is_current",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id",
+ "unique": true,
+ "columnNames": [
+ "student_id",
+ "diary_id",
+ "kindergarten_diary_id",
+ "semester_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Semesters_student_id_diary_id_kindergarten_diary_id_semester_id` ON `${TABLE_NAME}` (`student_id`, `diary_id`, `kindergarten_diary_id`, `semester_id`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Exams",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `group` TEXT NOT NULL, `type` TEXT NOT NULL, `description` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Timetable",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `number` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `subjectOld` TEXT NOT NULL, `group` TEXT NOT NULL, `room` TEXT NOT NULL, `roomOld` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacherOld` TEXT NOT NULL, `info` TEXT NOT NULL, `student_plan` INTEGER NOT NULL, `changes` INTEGER NOT NULL, `canceled` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectOld",
+ "columnName": "subjectOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "group",
+ "columnName": "group",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "roomOld",
+ "columnName": "roomOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherOld",
+ "columnName": "teacherOld",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "info",
+ "columnName": "info",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isStudentPlan",
+ "columnName": "student_plan",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "changes",
+ "columnName": "changes",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canceled",
+ "columnName": "canceled",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Attendance",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `time_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `excused` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `excusable` INTEGER NOT NULL, `excuse_status` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeId",
+ "columnName": "time_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excused",
+ "columnName": "excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deleted",
+ "columnName": "deleted",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excusable",
+ "columnName": "excusable",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "excuseStatus",
+ "columnName": "excuse_status",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "AttendanceSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `subject_id` INTEGER NOT NULL, `month` INTEGER NOT NULL, `presence` INTEGER NOT NULL, `absence` INTEGER NOT NULL, `absence_excused` INTEGER NOT NULL, `absence_for_school_reasons` INTEGER NOT NULL, `lateness` INTEGER NOT NULL, `lateness_excused` INTEGER NOT NULL, `exemption` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subjectId",
+ "columnName": "subject_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "month",
+ "columnName": "month",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presence",
+ "columnName": "presence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceExcused",
+ "columnName": "absence_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absenceForSchoolReasons",
+ "columnName": "absence_for_school_reasons",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lateness",
+ "columnName": "lateness",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "latenessExcused",
+ "columnName": "lateness_excused",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exemption",
+ "columnName": "exemption",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Grades",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `entry` TEXT NOT NULL, `value` REAL NOT NULL, `modifier` REAL NOT NULL, `comment` TEXT NOT NULL, `color` TEXT NOT NULL, `grade_symbol` TEXT NOT NULL, `description` TEXT NOT NULL, `weight` TEXT NOT NULL, `weightValue` REAL NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entry",
+ "columnName": "entry",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "modifier",
+ "columnName": "modifier",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "comment",
+ "columnName": "comment",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "color",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gradeSymbol",
+ "columnName": "grade_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weight",
+ "columnName": "weight",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "weightValue",
+ "columnName": "weightValue",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesSummary",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `position` INTEGER NOT NULL, `subject` TEXT NOT NULL, `predicted_grade` TEXT NOT NULL, `final_grade` TEXT NOT NULL, `proposed_points` TEXT NOT NULL, `final_points` TEXT NOT NULL, `points_sum` TEXT NOT NULL, `average` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_predicted_grade_notified` INTEGER NOT NULL, `is_final_grade_notified` INTEGER NOT NULL, `predicted_grade_last_change` INTEGER NOT NULL, `final_grade_last_change` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGrade",
+ "columnName": "predicted_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGrade",
+ "columnName": "final_grade",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "proposedPoints",
+ "columnName": "proposed_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalPoints",
+ "columnName": "final_points",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointsSum",
+ "columnName": "points_sum",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "average",
+ "columnName": "average",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPredictedGradeNotified",
+ "columnName": "is_predicted_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isFinalGradeNotified",
+ "columnName": "is_final_grade_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "predictedGradeLastChange",
+ "columnName": "predicted_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "finalGradeLastChange",
+ "columnName": "final_grade_last_change",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradePartialStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `class_average` TEXT NOT NULL, `student_average` TEXT NOT NULL, `class_amounts` TEXT NOT NULL, `student_amounts` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAverage",
+ "columnName": "class_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAverage",
+ "columnName": "student_average",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classAmounts",
+ "columnName": "class_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentAmounts",
+ "columnName": "student_amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesPointsStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `others` REAL NOT NULL, `student` REAL NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "others",
+ "columnName": "others",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "student",
+ "columnName": "student",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradeSemesterStatistics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `semester_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `amounts` TEXT NOT NULL, `student_grade` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "amounts",
+ "columnName": "amounts",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentGrade",
+ "columnName": "student_grade",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Messages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `message_global_key` TEXT NOT NULL, `mailbox_key` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `correspondents` TEXT NOT NULL, `subject` TEXT NOT NULL, `date` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `read_by` INTEGER, `unread_by` INTEGER, `has_attachments` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL, `content` TEXT NOT NULL, `sender` TEXT, `recipients` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageGlobalKey",
+ "columnName": "message_global_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mailboxKey",
+ "columnName": "mailbox_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "message_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "correspondents",
+ "columnName": "correspondents",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "folderId",
+ "columnName": "folder_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "readBy",
+ "columnName": "read_by",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "unreadBy",
+ "columnName": "unread_by",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "hasAttachments",
+ "columnName": "has_attachments",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sender",
+ "columnName": "sender",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "recipients",
+ "columnName": "recipients",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MessageAttachments",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`message_global_key`, `url`, `filename`))",
+ "fields": [
+ {
+ "fieldPath": "messageGlobalKey",
+ "columnName": "message_global_key",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filename",
+ "columnName": "filename",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "message_global_key",
+ "url",
+ "filename"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `category` TEXT NOT NULL, `category_type` INTEGER NOT NULL, `is_points_show` INTEGER NOT NULL, `points` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_read` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryType",
+ "columnName": "category_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isPointsShow",
+ "columnName": "is_points_show",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "points",
+ "columnName": "points",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isRead",
+ "columnName": "is_read",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Homework",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `entry_date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `attachments` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_done` INTEGER NOT NULL, `is_notified` INTEGER NOT NULL, `is_added_by_user` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "entryDate",
+ "columnName": "entry_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "attachments",
+ "columnName": "attachments",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isDone",
+ "columnName": "is_done",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isAddedByUser",
+ "columnName": "is_added_by_user",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Subjects",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `real_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "LuckyNumbers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `lucky_number` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "luckyNumber",
+ "columnName": "lucky_number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "CompletedLesson",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `number` INTEGER NOT NULL, `subject` TEXT NOT NULL, `topic` TEXT NOT NULL, `teacher` TEXT NOT NULL, `teacher_symbol` TEXT NOT NULL, `substitution` TEXT NOT NULL, `absence` TEXT NOT NULL, `resources` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "number",
+ "columnName": "number",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacher",
+ "columnName": "teacher",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "teacherSymbol",
+ "columnName": "teacher_symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "substitution",
+ "columnName": "substitution",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "absence",
+ "columnName": "absence",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "resources",
+ "columnName": "resources",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Mailboxes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `email` TEXT NOT NULL, `symbol` TEXT NOT NULL, `schoolId` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `studentName` TEXT NOT NULL, `schoolNameShort` TEXT NOT NULL, `type` TEXT NOT NULL, PRIMARY KEY(`globalKey`))",
+ "fields": [
+ {
+ "fieldPath": "globalKey",
+ "columnName": "globalKey",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "symbol",
+ "columnName": "symbol",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolId",
+ "columnName": "schoolId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fullName",
+ "columnName": "fullName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "userName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentName",
+ "columnName": "studentName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolNameShort",
+ "columnName": "schoolNameShort",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "globalKey"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Recipients",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mailboxGlobalKey` TEXT NOT NULL, `studentMailboxGlobalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `schoolShortName` TEXT NOT NULL, `type` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "mailboxGlobalKey",
+ "columnName": "mailboxGlobalKey",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentMailboxGlobalKey",
+ "columnName": "studentMailboxGlobalKey",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fullName",
+ "columnName": "fullName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "userName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "schoolShortName",
+ "columnName": "schoolShortName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MobileDevices",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `device_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "deviceId",
+ "columnName": "device_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Teachers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `name` TEXT NOT NULL, `short_name` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "short_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "School",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `class_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `address` TEXT NOT NULL, `contact` TEXT NOT NULL, `headmaster` TEXT NOT NULL, `pedagogue` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "classId",
+ "columnName": "class_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "contact",
+ "columnName": "contact",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "headmaster",
+ "columnName": "headmaster",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pedagogue",
+ "columnName": "pedagogue",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Conferences",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `subject` TEXT NOT NULL, `agenda` TEXT NOT NULL, `present_on_conference` TEXT NOT NULL, `conference_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "agenda",
+ "columnName": "agenda",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "presentOnConference",
+ "columnName": "present_on_conference",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "conferenceId",
+ "columnName": "conference_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "TimetableAdditional",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `repeat_id` BLOB DEFAULT NULL, `is_added_by_user` INTEGER NOT NULL DEFAULT 0)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "repeatId",
+ "columnName": "repeat_id",
+ "affinity": "BLOB",
+ "notNull": false,
+ "defaultValue": "NULL"
+ },
+ {
+ "fieldPath": "isAddedByUser",
+ "columnName": "is_added_by_user",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "StudentInfo",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `full_name` TEXT NOT NULL, `first_name` TEXT NOT NULL, `second_name` TEXT NOT NULL, `surname` TEXT NOT NULL, `birth_date` INTEGER NOT NULL, `birth_place` TEXT NOT NULL, `gender` TEXT NOT NULL, `has_polish_citizenship` INTEGER NOT NULL, `family_name` TEXT NOT NULL, `parents_names` TEXT NOT NULL, `address` TEXT NOT NULL, `registered_address` TEXT NOT NULL, `correspondence_address` TEXT NOT NULL, `phone_number` TEXT NOT NULL, `cell_phone_number` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `first_guardian_full_name` TEXT, `first_guardian_kinship` TEXT, `first_guardian_address` TEXT, `first_guardian_phones` TEXT, `first_guardian_email` TEXT, `second_guardian_full_name` TEXT, `second_guardian_kinship` TEXT, `second_guardian_address` TEXT, `second_guardian_phones` TEXT, `second_guardian_email` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fullName",
+ "columnName": "full_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "firstName",
+ "columnName": "first_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "secondName",
+ "columnName": "second_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "surname",
+ "columnName": "surname",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "birthDate",
+ "columnName": "birth_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "birthPlace",
+ "columnName": "birth_place",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gender",
+ "columnName": "gender",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasPolishCitizenship",
+ "columnName": "has_polish_citizenship",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "familyName",
+ "columnName": "family_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "parentsNames",
+ "columnName": "parents_names",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "address",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "registeredAddress",
+ "columnName": "registered_address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "correspondenceAddress",
+ "columnName": "correspondence_address",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "phoneNumber",
+ "columnName": "phone_number",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "cellPhoneNumber",
+ "columnName": "cell_phone_number",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "firstGuardian.fullName",
+ "columnName": "first_guardian_full_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "firstGuardian.kinship",
+ "columnName": "first_guardian_kinship",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "firstGuardian.address",
+ "columnName": "first_guardian_address",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "firstGuardian.phones",
+ "columnName": "first_guardian_phones",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "firstGuardian.email",
+ "columnName": "first_guardian_email",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "secondGuardian.fullName",
+ "columnName": "second_guardian_full_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "secondGuardian.kinship",
+ "columnName": "second_guardian_kinship",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "secondGuardian.address",
+ "columnName": "second_guardian_address",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "secondGuardian.phones",
+ "columnName": "second_guardian_phones",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "secondGuardian.email",
+ "columnName": "second_guardian_email",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "TimetableHeaders",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `diary_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "diaryId",
+ "columnName": "diary_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "SchoolAnnouncements",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_login_id` INTEGER NOT NULL, `date` INTEGER NOT NULL, `subject` TEXT NOT NULL, `content` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "user_login_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notifications",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`student_id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `type` TEXT NOT NULL, `destination` TEXT NOT NULL DEFAULT '{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}', `date` INTEGER NOT NULL, `data` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "destination",
+ "columnName": "destination",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}'"
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "data",
+ "columnName": "data",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "AdminMessages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `version_name` INTEGER, `version_max` INTEGER, `target_register_host` TEXT, `target_flavor` TEXT, `destination_url` TEXT, `priority` TEXT NOT NULL, `types` TEXT NOT NULL DEFAULT '[]', `is_ok_visible` INTEGER NOT NULL DEFAULT 0, `is_x_visible` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "content",
+ "columnName": "content",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "versionMin",
+ "columnName": "version_name",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "versionMax",
+ "columnName": "version_max",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "targetRegisterHost",
+ "columnName": "target_register_host",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "targetFlavor",
+ "columnName": "target_flavor",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "destinationUrl",
+ "columnName": "destination_url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "priority",
+ "columnName": "priority",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "types",
+ "columnName": "types",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "'[]'"
+ },
+ {
+ "fieldPath": "isOkVisible",
+ "columnName": "is_ok_visible",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "isXVisible",
+ "columnName": "is_x_visible",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MutedMessageSenders",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`author` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "author",
+ "columnName": "author",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "GradesDescriptive",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`semester_id` INTEGER NOT NULL, `student_id` INTEGER NOT NULL, `subject` TEXT NOT NULL, `description` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `is_notified` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "semesterId",
+ "columnName": "semester_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "studentId",
+ "columnName": "student_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subject",
+ "columnName": "subject",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isNotified",
+ "columnName": "is_notified",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3672d3f4d5e6b874e5a22d2bb458dc65')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json
index a7629c22..97ac9356 100644
--- a/app/src/main/assets/contributors.json
+++ b/app/src/main/assets/contributors.json
@@ -54,5 +54,9 @@
{
"displayName": "Antoni Paduch",
"githubUsername": "janAte1"
+ },
+ {
+ "displayName": "Kamil Wąsik",
+ "githubUsername": "JestemKamil"
}
]
diff --git a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
index 7c9cf9a3..6b6c9d32 100644
--- a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
@@ -254,6 +254,10 @@ internal class DataModule {
@Provides
fun provideAdminMessageDao(database: AppDatabase) = database.adminMessagesDao
+ @Singleton
+ @Provides
+ fun provideMutesDao(database: AppDatabase) = database.mutedMessageSendersDao
+
@Singleton
@Provides
fun provideGradeDescriptiveDao(database: AppDatabase) = database.gradeDescriptiveDao
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 8e5841fe..21a6e3f3 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
@@ -25,6 +25,7 @@ import io.github.wulkanowy.data.db.dao.MailboxDao
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
+import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao
import io.github.wulkanowy.data.db.dao.NoteDao
import io.github.wulkanowy.data.db.dao.NotificationDao
import io.github.wulkanowy.data.db.dao.RecipientDao
@@ -56,6 +57,7 @@ import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment
import io.github.wulkanowy.data.db.entities.MobileDevice
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
import io.github.wulkanowy.data.db.entities.Note
import io.github.wulkanowy.data.db.entities.Notification
import io.github.wulkanowy.data.db.entities.Recipient
@@ -157,6 +159,7 @@ import javax.inject.Singleton
SchoolAnnouncement::class,
Notification::class,
AdminMessage::class,
+ MutedMessageSender::class,
GradeDescriptive::class,
],
autoMigrations = [
@@ -169,6 +172,7 @@ import javax.inject.Singleton
AutoMigration(from = 56, to = 57, spec = Migration57::class),
AutoMigration(from = 57, to = 58, spec = Migration58::class),
AutoMigration(from = 58, to = 59),
+ AutoMigration(from = 59, to = 60),
],
version = AppDatabase.VERSION_SCHEMA,
exportSchema = true
@@ -177,7 +181,7 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() {
companion object {
- const val VERSION_SCHEMA = 59
+ const val VERSION_SCHEMA = 60
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
Migration2(),
@@ -303,5 +307,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract val adminMessagesDao: AdminMessageDao
+ abstract val mutedMessageSendersDao: MutedMessageSendersDao
+
abstract val gradeDescriptiveDao: GradeDescriptiveDao
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
index 1709f763..11e6da1e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
@@ -5,15 +5,23 @@ import androidx.room.Query
import androidx.room.Transaction
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
+import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor
import kotlinx.coroutines.flow.Flow
@Dao
interface MessagesDao : BaseDao {
-
@Transaction
@Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
fun loadMessageWithAttachment(messageGlobalKey: String): Flow
+ @Transaction
+ @Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
+ fun loadMessagesWithMutedAuthor(mailboxKey: String, folder: Int): Flow>
+
+ @Transaction
+ @Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
+ fun loadMessagesWithMutedAuthor(folder: Int, email: String): Flow>
+
@Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
fun loadAll(mailboxKey: String, folder: Int): Flow>
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt
new file mode 100644
index 00000000..0a866401
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt
@@ -0,0 +1,20 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
+
+@Dao
+interface MutedMessageSendersDao : BaseDao {
+
+ @Query("SELECT COUNT(*) FROM MutedMessageSenders WHERE author = :author")
+ suspend fun checkMute(author: String): Boolean
+
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ suspend fun insertMute(mute: MutedMessageSender): Long
+
+ @Query("DELETE FROM MutedMessageSenders WHERE author = :author")
+ suspend fun deleteMute(author: String)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
index cd468215..fc890e76 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
@@ -2,11 +2,15 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.Embedded
import androidx.room.Relation
+import java.io.Serializable
data class MessageWithAttachment(
@Embedded
val message: Message,
@Relation(parentColumn = "message_global_key", entityColumn = "message_global_key")
- val attachments: List
-)
+ val attachments: List,
+
+ @Relation(parentColumn = "correspondents", entityColumn = "author")
+ val mutedMessageSender: MutedMessageSender?,
+) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt
new file mode 100644
index 00000000..e3cd1ca7
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.Embedded
+import androidx.room.Relation
+
+data class MessageWithMutedAuthor(
+ @Embedded
+ val message: Message,
+
+ @Relation(parentColumn = "correspondents", entityColumn = "author")
+ val mutedMessageSender: MutedMessageSender?,
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt
new file mode 100644
index 00000000..f1770e64
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+
+@Entity(tableName = "MutedMessageSenders")
+data class MutedMessageSender(
+ @ColumnInfo(name = "author")
+ val author: String,
+) : Serializable {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
index c8fccb23..6d591c5b 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MessageRepository.kt
@@ -8,9 +8,12 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.dao.MailboxDao
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
import io.github.wulkanowy.data.db.dao.MessagesDao
+import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao
import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
+import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.enums.MessageFolder
@@ -42,6 +45,7 @@ import javax.inject.Singleton
@Singleton
class MessageRepository @Inject constructor(
private val messagesDb: MessagesDao,
+ private val mutedMessageSendersDao: MutedMessageSendersDao,
private val messageAttachmentDao: MessageAttachmentDao,
private val sdk: Sdk,
@ApplicationContext private val context: Context,
@@ -51,7 +55,6 @@ class MessageRepository @Inject constructor(
private val mailboxDao: MailboxDao,
private val getMailboxByStudentUseCase: GetMailboxByStudentUseCase,
) {
-
private val saveFetchResultMutex = Mutex()
private val messagesCacheKey = "message"
@@ -63,7 +66,7 @@ class MessageRepository @Inject constructor(
folder: MessageFolder,
forceRefresh: Boolean,
notify: Boolean = false,
- ): Flow>> = networkBoundResource(
+ ): Flow>> = networkBoundResource(
mutex = saveFetchResultMutex,
isResultEmpty = { it.isEmpty() },
shouldFetch = {
@@ -74,8 +77,8 @@ class MessageRepository @Inject constructor(
},
query = {
if (mailbox == null) {
- messagesDb.loadAll(folder.id, student.email)
- } else messagesDb.loadAll(mailbox.globalKey, folder.id)
+ messagesDb.loadMessagesWithMutedAuthor(folder.id, student.email)
+ } else messagesDb.loadMessagesWithMutedAuthor(mailbox.globalKey, folder.id)
},
fetch = {
sdk.init(student).getMessages(
@@ -83,10 +86,12 @@ class MessageRepository @Inject constructor(
mailboxKey = mailbox?.globalKey,
).mapToEntities(student, mailbox, mailboxDao.loadAll(student.email))
},
- saveFetchResult = { old, new ->
+ saveFetchResult = { oldWithAuthors, new ->
+ val old = oldWithAuthors.map { it.message }
messagesDb.deleteAll(old uniqueSubtract new)
messagesDb.insertAll((new uniqueSubtract old).onEach {
- it.isNotified = !notify
+ val muted = isMuted(it.correspondents)
+ it.isNotified = !notify || muted
})
refreshHelper.updateLastRefreshTimestamp(
@@ -106,9 +111,7 @@ class MessageRepository @Inject constructor(
Timber.d("Message content in db empty: ${it.message.content.isBlank()}")
(it.message.unread && markAsRead) || it.message.content.isBlank()
},
- query = {
- messagesDb.loadMessageWithAttachment(message.messageGlobalKey)
- },
+ query = { messagesDb.loadMessageWithAttachment(message.messageGlobalKey) },
fetch = {
sdk.init(student).getMessageDetails(
messageKey = it!!.message.messageGlobalKey,
@@ -236,4 +239,18 @@ class MessageRepository @Inject constructor(
context.getString(R.string.pref_key_message_draft),
value?.let { json.encodeToString(it) }
)
+
+ suspend fun isMuted(author: String): Boolean {
+ return mutedMessageSendersDao.checkMute(author)
+ }
+
+ suspend fun muteMessage(author: String) {
+ if (isMuted(author)) return
+ mutedMessageSendersDao.insertMute(MutedMessageSender(author))
+ }
+
+ suspend fun unmuteMessage(author: String) {
+ if (!isMuted(author)) return
+ mutedMessageSendersDao.deleteMute(author)
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
index 784ac112..3fec6256 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt
@@ -304,6 +304,7 @@ class DashboardPresenter @Inject constructor(
forceRefresh = forceRefresh
)
}
+ .mapResourceData { it.map { messageWithAuthor -> messageWithAuthor.message } }
.onResourceError { errorHandler.dispatch(it) }
.takeIf { DashboardItem.Tile.MESSAGES in selectedTiles } ?: flowSuccess
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
index d3c6b95c..b83f7e23 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
@@ -50,12 +50,15 @@ class MessagePreviewAdapter @Inject constructor() :
ViewType.MESSAGE.id -> MessageViewHolder(
ItemMessagePreviewBinding.inflate(inflater, parent, false)
)
+
ViewType.DIVIDER.id -> DividerViewHolder(
ItemMessageDividerBinding.inflate(inflater, parent, false)
)
+
ViewType.ATTACHMENT.id -> AttachmentViewHolder(
ItemMessageAttachmentBinding.inflate(inflater, parent, false)
)
+
else -> throw IllegalStateException()
}
}
@@ -66,6 +69,7 @@ class MessagePreviewAdapter @Inject constructor() :
holder,
requireNotNull(messageWithAttachment).message
)
+
is AttachmentViewHolder -> bindAttachment(
holder,
requireNotNull(messageWithAttachment).attachments[position - 2]
@@ -82,9 +86,11 @@ class MessagePreviewAdapter @Inject constructor() :
recipientCount > 1 -> {
context.getString(R.string.message_read_by, message.readBy, recipientCount)
}
+
message.readBy == 1 || (isReceived && !message.unread) -> {
context.getString(R.string.message_read, context.getString(R.string.all_yes))
}
+
else -> context.getString(R.string.message_read, context.getString(R.string.all_no))
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 3ed685cd..3b33bb51 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -50,12 +50,20 @@ class MessagePreviewFragment :
private var menuPrintButton: MenuItem? = null
+ private var menuMuteButton: MenuItem? = null
+
override val titleStringId: Int
get() = R.string.message_title
override val deleteMessageSuccessString: String
get() = getString(R.string.message_delete_success)
+ override val muteMessageSuccessString: String
+ get() = getString(R.string.message_mute_success)
+
+ override val unmuteMessageSuccessString: String
+ get() = getString(R.string.message_unmute_success)
+
override val messageNoSubjectString: String
get() = getString(R.string.message_no_subject)
@@ -106,6 +114,7 @@ class MessagePreviewFragment :
menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
menuShareButton = menu.findItem(R.id.messagePreviewMenuShare)
menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint)
+ menuMuteButton = menu.findItem(R.id.messagePreviewMenuMute)
presenter.onCreateOptionsMenu()
menu.findItem(R.id.mainMenuAccount).isVisible = false
@@ -118,6 +127,7 @@ class MessagePreviewFragment :
R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
R.id.messagePreviewMenuShare -> presenter.onShare()
R.id.messagePreviewMenuPrint -> presenter.onPrint()
+ R.id.messagePreviewMenuMute -> presenter.onMute()
else -> false
}
}
@@ -129,6 +139,11 @@ class MessagePreviewFragment :
}
}
+ override fun updateMuteToggleButton(isMuted: Boolean) {
+ menuMuteButton?.setTitle(if (isMuted) R.string.message_unmute else R.string.message_mute)
+
+ }
+
override fun showProgress(show: Boolean) {
binding.messagePreviewProgress.visibility = if (show) VISIBLE else GONE
}
@@ -143,6 +158,7 @@ class MessagePreviewFragment :
menuDeleteButton?.isVisible = show
menuShareButton?.isVisible = show
menuPrintButton?.isVisible = show
+ menuMuteButton?.isVisible = show && isReplayable
}
override fun setDeletedOptionsLabels() {
@@ -213,7 +229,7 @@ class MessagePreviewFragment :
}
override fun onSaveInstanceState(outState: Bundle) {
- outState.putSerializable(MESSAGE_ID_KEY, presenter.message)
+ outState.putSerializable(MESSAGE_ID_KEY, presenter.messageWithAttachments)
super.onSaveInstanceState(outState)
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
index cd7b7284..2eff245f 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
@@ -5,7 +5,7 @@ import androidx.core.text.parseAsHtml
import io.github.wulkanowy.R
import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.MessageAttachment
+import io.github.wulkanowy.data.db.entities.MessageWithAttachment
import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.data.repositories.MessageRepository
import io.github.wulkanowy.data.repositories.PreferencesRepository
@@ -26,9 +26,7 @@ class MessagePreviewPresenter @Inject constructor(
private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
- var message: Message? = null
-
- var attachments: List? = null
+ var messageWithAttachments: MessageWithAttachment? = null
private lateinit var lastError: Throwable
@@ -38,7 +36,6 @@ class MessagePreviewPresenter @Inject constructor(
super.onAttachView(view)
view.initView()
errorHandler.showErrorMessage = ::showErrorViewOnError
- this.message = message
loadData(requireNotNull(message))
}
@@ -66,13 +63,12 @@ class MessagePreviewPresenter @Inject constructor(
.logResourceStatus("message ${messageToLoad.messageId} preview")
.onResourceData {
if (it != null) {
- message = it.message
- attachments = it.attachments
+ messageWithAttachments = it
view?.apply {
setMessageWithAttachment(it)
showContent(true)
initOptions()
-
+ updateMuteToggleButton(isMuted = it.mutedMessageSender != null)
if (preferencesRepository.isIncognitoMode && it.message.unread) {
showMessage(R.string.message_incognito_description)
}
@@ -83,8 +79,7 @@ class MessagePreviewPresenter @Inject constructor(
popView()
}
}
- }
- .onResourceSuccess {
+ }.onResourceSuccess {
if (it != null) {
analytics.logEvent(
"load_item",
@@ -92,31 +87,28 @@ class MessagePreviewPresenter @Inject constructor(
"length" to it.message.content.length
)
}
- }
- .onResourceNotLoading { view?.showProgress(false) }
- .onResourceError {
+ }.onResourceNotLoading { view?.showProgress(false) }.onResourceError {
retryCallback = { onMessageLoadRetry(messageToLoad) }
errorHandler.dispatch(it)
- }
- .launch()
+ }.launch()
}
fun onReply(): Boolean {
- return if (message != null) {
- view?.openMessageReply(message)
+ return if (messageWithAttachments?.message != null) {
+ view?.openMessageReply(messageWithAttachments?.message)
true
} else false
}
fun onForward(): Boolean {
- return if (message != null) {
- view?.openMessageForward(message)
+ return if (messageWithAttachments?.message != null) {
+ view?.openMessageForward(messageWithAttachments?.message)
true
} else false
}
fun onShare(): Boolean {
- val message = message ?: return false
+ val message = messageWithAttachments?.message ?: return false
val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }
val text = buildString {
@@ -129,13 +121,15 @@ class MessagePreviewPresenter @Inject constructor(
appendLine(message.content.parseAsHtml())
- if (!attachments.isNullOrEmpty()) {
+ if (!messageWithAttachments?.attachments.isNullOrEmpty()) {
appendLine()
appendLine("Załączniki:")
- append(attachments.orEmpty().joinToString(separator = "\n") { attachment ->
- "${attachment.filename}: ${attachment.url}"
- })
+ append(
+ messageWithAttachments?.attachments.orEmpty()
+ .joinToString(separator = "\n") { attachment ->
+ "${attachment.filename}: ${attachment.url}"
+ })
}
}
@@ -148,7 +142,7 @@ class MessagePreviewPresenter @Inject constructor(
@SuppressLint("NewApi")
fun onPrint(): Boolean {
- val message = message ?: return false
+ val message = messageWithAttachments?.message ?: return false
val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }
val dateString = message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
@@ -159,8 +153,7 @@ class MessagePreviewPresenter @Inject constructor(
append("Od
${message.sender}
")
append("DO
${message.recipients}")
}
- val messageContent = "${message.content}
"
- .replace(Regex("[\\n\\r]{2,}"), "")
+ val messageContent = "
${message.content}
".replace(Regex("[\\n\\r]{2,}"), "")
.replace(Regex("[\\n\\r]"), "
")
val jobName = buildString {
@@ -171,9 +164,7 @@ class MessagePreviewPresenter @Inject constructor(
}
view?.apply {
- val html = printHTML
- .replace("%SUBJECT%", subject)
- .replace("%CONTENT%", messageContent)
+ val html = printHTML.replace("%SUBJECT%", subject).replace("%CONTENT%", messageContent)
.replace("%INFO%", infoContent)
printDocument(html, jobName)
}
@@ -182,7 +173,7 @@ class MessagePreviewPresenter @Inject constructor(
}
private fun deleteMessage() {
- message ?: return
+ messageWithAttachments?.message ?: return
view?.run {
showContent(false)
@@ -191,24 +182,22 @@ class MessagePreviewPresenter @Inject constructor(
showErrorView(false)
}
- Timber.i("Delete message ${message?.messageGlobalKey}")
+ Timber.i("Delete message ${messageWithAttachments?.message?.messageGlobalKey}")
presenterScope.launch {
runCatching {
val student = studentRepository.getCurrentStudent(decryptPass = true)
val mailbox = messageRepository.getMailboxByStudent(student)
- messageRepository.deleteMessage(student, mailbox, message!!)
+ messageRepository.deleteMessage(student, mailbox, messageWithAttachments?.message!!)
+ }.onFailure {
+ retryCallback = { onMessageDelete() }
+ errorHandler.dispatch(it)
+ }.onSuccess {
+ view?.run {
+ showMessage(deleteMessageSuccessString)
+ popView()
+ }
}
- .onFailure {
- retryCallback = { onMessageDelete() }
- errorHandler.dispatch(it)
- }
- .onSuccess {
- view?.run {
- showMessage(deleteMessageSuccessString)
- popView()
- }
- }
view?.showProgress(false)
}
@@ -232,10 +221,10 @@ class MessagePreviewPresenter @Inject constructor(
private fun initOptions() {
view?.apply {
showOptions(
- show = message != null,
- isReplayable = message?.folderId != MessageFolder.SENT.id,
+ show = messageWithAttachments?.message != null,
+ isReplayable = messageWithAttachments?.message?.folderId != MessageFolder.SENT.id,
)
- message?.let {
+ messageWithAttachments?.message?.let {
when (it.folderId == MessageFolder.TRASHED.id) {
true -> setDeletedOptionsLabels()
false -> setNotDeletedOptionsLabels()
@@ -248,4 +237,29 @@ class MessagePreviewPresenter @Inject constructor(
fun onCreateOptionsMenu() {
initOptions()
}
+
+ fun onMute(): Boolean {
+ val message = messageWithAttachments?.message ?: return false
+ val isMuted = messageWithAttachments?.mutedMessageSender != null
+
+ presenterScope.launch {
+ runCatching {
+ when (isMuted) {
+ true -> {
+ messageRepository.unmuteMessage(message.correspondents)
+ view?.run { showMessage(unmuteMessageSuccessString) }
+ }
+
+ false -> {
+ messageRepository.muteMessage(message.correspondents)
+ view?.run { showMessage(muteMessageSuccessString) }
+ }
+ }
+ }.onFailure {
+ errorHandler.dispatch(it)
+ }
+ }
+ view?.updateMuteToggleButton(isMuted)
+ return true
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
index 7f5f140b..cbe1c3cb 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
@@ -9,6 +9,10 @@ interface MessagePreviewView : BaseView {
val deleteMessageSuccessString: String
+ val muteMessageSuccessString: String
+
+ val unmuteMessageSuccessString: String
+
val messageNoSubjectString: String
val printHTML: String
@@ -19,6 +23,8 @@ interface MessagePreviewView : BaseView {
fun setMessageWithAttachment(item: MessageWithAttachment)
+ fun updateMuteToggleButton(isMuted: Boolean)
+
fun showProgress(show: Boolean)
fun showContent(show: Boolean)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
index 9792c708..fadc77e6 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabAdapter.kt
@@ -18,8 +18,7 @@ import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.toFormattedString
import javax.inject.Inject
-class MessageTabAdapter @Inject constructor() :
- RecyclerView.Adapter() {
+class MessageTabAdapter @Inject constructor() : RecyclerView.Adapter() {
lateinit var onItemClickListener: (MessageTabDataItem.MessageItem, position: Int) -> Unit
@@ -52,10 +51,11 @@ class MessageTabAdapter @Inject constructor() :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
- return when (MessageItemViewType.values()[viewType]) {
+ return when (MessageItemViewType.entries[viewType]) {
MessageItemViewType.FILTERS -> HeaderViewHolder(
ItemMessageChipsBinding.inflate(inflater, parent, false)
)
+
MessageItemViewType.MESSAGE -> ItemViewHolder(
ItemMessageBinding.inflate(inflater, parent, false)
)
@@ -137,7 +137,12 @@ class MessageTabAdapter @Inject constructor() :
ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(currentTextColor))
isVisible = message.hasAttachments
}
- messageItemUnreadIndicator.isVisible = message.unread
+ messageItemUnreadIndicator.isVisible = message.unread || item.isMuted
+
+ when (item.isMuted) {
+ true -> messageItemUnreadIndicator.setImageResource(R.drawable.ic_notifications_off)
+ else -> messageItemUnreadIndicator.setImageResource(R.drawable.ic_circle_notification)
+ }
root.setOnClickListener {
holder.bindingAdapterPosition.let {
@@ -165,8 +170,7 @@ class MessageTabAdapter @Inject constructor() :
RecyclerView.ViewHolder(binding.root)
private class MessageTabDiffUtil(
- private val old: List,
- private val new: List
+ private val old: List, private val new: List
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = old.size
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt
index c0bd4170..ef640e04 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabDataItem.kt
@@ -6,6 +6,7 @@ sealed class MessageTabDataItem(val viewType: MessageItemViewType) {
data class MessageItem(
val message: Message,
+ val isMuted: Boolean,
val isSelected: Boolean,
val isActionMode: Boolean
) : MessageTabDataItem(MessageItemViewType.MESSAGE)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
index 90f93b14..f8283721 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/tab/MessageTabPresenter.kt
@@ -4,6 +4,7 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.data.db.entities.Message
+import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor
import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.data.repositories.MessageRepository
import io.github.wulkanowy.data.repositories.StudentRepository
@@ -39,7 +40,7 @@ class MessageTabPresenter @Inject constructor(
private var mailboxes: List = emptyList()
private var selectedMailbox: Mailbox? = null
- private var messages = emptyList()
+ private var messages = emptyList()
private val searchChannel = Channel()
@@ -141,7 +142,7 @@ class MessageTabPresenter @Inject constructor(
}
fun onActionModeSelectCheckAll() {
- val messagesToSelect = getFilteredData()
+ val messagesToSelect = getFilteredData().map { it.message }
val isAllSelected = messagesToDelete.containsAll(messagesToSelect)
if (isAllSelected) {
@@ -188,7 +189,7 @@ class MessageTabPresenter @Inject constructor(
view?.showActionMode(false)
}
- val filteredData = getFilteredData()
+ val filteredData = getFilteredData().map { it.message }
view?.run {
updateActionModeTitle(messagesToDelete.size)
@@ -320,25 +321,31 @@ class MessageTabPresenter @Inject constructor(
}
}
- private fun getFilteredData(): List {
+ private fun getFilteredData(): List {
if (lastSearchQuery.trim().isEmpty()) {
- val sortedMessages = messages.sortedByDescending { it.date }
+ val sortedMessages = messages.sortedByDescending { it.message.date }
return when {
- (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { it.unread == onlyUnread && it.hasAttachments == onlyWithAttachments }
- (onlyUnread == true) -> sortedMessages.filter { it.unread == onlyUnread }
- onlyWithAttachments -> sortedMessages.filter { it.hasAttachments == onlyWithAttachments }
+ (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter {
+ it.message.unread == onlyUnread && it.message.hasAttachments == onlyWithAttachments
+ }
+
+ (onlyUnread == true) -> sortedMessages.filter { it.message.unread == onlyUnread }
+ onlyWithAttachments -> sortedMessages.filter { it.message.hasAttachments == onlyWithAttachments }
else -> sortedMessages
}
} else {
val sortedMessages = messages
- .map { it to calculateMatchRatio(it, lastSearchQuery) }
- .sortedWith(compareBy> { -it.second }.thenByDescending { it.first.date })
+ .map { it to calculateMatchRatio(it.message, lastSearchQuery) }
+ .sortedWith(compareBy> { -it.second }.thenByDescending { it.first.message.date })
.filter { it.second > 6000 }
.map { it.first }
return when {
- (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter { it.unread == onlyUnread && it.hasAttachments == onlyWithAttachments }
- (onlyUnread == true) -> sortedMessages.filter { it.unread == onlyUnread }
- onlyWithAttachments -> sortedMessages.filter { it.hasAttachments == onlyWithAttachments }
+ (onlyUnread == true) && onlyWithAttachments -> sortedMessages.filter {
+ it.message.unread == onlyUnread && it.message.hasAttachments == onlyWithAttachments
+ }
+
+ (onlyUnread == true) -> sortedMessages.filter { it.message.unread == onlyUnread }
+ onlyWithAttachments -> sortedMessages.filter { it.message.hasAttachments == onlyWithAttachments }
else -> sortedMessages
}
}
@@ -367,8 +374,9 @@ class MessageTabPresenter @Inject constructor(
addAll(data.map { message ->
MessageTabDataItem.MessageItem(
- message = message,
- isSelected = messagesToDelete.any { it.messageGlobalKey == message.messageGlobalKey },
+ message = message.message,
+ isMuted = message.mutedMessageSender != null,
+ isSelected = messagesToDelete.any { it.messageGlobalKey == message.message.messageGlobalKey },
isActionMode = isActionMode
)
})
diff --git a/app/src/main/res/drawable/ic_circle_notification.xml b/app/src/main/res/drawable/ic_circle_notification.xml
new file mode 100644
index 00000000..6059212c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_circle_notification.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_notifications_off.xml b/app/src/main/res/drawable/ic_notifications_off.xml
new file mode 100644
index 00000000..094ed75f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_notifications_off.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/item_message.xml b/app/src/main/res/layout/item_message.xml
index 39fbaad0..1346c3f0 100644
--- a/app/src/main/res/layout/item_message.xml
+++ b/app/src/main/res/layout/item_message.xml
@@ -81,9 +81,9 @@
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index faed4d18..5bb06a41 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -864,4 +864,10 @@
Feature disabled by your school
Feature not available. Login in a mode other than Mobile API
This field is required
+
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user
diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/MessageRepositoryTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/MessageRepositoryTest.kt
index 3a18ee97..58937e77 100644
--- a/app/src/test/java/io/github/wulkanowy/data/repositories/MessageRepositoryTest.kt
+++ b/app/src/test/java/io/github/wulkanowy/data/repositories/MessageRepositoryTest.kt
@@ -6,8 +6,10 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.dao.MailboxDao
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
import io.github.wulkanowy.data.db.dao.MessagesDao
+import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.data.errorOrNull
import io.github.wulkanowy.data.toFirstResult
@@ -19,9 +21,16 @@ import io.github.wulkanowy.sdk.pojo.Folder
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.Status
import io.github.wulkanowy.utils.status
-import io.mockk.*
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.checkEquals
+import io.mockk.coEvery
+import io.mockk.coVerify
+import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
+import io.mockk.just
+import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
@@ -45,6 +54,9 @@ class MessageRepositoryTest {
@MockK
private lateinit var messageDb: MessagesDao
+ @MockK
+ private lateinit var mutesDb: MutedMessageSendersDao
+
@MockK
private lateinit var messageAttachmentDao: MessageAttachmentDao
@@ -73,9 +85,22 @@ class MessageRepositoryTest {
fun setUp() {
MockKAnnotations.init(this)
every { refreshHelper.shouldBeRefreshed(any()) } returns false
-
+ coEvery { mutesDb.checkMute(any()) } returns false
+ coEvery {
+ messageDb.loadMessagesWithMutedAuthor(
+ mailboxKey = any(),
+ folder = any()
+ )
+ } returns flowOf(emptyList())
+ coEvery {
+ messageDb.loadMessagesWithMutedAuthor(
+ folder = any(),
+ email = any()
+ )
+ } returns flowOf(emptyList())
repository = MessageRepository(
messagesDb = messageDb,
+ mutedMessageSendersDao = mutesDb,
messageAttachmentDao = messageAttachmentDao,
sdk = sdk,
context = context,
@@ -131,7 +156,11 @@ class MessageRepositoryTest {
@Test
fun `get message when content already in db`() {
val testMessage = getMessageEntity(123, "Test", false)
- val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
+ val messageWithAttachment = MessageWithAttachment(
+ testMessage,
+ emptyList(),
+ MutedMessageSender("Jan Kowalski - P - (WULKANOWY)")
+ )
coEvery { messageDb.loadMessageWithAttachment("v4") } returns flowOf(
messageWithAttachment
@@ -149,8 +178,16 @@ class MessageRepositoryTest {
val testMessage = getMessageEntity(123, "", true)
val testMessageWithContent = testMessage.copy().apply { content = "Test" }
- val mWa = MessageWithAttachment(testMessage, emptyList())
- val mWaWithContent = MessageWithAttachment(testMessageWithContent, emptyList())
+ val mWa = MessageWithAttachment(
+ testMessage,
+ emptyList(),
+ MutedMessageSender("Jan Kowalski - P - (WULKANOWY)")
+ )
+ val mWaWithContent = MessageWithAttachment(
+ testMessageWithContent,
+ emptyList(),
+ MutedMessageSender("Jan Kowalski - P - (WULKANOWY)")
+ )
coEvery {
messageDb.loadMessageWithAttachment("v4")
From 2c1337bb518893397e04b3ae99384e20c564e6c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Borcz?=
Date: Thu, 29 Feb 2024 21:36:51 +0100
Subject: [PATCH 2/3] New Crowdin updates (#2439)
---
app/src/main/res/values-cs/strings.xml | 1 +
app/src/main/res/values-de/strings.xml | 1 +
app/src/main/res/values-pl/strings.xml | 1 +
app/src/main/res/values-ru/strings.xml | 1 +
app/src/main/res/values-sk/strings.xml | 1 +
app/src/main/res/values-uk/strings.xml | 1 +
6 files changed, 6 insertions(+)
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index e1cafa6e..2e0104b1 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -854,6 +854,7 @@
Žádné internetové připojení
Vyskytla se chyba. Zkontrolujte hodiny svého zařízení
+ This account is inactive. Try logging in again
Nelze se připojit ke deníku. Servery mohou být přetíženy. Prosím zkuste to znovu později
Načítání dat se nezdařilo. Prosím zkuste to znovu později
Je vyžadována změna hesla pro deník
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 5bd71bb2..b04558aa 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -760,6 +760,7 @@
Keine Internetverbindung
Es ist ein Fehler aufgetreten. Überprüfen Sie Ihre Geräteuhr
+ This account is inactive. Try logging in again
Registrierungsverbindung fehlgeschlagen. Server können überlastet sein. Bitte versuchen Sie es später noch einmal
Das Laden der Daten ist fehlgeschlagen. Bitte versuchen Sie es später noch einmal
Passwortänderung für Registrierung erforderlich
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 70d4982b..9a7ee3f8 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -854,6 +854,7 @@
Brak połączenia z internetem
Wystąpił błąd. Sprawdź poprawność daty w urządzeniu
+ Konto jest nieaktywne. Spróbuj zalogować się ponownie
Nie udało się połączyć z dziennikiem. Serwery mogą być przeciążone. Spróbuj ponownie później
Ładowanie danych nie powiodło się. Spróbuj ponownie później
Wymagana zmiana hasła do dziennika
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 717e0213..b7786546 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -854,6 +854,7 @@
Интернет-соединение отсутствует
Произошла ошибка. Проверьте время на вашем устройстве
+ This account is inactive. Try logging in again
Не удалось подключиться к дневнику. Возможно, сервера перегружены, повторите попытку позже
Не удалось загрузить данные, повторите попытку позже
Необходимо изменить пароль дневника
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 368ead9d..d34302ec 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -854,6 +854,7 @@
Žiadne internetové pripojenie
Vyskytla sa chyba. Skontrolujte hodiny svojho zariadenia
+ This account is inactive. Try logging in again
Nedá sa pripojiť ku denníku. Servery môžu byť preťažené. Prosím skúste to znova neskôr
Načítanie údajov zlyhalo. Skúste neskôr prosím
Je vyžadovaná zmena hesla pre denník
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 3d10f117..228b87d4 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -854,6 +854,7 @@
Немає з\'єднання з інтернетом
Сталася помилка. Перевірте годинник пристрою
+ This account is inactive. Try logging in again
Помилка підключення до щоденнику. Сервери можуть бути перевантажені, спробуйте пізніше
Помилка завантаження даних, спробуйте пізніше
Необхідна зміна пароля щоденника
From c198e6a2f7e55910f96142524c1ae03139d1e368 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Borcz?=
Date: Fri, 1 Mar 2024 00:06:54 +0100
Subject: [PATCH 3/3] New Crowdin updates (#2445)
---
app/src/main/res/values-cs/strings.xml | 5 +++++
app/src/main/res/values-de/strings.xml | 5 +++++
app/src/main/res/values-pl/strings.xml | 5 +++++
app/src/main/res/values-ru/strings.xml | 5 +++++
app/src/main/res/values-sk/strings.xml | 5 +++++
app/src/main/res/values-uk/strings.xml | 5 +++++
6 files changed, 30 insertions(+)
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index 2e0104b1..5c4c52da 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -866,4 +866,9 @@
Funkce je deaktivována přes vaší školou
Funkce není k dispozici. Přihlaste se v jiném režimu než Mobile API
Toto pole je povinné
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index b04558aa..a346bbd2 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -772,4 +772,9 @@
Funktion, die von Ihrer Schule deaktiviert wurde
Feature in diesem Modus nicht verfügbar
Dieses Feld ist erforderlich
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 9a7ee3f8..56a85ea2 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -866,4 +866,9 @@
Funkcja wyłączona przez szkołę
Funkcja niedostępna. Zaloguj się w trybie innym niż Mobilne API
To pole jest wymagane
+
+ Wycisz
+ Wyłącz wyciszenie
+ Wyciszyleś tego użytkownika
+ Wyłączyłeś wyciszenie tego użytkownika
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index b7786546..f7469675 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -866,4 +866,9 @@
Функция отключена вашей школой
Функция недоступна в режиме Mobile API. Воспользуйтесь другим режимом
Это поле обязательно
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index d34302ec..56238c10 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -866,4 +866,9 @@
Funkcia je deaktivovaná cez vašou školou
Funkcia nie je k dispozícii. Prihláste sa v inom režime než Mobile API
Toto pole je povinné
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 228b87d4..a8202747 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -866,4 +866,9 @@
Функція вимкнена вашою школою
Функція недоступна в режимі Mobile API. Увійдіть в інший режим
Це поле обовʼязкове
+
+ Mute
+ Unmute
+ You have muted this user
+ You have unmuted this user