From f98b17485726f43ed0390dd7bcd2ecc355c44671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 4 Apr 2020 21:31:14 +0200 Subject: [PATCH] [UI] Refactor Messages fragment. --- .../pl/szczodrzynski/edziennik/Extensions.kt | 2 +- .../szczodrzynski/edziennik/MainActivity.kt | 10 +- .../edziennik/data/api/Features.kt | 4 +- .../data/api/IdziennikApiMessagesInbox.kt | 27 ++-- .../data/api/IdziennikApiMessagesSent.kt | 17 ++- .../data/web/IdziennikWebGetMessage.kt | 21 ++- .../data/web/IdziennikWebSendMessage.kt | 2 +- .../data/messages/LibrusMessagesGetList.kt | 21 ++- .../data/messages/LibrusMessagesGetMessage.kt | 24 ++-- .../messages/LibrusMessagesSendMessage.kt | 2 +- .../data/web/MobidziennikWebGetMessage.kt | 25 ++-- .../data/web/MobidziennikWebMessagesAll.kt | 23 ++- .../data/web/MobidziennikWebMessagesInbox.kt | 19 ++- .../data/web/MobidziennikWebMessagesSent.kt | 17 ++- .../data/web/MobidziennikWebSendMessage.kt | 2 +- .../data/api/VulcanApiMessagesChangeStatus.kt | 2 +- .../vulcan/data/api/VulcanApiMessagesInbox.kt | 22 ++- .../vulcan/data/api/VulcanApiMessagesSent.kt | 17 ++- .../vulcan/data/api/VulcanApiSendMessage.kt | 2 +- .../edziennik/data/api/models/Data.kt | 13 +- .../edziennik/data/api/task/Notifications.kt | 4 +- .../szczodrzynski/edziennik/data/db/AppDb.kt | 5 +- .../edziennik/data/db/dao/MessageDao.java | 114 --------------- .../edziennik/data/db/dao/MessageDao.kt | 67 +++++++++ .../edziennik/data/db/dao/MetadataDao.java | 8 +- .../edziennik/data/db/entity/Message.java | 92 ------------ .../edziennik/data/db/entity/Message.kt | 76 ++++++++++ .../edziennik/data/db/full/MessageFull.java | 32 ----- .../edziennik/data/db/full/MessageFull.kt | 31 ++++ .../data/db/full/MessageRecipientFull.kt | 18 +-- .../data/db/migration/Migration84.kt | 40 ++++++ .../firebase/SzkolnyMobidziennikFirebase.kt | 2 +- .../ui/modules/grades/GradesListFragment.kt | 2 +- .../modules/homework/HomeworkListFragment.kt | 2 +- .../ui/modules/messages/MessageFragment.kt | 12 +- .../ui/modules/messages/MessagesAdapter.kt | 107 ++++++++------ .../ui/modules/messages/MessagesFragment.kt | 136 ++++++------------ .../modules/messages/MessagesListFragment.kt | 94 ++++++++++++ ...ment.java => MessagesListFragmentOld.java} | 26 ++-- .../ui/modules/messages/MessagesUtils.kt | 2 +- .../ui/modules/messages/SlideExplode.java | 75 ---------- .../ui/modules/messages/Transitions.java | 18 --- .../{ => compose}/MessagesComposeFragment.kt | 10 +- .../{ => compose}/MessagesComposeInfo.kt | 8 +- .../MessagesComposeSuggestionAdapter.kt | 2 +- .../NotificationsListFragment.kt | 2 +- .../ui/modules/template/TemplateFragment.kt | 17 ++- .../modules/template/TemplateListFragment.kt | 2 +- .../template/TemplateListPageFragment.kt | 4 +- app/src/main/res/drawable/ic_no_messages.xml | 10 ++ app/src/main/res/layout/messages_fragment.xml | 36 +++++ .../res/layout/messages_list_fragment.xml | 42 ++++++ .../main/res/layout/messages_list_item.xml | 118 +++++++++++++++ app/src/main/res/values-en/strings.xml | 4 +- app/src/main/res/values/strings.xml | 6 +- .../edziennik/codegen/FileGenerator.kt | 5 +- 56 files changed, 832 insertions(+), 669 deletions(-) delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration84.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.kt rename app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/{MessagesListFragment.java => MessagesListFragmentOld.java} (94%) delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/SlideExplode.java delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/Transitions.java rename app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/{ => compose}/MessagesComposeFragment.kt (97%) rename app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/{ => compose}/MessagesComposeInfo.kt (79%) rename app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/{ => compose}/MessagesComposeSuggestionAdapter.kt (98%) create mode 100644 app/src/main/res/drawable/ic_no_messages.xml create mode 100644 app/src/main/res/layout/messages_fragment.xml create mode 100644 app/src/main/res/layout/messages_list_fragment.xml create mode 100644 app/src/main/res/layout/messages_list_item.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 1a51ddbd..d911e132 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -816,7 +816,7 @@ fun View.findParentById(targetId: Int): View? { return null } -fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: () -> Unit) = launch { +fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: suspend CoroutineScope.() -> Unit) = launch { delay(delayMillis) if (repeatMillis > 0) { while (true) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 5a39dec5..d229e8c9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -68,9 +68,9 @@ import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment -import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeFragment import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment -import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesListFragment +import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesListFragmentOld +import pl.szczodrzynski.edziennik.ui.modules.messages.compose.MessagesComposeFragment import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsListFragment import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment @@ -889,9 +889,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope { } app.profileLoad(id) { MessagesFragment.pageSelection = -1 - MessagesListFragment.tapPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) - MessagesListFragment.topPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) - MessagesListFragment.bottomPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) + MessagesListFragmentOld.tapPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) + MessagesListFragmentOld.topPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) + MessagesListFragmentOld.bottomPositions = intArrayOf(RecyclerView.NO_POSITION, RecyclerView.NO_POSITION) setDrawerItems() // the drawer profile is updated automatically when the drawer item is clicked diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt index 0e75753b..e38b37b5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt @@ -13,8 +13,8 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOME import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT internal const val FEATURE_TIMETABLE = 1 internal const val FEATURE_AGENDA = 2 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt index c8d756fe..58e7660c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesInbox.kt @@ -11,8 +11,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.getBoolean import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.utils.Utils.crc32 @@ -33,11 +33,11 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik, return@apiGet } - json.asJsonObjectList()?.forEach { jMessage -> - val subject = jMessage.getString("tytul") - if (subject?.contains("(") == true && subject.startsWith("iDziennik - ")) + json.asJsonObjectList().forEach { jMessage -> + val subject = jMessage.getString("tytul") ?: "" + if (subject.contains("(") && subject.startsWith("iDziennik - ")) return@forEach - if (subject?.startsWith("Uwaga dla ucznia (klasa:") == true) + if (subject.startsWith("Uwaga dla ucznia (klasa:")) return@forEach val messageIdStr = jMessage.getString("id") @@ -64,13 +64,12 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik, rTeacher.setTeacherType(Teacher.TYPE_OTHER) val message = Message( - profileId, - messageId, - subject, - body, - if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED, - rTeacher.id, - -1 + profileId = profileId, + id = messageId, + type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED, + subject = subject, + body = body, + senderId = rTeacher.id ) val messageRecipient = MessageRecipient( @@ -81,7 +80,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik, /*messageId*/ messageId ) - data.messageIgnoreList.add(message) + data.messageList.add(message) data.messageRecipientList.add(messageRecipient) data.setSeenMetadataList.add(Metadata( profileId, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt index b0b17689..286c9896 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/api/IdziennikApiMessagesSent.kt @@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_SENT import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.utils.Utils.crc32 @@ -46,13 +46,12 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik, val sentDate = Date.fromIso(jMessage.get("dataWyslania").asString) val message = Message( - profileId, - messageId, - subject, - body, - TYPE_SENT, - -1, - -1 + profileId = profileId, + id = messageId, + type = TYPE_SENT, + subject = subject, + body = body, + senderId = null ) for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) { @@ -76,7 +75,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik, data.messageRecipientIgnoreList.add(messageRecipient) } - data.messageIgnoreList.add(message) + data.messageList.add(message) data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate)) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt index dfe9fba3..e709122d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt @@ -10,8 +10,8 @@ import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_MESSAGE import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull @@ -50,7 +50,11 @@ class IdziennikWebGetMessage(override val data: DataIdziennik, message.recipients?.clear() when (message.type) { TYPE_RECEIVED -> { - val recipientObject = MessageRecipientFull(profileId, -1, message.id) + val recipientObject = MessageRecipientFull( + profileId = profileId, + id = -1, + messageId = message.id + ) val readDateString = it.getString("DataOdczytania") recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis() @@ -67,7 +71,11 @@ class IdziennikWebGetMessage(override val data: DataIdziennik, val recipientName = recipient.getString("NazwaOdbiorcy") ?: return@forEach val teacher = data.getTeacherByLastFirst(recipientName) - val recipientObject = MessageRecipientFull(profileId, teacher.id, message.id) + val recipientObject = MessageRecipientFull( + profileId = profileId, + id = teacher.id, + messageId = message.id + ) recipientObject.readDate = recipient.getLong("Status") ?: return@forEach recipientObject.fullName = teacher.fullName @@ -91,9 +99,10 @@ class IdziennikWebGetMessage(override val data: DataIdziennik, )) } - EventBus.getDefault().postSticky(MessageGetEvent(message)) - data.messageList.add(message) + data.messageListReplace = true + + EventBus.getDefault().postSticky(MessageGetEvent(message)) onSuccess() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt index 9a997a32..973bc74f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt @@ -57,7 +57,7 @@ class IdziennikWebSendMessage(override val data: DataIdziennik, } IdziennikApiMessagesSent(data, null) { - val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } + val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt index 5574970f..35148cef 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetList.kt @@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESS import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESSAGES_SENT import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.fixName import pl.szczodrzynski.edziennik.singleOrNull import pl.szczodrzynski.edziennik.utils.Utils @@ -78,7 +78,7 @@ class LibrusMessagesGetList(override val data: DataLibrus, val senderId = when (type) { TYPE_RECEIVED -> recipientId - else -> -1 + else -> null } val receiverId = when (type) { @@ -92,13 +92,12 @@ class LibrusMessagesGetList(override val data: DataLibrus, } val messageObject = Message( - profileId, - id, - subject, - null, - type, - senderId, - -1 + profileId = profileId, + id = id, + type = type, + subject = subject, + body = null, + senderId = senderId ) val messageRecipientObject = MessageRecipient( @@ -111,10 +110,10 @@ class LibrusMessagesGetList(override val data: DataLibrus, element.select("isAnyFileAttached")?.text()?.let { if (it == "1") - messageObject.overrideHasAttachments = true + messageObject.hasAttachments = true } - data.messageIgnoreList.add(messageObject) + data.messageList.add(messageObject) data.messageRecipientList.add(messageRecipientObject) data.setSeenMetadataList.add(Metadata( profileId, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt index 824fdc5e..bb4c620b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesGetMessage.kt @@ -9,8 +9,8 @@ import org.greenrobot.eventbus.EventBus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusMessages import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.full.MessageFull @@ -102,11 +102,10 @@ class LibrusMessagesGetMessage(override val data: DataLibrus, } val messageRecipientObject = MessageRecipientFull( - profileId, - -1, - -1, - readDate, - messageObject.id + profileId = profileId, + id = -1, + messageId = messageObject.id, + readDate = readDate ) messageRecipientObject.fullName = profile.accountName ?: profile.studentNameLong ?: "" @@ -132,11 +131,10 @@ class LibrusMessagesGetMessage(override val data: DataLibrus, } val messageRecipientObject = MessageRecipientFull( - profileId, - receiverId, - -1, - readDate, - messageObject.id + profileId = profileId, + id = receiverId, + messageId = messageObject.id, + readDate = readDate ) messageRecipientObject.fullName = "$receiverFirstName $receiverLastName" @@ -159,7 +157,9 @@ class LibrusMessagesGetMessage(override val data: DataLibrus, messageObject.recipients = messageRecipientList data.messageRecipientList.addAll(messageRecipientList) + data.messageList.add(messageObject) + data.messageListReplace = true EventBus.getDefault().postSticky(MessageGetEvent(messageObject)) onSuccess() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt index 02215dea..9364f2b8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt @@ -48,7 +48,7 @@ class LibrusMessagesSendMessage(override val data: DataLibrus, } LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) { - val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id } + val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt index 5b462e57..1c44a219 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt @@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull @@ -61,19 +61,17 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik, } val recipient = MessageRecipientFull( - profileId, - -1, - -1, - readDate, - message.id + profileId = profileId, + id = -1, + messageId = message.id, + readDate = readDate ) recipient.fullName = profile?.accountName ?: profile?.studentNameLong ?: "" messageRecipientList.add(recipient) } else { - message.senderId = -1 - message.senderReplyId = -1 + message.senderId = null content.select("table.spis tr:has(td)")?.forEach { recipientEl -> val senderEl = recipientEl.select("td:eq(0)").first() @@ -100,11 +98,10 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik, } val recipient = MessageRecipientFull( - profileId, - receiverId, - -1, - readDate, - message.id + profileId = profileId, + id = receiverId, + messageId = message.id, + readDate = readDate ) recipient.fullName = teacher?.fullName ?: "?" @@ -149,7 +146,9 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik, message.recipients = messageRecipientList data.messageRecipientList.addAll(messageRecipientList) + data.messageList.add(message) + data.messageListReplace = true EventBus.getDefault().postSticky(MessageGetEvent(message)) onSuccess() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt index 61c9222e..c0373c54 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt @@ -10,8 +10,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.fixName @@ -54,12 +54,12 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik, type = TYPE_SENT val senderEl = item.select("td:eq(3) div").first() - var senderId: Long = -1 + var senderId: Long? = null if (type == TYPE_RECEIVED) { // search sender teacher val senderName = senderEl.text().fixName() - senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1 + senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id data.messageRecipientList.add(MessageRecipient(profileId, -1, id)) } else { // TYPE_SENT, so multiple recipients possible @@ -72,16 +72,15 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik, } val message = Message( - profileId, - id, - subject, - null, - type, - senderId, - -1 + profileId = profileId, + id = id, + type = type, + subject = subject, + body = null, + senderId = senderId ) - data.messageIgnoreList.add(message) + data.messageList.add(message) data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate)) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt index ee5cbd24..385ea71e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt @@ -52,25 +52,24 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik, val senderEl = item.select("td:eq(2)").first() val senderName = senderEl.ownText().fixName() - val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1 + val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id data.messageRecipientIgnoreList.add(MessageRecipient(profileId, -1, id)) val isRead = item.select("td:eq(3) span").first().hasClass("wiadomosc_przeczytana") val message = Message( - profileId, - id, - subject, - null, - Message.TYPE_RECEIVED, - senderId, - -1 + profileId = profileId, + id = id, + type = Message.TYPE_RECEIVED, + subject = subject, + body = null, + senderId = senderId ) if (hasAttachments) - message.setHasAttachments() + message.hasAttachments = true - data.messageIgnoreList.add(message) + data.messageList.add(message) data.setSeenMetadataList.add( Metadata( profileId, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt index 8e7123c3..918816c8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesSent.kt @@ -73,19 +73,18 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik, val addedDate = Date.fromIsoHm(addedDateEl.text()) val message = Message( - profileId, - id, - subject, - null, - Message.TYPE_SENT, - -1, - -1 + profileId = profileId, + id = id, + type = Message.TYPE_SENT, + subject = subject, + body = null, + senderId = null ) if (hasAttachments) - message.setHasAttachments() + message.hasAttachments = true - data.messageIgnoreList.add(message) + data.messageList.add(message) data.setSeenMetadataList.add( Metadata( profileId, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt index 074fb83e..d0cee4dc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebSendMessage.kt @@ -43,7 +43,7 @@ class MobidziennikWebSendMessage(override val data: DataMobidziennik, // TODO create MobidziennikWebMessagesSent and replace this MobidziennikWebMessagesAll(data, null) { - val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } + val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id } val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt index 3a72c963..5e226849 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt @@ -9,7 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_S import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.full.MessageFull diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt index e78b157e..388a97ad 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt @@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INBOX import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.db.entity.* -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.models.Date import kotlin.text.replace @@ -44,8 +44,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val body = message.getString("Tresc") ?: "" val senderLoginId = message.getString("NadawcaId") ?: return@forEach - val senderId = data.teacherList - .singleOrNull { it.loginId == senderLoginId }?.id ?: { + val senderId = data.teacherList.singleOrNull { it.loginId == senderLoginId }?.id ?: { val senderName = message.getString("Nadawca") ?: "" @@ -60,7 +59,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, data.teacherList.put(teacherObject.id, teacherObject) teacherObject.id } - }.invoke() ?: -1 + }.invoke() val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 } ?: -1 @@ -68,13 +67,12 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, ?: -1 val messageObject = Message( - profileId, - id, - subject, - body.replace("\n", "
"), - TYPE_RECEIVED, - senderId, - -1 + profileId = profileId, + id = id, + type = TYPE_RECEIVED, + subject = subject, + body = body.replace("\n", "
"), + senderId = senderId ) val messageRecipientObject = MessageRecipient( @@ -85,7 +83,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, id ) - data.messageIgnoreList.add(messageObject) + data.messageList.add(messageObject) data.messageRecipientList.add(messageRecipientObject) data.setSeenMetadataList.add(Metadata( profileId, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt index 7437aab4..d190c00f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt @@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_SENT import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Teacher @@ -92,16 +92,15 @@ class VulcanApiMessagesSent(override val data: DataVulcan, } val messageObject = Message( - profileId, - id, - subject, - body.replace("\n", "
"), - TYPE_SENT, - -1, - -1 + profileId = profileId, + id = id, + type = TYPE_SENT, + subject = subject, + body = body.replace("\n", "
"), + senderId = null ) - data.messageIgnoreList.add(messageObject) + data.messageList.add(messageObject) data.setSeenMetadataList.add(Metadata( profileId, Metadata.TYPE_MESSAGE, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt index c7f7b29e..b88ccdb6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt @@ -52,7 +52,7 @@ class VulcanApiSendMessage(override val data: DataVulcan, } VulcanApiMessagesSent(data, null) { - val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } + val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject } val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId } val event = MessageSentEvent(data.profileId, message, metadata?.addedDate) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt index 30fab35e..5e998425 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt @@ -87,6 +87,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt var teacherOnConflictStrategy = OnConflictStrategy.IGNORE var eventListReplace = false + var messageListReplace = false val classrooms = LongSparseArray() val attendanceTypes = LongSparseArray() @@ -126,7 +127,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt val teacherAbsenceList = mutableListOf() val messageList = mutableListOf() - val messageIgnoreList = mutableListOf() val messageRecipientList = mutableListOf() val messageRecipientIgnoreList = mutableListOf() @@ -182,7 +182,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt luckyNumberList.clear() teacherAbsenceList.clear() messageList.clear() - messageIgnoreList.clear() messageRecipientList.clear() messageRecipientIgnoreList.clear() metadataList.clear() @@ -305,10 +304,12 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt if (teacherAbsenceList.isNotEmpty()) db.teacherAbsenceDao().addAll(teacherAbsenceList) - if (messageList.isNotEmpty()) - db.messageDao().addAll(messageList) - if (messageIgnoreList.isNotEmpty()) - db.messageDao().addAllIgnore(messageIgnoreList) + if (messageList.isNotEmpty()) { + if (messageListReplace) + db.messageDao().replaceAll(messageList) + else + db.messageDao().upsertAll(messageList, removeNotKept = false) // TODO dataRemoveModel for messages + } if (messageRecipientList.isNotEmpty()) db.messageRecipientDao().addAll(messageRecipientList) if (messageRecipientIgnoreList.isNotEmpty()) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt index c29d96bb..39b68499 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt @@ -227,10 +227,10 @@ class Notifications(val app: App, val notifications: MutableList, } private fun messageNotifications() { - for (message in app.db.messageDao().receivedNotNotifiedNow) { + for (message in app.db.messageDao().getNotNotifiedNow()) { val text = app.getString( R.string.notification_message_format, - message.senderFullName, + message.senderName, message.subject ) notifications += Notification( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt index dfbf8cbe..32be6ac3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt @@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.* LibrusLesson::class, TimetableManual::class, Metadata::class -], version = 83) +], version = 84) @TypeConverters( ConverterTime::class, ConverterDate::class, @@ -168,7 +168,8 @@ abstract class AppDb : RoomDatabase() { Migration80(), Migration81(), Migration82(), - Migration83() + Migration83(), + Migration84() ).allowMainThreadQueries().build() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java deleted file mode 100644 index bc3a46a5..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-1-6 - */ - -package pl.szczodrzynski.edziennik.data.db.dao; - -import androidx.annotation.Nullable; -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Insert; -import androidx.room.OnConflictStrategy; -import androidx.room.Query; -import androidx.room.RawQuery; -import androidx.sqlite.db.SimpleSQLiteQuery; -import androidx.sqlite.db.SupportSQLiteQuery; - -import java.util.List; - -import pl.szczodrzynski.edziennik.data.db.entity.Message; -import pl.szczodrzynski.edziennik.data.db.entity.Metadata; -import pl.szczodrzynski.edziennik.data.db.full.MessageFull; - -import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED; -import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED; -import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT; -import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_MESSAGE; - -@Dao -public abstract class MessageDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - public abstract long add(Message message); - - @Insert(onConflict = OnConflictStrategy.REPLACE) - public abstract void addAll(List messageList); - - @Insert(onConflict = OnConflictStrategy.IGNORE) - public abstract void addAllIgnore(List messageList); - - @Query("DELETE FROM messages WHERE profileId = :profileId") - public abstract void clear(int profileId); - - @RawQuery(observedEntities = {Message.class}) - abstract LiveData> getAll(SupportSQLiteQuery query); - @RawQuery(observedEntities = {Message.class, Metadata.class}) - abstract List getNow(SupportSQLiteQuery query); - @RawQuery(observedEntities = {Message.class, Metadata.class}) - abstract MessageFull getOneNow(SupportSQLiteQuery query); - - public LiveData> getWithMetadataAndSenderName(int profileId, int messageType, String filter) { - return getAll(new SimpleSQLiteQuery("SELECT \n" + - "*, \n" + - "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" + - "FROM messages \n" + - "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" + - "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" + - "WHERE messages.profileId = "+profileId+" AND messageType = "+messageType+" AND "+filter+"\n" + - "ORDER BY addedDate DESC")); - } - - public LiveData> getWithMetadata(int profileId, int messageType, String filter) { - return getAll(new SimpleSQLiteQuery("SELECT \n" + - "* \n" + - "FROM messages \n" + - "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" + - "WHERE messages.profileId = "+profileId+" AND messageType = "+messageType+" AND "+filter+"\n" + - "ORDER BY addedDate DESC")); - } - - @Nullable - public MessageFull getById(int profileId, long messageId) { - return getOneNow(new SimpleSQLiteQuery("SELECT \n" + - "*, \n" + - "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" + - "FROM messages \n" + - "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" + - "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" + - "WHERE messages.profileId = "+profileId+" AND messageId = "+messageId+"\n" + - "ORDER BY addedDate DESC")); - } - - public LiveData> getReceived(int profileId) { - return getWithMetadataAndSenderName(profileId, TYPE_RECEIVED, "1"); - } - public LiveData> getDeleted(int profileId) { - return getWithMetadataAndSenderName(profileId, TYPE_DELETED, "1"); - } - public LiveData> getSent(int profileId) { - return getWithMetadata(profileId, TYPE_SENT, "1"); - } - - public List getReceivedNow(int profileId, String filter) { - return getNow(new SimpleSQLiteQuery("SELECT \n" + - "*, \n" + - "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" + - "FROM messages \n" + - "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" + - "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" + - "WHERE messages.profileId = "+profileId+" AND messageType = 0 AND "+filter+"\n" + - "ORDER BY addedDate DESC")); - } - public List getReceivedNotNotifiedNow(int profileId) { - return getReceivedNow(profileId, "notified = 0"); - } - - @Query("SELECT " + - "*, " + - "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName " + - "FROM messages " + - "LEFT JOIN teachers ON teachers.profileId = messages.profileId AND teacherId = senderId " + - "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = messages.profileId " + - "WHERE messageType = 0 AND notified = 0 " + - "ORDER BY addedDate DESC") - public abstract List getReceivedNotNotifiedNow(); -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt new file mode 100644 index 00000000..606f29a7 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2020-1-6 + */ +package pl.szczodrzynski.edziennik.data.db.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Query +import androidx.room.RawQuery +import androidx.sqlite.db.SupportSQLiteQuery +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.annotation.SelectiveDao +import pl.szczodrzynski.edziennik.annotation.UpdateSelective +import pl.szczodrzynski.edziennik.data.db.AppDb +import pl.szczodrzynski.edziennik.data.db.entity.Message +import pl.szczodrzynski.edziennik.data.db.entity.Metadata +import pl.szczodrzynski.edziennik.data.db.full.MessageFull + +@Dao +@SelectiveDao(db = AppDb::class) +abstract class MessageDao : BaseDao { + companion object { + private const val QUERY = """ + SELECT + *, + teachers.teacherName ||" "|| teachers.teacherSurname AS senderName + FROM messages + LEFT JOIN teachers ON teachers.profileId = messages.profileId AND teacherId = senderId + LEFT JOIN metadata ON messageId = thingId AND thingType = ${Metadata.TYPE_MESSAGE} AND metadata.profileId = messages.profileId + """ + + private const val ORDER_BY = """ORDER BY messageIsPinned, addedDate DESC""" + } + + private val selective by lazy { MessageDaoSelective(App.db) } + + @RawQuery(observedEntities = [Message::class]) + abstract override fun getRaw(query: SupportSQLiteQuery): LiveData> + + @UpdateSelective(primaryKeys = ["profileId", "messageId"], skippedColumns = ["messageType", "messageBody", "messageIsPinned", "attachmentIds", "attachmentNames", "attachmentSizes"]) + override fun update(item: Message) = selective.update(item) + override fun updateAll(items: List) = selective.updateAll(items) + + // CLEAR + @Query("DELETE FROM messages WHERE profileId = :profileId") + abstract override fun clear(profileId: Int) + + // GET ALL - LIVE DATA + fun getAll(profileId: Int) = + getRaw("$QUERY WHERE messages.profileId = $profileId $ORDER_BY") + fun getAllByType(profileId: Int, type: Int) = + getRaw("$QUERY WHERE messages.profileId = $profileId AND messageType = $type $ORDER_BY") + fun getReceived(profileId: Int) = getAllByType(profileId, Message.TYPE_RECEIVED) + fun getSent(profileId: Int) = getAllByType(profileId, Message.TYPE_SENT) + fun getDeleted(profileId: Int) = getAllByType(profileId, Message.TYPE_DELETED) + fun getDraft(profileId: Int) = getAllByType(profileId, Message.TYPE_DRAFT) + + // GET ALL - NOW + fun getAllNow(profileId: Int) = + getRawNow("$QUERY WHERE messages.profileId = $profileId $ORDER_BY") + fun getNotNotifiedNow() = + getRawNow("$QUERY WHERE notified = 0 AND messageType = ${Message.TYPE_RECEIVED} $ORDER_BY") + + // GET ONE - NOW + fun getByIdNow(profileId: Int, id: Long) = + getOneNow("$QUERY WHERE messages.profileId = $profileId AND messageId = $id") +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java index 510306fe..7a074bca 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java @@ -93,8 +93,8 @@ public abstract class MetadataDao { } } if (o instanceof Message) { - if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).id, seen, false, 0)) == -1) { - updateSeen(profileId, TYPE_MESSAGE, ((Message) o).id, seen); + if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen, false, 0)) == -1) { + updateSeen(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen); } } } @@ -132,8 +132,8 @@ public abstract class MetadataDao { } } if (o instanceof Message) { - if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).id, false, notified, 0)) == -1) { - updateNotified(profileId, TYPE_MESSAGE, ((Message) o).id, notified); + if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), false, notified, 0)) == -1) { + updateNotified(profileId, TYPE_MESSAGE, ((Message) o).getId(), notified); } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.java deleted file mode 100644 index f1b6453b..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-1-6 - */ - -package pl.szczodrzynski.edziennik.data.db.entity; - -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.Index; - -import java.util.ArrayList; -import java.util.List; - -@Entity(tableName = "messages", - primaryKeys = {"profileId", "messageId"}, - indices = {@Index(value = {"profileId"})}) -public class Message { - public int profileId; - - @ColumnInfo(name = "messageId") - public long id; - - @ColumnInfo(name = "messageSubject") - public String subject; - @Nullable - @ColumnInfo(name = "messageBody") - public String body = null; - - public static final int TYPE_RECEIVED = 0; - public static final int TYPE_SENT = 1; - public static final int TYPE_DELETED = 2; - public static final int TYPE_DRAFT = 3; - @ColumnInfo(name = "messageType") - public int type = TYPE_RECEIVED; - - public long senderId = -1; // -1 for sent messages - public long senderReplyId = -1; - public boolean overrideHasAttachments = false; // if the attachments are not yet downloaded but we already know there are some - public List attachmentIds = null; - public List attachmentNames = null; - public List attachmentSizes = null; - - @Ignore - public Message() {} - - public Message(int profileId, long id, String subject, @Nullable String body, int type, long senderId, long senderReplyId) { - this.profileId = profileId; - this.id = id; - this.subject = subject; - this.body = body; - this.type = type; - this.senderId = senderId; - this.senderReplyId = senderReplyId; - } - - /** - * Add an attachment - * @param id attachment ID - * @param name file name incl. extension - * @param size file size or -1 if unknown - * @return a Message to which the attachment has been added - */ - public Message addAttachment(long id, String name, long size) { - if (attachmentIds == null) - attachmentIds = new ArrayList<>(); - if (attachmentNames == null) - attachmentNames = new ArrayList<>(); - if (attachmentSizes == null) - attachmentSizes = new ArrayList<>(); - attachmentIds.add(id); - attachmentNames.add(name); - attachmentSizes.add(size); - return this; - } - - public void clearAttachments() { - attachmentIds = null; - attachmentNames = null; - attachmentSizes = null; - } - - public Message setHasAttachments() { - overrideHasAttachments = true; - return this; - } - - public boolean hasAttachments() { - return overrideHasAttachments || (attachmentIds != null && attachmentIds.size() > 0); - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.kt new file mode 100644 index 00000000..1cf9b3ba --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Message.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2020-1-6 + */ +package pl.szczodrzynski.edziennik.data.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.Index +import pl.szczodrzynski.edziennik.isNotNullNorEmpty + +@Entity(tableName = "messages", + primaryKeys = ["profileId", "messageId"], + indices = [ + Index(value = ["profileId", "messageType"]) + ]) +open class Message( + val profileId: Int, + @ColumnInfo(name = "messageId") + val id: Long, + @ColumnInfo(name = "messageType") + var type: Int, + + @ColumnInfo(name = "messageSubject") + var subject: String, + @ColumnInfo(name = "messageBody") + var body: String?, + + /** + * Keep in mind that this being null does NOT + * necessarily mean the message is sent. + */ + var senderId: Long? +) : Keepable() { + companion object { + const val TYPE_RECEIVED = 0 + const val TYPE_SENT = 1 + const val TYPE_DELETED = 2 + const val TYPE_DRAFT = 3 + } + + @ColumnInfo(name = "messageIsPinned") + var isPinned: Boolean = false + + var hasAttachments = false // if the attachments are not yet downloaded but we already know there are some + get() = field || attachmentIds.isNotNullNorEmpty() + var attachmentIds: MutableList? = null + var attachmentNames: MutableList? = null + var attachmentSizes: MutableList? = null + + @Ignore + var showAsUnseen: Boolean? = null + + /** + * Add an attachment + * @param id attachment ID + * @param name file name incl. extension + * @param size file size or -1 if unknown + * @return a Message to which the attachment has been added + */ + fun addAttachment(id: Long, name: String, size: Long): Message { + if (attachmentIds == null) attachmentIds = mutableListOf() + if (attachmentNames == null) attachmentNames = mutableListOf() + if (attachmentSizes == null) attachmentSizes = mutableListOf() + attachmentIds?.add(id) + attachmentNames?.add(name) + attachmentSizes?.add(size) + return this + } + + fun clearAttachments() { + attachmentIds = null + attachmentNames = null + attachmentSizes = null + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.java deleted file mode 100644 index be7ba692..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-1-6 - */ - -package pl.szczodrzynski.edziennik.data.db.full; - -import androidx.annotation.Nullable; -import androidx.room.Ignore; - -import java.util.ArrayList; -import java.util.List; - -import pl.szczodrzynski.edziennik.data.db.entity.Message; - -public class MessageFull extends Message { - public String senderFullName = null; - @Ignore - @Nullable - public List recipients = null; - - public MessageFull addRecipient(MessageRecipientFull recipient) { - if (recipients == null) - recipients = new ArrayList<>(); - recipients.add(recipient); - return this; - } - - // metadata - public boolean seen; - public boolean notified; - public long addedDate; -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.kt new file mode 100644 index 00000000..04f83595 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageFull.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2020-1-6 + */ +package pl.szczodrzynski.edziennik.data.db.full + +import androidx.room.Relation +import pl.szczodrzynski.edziennik.data.db.entity.Message +import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient + +class MessageFull( + profileId: Int, id: Long, type: Int, + subject: String, body: String?, senderId: Long? +) : Message( + profileId, id, type, + subject, body, senderId +) { + var senderName: String? = null + @Relation(parentColumn = "messageId", entityColumn = "messageId", entity = MessageRecipient::class) + var recipients: MutableList? = null + + fun addRecipient(recipient: MessageRecipientFull): MessageFull { + if (recipients == null) recipients = mutableListOf() + recipients?.add(recipient) + return this + } + + // metadata + var seen = false + var notified = false + var addedDate: Long = 0 +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageRecipientFull.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageRecipientFull.kt index 7f72245e..2126f872 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageRecipientFull.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/MessageRecipientFull.kt @@ -2,17 +2,13 @@ package pl.szczodrzynski.edziennik.data.db.full import androidx.room.Ignore import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient -import pl.szczodrzynski.edziennik.fixName - -class MessageRecipientFull : MessageRecipient { - var fullName: String? = "" - get() { - return field?.fixName() ?: "" - } +class MessageRecipientFull( + profileId: Int, + id: Long, + messageId: Long, + readDate: Long = -1L +) : MessageRecipient(profileId, id, -1, readDate, messageId) { @Ignore - constructor(profileId: Int, id: Long, replyId: Long, readDate: Long, messageId: Long) : super(profileId, id, replyId, readDate, messageId) {} - @Ignore - constructor(profileId: Int, id: Long, messageId: Long) : super(profileId, id, messageId) {} - constructor() : super() {} + var fullName: String? = null } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration84.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration84.kt new file mode 100644 index 00000000..67ae8dbc --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration84.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-4-4. + */ + +package pl.szczodrzynski.edziennik.data.db.migration + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +class Migration84 : Migration(83, 84) { + override fun migrate(database: SupportSQLiteDatabase) { + // The Message Update + database.execSQL("ALTER TABLE messages RENAME TO _messages;") + database.execSQL("""CREATE TABLE messages ( + profileId INTEGER NOT NULL, + messageId INTEGER NOT NULL, + messageType INTEGER NOT NULL, + messageSubject TEXT NOT NULL, + messageBody TEXT, + senderId INTEGER, + messageIsPinned INTEGER NOT NULL DEFAULT 0, + hasAttachments INTEGER NOT NULL DEFAULT 0, + attachmentIds TEXT DEFAULT NULL, + attachmentNames TEXT DEFAULT NULL, + attachmentSizes TEXT DEFAULT NULL, + keep INTEGER NOT NULL DEFAULT 1, + PRIMARY KEY(profileId, messageId) + )""") + database.execSQL("DROP INDEX IF EXISTS index_messages_profileId") + database.execSQL("CREATE INDEX index_messages_profileId_messageType ON messages (profileId, messageType)") + database.execSQL(""" + INSERT INTO messages (profileId, messageId, messageType, messageSubject, messageBody, senderId, hasAttachments, attachmentIds, attachmentNames, attachmentSizes) + SELECT profileId, messageId, messageType, messageSubject, messageBody, + CASE senderId WHEN -1 THEN NULL ELSE senderId END, + overrideHasAttachments, attachmentIds, attachmentNames, attachmentSizes + FROM _messages + """) + database.execSQL("DROP TABLE _messages") + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyMobidziennikFirebase.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyMobidziennikFirebase.kt index f102fc2a..b097dbed 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyMobidziennikFirebase.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/SzkolnyMobidziennikFirebase.kt @@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.task.IApiTask -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.getLong import pl.szczodrzynski.edziennik.getString diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt index 81b990a9..93773dd3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt @@ -71,7 +71,7 @@ class GradesListFragment : Fragment(), CoroutineScope { val adapter = GradesAdapter(activity) var firstRun = true - app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this, Observer { items -> launch { + app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { items -> launch { if (!isAdded) return@launch // load & configure the adapter diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkListFragment.kt index 525d31c5..1852c340 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkListFragment.kt @@ -94,7 +94,7 @@ class HomeworkListFragment : LazyFragment(), CoroutineScope { } } adapter.notifyDataSetChanged() - setSwipeToRefresh(false) // TODO + setSwipeToRefresh(items.isNullOrEmpty()) // show/hide relevant views b.progressBar.isVisible = false diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index 83f790f1..14693cb8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -37,8 +37,8 @@ import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent.Companion.T import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.LoginStore.Companion.LOGIN_TYPE_IDZIENNIK -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED -import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED +import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.databinding.MessageFragmentBinding import pl.szczodrzynski.edziennik.utils.Anim @@ -127,7 +127,7 @@ class MessageFragment : Fragment(), CoroutineScope { it.addedDate = arguments?.getLong("sentDate") ?: System.currentTimeMillis() } else - app.db.messageDao().getById(App.profileId, messageId) + app.db.messageDao().getByIdNow(App.profileId, messageId) msg?.also { it.recipients = app.db.messageRecipientDao().getAllByMessageId(it.profileId, it.id) @@ -290,10 +290,10 @@ class MessageFragment : Fragment(), CoroutineScope { // CREATE VIEWS AND AN OBJECT FOR EVERY ATTACHMENT - message.attachmentNames.forEachIndexed { index, name -> + message.attachmentNames?.forEachIndexed { index, name -> val messageId = message.id - val id = message.attachmentIds[index] - val size = message.attachmentSizes[index] + val id = message.attachmentIds?.getOrNull(index) ?: return@forEachIndexed + val size = message.attachmentSizes?.getOrNull(index) ?: return@forEachIndexed // create the parent val attachmentLayout = FrameLayout(b.root.context) attachmentLayout.setPadding(16.dp, 0, 16.dp, 0) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesAdapter.kt index 8cdbc005..c003bb50 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesAdapter.kt @@ -2,73 +2,88 @@ package pl.szczodrzynski.edziennik.ui.modules.messages import android.graphics.Typeface import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.AdapterView.OnItemClickListener -import androidx.core.view.ViewCompat -import androidx.databinding.DataBindingUtil +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerView.Adapter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.Message +import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.full.MessageFull -import pl.szczodrzynski.edziennik.databinding.MessagesItemBinding -import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesAdapter.ViewHolder +import pl.szczodrzynski.edziennik.databinding.MessagesListItemBinding +import pl.szczodrzynski.edziennik.onClick import pl.szczodrzynski.edziennik.utils.models.Date +import kotlin.coroutines.CoroutineContext -class MessagesAdapter(private val app: App, private val onItemClickListener: OnItemClickListener) : Adapter() { - var messageList: List = ArrayList() - fun setData(messageList: List) { - this.messageList = messageList - notifyDataSetChanged() +class MessagesAdapter( + val activity: AppCompatActivity, + val teachers: List, + val onItemClick: ((item: MessageFull) -> Unit)? = null +) : RecyclerView.Adapter(), CoroutineScope { + companion object { + private const val TAG = "TemplateAdapter" } + private val app = activity.applicationContext as App + // optional: place the manager here + + private val job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + var items = listOf() + private val typefaceNormal by lazy { Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) } + private val typefaceBold by lazy { Typeface.create(Typeface.DEFAULT, Typeface.BOLD) } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(parent.context) - return ViewHolder(DataBindingUtil.inflate(inflater, R.layout.messages_item, parent, false)) + val view = MessagesListItemBinding.inflate(inflater, parent, false) + return ViewHolder(view) } + @Suppress("DEPRECATION") override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = items[position] val b = holder.b - val message = messageList[position] - b.root.setOnClickListener { v: View? -> onItemClickListener.onItemClick(null, v, position, position.toLong()) } - ViewCompat.setTransitionName(b.root, message.id.toString()) - - b.messageSubject.text = message.subject - b.messageDate.text = Date.fromMillis(message.addedDate).formattedStringShort - b.messageAttachmentImage.visibility = if (message.hasAttachments()) View.VISIBLE else View.GONE - - val text = message.body?.substring(0, message.body!!.length.coerceAtMost(200)) ?: "" - b.messageBody.text = MessagesUtils.htmlToSpannable(b.root.context, text) - - if (message.type == Message.TYPE_SENT || message.type == Message.TYPE_DRAFT || message.seen) { - b.messageSender.setTextAppearance(b.messageSender.context, R.style.NavView_TextView_Small) - b.messageSender.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) - b.messageSender.textSize = 16f - b.messageSubject.setTextAppearance(b.messageSubject.context, R.style.NavView_TextView_Small) - b.messageSubject.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) - b.messageDate.setTextAppearance(b.messageDate.context, R.style.NavView_TextView_Small) - b.messageDate.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) - } else { - b.messageSender.setTextAppearance(b.messageSender.context, R.style.NavView_TextView_Normal) - b.messageSender.typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) - b.messageSender.textSize = 16f - b.messageSubject.setTextAppearance(b.messageSubject.context, R.style.NavView_TextView_Normal) - b.messageSubject.typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) - b.messageDate.setTextAppearance(b.messageDate.context, R.style.NavView_TextView_Normal) - b.messageDate.typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) + item.recipients?.forEach { recipient -> + if (recipient.fullName == null) { + recipient.fullName = teachers.firstOrNull { it.id == recipient.id }?.fullName ?: "" + } } - val messageInfo = MessagesUtils.getMessageInfo(app, message, 48, 24, 18, 12) + + b.messageSubject.text = item.subject + b.messageDate.text = Date.fromMillis(item.addedDate).formattedStringShort + b.messageAttachmentImage.isVisible = item.hasAttachments + + val text = item.body?.take(200) ?: "" + b.messageBody.text = MessagesUtils.htmlToSpannable(activity, text) + + val isRead = item.type == Message.TYPE_SENT || item.type == Message.TYPE_DRAFT || item.seen + val typeface = if (isRead) typefaceNormal else typefaceBold + val style = if (isRead) R.style.NavView_TextView_Small else R.style.NavView_TextView_Normal + // set text styles + b.messageSender.setTextAppearance(activity, style) + b.messageSender.typeface = typeface + b.messageSubject.setTextAppearance(activity, style) + b.messageSubject.typeface = typeface + b.messageDate.setTextAppearance(activity, style) + b.messageDate.typeface = typeface + + val messageInfo = MessagesUtils.getMessageInfo(app, item, 48, 24, 18, 12) b.messageProfileBackground.setImageBitmap(messageInfo.profileImage) b.messageSender.text = messageInfo.profileName + + onItemClick?.let { listener -> + b.root.onClick { listener(item) } + } } - override fun getItemCount(): Int { - return messageList.size - } - - inner class ViewHolder(var b: MessagesItemBinding) : RecyclerView.ViewHolder(b.root) + override fun getItemCount() = items.size + class ViewHolder(val b: MessagesListItemBinding) : RecyclerView.ViewHolder(b.root) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt index c4cbf7f7..4e2e50e7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt @@ -5,82 +5,79 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import androidx.viewpager.widget.ViewPager import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.MainActivity -import pl.szczodrzynski.edziennik.R +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Message -import pl.szczodrzynski.edziennik.databinding.FragmentMessagesBinding -import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment -import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyPagerAdapter -import pl.szczodrzynski.edziennik.utils.Themes +import pl.szczodrzynski.edziennik.databinding.MessagesFragmentBinding +import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.FragmentLazyPagerAdapter +import kotlin.coroutines.CoroutineContext -class MessagesFragment : Fragment() { +class MessagesFragment : Fragment(), CoroutineScope { companion object { + private const val TAG = "MessagesFragment" var pageSelection = 0 } private lateinit var app: App private lateinit var activity: MainActivity - private lateinit var b: FragmentMessagesBinding + private lateinit var b: MessagesFragmentBinding + + private val job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + // local/private variables go here override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null - if (context == null) - return null + context ?: return null app = activity.application as App - context!!.theme.applyStyle(Themes.appTheme, true) - if (app.profile == null) - return inflater.inflate(R.layout.fragment_loading, container, false) - // activity, context and profile is valid - b = FragmentMessagesBinding.inflate(inflater) + b = MessagesFragmentBinding.inflate(inflater) b.refreshLayout.setParent(activity.swipeRefreshLayout) return b.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - // TODO check if app, activity, b can be null - if (app.profile == null || !isAdded) - return + if (!isAdded) return val messageId = arguments?.getLong("messageId", -1L) ?: -1L if (messageId != -1L) { val args = Bundle() args.putLong("messageId", messageId) - arguments!!.remove("messageId") + arguments?.remove("messageId") activity.loadTarget(MainActivity.TARGET_MESSAGES_DETAILS, args) return } - b.viewPager.adapter = Adapter(childFragmentManager, b.refreshLayout).also { adapter -> + val pagerAdapter = FragmentLazyPagerAdapter( + fragmentManager ?: return, + b.refreshLayout, + listOf( + MessagesListFragment().apply { + arguments = Bundle("messageType" to Message.TYPE_RECEIVED) + } to getString(R.string.messages_tab_received), - adapter.addFragment(MessagesListFragment().also { fragment -> - fragment.arguments = Bundle().also { args -> - args.putInt("messageType", Message.TYPE_RECEIVED) - } - }, getString(R.string.menu_messages_inbox)) + MessagesListFragment().apply { + arguments = Bundle("messageType" to Message.TYPE_SENT) + } to getString(R.string.messages_tab_sent), - adapter.addFragment(MessagesListFragment().also { fragment -> - fragment.arguments = Bundle().also { args -> - args.putInt("messageType", Message.TYPE_SENT) - } - }, getString(R.string.menu_messages_sent)) - - } - - b.viewPager.currentItem = pageSelection - b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { - override fun onPageScrollStateChanged(state: Int) {} - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} - override fun onPageSelected(position: Int) { - pageSelection = position + MessagesListFragment().apply { + arguments = Bundle("messageType" to Message.TYPE_DELETED) + } to getString(R.string.messages_tab_deleted) + ) + ) + b.viewPager.apply { + offscreenPageLimit = 1 + adapter = pagerAdapter + currentItem = pageSelection + addOnPageSelectedListener { + pageSelection = it } - }) - - b.tabLayout.setupWithViewPager(b.viewPager) + b.tabLayout.setupWithViewPager(this) + } activity.navView.apply { bottomBar.apply { @@ -95,52 +92,5 @@ class MessagesFragment : Fragment() { } activity.gainAttentionFAB() - - /*if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getStudentData("accountPassword", null) == null) { - MaterialDialog.Builder(activity) - .title("Wiadomości w systemie Synergia") - .content("Moduł Wiadomości w aplikacji Szkolny.eu jest przeglądarką zasobów szkolnego konta Synergia. Z tego powodu, musisz wpisać swoje hasło do tego konta, aby móc korzystać z tej funkcji.") - .positiveText(R.string.ok) - .onPositive { dialog, which -> - MaterialDialog.Builder(activity) - .title("Zaloguj się") - .content(Html.fromHtml("Podaj hasło do konta Synergia z loginem " + app.profile.getStudentData("accountLogin", "???") + "")) - .inputType(InputType.TYPE_TEXT_VARIATION_PASSWORD) - .input(null, null) { dialog1, input -> - app.profile.putStudentData("accountPassword", input.toString()) - app.profileSaveFullAsync(app.profile) - EdziennikTask.syncProfile(App.profileId, listOf( - DRAWER_ITEM_MESSAGES to Message.TYPE_RECEIVED, - DRAWER_ITEM_MESSAGES to Message.TYPE_SENT - )).enqueue(context!!) - } - .positiveText(R.string.ok) - .negativeText(R.string.cancel) - .show() - } - .show() - }*/ - } - - internal class Adapter(manager: FragmentManager, swipeRefreshLayout: SwipeRefreshLayout) : LazyPagerAdapter(manager, swipeRefreshLayout) { - private val mFragmentList = mutableListOf() - private val mFragmentTitleList = mutableListOf() - - override fun getPage(position: Int): LazyFragment { - return mFragmentList[position] - } - - override fun getCount(): Int { - return mFragmentList.size - } - - fun addFragment(fragment: LazyFragment, title: String) { - mFragmentList.add(fragment) - mFragmentTitleList.add(title) - } - - override fun getPageTitle(position: Int): CharSequence { - return mFragmentTitleList[position] - } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.kt new file mode 100644 index 00000000..127bf017 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-4-4. + */ + +package pl.szczodrzynski.edziennik.ui.modules.messages + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.withContext +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.db.entity.Message +import pl.szczodrzynski.edziennik.data.db.entity.Teacher +import pl.szczodrzynski.edziennik.databinding.MessagesListFragmentBinding +import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment +import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration +import kotlin.coroutines.CoroutineContext + +class MessagesListFragment : LazyFragment(), CoroutineScope { + companion object { + private const val TAG = "MessagesListFragment" + } + + private lateinit var app: App + private lateinit var activity: MainActivity + private lateinit var b: MessagesListFragmentBinding + + private val job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + // local/private variables go here + var teachers = listOf() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + activity = (getActivity() as MainActivity?) ?: return null + context ?: return null + app = activity.application as App + b = MessagesListFragmentBinding.inflate(inflater) + return b.root + } + + override fun onPageCreated(): Boolean { startCoroutineTimer(100L) { + val messageType = arguments.getInt("messageType", Message.TYPE_RECEIVED) + + teachers = withContext(Dispatchers.Default) { + app.db.teacherDao().getAllNow(App.profileId) + } + + val adapter = MessagesAdapter(activity, teachers) { + + } + + app.db.messageDao().getAllByType(App.profileId, messageType).observe(this@MessagesListFragment, Observer { items -> + if (!isAdded) return@Observer + + items.forEach { message -> + message.recipients?.removeAll { it.profileId != message.profileId } + } + + // load & configure the adapter + adapter.items = items + if (items.isNotNullNorEmpty() && b.list.adapter == null) { + b.list.adapter = adapter + b.list.apply { + setHasFixedSize(true) + layoutManager = LinearLayoutManager(context) + addItemDecoration(SimpleDividerItemDecoration(context)) + if (messageType in Message.TYPE_RECEIVED..Message.TYPE_SENT) + addOnScrollListener(onScrollListener) + } + } + adapter.notifyDataSetChanged() + setSwipeToRefresh(messageType in Message.TYPE_RECEIVED..Message.TYPE_SENT && items.isNullOrEmpty()) + + // show/hide relevant views + b.progressBar.isVisible = false + if (items.isNullOrEmpty()) { + b.list.isVisible = false + b.noData.isVisible = true + } else { + b.list.isVisible = true + b.noData.isVisible = false + } + }) + }; return true } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragmentOld.java similarity index 94% rename from app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.java rename to app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragmentOld.java index fb48c6f5..c9574de7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesListFragmentOld.java @@ -33,7 +33,7 @@ import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; import static pl.szczodrzynski.edziennik.utils.Utils.d; -public class MessagesListFragment extends LazyFragment { +public class MessagesListFragmentOld extends LazyFragment { private App app = null; private MainActivity activity = null; @@ -90,19 +90,19 @@ public class MessagesListFragment extends LazyFragment { activity.syncCurrentFeature(messageType, b.refreshLayout); });*/ - messagesAdapter = new MessagesAdapter(app, ((parent, view1, position, id) -> { + /*messagesAdapter = new MessagesAdapter(app, ((parent, view1, position, id) -> { // TODO ANIMATION tapPositions[messageType] = position; topPositions[messageType] = ((LinearLayoutManager) b.emailList.getLayoutManager()).findFirstCompletelyVisibleItemPosition(); bottomPositions[messageType] = ((LinearLayoutManager) b.emailList.getLayoutManager()).findLastCompletelyVisibleItemPosition(); - /*view1.getGlobalVisibleRect(viewRect); + *//*view1.getGlobalVisibleRect(viewRect); ((Transition) MessagesListFragment.this.getExitTransition()).setEpicenterCallback(new Transition.EpicenterCallback() { @Override public Rect onGetEpicenter(@NonNull Transition transition) { return viewRect; } - });*/ + });*//* Bundle args = new Bundle(); args.putLong("messageId", messagesAdapter.getMessageList().get(position).id); @@ -110,7 +110,7 @@ public class MessagesListFragment extends LazyFragment { // KOD W WERSJI 2.7 // TODO ANIMATION - /*TransitionSet sharedElementTransition = new TransitionSet() + *//*TransitionSet sharedElementTransition = new TransitionSet() .addTransition(new Fade()) .addTransition(new ChangeBounds()) .addTransition(new ChangeTransform()) @@ -123,10 +123,10 @@ public class MessagesListFragment extends LazyFragment { args.putLong("messageId", messagesAdapter.messageList.get(position).id); fragment.setArguments(args); fragment.setSharedElementEnterTransition(sharedElementTransition); - fragment.setSharedElementReturnTransition(sharedElementTransition);*/ + fragment.setSharedElementReturnTransition(sharedElementTransition);*//* // JAKIS STARSZY KOD - /*Intent intent = new Intent(activity, MessagesDetailsActivity.class); + *//*Intent intent = new Intent(activity, MessagesDetailsActivity.class); intent.putExtra("item_id", 1); intent.putExtra("transition_name", ViewCompat.getTransitionName(view1)); @@ -143,17 +143,17 @@ public class MessagesListFragment extends LazyFragment { setExitTransition(sharedElementTransition); setSharedElementEnterTransition(sharedElementTransition); setSharedElementReturnTransition(sharedElementTransition); - startActivity(intent, options.toBundle());*/ + startActivity(intent, options.toBundle());*//* - /*activity.getSupportFragmentManager() + *//*activity.getSupportFragmentManager() .beginTransaction() .setReorderingAllowed(true) .replace(R.id.fragment_container, fragment) .addToBackStack(null) .addSharedElement(view1, getString(R.string.transition_name)) - .commit();*/ + .commit();*//* - })); + }));*/ //tapPosition = savedInstanceState != null ? savedInstanceState.getInt(TAP_POSITION, tapPosition) : tapPosition; @@ -195,7 +195,7 @@ public class MessagesListFragment extends LazyFragment { List messageRecipients = App.db.messageRecipientDao().getAll(App.Companion.getProfileId()); List messageIds = new ArrayList<>(); for (MessageFull messageFull: messageFulls) { - messageIds.add(messageFull.id); + messageIds.add(messageFull.getId()); } for (MessageRecipientFull messageRecipientFull: messageRecipients) { if (messageRecipientFull.id == -1) @@ -233,7 +233,7 @@ public class MessagesListFragment extends LazyFragment { private void createMessageList(List messageFulls) { b.progressBar.setVisibility(View.GONE); b.emailList.setVisibility(View.VISIBLE); - messagesAdapter.setData(messageFulls); + //messagesAdapter.setData(messageFulls); LinearLayoutManager layoutManager = (LinearLayoutManager) b.emailList.getLayoutManager(); if (tapPositions[messageType] != NO_POSITION && layoutManager != null) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesUtils.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesUtils.kt index 8a5549bd..07a0769a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesUtils.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesUtils.kt @@ -124,7 +124,7 @@ object MessagesUtils { var profileImage: Bitmap? = null var profileName: String? = null if (message.type == Message.TYPE_RECEIVED || message.type == Message.TYPE_DELETED) { - profileName = message.senderFullName?.fixName() + profileName = message.senderName?.fixName() profileImage = getProfileImage(diameterDp, textSizeBigDp, textSizeMediumDp, textSizeSmallDp, 1, profileName) } else if (message.type == Message.TYPE_SENT || message.type == Message.TYPE_DRAFT && message.recipients != null) { when (val count = message.recipients?.size ?: 0) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/SlideExplode.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/SlideExplode.java deleted file mode 100644 index 6161b6dd..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/SlideExplode.java +++ /dev/null @@ -1,75 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.messages; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.graphics.Rect; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.transition.TransitionValues; -import androidx.transition.Visibility; - -public class SlideExplode extends Visibility { - private static final String KEY_SCREEN_BOUNDS = "screenBounds"; - - private int[] mTempLoc = new int[2]; - - private void captureValues(TransitionValues transitionValues) { - View view = transitionValues.view; - view.getLocationOnScreen(mTempLoc); - int left = mTempLoc[0]; - int top = mTempLoc[1]; - int right = left + view.getWidth(); - int bottom = top + view.getHeight(); - transitionValues.values.put(KEY_SCREEN_BOUNDS, new Rect(left, top, right, bottom)); - } - - @Override - public void captureStartValues(@NonNull TransitionValues transitionValues) { - super.captureStartValues(transitionValues); - captureValues(transitionValues); - } - - @Override - public void captureEndValues(@NonNull TransitionValues transitionValues) { - super.captureEndValues(transitionValues); - captureValues(transitionValues); - } - - @Override - public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { - if (endValues == null) - return null; - - Rect bounds = (Rect) endValues.values.get(KEY_SCREEN_BOUNDS); - float endY = view.getTranslationY(); - float startY = endY + calculateDistance(sceneRoot, bounds); - return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY); - } - - @Override - public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { - if (startValues == null) - return null; - - Rect bounds = (Rect) startValues.values.get(KEY_SCREEN_BOUNDS); - float startY = view.getTranslationY(); - float endY = startY + calculateDistance(sceneRoot, bounds); - return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY); - } - - private int calculateDistance(View sceneRoot, Rect viewBounds) { - sceneRoot.getLocationOnScreen(mTempLoc); - int sceneRootY = mTempLoc[1]; - if (getEpicenter() == null) { - return -sceneRoot.getHeight(); - } - else if (viewBounds.top <= getEpicenter().top) { - return sceneRootY - getEpicenter().top; - } - else { - return sceneRootY + sceneRoot.getHeight() - getEpicenter().bottom; - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/Transitions.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/Transitions.java deleted file mode 100644 index 4e6f38a2..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/Transitions.java +++ /dev/null @@ -1,18 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.messages; - -import android.animation.TimeInterpolator; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.transition.TransitionSet; - -public class Transitions extends TransitionSet { - @NonNull - @Override - public TransitionSet setInterpolator(@Nullable TimeInterpolator interpolator) { - for (int i = 0; i < getTransitionCount(); i++) { - getTransitionAt(i).setInterpolator(interpolator); - } - return this; - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt similarity index 97% rename from app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt rename to app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt index 78097956..819978c1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt @@ -1,8 +1,8 @@ /* - * Copyright (c) Kuba Szczodrzyński 2019-12-22. + * Copyright (c) Kuba Szczodrzyński 2020-4-4. */ -package pl.szczodrzynski.edziennik.ui.modules.messages +package pl.szczodrzynski.edziennik.ui.modules.messages.compose import android.content.Context import android.graphics.Typeface @@ -43,6 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.databinding.MessagesComposeFragmentBinding +import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils.getProfileImage import pl.szczodrzynski.edziennik.utils.Colors import pl.szczodrzynski.edziennik.utils.Themes @@ -361,7 +362,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { span.appendText("W dniu ") span.appendSpan(dateString, StyleSpan(Typeface.ITALIC), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) span.appendText(", ") - span.appendSpan(msg.senderFullName.fixName(), StyleSpan(Typeface.ITALIC), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + span.appendSpan(msg.senderName.fixName(), StyleSpan(Typeface.ITALIC), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) span.appendText(" napisał(a):") span.setSpan(StyleSpan(Typeface.BOLD), 0, span.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) span.appendText("\n\n") @@ -380,7 +381,8 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { span.replace(0, 0, "\n\n") subject = "Fwd: ${msg.subject}" } - body = MessagesUtils.htmlToSpannable(activity,msg.body ?: "Nie udało się wczytać oryginalnej wiadomości.")//Html.fromHtml(msg.body?.replace("".toRegex(), "\n") ?: "Nie udało się wczytać oryginalnej wiadomości.") + body = MessagesUtils.htmlToSpannable(activity, msg.body + ?: "Nie udało się wczytać oryginalnej wiadomości.")//Html.fromHtml(msg.body?.replace("".toRegex(), "\n") ?: "Nie udało się wczytać oryginalnej wiadomości.") } b.recipients.addTextWithChips(chipList) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeInfo.kt similarity index 79% rename from app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeInfo.kt rename to app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeInfo.kt index fcb509f8..30b89472 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeInfo.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeInfo.kt @@ -1,4 +1,8 @@ -package pl.szczodrzynski.edziennik.ui.modules.messages +/* + * Copyright (c) Kuba Szczodrzyński 2020-4-4. + */ + +package pl.szczodrzynski.edziennik.ui.modules.messages.compose class MessagesComposeInfo( /** @@ -18,4 +22,4 @@ class MessagesComposeInfo( * -1 means unlimited length. */ var maxBodyLength: Int -) \ No newline at end of file +) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeSuggestionAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeSuggestionAdapter.kt similarity index 98% rename from app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeSuggestionAdapter.kt rename to app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeSuggestionAdapter.kt index 935d2d34..88600864 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesComposeSuggestionAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeSuggestionAdapter.kt @@ -1,4 +1,4 @@ -package pl.szczodrzynski.edziennik.ui.modules.messages +package pl.szczodrzynski.edziennik.ui.modules.messages.compose import android.content.Context import android.graphics.Typeface.BOLD diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsListFragment.kt index 96f25bd5..7cd9703b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsListFragment.kt @@ -72,7 +72,7 @@ class NotificationsListFragment : Fragment(), CoroutineScope { app.sendBroadcast(intent) } - app.db.notificationDao().getAll().observe(this, Observer { items -> + app.db.notificationDao().getAll().observe(this@NotificationsListFragment, Observer { items -> if (!isAdded) return@Observer // load & configure the adapter diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateFragment.kt index 1dff7db0..8adee96a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateFragment.kt @@ -12,12 +12,11 @@ import androidx.fragment.app.Fragment import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.MainActivity -import pl.szczodrzynski.edziennik.addOnPageSelectedListener +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.databinding.TemplateFragmentBinding import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.FragmentLazyPagerAdapter -import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment +import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkDate +import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkListFragment import kotlin.coroutines.CoroutineContext class TemplateFragment : Fragment(), CoroutineScope { @@ -52,6 +51,14 @@ class TemplateFragment : Fragment(), CoroutineScope { fragmentManager ?: return, b.refreshLayout, listOf( + HomeworkListFragment().apply { + arguments = Bundle("homeworkDate" to HomeworkDate.CURRENT) + } to getString(R.string.homework_tab_current), + + HomeworkListFragment().apply { + arguments = Bundle("homeworkDate" to HomeworkDate.PAST) + } to getString(R.string.homework_tab_past), + TemplatePageFragment() to "Pager 0", TemplatePageFragment() to "Pager 1", TemplatePageFragment() to "Pager 2", @@ -67,7 +74,7 @@ class TemplateFragment : Fragment(), CoroutineScope { adapter = pagerAdapter currentItem = pageSelection addOnPageSelectedListener { - HomeworkFragment.pageSelection = it + pageSelection = it } b.tabLayout.setupWithViewPager(this) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListFragment.kt index e2d6c220..c044c4cf 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListFragment.kt @@ -49,7 +49,7 @@ class TemplateListFragment : Fragment(), CoroutineScope { val adapter = TemplateAdapter(activity) - app.db.notificationDao().getAll().observe(this, Observer { items -> + app.db.notificationDao().getAll().observe(this@TemplateListFragment, Observer { items -> if (!isAdded) return@Observer // load & configure the adapter diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListPageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListPageFragment.kt index ce5c5001..e2395668 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListPageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/template/TemplateListPageFragment.kt @@ -49,7 +49,7 @@ class TemplateListPageFragment : LazyFragment(), CoroutineScope { override fun onPageCreated(): Boolean { startCoroutineTimer(100L) { val adapter = TemplateAdapter(activity) - app.db.notificationDao().getAll().observe(this, Observer { items -> + app.db.notificationDao().getAll().observe(this@TemplateListPageFragment, Observer { items -> if (!isAdded) return@Observer // load & configure the adapter @@ -64,7 +64,7 @@ class TemplateListPageFragment : LazyFragment(), CoroutineScope { } } adapter.notifyDataSetChanged() - setSwipeToRefresh(false) // TODO + setSwipeToRefresh(items.isNullOrEmpty()) // show/hide relevant views b.progressBar.isVisible = false diff --git a/app/src/main/res/drawable/ic_no_messages.xml b/app/src/main/res/drawable/ic_no_messages.xml new file mode 100644 index 00000000..dfbf4678 --- /dev/null +++ b/app/src/main/res/drawable/ic_no_messages.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/src/main/res/layout/messages_fragment.xml b/app/src/main/res/layout/messages_fragment.xml new file mode 100644 index 00000000..b09dc1f5 --- /dev/null +++ b/app/src/main/res/layout/messages_fragment.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/messages_list_fragment.xml b/app/src/main/res/layout/messages_list_fragment.xml new file mode 100644 index 00000000..0399af9b --- /dev/null +++ b/app/src/main/res/layout/messages_list_fragment.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/messages_list_item.xml b/app/src/main/res/layout/messages_list_item.xml new file mode 100644 index 00000000..6bd8af55 --- /dev/null +++ b/app/src/main/res/layout/messages_list_item.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index f8bc7c51..66259890 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -414,8 +414,8 @@ Manage profiles Mark as read Messages - Inbox - Sent + Inbox + Sent Behaviour Notifications Settings diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 423df0a0..ae5cd7ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -458,8 +458,8 @@ Oznacz jako przeczytane Oznacz wszystko jako przeczytane Wiadomości - Odebrane - Wysłane + Odebrane + Wysłane Zachowanie Powiadomienia Ustaw numer w dzienniku @@ -1287,4 +1287,6 @@ Załączniki Pobierz ponownie Laboratorium + Nie masz żadnych wiadomości. + Usunięte diff --git a/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt b/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt index d1a9fefa..5b5b1f71 100644 --- a/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt +++ b/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt @@ -158,9 +158,12 @@ class FileGenerator : AbstractProcessor() { allFields.removeAll { skippedColumns.contains(it.name()) } allFields.removeAll { it.getAnnotation(Ignore::class.java) != null } - allFields.removeAll { field -> field.modifiers.any { it == Modifier.STATIC || it == Modifier.FINAL } } + allFields.removeAll { field -> field.modifiers.any { it == Modifier.STATIC } } val allFieldsDistinct = allFields.distinct() + // dump fields + //processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, allFieldsDistinct.joinToString()) + val fields = allFieldsDistinct.filterNot { primaryKeys.contains(it.name()) } val primaryFields = allFieldsDistinct.filter { primaryKeys.contains(it.name()) } val fieldNames = fields.map { it.name() }