update temp messages also for initial pull of messages

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2024-12-09 18:55:35 +01:00
parent aff7845e83
commit 1efc219e73
No known key found for this signature in database
GPG key ID: C793F8B59F43CE7B
4 changed files with 47 additions and 45 deletions

View file

@ -918,8 +918,7 @@ class ChatActivity :
this.lifecycleScope.launch {
chatViewModel.getRemoveMessageFlow
.onEach {
adapter!!.delete(it)
adapter!!.notifyDataSetChanged()
removeMessageById(it.id)
}
.collect()
}
@ -1065,9 +1064,15 @@ class ChatActivity :
}
private fun removeUnreadMessagesMarker() {
val index = adapter?.getMessagePositionById(UNREAD_MESSAGES_MARKER_ID.toString())
removeMessageById(UNREAD_MESSAGES_MARKER_ID.toString())
}
// do not use adapter.deleteById() as it seems to contain a bug! Use this method instead!
private fun removeMessageById(idToDelete: String) {
val index = adapter?.getMessagePositionById(idToDelete)
if (index != null && index != -1) {
adapter?.items?.removeAt(index)
adapter?.notifyItemRemoved(index)
}
}

View file

@ -178,14 +178,19 @@ class OfflineFirstChatRepository @Inject constructor(
if (newestMessageIdFromDb.toInt() != 0) {
val limit = getCappedMessagesAmountOfChatBlock(newestMessageIdFromDb)
// TODO: somewhere here also handle temp messages. updateUiMessages(chatMessages, showUnreadMessagesMarker)
showMessagesBeforeAndEqual(
internalConversationId,
val list = getMessagesBeforeAndEqual(
newestMessageIdFromDb,
internalConversationId,
limit
)
if (list.isNotEmpty()) {
updateUiMessages(
chatMessages = list,
lookIntoFuture = false,
showUnreadMessagesMarker = false
)
}
// delay is a dirty workaround to make sure messages are added to adapter on initial load before dealing
// with them (otherwise there is a race condition).
@ -302,7 +307,11 @@ class OfflineFirstChatRepository @Inject constructor(
val weHaveMessagesFromOurself = chatMessages.any { it.actorId == currentUser.userId }
showUnreadMessagesMarker = showUnreadMessagesMarker && !weHaveMessagesFromOurself
updateUiMessages(chatMessages, showUnreadMessagesMarker)
updateUiMessages(
chatMessages = chatMessages,
lookIntoFuture = true,
showUnreadMessagesMarker = showUnreadMessagesMarker
)
} else {
Log.d(TAG, "resultsFromSync are null or empty")
}
@ -325,25 +334,30 @@ class OfflineFirstChatRepository @Inject constructor(
}
}
private suspend fun updateUiMessages(chatMessages : List<ChatMessage>, showUnreadMessagesMarker: Boolean) {
private suspend fun updateUiMessages(
chatMessages : List<ChatMessage>,
lookIntoFuture: Boolean,
showUnreadMessagesMarker: Boolean
) {
// remove all temp messages from UI
val oldTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
.first()
.map(ChatMessageEntity::asModel)
oldTempMessages.forEach { _removeMessageFlow.emit(it) }
val tripleChatMessages = Triple(true, showUnreadMessagesMarker, chatMessages)
// add new messages to UI
val tripleChatMessages = Triple(lookIntoFuture, showUnreadMessagesMarker, chatMessages)
_messageFlow.emit(tripleChatMessages)
// remove temp messages from DB that are now found in the new messages
val chatMessagesReferenceIds = chatMessages.mapTo(HashSet(chatMessages.size)) { it.referenceId }
val tempChatMessagesThatCanBeReplaced = oldTempMessages.filter { it.referenceId in chatMessagesReferenceIds }
chatDao.deleteTempChatMessages(
internalConversationId,
tempChatMessagesThatCanBeReplaced.map { it.referenceId!! }
)
// add the remaining temp messages to UI again
val remainingTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
.first()
.map(ChatMessageEntity::asModel)
@ -706,31 +720,19 @@ class OfflineFirstChatRepository @Inject constructor(
}
}
private suspend fun showMessagesBeforeAndEqual(internalConversationId: String, messageId: Long, limit: Int) {
suspend fun getMessagesBeforeAndEqual(
messageId: Long,
internalConversationId: String,
messageLimit: Int
): List<ChatMessage> =
chatDao.getMessagesForConversationBeforeAndEqual(
internalConversationId,
messageId,
messageLimit
).map {
it.map(ChatMessageEntity::asModel)
}.first()
val list = getMessagesBeforeAndEqual(
messageId,
suspend fun getMessagesBeforeAndEqual(
messageId: Long,
internalConversationId: String,
messageLimit: Int
): List<ChatMessage> =
chatDao.getMessagesForConversationBeforeAndEqual(
internalConversationId,
limit
)
messageId,
messageLimit
).map {
it.map(ChatMessageEntity::asModel)
}.first()
if (list.isNotEmpty()) {
val triple = Triple(false, false, list)
_messageFlow.emit(triple)
}
}
private suspend fun showMessagesBefore(internalConversationId: String, messageId: Long, limit: Int) {
suspend fun getMessagesBefore(
@ -835,9 +837,6 @@ class OfflineFirstChatRepository @Inject constructor(
message.toString(),
referenceId
)
// accessing internalConversationId creates UninitializedPropertyException because ChatViewModel and
// MessageInputViewModel use different instances of ChatRepository for now
chatDao.upsertChatMessage(tempChatMessageEntity)
@ -847,9 +846,6 @@ class OfflineFirstChatRepository @Inject constructor(
val triple = Triple(true, false, listOf(tempChatMessageModel))
_messageFlow.emit(triple)
// emit()
} catch (e: Exception) {
Log.e(TAG, "Something went wrong when adding temporary message", e)
emit(Result.failure(e))

View file

@ -151,8 +151,6 @@ class MessageInputViewModel @Inject constructor(
replyTo: Int,
sendWithoutNotification: Boolean
) {
// TODO: add temporary message with ref id
val referenceId = SendMessageUtils().generateReferenceId()
Log.d(TAG, "Random SHA-256 Hash: $referenceId")
@ -173,7 +171,6 @@ class MessageInputViewModel @Inject constructor(
}
}
if (isQueueing) {
val tempID = System.currentTimeMillis().toInt()
val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification)

View file

@ -99,6 +99,7 @@ interface ChatMessagesDao {
SELECT *
FROM ChatMessages
WHERE internalConversationId = :internalConversationId AND id >= :messageId
AND isTemporary = 0
ORDER BY timestamp ASC, id ASC
"""
)
@ -109,6 +110,7 @@ interface ChatMessagesDao {
SELECT *
FROM ChatMessages
WHERE internalConversationId = :internalConversationId
AND isTemporary = 0
AND id < :messageId
ORDER BY timestamp DESC, id DESC
LIMIT :limit
@ -125,6 +127,7 @@ interface ChatMessagesDao {
SELECT *
FROM ChatMessages
WHERE internalConversationId = :internalConversationId
AND isTemporary = 0
AND id <= :messageId
ORDER BY timestamp DESC, id DESC
LIMIT :limit
@ -141,6 +144,7 @@ interface ChatMessagesDao {
SELECT COUNT(*)
FROM ChatMessages
WHERE internalConversationId = :internalConversationId
AND isTemporary = 0
AND id BETWEEN :newestMessageId AND :oldestMessageId
"""
)