From 9d47127921d5a1d8bff07bb708e284f00ef10bd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Pich?=
Date: Mon, 22 Aug 2022 14:30:50 +0200
Subject: [PATCH] Add support for messages plus API (#1945)
---
app/build.gradle | 2 +-
.../51.json | 2409 +++++++++++++++++
.../io/github/wulkanowy/data/DataModule.kt | 4 +-
.../github/wulkanowy/data/db/AppDatabase.kt | 9 +-
.../wulkanowy/data/db/dao/MailboxDao.kt | 17 +
.../wulkanowy/data/db/dao/MessagesDao.kt | 8 +-
.../wulkanowy/data/db/dao/RecipientDao.kt | 5 +-
.../wulkanowy/data/db/dao/ReportingUnitDao.kt | 17 -
.../wulkanowy/data/db/entities/Mailbox.kt | 25 +
.../wulkanowy/data/db/entities/Message.kt | 27 +-
.../data/db/entities/MessageAttachment.kt | 7 +-
.../data/db/entities/MessageWithAttachment.kt | 2 +-
.../wulkanowy/data/db/entities/Recipient.kt | 31 +-
.../data/db/entities/ReportingUnit.kt | 32 -
.../data/db/migrations/Migration51.kt | 88 +
.../wulkanowy/data/mappers/MailboxMapper.kt | 18 +
.../wulkanowy/data/mappers/MessageMapper.kt | 46 +-
.../wulkanowy/data/mappers/RecipientMapper.kt | 17 +-
.../data/mappers/ReportingUnitMapper.kt | 16 -
.../data/repositories/MailboxRepository.kt | 48 +
.../data/repositories/MessageRepository.kt | 114 +-
.../data/repositories/RecipientRepository.kt | 37 +-
.../repositories/ReportingUnitRepository.kt | 53 -
.../notifications/NewMessageNotification.kt | 2 +-
.../services/sync/works/MessageWork.kt | 7 +-
.../services/sync/works/RecipientWork.kt | 15 +-
.../modules/dashboard/DashboardPresenter.kt | 4 +-
.../debug/notification/mock/message.kt | 13 +-
.../message/preview/MessagePreviewAdapter.kt | 26 +-
.../message/preview/MessagePreviewFragment.kt | 4 +-
.../preview/MessagePreviewPresenter.kt | 114 +-
.../message/preview/MessagePreviewView.kt | 2 +-
.../message/send/SendMessageActivity.kt | 31 +-
.../message/send/SendMessagePresenter.kt | 128 +-
.../modules/message/send/SendMessageView.kt | 12 +-
.../modules/message/tab/MessageTabAdapter.kt | 11 +-
.../message/tab/MessageTabPresenter.kt | 22 +-
.../main/res/layout/activity_send_message.xml | 3 +-
app/src/main/res/values/strings.xml | 5 +-
.../io/github/wulkanowy/TestEnityCreator.kt | 12 +
.../repositories/MessageRepositoryTest.kt | 116 +-
.../data/repositories/RecipientLocalTest.kt | 81 +-
42 files changed, 3065 insertions(+), 575 deletions(-)
create mode 100644 app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt
delete mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt
delete mode 100644 app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/mappers/MailboxMapper.kt
delete mode 100644 app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt
create mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/MailboxRepository.kt
delete mode 100644 app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt
diff --git a/app/build.gradle b/app/build.gradle
index 6d33ac476..0efb9c303 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -186,7 +186,7 @@ ext {
}
dependencies {
- implementation "io.github.wulkanowy:sdk:9032e33686"
+ implementation "io.github.wulkanowy:sdk:dbe87aac"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
diff --git a/app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
new file mode 100644
index 000000000..271b8c90b
--- /dev/null
+++ b/app/schemas/io.github.wulkanowy.data.db.AppDatabase/51.json
@@ -0,0 +1,2409 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 51,
+ "identityHash": "51f9cb1d80df003c03bb655c0162487c",
+ "entities": [
+ {
+ "tableName": "Students",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`scrapper_base_url` TEXT NOT NULL, `mobile_base_url` TEXT NOT NULL, `login_type` TEXT NOT NULL, `login_mode` TEXT NOT NULL, `certificate_key` TEXT NOT NULL, `private_key` TEXT NOT NULL, `is_parent` INTEGER NOT NULL, `email` TEXT NOT NULL, `password` TEXT NOT NULL, `symbol` TEXT NOT NULL, `student_id` INTEGER NOT NULL, `user_login_id` INTEGER NOT NULL, `user_name` TEXT NOT NULL, `student_name` TEXT NOT NULL, `school_id` TEXT NOT NULL, `school_short` TEXT NOT NULL, `school_name` TEXT NOT NULL, `class_name` TEXT NOT NULL, `class_id` INTEGER NOT NULL, `is_current` INTEGER NOT NULL, `registration_date` INTEGER NOT NULL, `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": "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_Students_email_symbol_student_id_school_id_class_id",
+ "unique": true,
+ "columnNames": [
+ "email",
+ "symbol",
+ "student_id",
+ "school_id",
+ "class_id"
+ ],
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Messages",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`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, `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": "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": "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "MessageAttachments",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`real_id` INTEGER NOT NULL, `message_global_key` TEXT NOT NULL, `url` TEXT NOT NULL, `filename` TEXT NOT NULL, PRIMARY KEY(`real_id`))",
+ "fields": [
+ {
+ "fieldPath": "realId",
+ "columnName": "real_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "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": {
+ "columnNames": [
+ "real_id"
+ ],
+ "autoGenerate": false
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Mailboxes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalKey` TEXT NOT NULL, `fullName` TEXT NOT NULL, `userName` TEXT NOT NULL, `userLoginId` INTEGER 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": "fullName",
+ "columnName": "fullName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userName",
+ "columnName": "userName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userLoginId",
+ "columnName": "userLoginId",
+ "affinity": "INTEGER",
+ "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": {
+ "columnNames": [
+ "globalKey"
+ ],
+ "autoGenerate": false
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "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, `type` TEXT NOT NULL, `is_dismissible` INTEGER NOT NULL, 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": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isDismissible",
+ "columnName": "is_dismissible",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": false
+ },
+ "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, '51f9cb1d80df003c03bb655c0162487c')"
+ ]
+ }
+}
\ No newline at end of file
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 cac3ffc23..22123cbec 100644
--- a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
@@ -19,7 +19,6 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AppInfo
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
@@ -110,7 +109,6 @@ internal class DataModule {
fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context)
- @OptIn(ExperimentalCoroutinesApi::class)
@Singleton
@Provides
fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
@@ -197,7 +195,7 @@ internal class DataModule {
@Singleton
@Provides
- fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
+ fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
@Singleton
@Provides
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
index 87915a9ed..15b38805b 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
@@ -30,7 +30,7 @@ import javax.inject.Singleton
Subject::class,
LuckyNumber::class,
CompletedLesson::class,
- ReportingUnit::class,
+ Mailbox::class,
Recipient::class,
MobileDevice::class,
Teacher::class,
@@ -55,7 +55,7 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() {
companion object {
- const val VERSION_SCHEMA = 50
+ const val VERSION_SCHEMA = 51
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
Migration2(),
@@ -103,7 +103,8 @@ abstract class AppDatabase : RoomDatabase() {
Migration44(),
Migration46(),
Migration49(),
- Migration50()
+ Migration50(),
+ Migration51(),
)
fun newInstance(
@@ -154,7 +155,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract val completedLessonsDao: CompletedLessonsDao
- abstract val reportingUnitDao: ReportingUnitDao
+ abstract val mailboxDao: MailboxDao
abstract val recipientDao: RecipientDao
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt
new file mode 100644
index 000000000..8589db311
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.Mailbox
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface MailboxDao : BaseDao {
+
+ @Query("SELECT * FROM Mailboxes WHERE userLoginId = :userLoginId ")
+ suspend fun loadAll(userLoginId: Int): List
+
+ @Query("SELECT * FROM Mailboxes WHERE userLoginId = :userLoginId AND studentName = :studentName ")
+ suspend fun load(userLoginId: Int, studentName: String): Mailbox?
+}
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 729ba6a68..8c730c9bc 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
@@ -11,9 +11,9 @@ import kotlinx.coroutines.flow.Flow
interface MessagesDao : BaseDao {
@Transaction
- @Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
- fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow
+ @Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
+ fun loadMessageWithAttachment(messageGlobalKey: String): Flow
- @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder ORDER BY date DESC")
- fun loadAll(studentId: Int, folder: Int): 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/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
index c2787ac3b..1956261eb 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
@@ -2,6 +2,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.MailboxType
import io.github.wulkanowy.data.db.entities.Recipient
import javax.inject.Singleton
@@ -9,6 +10,6 @@ import javax.inject.Singleton
@Dao
interface RecipientDao : BaseDao {
- @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND unit_id = :unitId AND role = :role")
- suspend fun loadAll(studentId: Int, unitId: Int, role: Int): List
+ @Query("SELECT * FROM Recipients WHERE type = :type AND studentMailboxGlobalKey = :studentMailboxGlobalKey")
+ suspend fun loadAll(type: MailboxType, studentMailboxGlobalKey: String): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
deleted file mode 100644
index ca697eda8..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.github.wulkanowy.data.db.dao
-
-import androidx.room.Dao
-import androidx.room.Query
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import javax.inject.Singleton
-
-@Singleton
-@Dao
-interface ReportingUnitDao : BaseDao {
-
- @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
- suspend fun load(studentId: Int): List
-
- @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
- suspend fun loadOne(studentId: Int, unitId: Int): ReportingUnit?
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt
new file mode 100644
index 000000000..7c08e481d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt
@@ -0,0 +1,25 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "Mailboxes")
+data class Mailbox(
+
+ @PrimaryKey
+ val globalKey: String,
+ val fullName: String,
+ val userName: String,
+ val userLoginId: Int,
+ val studentName: String,
+ val schoolNameShort: String,
+ val type: MailboxType,
+)
+
+enum class MailboxType {
+ STUDENT,
+ PARENT,
+ GUARDIAN,
+ EMPLOYEE,
+ UNKNOWN,
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
index 8782bc765..77874e03d 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
@@ -9,23 +9,16 @@ import java.time.Instant
@Entity(tableName = "Messages")
data class Message(
- @ColumnInfo(name = "student_id")
- val studentId: Long,
+ @ColumnInfo(name = "message_global_key")
+ val messageGlobalKey: String,
- @ColumnInfo(name = "real_id")
- val realId: Int,
+ @ColumnInfo(name = "mailbox_key")
+ val mailboxKey: String,
@ColumnInfo(name = "message_id")
val messageId: Int,
- @ColumnInfo(name = "sender_name")
- val sender: String,
-
- @ColumnInfo(name = "sender_id")
- val senderId: Int,
-
- @ColumnInfo(name = "recipient_name")
- val recipient: String,
+ val correspondents: String,
val subject: String,
@@ -36,8 +29,6 @@ data class Message(
var unread: Boolean,
- val removed: Boolean,
-
@ColumnInfo(name = "has_attachments")
val hasAttachments: Boolean
) : Serializable {
@@ -48,11 +39,7 @@ data class Message(
@ColumnInfo(name = "is_notified")
var isNotified: Boolean = true
- @ColumnInfo(name = "unread_by")
- var unreadBy: Int = 0
-
- @ColumnInfo(name = "read_by")
- var readBy: Int = 0
-
var content: String = ""
+ var sender: String? = null
+ var recipients: String? = null
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
index d1886e910..93f042999 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
@@ -12,11 +12,8 @@ data class MessageAttachment(
@ColumnInfo(name = "real_id")
val realId: Int,
- @ColumnInfo(name = "message_id")
- val messageId: Int,
-
- @ColumnInfo(name = "one_drive_id")
- val oneDriveId: String,
+ @ColumnInfo(name = "message_global_key")
+ val messageGlobalKey: String,
@ColumnInfo(name = "url")
val url: 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 2e7af0f40..cd468215d 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
@@ -7,6 +7,6 @@ data class MessageWithAttachment(
@Embedded
val message: Message,
- @Relation(parentColumn = "message_id", entityColumn = "message_id")
+ @Relation(parentColumn = "message_global_key", entityColumn = "message_global_key")
val attachments: List
)
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
index 223322705..d09742cd2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
@@ -1,6 +1,5 @@
package io.github.wulkanowy.data.db.entities
-import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
@@ -8,32 +7,16 @@ import java.io.Serializable
@kotlinx.serialization.Serializable
@Entity(tableName = "Recipients")
data class Recipient(
-
- @ColumnInfo(name = "student_id")
- val studentId: Int,
-
- @ColumnInfo(name = "real_id")
- val realId: String,
-
- val name: String,
-
- @ColumnInfo(name = "real_name")
- val realName: String,
-
- @ColumnInfo(name = "login_id")
- val loginId: Int,
-
- @ColumnInfo(name = "unit_id")
- val unitId: Int,
-
- val role: Int,
-
- val hash: String
-
+ val mailboxGlobalKey: String,
+ val studentMailboxGlobalKey: String,
+ val fullName: String,
+ val userName: String,
+ val schoolShortName: String,
+ val type: MailboxType,
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
- override fun toString() = name
+ override fun toString() = userName
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
deleted file mode 100644
index 0570a2ffd..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.github.wulkanowy.data.db.entities
-
-import androidx.room.ColumnInfo
-import androidx.room.Entity
-import androidx.room.PrimaryKey
-import java.io.Serializable
-
-@Entity(tableName = "ReportingUnits")
-data class ReportingUnit(
-
- @ColumnInfo(name = "student_id")
- val studentId: Int,
-
- @ColumnInfo(name = "real_id")
- val unitId: Int,
-
- @ColumnInfo(name = "short")
- val shortName: String,
-
- @ColumnInfo(name = "sender_id")
- val senderId: Int,
-
- @ColumnInfo(name = "sender_name")
- val senderName: String,
-
- val roles: List
-
-) : Serializable {
-
- @PrimaryKey(autoGenerate = true)
- var id: Long = 0
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt
new file mode 100644
index 000000000..e78e2e3a7
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt
@@ -0,0 +1,88 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration51 : Migration(50, 51) {
+
+ override fun migrate(database: SupportSQLiteDatabase) {
+ createMailboxTable(database)
+ recreateMessagesTable(database)
+ recreateMessageAttachmentsTable(database)
+ recreateRecipientsTable(database)
+ deleteReportingUnitTable(database)
+ }
+
+ private fun createMailboxTable(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS Mailboxes")
+ database.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Mailboxes` (
+ `globalKey` TEXT NOT NULL,
+ `fullName` TEXT NOT NULL,
+ `userName` TEXT NOT NULL,
+ `userLoginId` INTEGER NOT NULL,
+ `studentName` TEXT NOT NULL,
+ `schoolNameShort` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ PRIMARY KEY(`globalKey`)
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateMessagesTable(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS Messages")
+ database.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Messages` (
+ `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,
+ `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
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateMessageAttachmentsTable(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS MessageAttachments")
+ database.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `MessageAttachments` (
+ `real_id` INTEGER NOT NULL,
+ `message_global_key` TEXT NOT NULL,
+ `url` TEXT NOT NULL,
+ `filename` TEXT NOT NULL,
+ PRIMARY KEY(`real_id`)
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateRecipientsTable(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS Recipients")
+ database.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Recipients` (
+ `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
+ )""".trimIndent()
+ )
+ }
+
+ private fun deleteReportingUnitTable(database: SupportSQLiteDatabase) {
+ database.execSQL("DROP TABLE IF EXISTS ReportingUnits")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MailboxMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MailboxMapper.kt
new file mode 100644
index 000000000..2ccca1b90
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MailboxMapper.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Mailbox
+import io.github.wulkanowy.data.db.entities.MailboxType
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.sdk.pojo.Mailbox as SdkMailbox
+
+fun List.mapToEntities(student: Student) = map {
+ Mailbox(
+ globalKey = it.globalKey,
+ fullName = it.fullName,
+ userName = it.userName,
+ userLoginId = student.userLoginId,
+ studentName = it.studentName,
+ schoolNameShort = it.schoolNameShort,
+ type = MailboxType.valueOf(it.type.name),
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
index 13f0ab33e..2e7967f0e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/MessageMapper.kt
@@ -1,40 +1,31 @@
package io.github.wulkanowy.data.mappers
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.MessageAttachment
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.Student
-import java.time.Instant
+import io.github.wulkanowy.data.db.entities.*
+import io.github.wulkanowy.sdk.pojo.MailboxType
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
-fun List.mapToEntities(student: Student) = map {
+fun List.mapToEntities(mailbox: Mailbox) = map {
Message(
- studentId = student.id,
- realId = it.id ?: 0,
- messageId = it.messageId ?: 0,
- sender = it.sender?.name.orEmpty(),
- senderId = it.sender?.loginId ?: 0,
- recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
+ messageGlobalKey = it.globalKey,
+ mailboxKey = mailbox.globalKey,
+ messageId = it.id,
+ correspondents = it.correspondents,
subject = it.subject.trim(),
- date = it.dateZoned?.toInstant() ?: Instant.now(),
+ date = it.dateZoned.toInstant(),
folderId = it.folderId,
- unread = it.unread ?: false,
- removed = it.removed,
+ unread = it.unread,
hasAttachments = it.hasAttachments
).apply {
content = it.content.orEmpty()
- unreadBy = it.unreadBy ?: 0
- readBy = it.readBy ?: 0
}
}
-fun List.mapToEntities() = map {
+fun List.mapToEntities(messageGlobalKey: String) = map {
MessageAttachment(
- realId = it.id,
- messageId = it.messageId,
- oneDriveId = it.oneDriveId,
+ messageGlobalKey = messageGlobalKey,
+ realId = it.url.hashCode(),
url = it.url,
filename = it.filename
)
@@ -42,12 +33,11 @@ fun List.mapToEntities() = map {
fun List.mapFromEntities() = map {
SdkRecipient(
- id = it.realId,
- name = it.realName,
- loginId = it.loginId,
- reportingUnitId = it.unitId,
- role = it.role,
- hash = it.hash,
- shortName = it.name
+ fullName = it.fullName,
+ userName = it.userName,
+ studentName = it.userName,
+ mailboxGlobalKey = it.mailboxGlobalKey,
+ schoolNameShort = it.schoolShortName,
+ type = MailboxType.valueOf(it.type.name),
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt
index 80bddaab1..eb993a0f0 100644
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/RecipientMapper.kt
@@ -1,17 +1,16 @@
package io.github.wulkanowy.data.mappers
+import io.github.wulkanowy.data.db.entities.MailboxType
import io.github.wulkanowy.data.db.entities.Recipient
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
-fun List.mapToEntities(userLoginId: Int) = map {
+fun List.mapToEntities(studentMailboxGlobalKey: String) = map {
Recipient(
- studentId = userLoginId,
- realId = it.id,
- realName = it.name,
- name = it.shortName,
- hash = it.hash,
- loginId = it.loginId,
- role = it.role,
- unitId = it.reportingUnitId ?: 0
+ mailboxGlobalKey = it.mailboxGlobalKey,
+ fullName = it.fullName,
+ userName = it.userName,
+ studentMailboxGlobalKey = studentMailboxGlobalKey,
+ schoolShortName = it.schoolNameShort,
+ type = MailboxType.valueOf(it.type.name),
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt
deleted file mode 100644
index 6a21d59fc..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/mappers/ReportingUnitMapper.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.github.wulkanowy.data.mappers
-
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.sdk.pojo.ReportingUnit as SdkReportingUnit
-
-fun List.mapToEntities(student: Student) = map {
- ReportingUnit(
- studentId = student.id.toInt(),
- unitId = it.id,
- roles = it.roles,
- senderId = it.senderId,
- senderName = it.senderName,
- shortName = it.short
- )
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/MailboxRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/MailboxRepository.kt
new file mode 100644
index 000000000..7f5974920
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/MailboxRepository.kt
@@ -0,0 +1,48 @@
+package io.github.wulkanowy.data.repositories
+
+import io.github.wulkanowy.data.db.dao.MailboxDao
+import io.github.wulkanowy.data.db.entities.Mailbox
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.AutoRefreshHelper
+import io.github.wulkanowy.utils.getRefreshKey
+import io.github.wulkanowy.utils.init
+import io.github.wulkanowy.utils.uniqueSubtract
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class MailboxRepository @Inject constructor(
+ private val mailboxDao: MailboxDao,
+ private val sdk: Sdk,
+ private val refreshHelper: AutoRefreshHelper,
+) {
+ private val cacheKey = "mailboxes"
+
+ suspend fun refreshMailboxes(student: Student) {
+ val new = sdk.init(student).getMailboxes().mapToEntities(student)
+ val old = mailboxDao.loadAll(student.userLoginId)
+
+ mailboxDao.deleteAll(old uniqueSubtract new)
+ mailboxDao.insertAll(new uniqueSubtract old)
+
+ refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
+ }
+
+ suspend fun getMailbox(student: Student): Mailbox {
+ val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
+ val mailbox = mailboxDao.load(student.userLoginId, student.studentName)
+
+ return if (isExpired || mailbox == null) {
+ refreshMailboxes(student)
+ val newMailbox = mailboxDao.load(student.userLoginId, student.studentName)
+
+ requireNotNull(newMailbox) {
+ "Mailbox for ${student.userName} - ${student.studentName} not found!"
+ }
+
+ newMailbox
+ } else mailbox
+ }
+}
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 05fb97657..00cbffb84 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
@@ -10,24 +10,24 @@ import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.entities.*
import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
+import io.github.wulkanowy.data.enums.MessageFolder.TRASHED
import io.github.wulkanowy.data.mappers.mapFromEntities
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.data.pojos.MessageDraft
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Folder
-import io.github.wulkanowy.sdk.pojo.SentMessage
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey
import io.github.wulkanowy.utils.init
import io.github.wulkanowy.utils.uniqueSubtract
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.sync.Mutex
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import timber.log.Timber
-import java.time.LocalDateTime.now
import javax.inject.Inject
import javax.inject.Singleton
@@ -49,7 +49,7 @@ class MessageRepository @Inject constructor(
@Suppress("UNUSED_PARAMETER")
fun getMessages(
student: Student,
- semester: Semester,
+ mailbox: Mailbox,
folder: MessageFolder,
forceRefresh: Boolean,
notify: Boolean = false,
@@ -62,42 +62,20 @@ class MessageRepository @Inject constructor(
)
it.isEmpty() || forceRefresh || isExpired
},
- query = { messagesDb.loadAll(student.id.toInt(), folder.id) },
+ query = { messagesDb.loadAll(mailbox.globalKey, folder.id) },
fetch = {
- sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now())
- .mapToEntities(student)
+ sdk.init(student).getMessages(Folder.valueOf(folder.name)).mapToEntities(mailbox)
},
saveFetchResult = { old, new ->
messagesDb.deleteAll(old uniqueSubtract new)
messagesDb.insertAll((new uniqueSubtract old).onEach {
it.isNotified = !notify
})
- messagesDb.updateAll(getMessagesWithReadByChange(old, new, !notify))
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder))
}
)
- private fun getMessagesWithReadByChange(
- old: List,
- new: List,
- setNotified: Boolean
- ): List {
- val oldMeta = old.map { Triple(it, it.readBy, it.unreadBy) }
- val newMeta = new.map { Triple(it, it.readBy, it.unreadBy) }
-
- val updatedItems = newMeta uniqueSubtract oldMeta
-
- return updatedItems.map {
- val oldItem = old.find { item -> item.messageId == it.first.messageId }
- it.first.apply {
- id = oldItem?.id ?: 0
- isNotified = oldItem?.isNotified ?: setNotified
- content = oldItem?.content.orEmpty()
- }
- }
- }
-
fun getMessage(
student: Student,
message: Message,
@@ -106,34 +84,34 @@ class MessageRepository @Inject constructor(
isResultEmpty = { it?.message?.content.isNullOrBlank() },
shouldFetch = {
checkNotNull(it) { "This message no longer exist!" }
- Timber.d("Message content in db empty: ${it.message.content.isEmpty()}")
- it.message.unread || it.message.content.isEmpty()
+ Timber.d("Message content in db empty: ${it.message.content.isBlank()}")
+ it.message.unread || it.message.content.isBlank()
},
- query = { messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId) },
+ query = { messagesDb.loadMessageWithAttachment(message.messageGlobalKey) },
fetch = {
- sdk.init(student).getMessageDetails(
- messageId = it!!.message.messageId,
- folderId = message.folderId,
- read = markAsRead,
- id = message.realId
- ).let { details ->
- details.content to details.attachments.mapToEntities()
- }
+ sdk.init(student).getMessageDetails(it!!.message.messageGlobalKey)
},
- saveFetchResult = { old, (downloadedMessage, attachments) ->
+ saveFetchResult = { old, new ->
checkNotNull(old) { "Fetched message no longer exist!" }
- messagesDb.updateAll(listOf(old.message.apply {
- id = old.message.id
- unread = !markAsRead
- content = content.ifBlank { downloadedMessage }
- }))
- messageAttachmentDao.insertAttachments(attachments)
+ messagesDb.updateAll(
+ listOf(old.message.apply {
+ id = message.id
+ unread = !markAsRead
+ sender = new.sender
+ recipients = new.recipients.firstOrNull() ?: "Wielu adresoatów"
+ content = content.ifBlank { new.content }
+ })
+ )
+ messageAttachmentDao.insertAttachments(
+ items = new.attachments.mapToEntities(message.messageGlobalKey),
+ )
+
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
}
)
- fun getMessagesFromDatabase(student: Student): Flow> {
- return messagesDb.loadAll(student.id.toInt(), RECEIVED.id)
+ fun getMessagesFromDatabase(mailbox: Mailbox): Flow> {
+ return messagesDb.loadAll(mailbox.globalKey, RECEIVED.id)
}
suspend fun updateMessages(messages: List) {
@@ -145,32 +123,48 @@ class MessageRepository @Inject constructor(
subject: String,
content: String,
recipients: List,
- ): SentMessage = sdk.init(student).sendMessage(
- subject = subject,
- content = content,
- recipients = recipients.mapFromEntities()
- )
+ mailboxId: String,
+ ) {
+ sdk.init(student).sendMessage(
+ subject = subject,
+ content = content,
+ recipients = recipients.mapFromEntities(),
+ mailboxId = mailboxId,
+ )
+ }
- suspend fun deleteMessages(student: Student, messages: List) {
- val folderId = messages.first().folderId
- val isDeleted = sdk.init(student)
- .deleteMessages(messages = messages.map { it.messageId }, folderId = folderId)
+ suspend fun deleteMessages(student: Student, mailbox: Mailbox, messages: List) {
+ val firstMessage = messages.first()
+ sdk.init(student).deleteMessages(
+ messages = messages.map { it.messageGlobalKey },
+ removeForever = firstMessage.folderId == TRASHED.id,
+ )
- if (folderId != MessageFolder.TRASHED.id && isDeleted) {
+ if (firstMessage.folderId != TRASHED.id) {
val deletedMessages = messages.map {
- it.copy(folderId = MessageFolder.TRASHED.id)
+ it.copy(folderId = TRASHED.id)
.apply {
id = it.id
content = it.content
+ sender = it.sender
+ recipients = it.recipients
}
}
messagesDb.updateAll(deletedMessages)
} else messagesDb.deleteAll(messages)
+
+ getMessages(
+ student = student,
+ mailbox = mailbox,
+ folder = TRASHED,
+ forceRefresh = true,
+ ).first()
}
- suspend fun deleteMessage(student: Student, message: Message) =
- deleteMessages(student, listOf(message))
+ suspend fun deleteMessage(student: Student, mailbox: Mailbox, message: Message) {
+ deleteMessages(student, mailbox, listOf(message))
+ }
var draftMessage: MessageDraft?
get() = sharedPrefProvider.getString(context.getString(R.string.pref_key_message_send_draft))
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
index 60e6f248f..e80f028e1 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/repositories/RecipientRepository.kt
@@ -1,10 +1,7 @@
package io.github.wulkanowy.data.repositories
import io.github.wulkanowy.data.db.dao.RecipientDao
-import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.db.entities.*
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AutoRefreshHelper
@@ -23,9 +20,10 @@ class RecipientRepository @Inject constructor(
private val cacheKey = "recipient"
- suspend fun refreshRecipients(student: Student, unit: ReportingUnit, role: Int) {
- val new = sdk.init(student).getRecipients(unit.unitId, role).mapToEntities(unit.studentId)
- val old = recipientDb.loadAll(unit.studentId, unit.unitId, role)
+ suspend fun refreshRecipients(student: Student, mailbox: Mailbox, type: MailboxType) {
+ val new = sdk.init(student).getRecipients(mailbox.globalKey)
+ .mapToEntities(mailbox.globalKey)
+ val old = recipientDb.loadAll(type, mailbox.globalKey)
recipientDb.deleteAll(old uniqueSubtract new)
recipientDb.insertAll(new uniqueSubtract old)
@@ -33,18 +31,27 @@ class RecipientRepository @Inject constructor(
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
}
- suspend fun getRecipients(student: Student, unit: ReportingUnit, role: Int): List {
- val cached = recipientDb.loadAll(unit.studentId, unit.unitId, role)
+ suspend fun getRecipients(
+ student: Student,
+ mailbox: Mailbox,
+ type: MailboxType
+ ): List {
+ val cached = recipientDb.loadAll(type, mailbox.globalKey)
val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
return if (cached.isEmpty() || isExpired) {
- refreshRecipients(student, unit, role)
- recipientDb.loadAll(unit.studentId, unit.unitId, role)
+ refreshRecipients(student, mailbox, type)
+ recipientDb.loadAll(type, mailbox.globalKey)
} else cached
}
- suspend fun getMessageRecipients(student: Student, message: Message): List {
- return sdk.init(student).getMessageRecipients(message.messageId, message.senderId)
- .mapToEntities(student.studentId)
- }
+ suspend fun getMessageSender(
+ student: Student,
+ mailbox: Mailbox,
+ message: Message
+ ): List = sdk.init(student)
+ .getMessageReplayDetails(message.messageGlobalKey)
+ .sender
+ .let(::listOf)
+ .mapToEntities(mailbox.globalKey)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt
deleted file mode 100644
index 84055cef0..000000000
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/ReportingUnitRepository.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.github.wulkanowy.data.repositories
-
-import io.github.wulkanowy.data.db.dao.ReportingUnitDao
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.github.wulkanowy.data.db.entities.Student
-import io.github.wulkanowy.data.mappers.mapToEntities
-import io.github.wulkanowy.sdk.Sdk
-import io.github.wulkanowy.utils.AutoRefreshHelper
-import io.github.wulkanowy.utils.getRefreshKey
-import io.github.wulkanowy.utils.init
-import io.github.wulkanowy.utils.uniqueSubtract
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReportingUnitRepository @Inject constructor(
- private val reportingUnitDb: ReportingUnitDao,
- private val sdk: Sdk,
- private val refreshHelper: AutoRefreshHelper,
-) {
-
- private val cacheKey = "reporting_unit"
-
- suspend fun refreshReportingUnits(student: Student) {
- val new = sdk.init(student).getReportingUnits().mapToEntities(student)
- val old = reportingUnitDb.load(student.id.toInt())
-
- reportingUnitDb.deleteAll(old.uniqueSubtract(new))
- reportingUnitDb.insertAll(new.uniqueSubtract(old))
-
- refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
- }
-
- suspend fun getReportingUnits(student: Student): List {
- val cached = reportingUnitDb.load(student.id.toInt())
- val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
-
- return if (cached.isEmpty() || isExpired) {
- refreshReportingUnits(student)
- reportingUnitDb.load(student.id.toInt())
- } else cached
- }
-
- suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
- val cached = reportingUnitDb.loadOne(student.id.toInt(), unitId)
- val isExpired = refreshHelper.shouldBeRefreshed(getRefreshKey(cacheKey, student))
-
- return if (cached == null || isExpired) {
- refreshReportingUnits(student)
- reportingUnitDb.loadOne(student.id.toInt(), unitId)
- } else cached
- }
-}
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewMessageNotification.kt b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewMessageNotification.kt
index 5c3c52c5b..3b7bcff05 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewMessageNotification.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/notifications/NewMessageNotification.kt
@@ -21,7 +21,7 @@ class NewMessageNotification @Inject constructor(
val notificationDataList = items.map {
NotificationData(
title = context.getPlural(R.plurals.message_new_items, 1),
- content = "${it.sender}: ${it.subject}",
+ content = "${it.correspondents}: ${it.subject}",
destination = Destination.Message,
)
}
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
index 26fac1a2f..180568267 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/MessageWork.kt
@@ -3,6 +3,7 @@ package io.github.wulkanowy.services.sync.works
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
+import io.github.wulkanowy.data.repositories.MailboxRepository
import io.github.wulkanowy.data.repositories.MessageRepository
import io.github.wulkanowy.data.waitForResult
import io.github.wulkanowy.services.sync.notifications.NewMessageNotification
@@ -11,19 +12,21 @@ import javax.inject.Inject
class MessageWork @Inject constructor(
private val messageRepository: MessageRepository,
+ private val mailboxRepository: MailboxRepository,
private val newMessageNotification: NewMessageNotification,
) : Work {
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
+ val mailbox = mailboxRepository.getMailbox(student)
messageRepository.getMessages(
student = student,
- semester = semester,
+ mailbox = mailbox,
folder = RECEIVED,
forceRefresh = true,
notify = notify
).waitForResult()
- messageRepository.getMessagesFromDatabase(student).first()
+ messageRepository.getMessagesFromDatabase(mailbox).first()
.filter { !it.isNotified && it.unread }.let {
if (it.isNotEmpty()) newMessageNotification.notify(it, student)
messageRepository.updateMessages(it.onEach { message -> message.isNotified = true })
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
index 425e68b91..b1322ada3 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/works/RecipientWork.kt
@@ -1,23 +1,22 @@
package io.github.wulkanowy.services.sync.works
+import io.github.wulkanowy.data.db.entities.MailboxType
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.repositories.MailboxRepository
import io.github.wulkanowy.data.repositories.RecipientRepository
-import io.github.wulkanowy.data.repositories.ReportingUnitRepository
import javax.inject.Inject
class RecipientWork @Inject constructor(
- private val reportingUnitRepository: ReportingUnitRepository,
+ private val mailboxRepository: MailboxRepository,
private val recipientRepository: RecipientRepository
) : Work {
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
- reportingUnitRepository.refreshReportingUnits(student)
+ mailboxRepository.refreshMailboxes(student)
- reportingUnitRepository.getReportingUnits(student).let { units ->
- units.map {
- recipientRepository.refreshRecipients(student, it, 2)
- }
- }
+ val mailbox = mailboxRepository.getMailbox(student)
+
+ recipientRepository.refreshRecipients(student, mailbox, MailboxType.EMPLOYEE)
}
}
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 5d7c7df4b..350300937 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
@@ -25,6 +25,7 @@ class DashboardPresenter @Inject constructor(
private val gradeRepository: GradeRepository,
private val semesterRepository: SemesterRepository,
private val messageRepository: MessageRepository,
+ private val mailboxRepository: MailboxRepository,
private val attendanceSummaryRepository: AttendanceSummaryRepository,
private val timetableRepository: TimetableRepository,
private val homeworkRepository: HomeworkRepository,
@@ -227,6 +228,7 @@ class DashboardPresenter @Inject constructor(
private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) {
flow {
val semester = semesterRepository.getCurrentSemester(student)
+ val mailbox = mailboxRepository.getMailbox(student)
val selectedTiles = preferencesRepository.selectedDashboardTiles
val flowSuccess = flowOf(Resource.Success(null))
@@ -238,7 +240,7 @@ class DashboardPresenter @Inject constructor(
val messageFLow = messageRepository.getMessages(
student = student,
- semester = semester,
+ mailbox = mailbox,
folder = MessageFolder.RECEIVED,
forceRefresh = forceRefresh
).takeIf { DashboardItem.Tile.MESSAGES in selectedTiles } ?: flowSuccess
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/message.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/message.kt
index 53d439612..6ff26162b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/message.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/debug/notification/mock/message.kt
@@ -17,16 +17,13 @@ val debugMessageItems = listOf(
)
private fun generateMessage(sender: String, subject: String) = Message(
- sender = sender,
subject = subject,
- studentId = 0,
- realId = 0,
- messageId = 0,
- senderId = 0,
- recipient = "",
+ messageId = 123,
date = Instant.now(),
folderId = 0,
unread = true,
- removed = false,
- hasAttachments = false
+ hasAttachments = false,
+ messageGlobalKey = "",
+ correspondents = sender,
+ mailboxKey = "",
)
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 d75128be1..3c1c53d39 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
@@ -4,6 +4,8 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT
+import androidx.core.text.parseAsHtml
import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message
@@ -75,29 +77,25 @@ class MessagePreviewAdapter @Inject constructor() :
@SuppressLint("SetTextI18n")
private fun bindMessage(holder: MessageViewHolder, message: Message) {
val context = holder.binding.root.context
- val recipientCount = message.unreadBy + message.readBy
- val readText = when {
- recipientCount > 1 -> {
- context.getString(R.string.message_read_by, message.readBy, recipientCount)
- }
- message.readBy == 1 -> {
- 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))
+ val readTextValue = when {
+ !message.unread -> R.string.all_yes
+ else -> R.string.all_no
}
+ val readText = context.getString(R.string.message_read, context.getString(readTextValue))
with(holder.binding) {
- messagePreviewSubject.text =
- message.subject.ifBlank { root.context.getString(R.string.message_no_subject) }
- messagePreviewDate.text = root.context.getString(
+ messagePreviewSubject.text = message.subject.ifBlank {
+ context.getString(R.string.message_no_subject)
+ }
+ messagePreviewDate.text = context.getString(
R.string.message_date,
message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
)
messagePreviewRead.text = readText
- messagePreviewContent.text = message.content
+ messagePreviewContent.text = message.content.parseAsHtml(FROM_HTML_MODE_COMPACT)
messagePreviewFromSender.text = message.sender
- messagePreviewToRecipient.text = message.recipient
+ messagePreviewToRecipient.text = message.recipients
}
}
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 4b2685c6d..2a5523f4d 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
@@ -135,8 +135,8 @@ class MessagePreviewFragment :
binding.messagePreviewRecycler.visibility = if (show) VISIBLE else GONE
}
- override fun showOptions(show: Boolean) {
- menuReplyButton?.isVisible = show
+ override fun showOptions(show: Boolean, isReplayable: Boolean) {
+ menuReplyButton?.isVisible = isReplayable
menuForwardButton?.isVisible = show
menuDeleteButton?.isVisible = show
menuShareButton?.isVisible = show
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 39c337bf2..c011f41f3 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
@@ -1,10 +1,12 @@
package io.github.wulkanowy.ui.modules.message.preview
import android.annotation.SuppressLint
+import androidx.core.text.parseAsHtml
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.enums.MessageFolder
+import io.github.wulkanowy.data.repositories.MailboxRepository
import io.github.wulkanowy.data.repositories.MessageRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
@@ -19,6 +21,7 @@ class MessagePreviewPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val messageRepository: MessageRepository,
+ private val mailboxRepository: MailboxRepository,
private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
@@ -52,7 +55,7 @@ class MessagePreviewPresenter @Inject constructor(
private fun loadData(messageToLoad: Message) {
flatResourceFlow {
- val student = studentRepository.getStudentById(messageToLoad.studentId)
+ val student = studentRepository.getCurrentStudent()
messageRepository.getMessage(student, messageToLoad, true)
}
.logResourceStatus("message ${messageToLoad.messageId} preview")
@@ -104,62 +107,69 @@ class MessagePreviewPresenter @Inject constructor(
}
fun onShare(): Boolean {
- message?.let {
- var text =
- "Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) {
- true -> "Od: ${it.sender}\n"
- false -> "Do: ${it.recipient}\n"
- } + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}"
+ val message = message ?: return false
+ val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }
- attachments?.let { attachments ->
- if (attachments.isNotEmpty()) {
- text += "\n\nZałączniki:"
+ val text = buildString {
+ appendLine("Temat: $subject")
+ appendLine("Od: ${message.sender}")
+ appendLine("Do: ${message.recipients}")
+ appendLine("Data: ${message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}")
- attachments.forEach { attachment ->
- text += "\n${attachment.filename}: ${attachment.url}"
- }
- }
+ appendLine()
+
+ appendLine(message.content.parseAsHtml())
+
+ if (!attachments.isNullOrEmpty()) {
+ appendLine()
+ appendLine("Załączniki:")
+
+ append(attachments.orEmpty().joinToString(separator = "\n") { attachment ->
+ "${attachment.filename}: ${attachment.url}"
+ })
}
-
- view?.shareText(
- text,
- "FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}"
- )
- return true
}
- return false
+
+ view?.shareText(
+ subject = "FW: $subject",
+ text = text,
+ )
+ return true
}
@SuppressLint("NewApi")
fun onPrint(): Boolean {
- message?.let {
- val dateString = it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
- val infoContent = "Data wysłania
$dateString
" + when {
- it.sender.isNotEmpty() -> "Od
${it.sender}"
- else -> "Do
${it.recipient}"
- }
+ val message = message ?: return false
+ val subject = message.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }
- val messageContent = "${it.content}
"
- .replace(Regex("[\\n\\r]{2,}"), "")
- .replace(Regex("[\\n\\r]"), "
")
+ val dateString = message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
- val jobName = "Wiadomość " + when {
- it.sender.isNotEmpty() -> "od ${it.sender}"
- else -> "do ${it.recipient}"
- } + " $dateString: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }} | Wulkanowy"
+ val infoContent = buildString {
+ append("
Data wysłania
$dateString")
- view?.apply {
- val html = printHTML
- .replace(
- "%SUBJECT%",
- it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() })
- .replace("%CONTENT%", messageContent)
- .replace("%INFO%", infoContent)
- printDocument(html, jobName)
- }
- return true
+ append("Od
${message.sender}")
+ append("DO
${message.recipients}")
}
- return false
+ val messageContent = "${message.content}
"
+ .replace(Regex("[\\n\\r]{2,}"), "")
+ .replace(Regex("[\\n\\r]"), "
")
+
+ val jobName = buildString {
+ append("Wiadomość ")
+ append("od ${message.correspondents}")
+ append("do ${message.correspondents}")
+ append(" $dateString: $subject | Wulkanowy")
+ }
+
+ view?.apply {
+ val html = printHTML
+ .replace("%SUBJECT%", subject)
+ .replace("%CONTENT%", messageContent)
+ .replace("%INFO%", infoContent)
+ printDocument(html, jobName)
+ }
+
+ return true
}
private fun deleteMessage() {
@@ -168,16 +178,17 @@ class MessagePreviewPresenter @Inject constructor(
view?.run {
showContent(false)
showProgress(true)
- showOptions(false)
+ showOptions(show = false, isReplayable = false)
showErrorView(false)
}
- Timber.i("Delete message ${message?.id}")
+ Timber.i("Delete message ${message?.messageGlobalKey}")
presenterScope.launch {
runCatching {
- val student = studentRepository.getCurrentStudent()
- messageRepository.deleteMessage(student, message!!)
+ val student = studentRepository.getCurrentStudent(decryptPass = true)
+ val mailbox = mailboxRepository.getMailbox(student)
+ messageRepository.deleteMessage(student, mailbox, message!!)
}
.onFailure {
retryCallback = { onMessageDelete() }
@@ -211,7 +222,10 @@ class MessagePreviewPresenter @Inject constructor(
private fun initOptions() {
view?.apply {
- showOptions(message != null)
+ showOptions(
+ show = message != null,
+ isReplayable = message?.folderId != MessageFolder.SENT.id,
+ )
message?.let {
when (it.folderId == MessageFolder.TRASHED.id) {
true -> setDeletedOptionsLabels()
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 88fe77d94..c5a947939 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
@@ -28,7 +28,7 @@ interface MessagePreviewView : BaseView {
fun setErrorRetryCallback(callback: () -> Unit)
- fun showOptions(show: Boolean)
+ fun showOptions(show: Boolean, isReplayable: Boolean)
fun setDeletedOptionsLabels()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
index 70f9a9b54..334e389e2 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageActivity.kt
@@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.os.Bundle
+import android.text.Spanned
import android.view.Menu
import android.view.MenuItem
import android.view.TouchDelegate
@@ -13,11 +14,12 @@ import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
+import androidx.core.text.parseAsHtml
+import androidx.core.text.toHtml
import androidx.core.widget.doOnTextChanged
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message
-import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.databinding.ActivitySendMessageBinding
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.utils.dpToPx
@@ -72,17 +74,32 @@ class SendMessageActivity : BaseActivity
formSubjectValue = binding.sendMessageSubject.text.toString()
- formContentValue = binding.sendMessageMessageContent.text.toString()
+ formContentValue =
+ binding.sendMessageMessageContent.text.toString().parseAsHtml().toString()
presenter.onAttachView(
view = this,
@@ -110,7 +127,7 @@ class SendMessageActivity : BaseActivity) {
@@ -165,7 +182,7 @@ class SendMessageActivity : BaseActivity "Re: "
+ true -> "RE: "
else -> "FW: "
} + message.subject
)
if (preferencesRepository.fillMessageContent || reply != true) {
- setContent(
- when (reply) {
- true -> "\n\n"
- else -> ""
- } + when (message.sender.isNotEmpty()) {
- true -> "Od: ${message.sender}\n"
- false -> "Do: ${message.recipient}\n"
- } + "Data: ${message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${message.content}"
- )
+ setContent(buildString {
+ if (reply == true) {
+ append("
")
+ }
+
+ append("Od: ${message.sender}
")
+ append("Do: ${message.recipients}
")
+ append("Data: ${message.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}
")
+ append(message.content)
+ })
}
}
}
@@ -111,21 +113,24 @@ class SendMessagePresenter @Inject constructor(
private fun loadData(message: Message?, reply: Boolean?) {
resourceFlow {
val student = studentRepository.getCurrentStudent()
- val semester = semesterRepository.getCurrentSemester(student)
- val unit = reportingUnitRepository.getReportingUnit(student, semester.unitId)
+ val mailbox = mailboxRepository.getMailbox(student)
Timber.i("Loading recipients started")
- val recipients = when {
- unit != null -> recipientRepository.getRecipients(student, unit, 2)
- else -> listOf()
- }.let { createChips(it) }
+ val recipients = createChips(
+ recipients = recipientRepository.getRecipients(
+ student = student,
+ mailbox = mailbox,
+ type = MailboxType.EMPLOYEE,
+ )
+ )
Timber.i("Loading recipients result: Success, fetched %d recipients", recipients.size)
Timber.i("Loading message recipients started")
val messageRecipients = when {
- message != null && reply == true -> recipientRepository.getMessageRecipients(
- student,
- message
+ message != null && reply == true -> recipientRepository.getMessageSender(
+ student = student,
+ message = message,
+ mailbox = mailbox,
)
else -> emptyList()
}.let { createChips(it) }
@@ -134,7 +139,7 @@ class SendMessagePresenter @Inject constructor(
messageRecipients.size
)
- Triple(unit, recipients, messageRecipients)
+ Triple(mailbox, recipients, messageRecipients)
}
.logResourceStatus("load recipients")
.onEach {
@@ -143,19 +148,14 @@ class SendMessagePresenter @Inject constructor(
showProgress(true)
showContent(false)
}
- is Resource.Success -> it.data.let { (reportingUnit, recipientChips, selectedRecipientChips) ->
+ is Resource.Success -> it.data.let { (mailbox, recipientChips, selectedRecipientChips) ->
view?.run {
- if (reportingUnit != null) {
- setReportingUnit(reportingUnit)
- setRecipients(recipientChips)
- if (selectedRecipientChips.isNotEmpty()) setSelectedRecipients(
- selectedRecipientChips
- )
- showContent(true)
- } else {
- Timber.i("Loading recipients result: Can't find the reporting unit")
- view?.showEmpty(true)
- }
+ setMailbox(getMailboxName(mailbox))
+ setRecipients(recipientChips)
+ if (selectedRecipientChips.isNotEmpty()) setSelectedRecipients(
+ selectedRecipientChips
+ )
+ showContent(true)
}
}
is Resource.Error -> {
@@ -171,7 +171,14 @@ class SendMessagePresenter @Inject constructor(
private fun sendMessage(subject: String, content: String, recipients: List) {
resourceFlow {
val student = studentRepository.getCurrentStudent()
- messageRepository.sendMessage(student, subject, content, recipients)
+ val mailbox = mailboxRepository.getMailbox(student)
+ messageRepository.sendMessage(
+ student = student,
+ subject = subject,
+ content = content,
+ recipients = recipients,
+ mailboxId = mailbox.globalKey,
+ )
}.logResourceStatus("sending message").onEach {
when (it) {
is Resource.Loading -> view?.run {
@@ -201,31 +208,44 @@ class SendMessagePresenter @Inject constructor(
}
private fun createChips(recipients: List): List {
- fun generateCorrectSummary(recipientRealName: String): String {
- val substring = recipientRealName.substringBeforeLast("-")
- return when {
- substring == recipientRealName -> recipientRealName
- substring.indexOf("(") != -1 -> {
- recipientRealName.indexOf("(")
- .let { recipientRealName.substring(if (it != -1) it else 0) }
- }
- substring.indexOf("[") != -1 -> {
- recipientRealName.indexOf("[")
- .let { recipientRealName.substring(if (it != -1) it else 0) }
- }
- else -> recipientRealName.substringAfter("-")
- }.trim()
- }
-
return recipients.map {
RecipientChipItem(
- title = it.name,
- summary = generateCorrectSummary(it.realName),
+ title = it.userName,
+ summary = buildString {
+ getMailboxType(it.type)?.let(::append)
+ if (isNotBlank()) append(" ")
+
+ append("(${it.schoolShortName})")
+ },
recipient = it
)
}
}
+ private fun getMailboxName(mailbox: Mailbox): String {
+ return buildString {
+ append(mailbox.userName)
+ append(" - ")
+ append(getMailboxType(mailbox.type))
+
+ if (mailbox.type == MailboxType.PARENT) {
+ append(" - ")
+ append(mailbox.studentName)
+ }
+
+ append(" - ")
+ append("(${mailbox.schoolNameShort})")
+ }
+ }
+
+ private fun getMailboxType(type: MailboxType): String? = when (type) {
+ MailboxType.STUDENT -> view?.mailboxStudent
+ MailboxType.PARENT -> view?.mailboxParent
+ MailboxType.GUARDIAN -> view?.mailboxGuardian
+ MailboxType.EMPLOYEE -> view?.mailboxEmployee
+ MailboxType.UNKNOWN -> null
+ }
+
fun onMessageContentChange() {
presenterScope.launch {
messageUpdateChannel.send(Unit)
@@ -263,7 +283,7 @@ class SendMessagePresenter @Inject constructor(
fun getRecipientsNames(): String {
return messageRepository.draftMessage?.recipients.orEmpty()
- .joinToString { it.recipient.name }
+ .joinToString { it.recipient.userName }
}
fun clearDraft() {
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt
index 21b42e3e4..1057114b8 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/send/SendMessageView.kt
@@ -1,6 +1,6 @@
package io.github.wulkanowy.ui.modules.message.send
-import io.github.wulkanowy.data.db.entities.ReportingUnit
+import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.ui.base.BaseView
interface SendMessageView : BaseView {
@@ -18,9 +18,17 @@ interface SendMessageView : BaseView {
val messageSuccess: String
+ val mailboxStudent: String
+
+ val mailboxParent: String
+
+ val mailboxGuardian: String
+
+ val mailboxEmployee: String
+
fun initView()
- fun setReportingUnit(unit: ReportingUnit)
+ fun setMailbox(mailbox: String)
fun setRecipients(recipients: List)
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 af0923b94..55f03ef84 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
@@ -8,7 +8,6 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R
-import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.databinding.ItemMessageBinding
import io.github.wulkanowy.databinding.ItemMessageChipsBinding
import io.github.wulkanowy.utils.toFormattedString
@@ -88,12 +87,8 @@ class MessageTabAdapter @Inject constructor() :
with(holder.binding) {
val style = if (message.unread) Typeface.BOLD else Typeface.NORMAL
- messageItemAuthor.run {
- text = if (message.folderId == MessageFolder.SENT.id) {
- message.recipient
- } else {
- message.sender
- }
+ with(messageItemAuthor) {
+ text = message.correspondents
setTypeface(null, style)
}
messageItemSubject.run {
@@ -145,7 +140,7 @@ class MessageTabAdapter @Inject constructor() :
val newItem = new[newItemPosition]
return if (oldItem is MessageTabDataItem.MessageItem && newItem is MessageTabDataItem.MessageItem) {
- oldItem.message.id == newItem.message.id
+ oldItem.message.messageGlobalKey == newItem.message.messageGlobalKey
} else {
oldItem.viewType == newItem.viewType
}
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 870b6433e..54711a689 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
@@ -3,8 +3,8 @@ package io.github.wulkanowy.ui.modules.message.tab
import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.enums.MessageFolder
+import io.github.wulkanowy.data.repositories.MailboxRepository
import io.github.wulkanowy.data.repositories.MessageRepository
-import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
@@ -26,7 +26,7 @@ class MessageTabPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val messageRepository: MessageRepository,
- private val semesterRepository: SemesterRepository,
+ private val mailboxRepository: MailboxRepository,
private val analytics: AnalyticsHelper
) : BasePresenter(errorHandler, studentRepository) {
@@ -122,7 +122,8 @@ class MessageTabPresenter @Inject constructor(
runCatching {
val student = studentRepository.getCurrentStudent(true)
- messageRepository.deleteMessages(student, messageList)
+ val mailbox = mailboxRepository.getMailbox(student)
+ messageRepository.deleteMessages(student, mailbox, messageList)
}
.onFailure(errorHandler::dispatch)
.onSuccess { view?.showMessagesDeleted() }
@@ -159,7 +160,7 @@ class MessageTabPresenter @Inject constructor(
}
fun onMessageItemSelected(messageItem: MessageTabDataItem.MessageItem, position: Int) {
- Timber.i("Select message ${messageItem.message.id} item (position: $position)")
+ Timber.i("Select message ${messageItem.message.messageGlobalKey} item (position: $position)")
if (!isActionMode) {
view?.run {
@@ -206,8 +207,8 @@ class MessageTabPresenter @Inject constructor(
flatResourceFlow {
val student = studentRepository.getCurrentStudent()
- val semester = semesterRepository.getCurrentSemester(student)
- messageRepository.getMessages(student, semester, folder, forceRefresh)
+ val mailbox = mailboxRepository.getMailbox(student)
+ messageRepository.getMessages(student, mailbox, folder, forceRefresh)
}
.logResourceStatus("load $folder message")
.onResourceData {
@@ -333,7 +334,7 @@ class MessageTabPresenter @Inject constructor(
addAll(data.map { message ->
MessageTabDataItem.MessageItem(
message = message,
- isSelected = messagesToDelete.any { it.id == message.id },
+ isSelected = messagesToDelete.any { it.messageGlobalKey == message.messageGlobalKey },
isActionMode = isActionMode
)
})
@@ -345,10 +346,9 @@ class MessageTabPresenter @Inject constructor(
private fun calculateMatchRatio(message: Message, query: String): Int {
val subjectRatio = FuzzySearch.tokenSortPartialRatio(query.lowercase(), message.subject)
- val senderOrRecipientRatio = FuzzySearch.tokenSortPartialRatio(
+ val correspondentsRatio = FuzzySearch.tokenSortPartialRatio(
query.lowercase(),
- if (message.sender.isNotEmpty()) message.sender.lowercase()
- else message.recipient.lowercase()
+ message.correspondents
)
val dateRatio = listOf(
@@ -364,7 +364,7 @@ class MessageTabPresenter @Inject constructor(
return (subjectRatio.toDouble().pow(2)
- + senderOrRecipientRatio.toDouble().pow(2)
+ + correspondentsRatio.toDouble().pow(2)
+ dateRatio.toDouble().pow(2) * 2
).toInt()
}
diff --git a/app/src/main/res/layout/activity_send_message.xml b/app/src/main/res/layout/activity_send_message.xml
index 10b581f77..320782bdc 100644
--- a/app/src/main/res/layout/activity_send_message.xml
+++ b/app/src/main/res/layout/activity_send_message.xml
@@ -16,8 +16,7 @@
app:layout_constraintBottom_toTopOf="@id/sendMessageScroll"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- tools:targetApi="lollipop" />
+ app:layout_constraintTop_toTopOf="parent" />
Move to trash
Delete permanently
Message deleted successfully
+ student
+ parent
+ guardian
+ employee
Share
Print
Subject
@@ -300,7 +304,6 @@
Only unread
Only with attachments
Read: %s
- Read by: %1$d of %2$d people
- %1$d message
- %1$d messages
diff --git a/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt b/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt
index 225399306..ff0a53135 100644
--- a/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt
+++ b/app/src/test/java/io/github/wulkanowy/TestEnityCreator.kt
@@ -1,5 +1,7 @@
package io.github.wulkanowy
+import io.github.wulkanowy.data.db.entities.Mailbox
+import io.github.wulkanowy.data.db.entities.MailboxType
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.sdk.Sdk
@@ -21,6 +23,16 @@ fun getSemesterEntity(diaryId: Int = 1, semesterId: Int = 1, start: LocalDate =
end = end
)
+fun getMailboxEntity() = Mailbox(
+ globalKey = "v4",
+ fullName = "",
+ userName = "",
+ userLoginId = 0,
+ studentName = "",
+ schoolNameShort = "",
+ type = MailboxType.UNKNOWN,
+)
+
fun getSemesterPojo(diaryId: Int, semesterId: Int, start: LocalDate, end: LocalDate, semesterName: Int = 1) = SdkSemester(
diaryId = diaryId,
kindergartenDiaryId = 0,
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 2a5d2e2b4..24306bfeb 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
@@ -10,12 +10,10 @@ import io.github.wulkanowy.data.db.entities.MessageWithAttachment
import io.github.wulkanowy.data.enums.MessageFolder
import io.github.wulkanowy.data.errorOrNull
import io.github.wulkanowy.data.toFirstResult
-import io.github.wulkanowy.getSemesterEntity
+import io.github.wulkanowy.getMailboxEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Folder
-import io.github.wulkanowy.sdk.pojo.MessageDetails
-import io.github.wulkanowy.sdk.pojo.Sender
import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.Status
import io.github.wulkanowy.utils.status
@@ -23,7 +21,6 @@ import io.mockk.*
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.runBlocking
@@ -60,7 +57,7 @@ class MessageRepositoryTest {
private val student = getStudentEntity()
- private val semester = getSemesterEntity()
+ private val mailbox = getMailboxEntity()
private lateinit var repository: MessageRepository
@@ -80,59 +77,18 @@ class MessageRepositoryTest {
)
}
- @Test
- fun `get messages when read by values was changed on already read message`() = runTest {
- every { messageDb.loadAll(any(), any()) } returns flow {
- val dbMessage = getMessageEntity(3, "", false).apply {
- unreadBy = 10
- readBy = 5
- isNotified = true
- }
- emit(listOf(dbMessage))
- }
- coEvery { sdk.getMessages(Folder.RECEIVED, any(), any()) } returns listOf(
- getMessageDto(messageId = 3, content = "", unread = false).copy(
- unreadBy = 5,
- readBy = 10,
- )
- )
- coEvery { messageDb.deleteAll(any()) } just Runs
- coEvery { messageDb.insertAll(any()) } returns listOf()
-
- repository.getMessages(
- student = student,
- semester = semester,
- folder = MessageFolder.RECEIVED,
- forceRefresh = true,
- notify = true, // all new messages will be marked as not notified
- ).toFirstResult().dataOrNull.orEmpty()
-
- coVerify(exactly = 1) { messageDb.deleteAll(emptyList()) }
- coVerify(exactly = 1) { messageDb.insertAll(emptyList()) }
- coVerify(exactly = 1) {
- messageDb.updateAll(withArg {
- assertEquals(1, it.size)
- assertEquals(5, it.single().unreadBy)
- assertEquals(10, it.single().readBy)
- })
- }
- }
-
@Test
fun `get messages when fetched completely new message without notify`() = runBlocking {
every { messageDb.loadAll(any(), any()) } returns flowOf(emptyList())
- coEvery { sdk.getMessages(Folder.RECEIVED, any(), any()) } returns listOf(
- getMessageDto(messageId = 4, content = "Test", unread = true).copy(
- unreadBy = 5,
- readBy = 10,
- )
+ coEvery { sdk.getMessages(Folder.RECEIVED, any()) } returns listOf(
+ getMessageDto()
)
coEvery { messageDb.deleteAll(any()) } just Runs
coEvery { messageDb.insertAll(any()) } returns listOf()
repository.getMessages(
student = student,
- semester = semester,
+ mailbox = mailbox,
folder = MessageFolder.RECEIVED,
forceRefresh = true,
notify = false,
@@ -151,7 +107,7 @@ class MessageRepositoryTest {
fun `throw error when message is not in the db`() {
val testMessage = getMessageEntity(1, "", false)
coEvery {
- messageDb.loadMessageWithAttachment(1, 1)
+ messageDb.loadMessageWithAttachment("v4")
} throws NoSuchElementException("No message in database")
runBlocking { repository.getMessage(student, testMessage).toFirstResult() }
@@ -162,7 +118,7 @@ class MessageRepositoryTest {
val testMessage = getMessageEntity(123, "Test", false)
val messageWithAttachment = MessageWithAttachment(testMessage, emptyList())
- coEvery { messageDb.loadMessageWithAttachment(1, testMessage.messageId) } returns flowOf(
+ coEvery { messageDb.loadMessageWithAttachment("v4") } returns flowOf(
messageWithAttachment
)
@@ -174,7 +130,7 @@ class MessageRepositoryTest {
}
@Test
- fun `get message when content in db is empty`() {
+ fun `get message when content in db is empty`() = runTest {
val testMessage = getMessageEntity(123, "", true)
val testMessageWithContent = testMessage.copy().apply { content = "Test" }
@@ -182,23 +138,19 @@ class MessageRepositoryTest {
val mWaWithContent = MessageWithAttachment(testMessageWithContent, emptyList())
coEvery {
- messageDb.loadMessageWithAttachment(
- 1,
- testMessage.messageId
- )
+ messageDb.loadMessageWithAttachment("v4")
} returnsMany listOf(flowOf(mWa), flowOf(mWaWithContent))
coEvery {
- sdk.getMessageDetails(
- messageId = testMessage.messageId,
- folderId = 1,
- read = false,
- id = testMessage.realId
- )
- } returns MessageDetails("Test", emptyList())
+ sdk.getMessageDetails("v4")
+ } returns mockk {
+ every { sender } returns ""
+ every { recipients } returns listOf("")
+ every { attachments } returns listOf()
+ }
coEvery { messageDb.updateAll(any()) } just Runs
coEvery { messageAttachmentDao.insertAttachments(any()) } returns listOf(1)
- val res = runBlocking { repository.getMessage(student, testMessage).toFirstResult() }
+ val res = repository.getMessage(student, testMessage).toFirstResult()
assertEquals(null, res.errorOrNull)
assertEquals(Status.SUCCESS, res.status)
@@ -211,7 +163,7 @@ class MessageRepositoryTest {
val testMessage = getMessageEntity(123, "", false)
coEvery {
- messageDb.loadMessageWithAttachment(1, testMessage.messageId)
+ messageDb.loadMessageWithAttachment("v4")
} throws UnknownHostException()
runBlocking { repository.getMessage(student, testMessage).toFirstResult() }
@@ -222,7 +174,7 @@ class MessageRepositoryTest {
val testMessage = getMessageEntity(123, "", true)
coEvery {
- messageDb.loadMessageWithAttachment(1, testMessage.messageId)
+ messageDb.loadMessageWithAttachment("v4")
} throws UnknownHostException()
runBlocking { repository.getMessage(student, testMessage).toList()[1] }
@@ -233,42 +185,30 @@ class MessageRepositoryTest {
content: String,
unread: Boolean
) = Message(
- studentId = 1,
- realId = 1,
+ messageGlobalKey = "v4",
+ mailboxKey = "",
+ correspondents = "",
messageId = messageId,
- sender = "",
- senderId = 0,
- recipient = "Wielu adresatów",
subject = "",
date = Instant.EPOCH,
folderId = 1,
unread = unread,
- removed = false,
hasAttachments = false
).apply {
this.content = content
- unreadBy = 1
- readBy = 1
}
- private fun getMessageDto(
- messageId: Int,
- content: String,
- unread: Boolean,
- ) = io.github.wulkanowy.sdk.pojo.Message(
- id = 1,
- messageId = messageId,
- sender = Sender("", "", 0, 0, 0, ""),
+ private fun getMessageDto() = io.github.wulkanowy.sdk.pojo.Message(
+ globalKey = "v4",
+ mailbox = "",
+ correspondents = "",
+ id = 4,
recipients = listOf(),
subject = "",
- content = content,
- date = Instant.EPOCH.atZone(ZoneOffset.UTC).toLocalDateTime(),
+ content = "Test",
dateZoned = Instant.EPOCH.atZone(ZoneOffset.UTC),
folderId = 1,
- unread = unread,
- unreadBy = 0,
- readBy = 0,
- removed = false,
+ unread = true,
hasAttachments = false,
)
}
diff --git a/app/src/test/java/io/github/wulkanowy/data/repositories/RecipientLocalTest.kt b/app/src/test/java/io/github/wulkanowy/data/repositories/RecipientLocalTest.kt
index 980abac0a..ae73a7958 100644
--- a/app/src/test/java/io/github/wulkanowy/data/repositories/RecipientLocalTest.kt
+++ b/app/src/test/java/io/github/wulkanowy/data/repositories/RecipientLocalTest.kt
@@ -1,19 +1,15 @@
package io.github.wulkanowy.data.repositories
import io.github.wulkanowy.data.db.dao.RecipientDao
-import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.mappers.mapToEntities
+import io.github.wulkanowy.getMailboxEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.sdk.pojo.MailboxType
import io.github.wulkanowy.utils.AutoRefreshHelper
-import io.mockk.MockKAnnotations
-import io.mockk.Runs
-import io.mockk.coEvery
-import io.mockk.coVerify
-import io.mockk.every
+import io.mockk.*
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
-import io.mockk.just
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -36,9 +32,30 @@ class RecipientLocalTest {
private lateinit var recipientRepository: RecipientRepository
private val remoteList = listOf(
- SdkRecipient("2rPracownik", "Kowalski Jan", 3, 4, 2, "hash", "Kowalski Jan [KJ] - Pracownik (Fake123456)"),
- SdkRecipient("3rPracownik", "Kowalska Karolina", 4, 4, 2, "hash", "Kowalska Karolina [KK] - Pracownik (Fake123456)"),
- SdkRecipient("4rPracownik", "Krupa Stanisław", 5, 4, 1, "hash", "Krupa Stanisław [KS] - Uczeń (Fake123456)")
+ SdkRecipient(
+ mailboxGlobalKey = "2rPracownik",
+ userName = "Kowalski Jan",
+ fullName = "Kowalski Jan [KJ] - Pracownik (Fake123456)",
+ studentName = "",
+ schoolNameShort = "",
+ type = MailboxType.UNKNOWN,
+ ),
+ SdkRecipient(
+ mailboxGlobalKey = "3rPracownik",
+ userName = "Kowalska Karolina",
+ fullName = "Kowalska Karolina [KK] - Pracownik (Fake123456)",
+ studentName = "",
+ schoolNameShort = "",
+ type = MailboxType.UNKNOWN,
+ ),
+ SdkRecipient(
+ mailboxGlobalKey = "4rPracownik",
+ userName = "Krupa Stanisław",
+ fullName = "Krupa Stanisław [KS] - Uczeń (Fake123456)",
+ studentName = "",
+ schoolNameShort = "",
+ type = MailboxType.UNKNOWN,
+ )
)
@Before
@@ -52,39 +69,61 @@ class RecipientLocalTest {
@Test
fun `load recipients when items already in database`() {
// prepare
- coEvery { recipientDb.loadAll(4, 123, 7) } returnsMany listOf(
- remoteList.mapToEntities(4),
- remoteList.mapToEntities(4)
+ coEvery { recipientDb.loadAll(io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN, "v4") } returnsMany listOf(
+ remoteList.mapToEntities("v4"),
+ remoteList.mapToEntities("v4")
)
coEvery { recipientDb.insertAll(any()) } returns listOf(1, 2, 3)
coEvery { recipientDb.deleteAll(any()) } just Runs
// execute
- val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(4, 123, "", 4, "", listOf()), 7) }
+ val res = runBlocking {
+ recipientRepository.getRecipients(
+ student = student,
+ mailbox = getMailboxEntity(),
+ type = io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN,
+ )
+ }
// verify
assertEquals(3, res.size)
- coVerify { recipientDb.loadAll(4, 123, 7) }
+ coVerify {
+ recipientDb.loadAll(
+ type = io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN,
+ studentMailboxGlobalKey = "v4"
+ )
+ }
}
@Test
fun `load recipients when database is empty`() {
// prepare
- coEvery { sdk.getRecipients(123, 7) } returns remoteList
- coEvery { recipientDb.loadAll(4, 123, 7) } returnsMany listOf(
+ coEvery { sdk.getRecipients("v4") } returns remoteList
+ coEvery {
+ recipientDb.loadAll(
+ io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN,
+ "v4"
+ )
+ } returnsMany listOf(
emptyList(),
- remoteList.mapToEntities(4)
+ remoteList.mapToEntities("v4")
)
coEvery { recipientDb.insertAll(any()) } returns listOf(1, 2, 3)
coEvery { recipientDb.deleteAll(any()) } just Runs
// execute
- val res = runBlocking { recipientRepository.getRecipients(student, ReportingUnit(4, 123, "", 4, "", listOf()), 7) }
+ val res = runBlocking {
+ recipientRepository.getRecipients(
+ student = student,
+ mailbox = getMailboxEntity(),
+ type = io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN,
+ )
+ }
// verify
assertEquals(3, res.size)
- coVerify { sdk.getRecipients(123, 7) }
- coVerify { recipientDb.loadAll(4, 123, 7) }
+ coVerify { sdk.getRecipients("v4") }
+ coVerify { recipientDb.loadAll(io.github.wulkanowy.data.db.entities.MailboxType.UNKNOWN, "v4") }
coVerify { recipientDb.insertAll(match { it.isEmpty() }) }
coVerify { recipientDb.deleteAll(match { it.isEmpty() }) }
}