diff --git a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt index 33725b5cf..89893d74b 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt @@ -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() } diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt b/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt index 6ad2599ef..891db34a5 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt @@ -100,4 +100,9 @@ interface ChatMessageRepository : LifecycleAwareManager { suspend fun editChatMessage(credentials: String, url: String, text: String): Flow> suspend fun editTempChatMessage(message: ChatMessage, editedMessageText: String): Flow + + suspend fun sendTempChatMessages( + credentials: String, + url: String + ) } 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 25372edc8..5bb113d96 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 @@ -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, diff --git a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/MessageInputViewModel.kt b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/MessageInputViewModel.kt index 1e2a89e43..4077224a2 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/MessageInputViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/MessageInputViewModel.kt @@ -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( diff --git a/app/src/main/java/com/nextcloud/talk/extensions/LongFormatExtension.kt b/app/src/main/java/com/nextcloud/talk/extensions/LongFormatExtension.kt new file mode 100644 index 000000000..02cbe262f --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/extensions/LongFormatExtension.kt @@ -0,0 +1,15 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2024 Marcel Hibbe + * 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 + } +} diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/SendMessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/SendMessageUtils.kt index 29b9700ea..4d42bfa6a 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/SendMessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/SendMessageUtils.kt @@ -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 }