resend queued messages when connection gained

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2024-12-27 11:25:22 +01:00
parent f88b1f17f2
commit 5ac130a020
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
6 changed files with 88 additions and 4 deletions

View File

@ -198,7 +198,16 @@ class MessageInputFragment : Fragment() {
wasOnline = !binding.fragmentConnectionLost.isShown
val connectionGained = (!wasOnline && isOnline)
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
// handleMessageQueue(isOnline)
if (connectionGained) {
chatActivity.messageInputViewModel.sendTempMessages(
chatActivity.conversationUser!!.getCredentials(),
ApiUtils.getUrlForChat(
chatActivity.chatApiVersion,
chatActivity.conversationUser!!.baseUrl!!,
chatActivity.roomToken
)
)
}
handleUI(isOnline, connectionGained)
}.collect()
}

View File

@ -100,4 +100,9 @@ interface ChatMessageRepository : LifecycleAwareManager {
suspend fun editChatMessage(credentials: String, url: String, text: String): Flow<Result<ChatOverallSingleMessage>>
suspend fun editTempChatMessage(message: ChatMessage, editedMessageText: String): Flow<Boolean>
suspend fun sendTempChatMessages(
credentials: String,
url: String
)
}

View File

@ -21,12 +21,14 @@ import com.nextcloud.talk.data.database.model.ChatBlockEntity
import com.nextcloud.talk.data.database.model.ChatMessageEntity
import com.nextcloud.talk.data.network.NetworkMonitor
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.extensions.toIntOrZero
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.chat.ChatMessageJson
import com.nextcloud.talk.models.json.chat.ChatOverall
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import com.nextcloud.talk.utils.message.SendMessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
@ -41,9 +43,7 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.retryWhen
import kotlinx.coroutines.launch
import java.io.IOException
import javax.inject.Inject
class OfflineFirstChatRepository @Inject constructor(
@ -124,6 +124,8 @@ class OfflineFirstChatRepository @Inject constructor(
override fun loadInitialMessages(withNetworkParams: Bundle): Job =
scope.launch {
sendTempChatMessages(credentials, urlForChatting)
Log.d(TAG, "---- loadInitialMessages ------------")
newXChatLastCommonRead = conversationModel.lastCommonReadMessage
@ -363,6 +365,7 @@ class OfflineFirstChatRepository @Inject constructor(
// add the remaining temp messages to UI again
val remainingTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
.first()
.sortedBy { it.internalId }
.map(ChatMessageEntity::asModel)
val triple = Triple(true, false, remainingTempMessages)
@ -882,6 +885,31 @@ class OfflineFirstChatRepository @Inject constructor(
}
}
override suspend fun sendTempChatMessages(
credentials: String,
url: String
) {
val tempMessages = chatDao.getTempMessagesForConversation(internalConversationId).first()
tempMessages.sortedBy { it.internalId }.onEach {
sendChatMessage(
credentials,
url,
it.message,
it.actorDisplayName,
it.parentMessageId?.toIntOrZero() ?: 0,
false,
it.referenceId.orEmpty()
).collect { result ->
if (result.isSuccess) {
Log.d(TAG, "sent temp message")
} else {
Log.e(TAG, "Failed to send temp message")
}
}
}
}
override suspend fun addTemporaryMessage(
message: CharSequence,
displayName: String,
@ -918,10 +946,12 @@ class OfflineFirstChatRepository @Inject constructor(
val currentTimeMillies = System.currentTimeMillis()
val currentTimeWithoutYear = SendMessageUtils().removeYearFromTimestamp(currentTimeMillies)
val entity = ChatMessageEntity(
internalId = internalConversationId + "@_temp_" + currentTimeMillies,
internalConversationId = internalConversationId,
id = currentTimeMillies, // TODO: currentTimeMillies fails as id because later on in the model it's not Long but Int!!!!
id = currentTimeWithoutYear.toLong(),
message = message,
deleted = false,
token = conversationModel.token,

View File

@ -203,6 +203,18 @@ class MessageInputViewModel @Inject constructor(
}
}
fun sendTempMessages(
credentials: String,
url: String,
) {
viewModelScope.launch {
chatRepository.sendTempChatMessages(
credentials,
url
)
}
}
fun editChatMessage(credentials: String, url: String, text: String) {
viewModelScope.launch {
chatRepository.editChatMessage(

View File

@ -0,0 +1,15 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.extensions
fun Long.toIntOrZero(): Int {
return if (this >= Int.MIN_VALUE && this <= Int.MAX_VALUE) {
toInt()
} else {
0
}
}

View File

@ -7,6 +7,7 @@
package com.nextcloud.talk.utils.message
import java.security.MessageDigest
import java.util.Calendar
import java.util.UUID
class SendMessageUtils {
@ -17,6 +18,18 @@ class SendMessageUtils {
return hashBytes.joinToString("") { "%02x".format(it) }
}
@Suppress("MagicNumber")
fun removeYearFromTimestamp(timestampMillis: Long): Int {
val calendar = Calendar.getInstance().apply { timeInMillis = timestampMillis }
val month = calendar.get(Calendar.MONTH)
val day = calendar.get(Calendar.DAY_OF_MONTH)
val hour = calendar.get(Calendar.HOUR_OF_DAY)
val minute = calendar.get(Calendar.MINUTE)
val second = calendar.get(Calendar.SECOND)
return (month * 1000000) + (day * 10000) + (hour * 100) + (minute * 10) + second
}
companion object {
private val TAG = SendMessageUtils::class.java.simpleName
}