mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-28 16:09:39 +01:00
handle special system messages in ChatRepo instead in UI
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
db8d7b91d4
commit
85f4d8cd92
@ -2,7 +2,7 @@
|
|||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 10,
|
"version": 10,
|
||||||
"identityHash": "93ef64fac7a9a811c4a3c2f5a6406f87",
|
"identityHash": "234cdb754d42d9ebf2349763a58a4578",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "User",
|
"tableName": "User",
|
||||||
@ -438,7 +438,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "ChatMessages",
|
"tableName": "ChatMessages",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER, `token` TEXT, `id` INTEGER NOT NULL, `internalConversationId` TEXT, `actorType` TEXT, `actorId` TEXT, `actorDisplayName` TEXT, `timestamp` INTEGER NOT NULL, `systemMessage` TEXT, `messageType` TEXT, `isReplyable` INTEGER NOT NULL, `message` TEXT, `messageParameters` TEXT, `expirationTimestamp` INTEGER NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `markdown` INTEGER, `lastEditActorType` TEXT, `lastEditActorId` TEXT, `lastEditActorDisplayName` TEXT, `lastEditTimestamp` INTEGER, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER, `token` TEXT, `id` INTEGER NOT NULL, `internalConversationId` TEXT, `actorType` TEXT, `actorId` TEXT, `actorDisplayName` TEXT, `timestamp` INTEGER NOT NULL, `systemMessage` TEXT, `messageType` TEXT, `isReplyable` INTEGER NOT NULL, `message` TEXT, `messageParameters` TEXT, `expirationTimestamp` INTEGER NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `markdown` INTEGER, `lastEditActorType` TEXT, `lastEditActorId` TEXT, `lastEditActorDisplayName` TEXT, `lastEditTimestamp` INTEGER, `deleted` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "internalId",
|
"fieldPath": "internalId",
|
||||||
@ -577,6 +577,12 @@
|
|||||||
"columnName": "lastEditTimestamp",
|
"columnName": "lastEditTimestamp",
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "deleted",
|
||||||
|
"columnName": "deleted",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
@ -667,7 +673,7 @@
|
|||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '93ef64fac7a9a811c4a3c2f5a6406f87')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '234cdb754d42d9ebf2349763a58a4578')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -829,7 +829,7 @@ class ChatActivity :
|
|||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
chatViewModel.getUpdateMessageFlow
|
chatViewModel.getUpdateMessageFlow
|
||||||
.onEach {
|
.onEach {
|
||||||
updateAdapterForReaction(it)
|
updateMessageInsideAdapter(it)
|
||||||
}
|
}
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -2923,42 +2923,17 @@ class ChatActivity :
|
|||||||
|
|
||||||
private fun handleSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
private fun handleSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||||
val chatMessageMap = chatMessageList.map { it.id to it }.toMap().toMutableMap()
|
val chatMessageMap = chatMessageList.map { it.id to it }.toMap().toMutableMap()
|
||||||
|
|
||||||
val chatMessageIterator = chatMessageMap.iterator()
|
val chatMessageIterator = chatMessageMap.iterator()
|
||||||
while (chatMessageIterator.hasNext()) {
|
while (chatMessageIterator.hasNext()) {
|
||||||
val currentMessage = chatMessageIterator.next()
|
val currentMessage = chatMessageIterator.next()
|
||||||
|
|
||||||
// setDeletionFlagsAndRemoveInfomessages
|
|
||||||
if (isInfoMessageAboutDeletion(currentMessage)) {
|
|
||||||
if (!chatMessageMap.containsKey(currentMessage.value.parentMessageId.toString())) {
|
|
||||||
// if chatMessageMap doesn't contain message to delete (this happens when lookingIntoFuture),
|
|
||||||
// the message to delete has to be modified directly inside the adapter
|
|
||||||
|
|
||||||
val id = currentMessage.value.parentMessageId.toString()
|
|
||||||
val index = adapter?.getMessagePositionById(id) ?: 0
|
|
||||||
|
|
||||||
if (index > 0) {
|
|
||||||
val message = adapter?.items?.get(index)?.item as ChatMessage
|
|
||||||
setMessageAsDeleted(message)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
chatMessageMap[currentMessage.value.parentMessageId.toString()]!!.isDeleted = true
|
|
||||||
}
|
|
||||||
chatMessageIterator.remove()
|
|
||||||
} else if (isReactionsMessage(currentMessage)) {
|
|
||||||
// delete reactions system messages
|
|
||||||
if (!chatMessageMap.containsKey(currentMessage.value.parentMessageId.toString())) {
|
|
||||||
// updateAdapterForReaction(currentMessage.value.parentMessage) TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
chatMessageIterator.remove()
|
|
||||||
} else if (isPollVotedMessage(currentMessage)) {
|
|
||||||
// delete poll system messages
|
|
||||||
chatMessageIterator.remove()
|
|
||||||
} else if (isEditMessage(currentMessage)) {
|
|
||||||
if (!chatMessageMap.containsKey(currentMessage.value.parentMessageId.toString())) {
|
|
||||||
// setMessageAsEdited(currentMessage.value.parentMessage) TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (isInfoMessageAboutDeletion(currentMessage) ||
|
||||||
|
isReactionsMessage(currentMessage) ||
|
||||||
|
isPollVotedMessage(currentMessage) ||
|
||||||
|
isEditMessage(currentMessage)
|
||||||
|
) {
|
||||||
chatMessageIterator.remove()
|
chatMessageIterator.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3401,10 +3376,11 @@ class ChatActivity :
|
|||||||
adapter?.update(messageTemp)
|
adapter?.update(messageTemp)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAdapterForReaction(message: IMessage?) {
|
private fun updateMessageInsideAdapter(message: IMessage?) {
|
||||||
message?.let {
|
message?.let {
|
||||||
val messageTemp = message as ChatMessage
|
val messageTemp = message as ChatMessage
|
||||||
|
|
||||||
|
// TODO is this needed?
|
||||||
messageTemp.isOneToOneConversation =
|
messageTemp.isOneToOneConversation =
|
||||||
currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||||
messageTemp.activeUser = conversationUser
|
messageTemp.activeUser = conversationUser
|
||||||
|
@ -9,8 +9,6 @@ package com.nextcloud.talk.chat.data
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.nextcloud.talk.chat.data.io.LifecycleAwareManager
|
import com.nextcloud.talk.chat.data.io.LifecycleAwareManager
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessageJson
|
|
||||||
import com.nextcloud.talk.data.sync.Syncable
|
|
||||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||||
import com.nextcloud.talk.models.domain.ConversationModel
|
import com.nextcloud.talk.models.domain.ConversationModel
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -415,9 +415,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
if (result.second.isNotEmpty()) {
|
if (result.second.isNotEmpty()) {
|
||||||
val chatMessagesJson = result.second
|
val chatMessagesJson = result.second
|
||||||
|
|
||||||
if (lookIntoFuture) {
|
handleUpdateMessages(chatMessagesJson)
|
||||||
handleUpdateMessages(chatMessagesJson)
|
|
||||||
}
|
|
||||||
|
|
||||||
chatMessagesFromSync = chatMessagesJson.map {
|
chatMessagesFromSync = chatMessagesJson.map {
|
||||||
it.asEntity(currentUser.id!!)
|
it.asEntity(currentUser.id!!)
|
||||||
@ -467,7 +465,14 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
private suspend fun handleUpdateMessages(messagesJson: List<ChatMessageJson>) {
|
private suspend fun handleUpdateMessages(messagesJson: List<ChatMessageJson>) {
|
||||||
messagesJson.forEach { messageJson ->
|
messagesJson.forEach { messageJson ->
|
||||||
when (messageJson.systemMessageType) {
|
when (messageJson.systemMessageType) {
|
||||||
ChatMessage.SystemMessageType.REACTION -> {
|
ChatMessage.SystemMessageType.REACTION,
|
||||||
|
ChatMessage.SystemMessageType.REACTION_REVOKED,
|
||||||
|
ChatMessage.SystemMessageType.REACTION_DELETED,
|
||||||
|
ChatMessage.SystemMessageType.MESSAGE_DELETED,
|
||||||
|
ChatMessage.SystemMessageType.POLL_VOTED,
|
||||||
|
ChatMessage.SystemMessageType.MESSAGE_EDITED -> {
|
||||||
|
// the parent message is always the newest state, no matter how old the system message is.
|
||||||
|
// that's why we can just take the parent, update it in DB and update the UI
|
||||||
messageJson.parentMessage?.let { parentMessageJson ->
|
messageJson.parentMessage?.let { parentMessageJson ->
|
||||||
val parentMessageEntity = parentMessageJson.asEntity(currentUser.id!!)
|
val parentMessageEntity = parentMessageJson.asEntity(currentUser.id!!)
|
||||||
chatDao.upsertChatMessage(parentMessageEntity)
|
chatDao.upsertChatMessage(parentMessageEntity)
|
||||||
@ -475,26 +480,6 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.REACTION_REVOKED -> {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.REACTION_DELETED -> {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.MESSAGE_DELETED -> {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.POLL_VOTED -> {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.MESSAGE_EDITED -> {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.SystemMessageType.CLEARED_CHAT -> {
|
ChatMessage.SystemMessageType.CLEARED_CHAT -> {
|
||||||
val pattern = "$internalConversationId%" // LIKE "<accountId>@<conversationId>@%"
|
val pattern = "$internalConversationId%" // LIKE "<accountId>@<conversationId>@%"
|
||||||
chatDao.clearAllMessagesForUser(pattern)
|
chatDao.clearAllMessagesForUser(pattern)
|
||||||
|
@ -38,7 +38,8 @@ fun ChatMessageJson.asEntity(accountId: Long) =
|
|||||||
lastEditActorDisplayName = lastEditActorDisplayName,
|
lastEditActorDisplayName = lastEditActorDisplayName,
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
|
deleted = deleted
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ChatMessageEntity.asModel() =
|
fun ChatMessageEntity.asModel() =
|
||||||
@ -62,7 +63,8 @@ fun ChatMessageEntity.asModel() =
|
|||||||
lastEditActorDisplayName = lastEditActorDisplayName,
|
lastEditActorDisplayName = lastEditActorDisplayName,
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
|
isDeleted = deleted
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ChatMessageJson.asModel() =
|
fun ChatMessageJson.asModel() =
|
||||||
@ -86,5 +88,6 @@ fun ChatMessageJson.asModel() =
|
|||||||
lastEditActorDisplayName = lastEditActorDisplayName,
|
lastEditActorDisplayName = lastEditActorDisplayName,
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
|
isDeleted = deleted
|
||||||
)
|
)
|
||||||
|
@ -58,6 +58,7 @@ data class ChatMessageEntity(
|
|||||||
@ColumnInfo(name = "lastEditActorType") var lastEditActorType: String? = null,
|
@ColumnInfo(name = "lastEditActorType") var lastEditActorType: String? = null,
|
||||||
@ColumnInfo(name = "lastEditActorId") var lastEditActorId: String? = null,
|
@ColumnInfo(name = "lastEditActorId") var lastEditActorId: String? = null,
|
||||||
@ColumnInfo(name = "lastEditActorDisplayName") var lastEditActorDisplayName: String? = null,
|
@ColumnInfo(name = "lastEditActorDisplayName") var lastEditActorDisplayName: String? = null,
|
||||||
@ColumnInfo(name = "lastEditTimestamp") var lastEditTimestamp: Long? = 0
|
@ColumnInfo(name = "lastEditTimestamp") var lastEditTimestamp: Long? = 0,
|
||||||
|
@ColumnInfo(name = "deleted") var deleted: Boolean = false,
|
||||||
// TODO: add "silent"
|
// TODO: add "silent"
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,7 @@ import kotlinx.parcelize.Parcelize
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
@JsonObject
|
@JsonObject
|
||||||
data class ChatMessageJson(
|
data class ChatMessageJson(
|
||||||
@JsonField(name = ["id"]) override var id: Long = 0,
|
@JsonField(name = ["id"]) var id: Long = 0,
|
||||||
@JsonField(name = ["token"]) var token: String? = null,
|
@JsonField(name = ["token"]) var token: String? = null,
|
||||||
@JsonField(name = ["actorType"]) var actorType: String? = null,
|
@JsonField(name = ["actorType"]) var actorType: String? = null,
|
||||||
@JsonField(name = ["actorId"]) var actorId: String? = null,
|
@JsonField(name = ["actorId"]) var actorId: String? = null,
|
||||||
@ -43,7 +43,5 @@ data class ChatMessageJson(
|
|||||||
@JsonField(name = ["lastEditActorId"]) var lastEditActorId: String? = null,
|
@JsonField(name = ["lastEditActorId"]) var lastEditActorId: String? = null,
|
||||||
@JsonField(name = ["lastEditActorType"]) var lastEditActorType: String? = null,
|
@JsonField(name = ["lastEditActorType"]) var lastEditActorType: String? = null,
|
||||||
@JsonField(name = ["lastEditTimestamp"]) var lastEditTimestamp: Long? = 0,
|
@JsonField(name = ["lastEditTimestamp"]) var lastEditTimestamp: Long? = 0,
|
||||||
|
@JsonField(name = ["deleted"]) var deleted: Boolean = false,
|
||||||
// override var markedForDeletion: Boolean = "comment_deleted" == messageType
|
) : Parcelable
|
||||||
override var markedForDeletion: Boolean = false
|
|
||||||
) : Parcelable, SyncableModel
|
|
||||||
|
Loading…
Reference in New Issue
Block a user