From 12eb375956b1d873c2904160ec6d84a4fab412c6 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Tue, 10 Dec 2024 14:35:56 +0100 Subject: [PATCH] show x when sending failed Signed-off-by: Marcel Hibbe --- .../OutcomingTextMessageViewHolder.kt | 44 ++++++++++++------- .../com/nextcloud/talk/chat/ChatActivity.kt | 14 ++++-- .../talk/chat/data/model/ChatMessage.kt | 8 ++-- .../network/OfflineFirstChatRepository.kt | 23 +++++++--- .../talk/data/database/dao/ChatMessagesDao.kt | 12 +++++ .../database/mappers/ChatMessageMapUtils.kt | 16 ++++++- .../talk/models/json/chat/ReadStatus.kt | 4 +- .../item_custom_outcoming_text_message.xml | 26 +++++++++++ 8 files changed, 117 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt index f1dc83286d..2858fe97c3 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt @@ -115,26 +115,19 @@ class OutcomingTextMessageViewHolder(itemView: View) : binding.messageQuote.quotedChatMessageView.visibility = View.GONE } - val readStatusDrawableInt = when (message.readStatus) { - ReadStatus.READ -> R.drawable.ic_check_all - ReadStatus.SENT -> R.drawable.ic_check - else -> null - } - val readStatusContentDescriptionString = when (message.readStatus) { - ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) - ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) + when (message.readStatus) { + ReadStatus.READ -> updateReadStatus(R.drawable.ic_check_all, context.resources?.getString(R.string.nc_message_read)) + ReadStatus.SENT -> updateReadStatus(R.drawable.ic_check, context.resources?.getString(R.string.nc_message_sent)) + ReadStatus.SENDING -> updateSendingStatus() + ReadStatus.FAILED -> updateReadStatus( + R.drawable.ic_baseline_close_24, + "failed" + ) else -> null } - readStatusDrawableInt?.let { drawableInt -> - ResourcesCompat.getDrawable(context.resources, drawableInt, null)?.let { - binding.checkMark.setImageDrawable(it) - viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) - } - } - binding.checkMark.contentDescription = readStatusContentDescriptionString itemView.setTag(R.string.replyable_message_view_tag, message.replyable) @@ -149,6 +142,27 @@ class OutcomingTextMessageViewHolder(itemView: View) : ) } + private fun updateReadStatus(readStatusDrawableInt: Int, description: String?) { + binding.sendingProgress.visibility = View.GONE + binding.checkMark.visibility = View.VISIBLE + readStatusDrawableInt.let { drawableInt -> + ResourcesCompat.getDrawable(context.resources, drawableInt, null)?.let { + binding.checkMark.setImageDrawable(it) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) + } + } + binding.checkMark.contentDescription = description + } + + private fun updateSendingStatus() { + binding.sendingProgress.visibility = View.VISIBLE + binding.checkMark.visibility = View.GONE + + viewThemeUtils.material.colorProgressBar(binding.sendingProgress) + } + + + private fun longClickOnReaction(chatMessage: ChatMessage) { commonMessageInterface.onLongClickReactions(chatMessage) } diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 5068409a6b..a95fdcf968 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -577,7 +577,7 @@ class ChatActivity : list.forEachIndexed { _, qMsg -> val temporaryChatMessage = ChatMessage() temporaryChatMessage.jsonMessageId = TEMPORARY_MESSAGE_ID_INT - temporaryChatMessage.actorId = "-3" + temporaryChatMessage.actorId = TEMPORARY_MESSAGE_ID_STRING temporaryChatMessage.timestamp = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS temporaryChatMessage.message = qMsg.message.toString() temporaryChatMessage.tempMessageId = qMsg.id @@ -791,6 +791,8 @@ class ChatActivity : } is MessageInputViewModel.SendChatMessageErrorState -> { + binding.messagesListView.smoothScrollToPosition(0) + // if (state.e is HttpException) { // val code = state.e.code() // if (code.toString().startsWith("2")) { @@ -2723,7 +2725,11 @@ class ChatActivity : if (message.item is ChatMessage) { val chatMessage = message.item as ChatMessage - if (chatMessage.jsonMessageId <= xChatLastCommonRead) { + if (chatMessage.sendingFailed) { + chatMessage.readStatus = ReadStatus.FAILED + } else if (chatMessage.isTempMessage) { + chatMessage.readStatus = ReadStatus.SENDING + } else if (chatMessage.jsonMessageId <= xChatLastCommonRead) { chatMessage.readStatus = ReadStatus.READ } else { chatMessage.readStatus = ReadStatus.SENT @@ -3229,7 +3235,7 @@ class ChatActivity : val message = iMessage as ChatMessage if (hasVisibleItems(message) && !isSystemMessage(message) && - message.id != "-3" + message.id != TEMPORARY_MESSAGE_ID_STRING ) { MessageActionsDialog( this, @@ -3633,7 +3639,7 @@ class ChatActivity : CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage) CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == UNREAD_MESSAGES_MARKER_ID.toString() CONTENT_TYPE_CALL_STARTED -> message.id == "-2" - CONTENT_TYPE_TEMP -> message.id == "-3" + CONTENT_TYPE_TEMP -> message.id == TEMPORARY_MESSAGE_ID_STRING CONTENT_TYPE_DECK_CARD -> message.isDeckCard() else -> false diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt b/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt index ed06df75de..a899313fb4 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt @@ -113,11 +113,13 @@ data class ChatMessage( var openWhenDownloaded: Boolean = true, - var isTempMessage: Boolean = false, + var isTempMessage: Boolean = false, // TODO: replace logic from message drafts with logic from temp message sending - var tempMessageId: Int = -1, + var tempMessageId: Int = -1, // TODO: replace logic from message drafts with logic from temp message sending - var referenceId: String? = null + var referenceId: String? = null, + + var sendingFailed: Boolean = true ) : MessageContentType, MessageContentType.Image { diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt index 5c1a2bad49..6d123564c6 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt @@ -186,7 +186,7 @@ class OfflineFirstChatRepository @Inject constructor( ) if (list.isNotEmpty()) { updateUiMessages( - chatMessages = list, + receivedChatMessages = list, lookIntoFuture = false, showUnreadMessagesMarker = false ) @@ -308,7 +308,7 @@ class OfflineFirstChatRepository @Inject constructor( showUnreadMessagesMarker = showUnreadMessagesMarker && !weHaveMessagesFromOurself updateUiMessages( - chatMessages = chatMessages, + receivedChatMessages = chatMessages, lookIntoFuture = true, showUnreadMessagesMarker = showUnreadMessagesMarker ) @@ -335,7 +335,7 @@ class OfflineFirstChatRepository @Inject constructor( } private suspend fun updateUiMessages( - chatMessages : List, + receivedChatMessages : List, lookIntoFuture: Boolean, showUnreadMessagesMarker: Boolean ) { @@ -346,11 +346,11 @@ class OfflineFirstChatRepository @Inject constructor( oldTempMessages.forEach { _removeMessageFlow.emit(it) } // add new messages to UI - val tripleChatMessages = Triple(lookIntoFuture, showUnreadMessagesMarker, chatMessages) + val tripleChatMessages = Triple(lookIntoFuture, showUnreadMessagesMarker, receivedChatMessages) _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 chatMessagesReferenceIds = receivedChatMessages.mapTo(HashSet(receivedChatMessages.size)) { it.referenceId } val tempChatMessagesThatCanBeReplaced = oldTempMessages.filter { it.referenceId in chatMessagesReferenceIds } chatDao.deleteTempChatMessages( internalConversationId, @@ -802,6 +802,17 @@ class OfflineFirstChatRepository @Inject constructor( emit(Result.success(chatMessageModel)) } catch (e: Exception) { Log.e(TAG, "Error when sending message", e) + + val failedMessage = chatDao.getTempMessageForConversation(internalConversationId, referenceId).first() + failedMessage.sendingFailed = true + chatDao.updateChatMessage(failedMessage) + + val failedMessageModel = failedMessage.asModel() + _removeMessageFlow.emit(failedMessageModel) + + val tripleChatMessages = Triple(true, false, listOf(failedMessageModel)) + _messageFlow.emit(tripleChatMessages) + emit(Result.failure(e)) } } @@ -864,7 +875,7 @@ class OfflineFirstChatRepository @Inject constructor( internalId = internalConversationId + "@_temp_" + currentTimeMillies, internalConversationId = internalConversationId, id = currentTimeMillies, - message = message + " (temp)", + message = message, deleted = false, token = conversationModel.token, actorId = currentUser.userId!!, diff --git a/app/src/main/java/com/nextcloud/talk/data/database/dao/ChatMessagesDao.kt b/app/src/main/java/com/nextcloud/talk/data/database/dao/ChatMessagesDao.kt index a15cdbe1cd..b3179c1497 100644 --- a/app/src/main/java/com/nextcloud/talk/data/database/dao/ChatMessagesDao.kt +++ b/app/src/main/java/com/nextcloud/talk/data/database/dao/ChatMessagesDao.kt @@ -48,6 +48,18 @@ interface ChatMessagesDao { ) fun getTempMessagesForConversation(internalConversationId: String): Flow> + @Query( + """ + SELECT * + FROM ChatMessages + WHERE internalConversationId = :internalConversationId + AND referenceId = :referenceId + AND isTemporary = 1 + ORDER BY timestamp DESC, id DESC + """ + ) + fun getTempMessageForConversation(internalConversationId: String, referenceId: String): Flow + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun upsertChatMessages(chatMessages: List) diff --git a/app/src/main/java/com/nextcloud/talk/data/database/mappers/ChatMessageMapUtils.kt b/app/src/main/java/com/nextcloud/talk/data/database/mappers/ChatMessageMapUtils.kt index 4ab3c49555..1392a29201 100644 --- a/app/src/main/java/com/nextcloud/talk/data/database/mappers/ChatMessageMapUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/data/database/mappers/ChatMessageMapUtils.kt @@ -10,6 +10,7 @@ package com.nextcloud.talk.data.database.mappers import com.nextcloud.talk.models.json.chat.ChatMessageJson import com.nextcloud.talk.data.database.model.ChatMessageEntity import com.nextcloud.talk.chat.data.model.ChatMessage +import com.nextcloud.talk.models.json.chat.ReadStatus fun ChatMessageJson.asEntity(accountId: Long) = ChatMessageEntity( @@ -64,9 +65,22 @@ fun ChatMessageEntity.asModel() = lastEditActorType = lastEditActorType, lastEditTimestamp = lastEditTimestamp, isDeleted = deleted, - referenceId = referenceId + referenceId = referenceId, + isTempMessage = isTemporary, + sendingFailed = sendingFailed, + readStatus = setStatus(isTemporary, sendingFailed) ) +fun setStatus(isTemporary: Boolean, sendingFailed: Boolean): ReadStatus { + return if (sendingFailed) { + ReadStatus.FAILED + } else if (isTemporary) { + ReadStatus.SENDING + } else { + ReadStatus.NONE + } +} + fun ChatMessageJson.asModel() = ChatMessage( jsonMessageId = id.toInt(), diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ReadStatus.kt b/app/src/main/java/com/nextcloud/talk/models/json/chat/ReadStatus.kt index 40a1e283cf..1441dd521a 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ReadStatus.kt +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ReadStatus.kt @@ -9,5 +9,7 @@ package com.nextcloud.talk.models.json.chat enum class ReadStatus { NONE, SENT, - READ + READ, + SENDING, + FAILED } diff --git a/app/src/main/res/layout/item_custom_outcoming_text_message.xml b/app/src/main/res/layout/item_custom_outcoming_text_message.xml index 4d0d2d4522..7c93c5d2a1 100644 --- a/app/src/main/res/layout/item_custom_outcoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_outcoming_text_message.xml @@ -84,6 +84,32 @@ app:layout_alignSelf="center" app:tint="@color/high_emphasis_text" /> + + + +