add manual resend button

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2024-12-27 12:40:32 +01:00
parent e9f3863375
commit 2c397ad517
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
6 changed files with 123 additions and 2 deletions

View File

@ -90,6 +90,16 @@ interface ChatMessageRepository : LifecycleAwareManager {
referenceId: String referenceId: String
): Flow<Result<ChatMessage?>> ): Flow<Result<ChatMessage?>>
suspend fun resendChatMessage(
credentials: String,
url: String,
message: String,
displayName: String,
replyTo: Int,
sendWithoutNotification: Boolean,
referenceId: String
): Flow<Result<ChatMessage?>>
suspend fun addTemporaryMessage( suspend fun addTemporaryMessage(
message: CharSequence, message: CharSequence,
displayName: String, displayName: String,

View File

@ -124,8 +124,6 @@ class OfflineFirstChatRepository @Inject constructor(
override fun loadInitialMessages(withNetworkParams: Bundle): Job = override fun loadInitialMessages(withNetworkParams: Bundle): Job =
scope.launch { scope.launch {
sendTempChatMessages(credentials, urlForChatting)
Log.d(TAG, "---- loadInitialMessages ------------") Log.d(TAG, "---- loadInitialMessages ------------")
newXChatLastCommonRead = conversationModel.lastCommonReadMessage newXChatLastCommonRead = conversationModel.lastCommonReadMessage
@ -197,6 +195,8 @@ class OfflineFirstChatRepository @Inject constructor(
) )
} }
sendTempChatMessages(credentials, urlForChatting)
// delay is a dirty workaround to make sure messages are added to adapter on initial load before dealing // 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). // with them (otherwise there is a race condition).
delay(DELAY_TO_ENSURE_MESSAGES_ARE_ADDED) delay(DELAY_TO_ENSURE_MESSAGES_ARE_ADDED)
@ -843,6 +843,37 @@ class OfflineFirstChatRepository @Inject constructor(
emit(Result.failure(e)) emit(Result.failure(e))
} }
override suspend fun resendChatMessage(
credentials: String,
url: String,
message: String,
displayName: String,
replyTo: Int,
sendWithoutNotification: Boolean,
referenceId: String
): Flow<Result<ChatMessage?>> {
val messageToResend = chatDao.getTempMessageForConversation(internalConversationId, referenceId).first()
messageToResend.sendingFailed = false
chatDao.updateChatMessage(messageToResend)
val messageToResendModel = messageToResend.asModel()
_removeMessageFlow.emit(messageToResendModel)
val tripleChatMessages = Triple(true, false, listOf(messageToResendModel))
_messageFlow.emit(tripleChatMessages)
return sendChatMessage(
credentials,
url,
message,
displayName,
replyTo,
sendWithoutNotification,
referenceId
)
}
override suspend fun editChatMessage( override suspend fun editChatMessage(
credentials: String, credentials: String,
url: String, url: String,

View File

@ -24,6 +24,7 @@ import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.extensions.toIntOrZero
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
import com.nextcloud.talk.models.domain.ConversationModel import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.domain.ReactionAddedModel import com.nextcloud.talk.models.domain.ReactionAddedModel
@ -799,6 +800,29 @@ class ChatViewModel @Inject constructor(
} }
} }
fun resendMessage(
credentials: String,
urlForChat: String,
message: ChatMessage) {
viewModelScope.launch {
chatRepository.resendChatMessage(
credentials,
urlForChat,
message.message.orEmpty(),
message.actorDisplayName.orEmpty(),
message.parentMessageId?.toIntOrZero() ?: 0,
false,
message.referenceId.orEmpty()
).collect { result ->
if (result.isSuccess) {
Log.d(TAG, "resend successful")
} else {
Log.e(TAG, "resend failed")
}
}
}
}
companion object { companion object {
private val TAG = ChatViewModel::class.simpleName private val TAG = ChatViewModel::class.simpleName
const val JOIN_ROOM_RETRY_COUNT: Long = 3 const val JOIN_ROOM_RETRY_COUNT: Long = 3

View File

@ -68,6 +68,7 @@ class TempMessageActionsDialog(
private fun initMenuItems() { private fun initMenuItems() {
this.lifecycleScope.launch { this.lifecycleScope.launch {
initResendMessage(true)
initMenuEditMessage(true) initMenuEditMessage(true)
initMenuDeleteMessage(true) initMenuDeleteMessage(true)
} }
@ -80,6 +81,27 @@ class TempMessageActionsDialog(
behavior.state = BottomSheetBehavior.STATE_COLLAPSED behavior.state = BottomSheetBehavior.STATE_COLLAPSED
} }
private fun initResendMessage(visible: Boolean) {
if (visible) {
binding.menuResendMessage.setOnClickListener {
chatActivity.chatViewModel.resendMessage(
chatActivity.conversationUser!!.getCredentials(),
ApiUtils.getUrlForChat(
chatActivity.chatApiVersion,
chatActivity.conversationUser!!.baseUrl!!,
chatActivity.roomToken
),
message
)
dismiss()
}
}
binding.menuResendMessage.visibility = getVisibility(visible)
}
private fun initMenuDeleteMessage(visible: Boolean) { private fun initMenuDeleteMessage(visible: Boolean) {
if (visible) { if (visible) {
binding.menuDeleteMessage.setOnClickListener { binding.menuDeleteMessage.setOnClickListener {

View File

@ -27,6 +27,39 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout
android:id="@+id/menu_resend_message"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/menu_icon_resend_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:paddingStart="@dimen/standard_padding"
android:paddingEnd="@dimen/zero"
android:src="@drawable/ic_send"
app:tint="@color/high_emphasis_menu_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/menu_text_resend_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/standard_padding"
android:text="@string/resend_message"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/menu_copy_message" android:id="@+id/menu_copy_message"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -843,4 +843,5 @@ How to translate with transifex:
<string name="user_absence">%1$s is out of office and might not respond</string> <string name="user_absence">%1$s is out of office and might not respond</string>
<string name="user_absence_for_one_day">%1$s is out of office today</string> <string name="user_absence_for_one_day">%1$s is out of office today</string>
<string name="user_absence_replacement">Replacement: </string> <string name="user_absence_replacement">Replacement: </string>
<string name="resend_message">Resend</string>
</resources> </resources>