mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
show x when sending failed
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
a78c9e1c08
commit
e1c1574d6c
@ -114,7 +114,19 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
||||
binding.messageQuote.quotedChatMessageView.visibility = View.GONE
|
||||
}
|
||||
|
||||
setReadStatus(message.readStatus)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
itemView.setTag(R.string.replyable_message_view_tag, message.replyable)
|
||||
|
||||
@ -129,29 +141,27 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
||||
)
|
||||
}
|
||||
|
||||
private fun setReadStatus(readStatus: Enum<ReadStatus>) {
|
||||
val readStatusDrawableInt = when (readStatus) {
|
||||
ReadStatus.READ -> R.drawable.ic_check_all
|
||||
ReadStatus.SENT -> R.drawable.ic_check
|
||||
else -> null
|
||||
}
|
||||
|
||||
val readStatusContentDescriptionString = when (readStatus) {
|
||||
ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read)
|
||||
ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent)
|
||||
else -> null
|
||||
}
|
||||
|
||||
readStatusDrawableInt?.let { drawableInt ->
|
||||
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 = readStatusContentDescriptionString
|
||||
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)
|
||||
}
|
||||
|
@ -587,7 +587,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
|
||||
@ -813,6 +813,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")) {
|
||||
@ -2933,7 +2935,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
|
||||
@ -3439,7 +3445,7 @@ class ChatActivity :
|
||||
val message = iMessage as ChatMessage
|
||||
if (hasVisibleItems(message) &&
|
||||
!isSystemMessage(message) &&
|
||||
message.id != "-3"
|
||||
message.id != TEMPORARY_MESSAGE_ID_STRING
|
||||
) {
|
||||
MessageActionsDialog(
|
||||
this,
|
||||
@ -3863,7 +3869,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
|
||||
|
@ -115,11 +115,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 {
|
||||
|
@ -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<ChatMessage>,
|
||||
receivedChatMessages : List<ChatMessage>,
|
||||
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,
|
||||
@ -815,6 +815,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))
|
||||
}
|
||||
}
|
||||
@ -877,7 +888,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!!,
|
||||
|
@ -48,6 +48,18 @@ interface ChatMessagesDao {
|
||||
)
|
||||
fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
||||
|
||||
@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<ChatMessageEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>)
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -9,5 +9,7 @@ package com.nextcloud.talk.models.json.chat
|
||||
enum class ReadStatus {
|
||||
NONE,
|
||||
SENT,
|
||||
READ
|
||||
READ,
|
||||
SENDING,
|
||||
FAILED
|
||||
}
|
||||
|
@ -84,6 +84,32 @@
|
||||
app:layout_alignSelf="center"
|
||||
app:tint="@color/high_emphasis_text" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sending_failed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/message_bubble_checkmark_height"
|
||||
android:layout_below="@id/messageTime"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@null"
|
||||
app:layout_alignSelf="center"
|
||||
app:tint="@color/high_emphasis_text" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/sending_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/message_bubble_checkmark_height"
|
||||
android:layout_below="@id/messageTime"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@null"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
app:indicatorColor="@color/colorPrimary"
|
||||
app:indicatorSize="14dp"
|
||||
app:trackColor="@color/colorPrimary"
|
||||
app:trackThickness="2dp"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
|
||||
<include
|
||||
android:id="@+id/reactions"
|
||||
layout="@layout/reactions_inside_message" />
|
||||
|
Loading…
Reference in New Issue
Block a user