From 0f53244652358493653e352d58ca5c6e3dde29aa Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Wed, 11 Dec 2024 15:27:52 +0100 Subject: [PATCH] prepare to replace no-internet-connection message handling (sorry Julius!!) Signed-off-by: Marcel Hibbe --- .../OutcomingTextMessageViewHolder.kt | 14 +- .../com/nextcloud/talk/chat/ChatActivity.kt | 69 ++++--- .../talk/chat/MessageInputFragment.kt | 35 ++-- .../chat/viewmodels/MessageInputViewModel.kt | 170 +++++++++--------- .../talk/jobs/AccountRemovalWorker.java | 1 - .../utils/preferences/AppPreferences.java | 6 - .../utils/preferences/AppPreferencesImpl.kt | 136 +++++++------- 7 files changed, 211 insertions(+), 220 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 6d995febd..ea29e7960 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 @@ -120,17 +120,17 @@ class OutcomingTextMessageViewHolder(itemView: View) : } - // CoroutineScope(Dispatchers.Main).launch { + CoroutineScope(Dispatchers.Main).launch { if (message.sendingFailed) { updateStatus( R.drawable.baseline_report_problem_24, "failed" ) - // } else if (message.isTempMessage && !networkMonitor.isOnline.first()) { - // updateStatus( - // R.drawable.ic_signal_wifi_off_white_24dp, - // "offline" - // ) + } else if (message.isTempMessage && !networkMonitor.isOnline.first()) { + updateStatus( + R.drawable.ic_signal_wifi_off_white_24dp, + "offline" + ) } else if (message.isTempMessage) { updateSendingStatus() } else if(message.readStatus == ReadStatus.READ){ @@ -138,7 +138,7 @@ class OutcomingTextMessageViewHolder(itemView: View) : } else if(message.readStatus == ReadStatus.SENT) { updateStatus(R.drawable.ic_check, context.resources?.getString(R.string.nc_message_sent)) } - // } + } itemView.setTag(R.string.replyable_message_view_tag, message.replyable) 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 d2d281b0e..3a73dc130 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -583,21 +583,21 @@ class ChatActivity : private fun initObservers() { Log.d(TAG, "initObservers Called") - messageInputViewModel.messageQueueFlow.observe(this) { list -> - list.forEachIndexed { _, qMsg -> - val temporaryChatMessage = ChatMessage() - temporaryChatMessage.jsonMessageId = TEMPORARY_MESSAGE_ID_INT - temporaryChatMessage.actorId = TEMPORARY_MESSAGE_ID_STRING - temporaryChatMessage.timestamp = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS - temporaryChatMessage.message = qMsg.message.toString() - temporaryChatMessage.tempMessageId = qMsg.id - temporaryChatMessage.isTempMessage = true - temporaryChatMessage.parentMessageId = qMsg.replyTo!!.toLong() - val pos = adapter?.getMessagePositionById(qMsg.replyTo.toString()) - adapter?.addToStart(temporaryChatMessage, true) - adapter?.notifyDataSetChanged() - } - } + // messageInputViewModel.messageQueueFlow.observe(this) { list -> + // list.forEachIndexed { _, qMsg -> + // val temporaryChatMessage = ChatMessage() + // temporaryChatMessage.jsonMessageId = TEMPORARY_MESSAGE_ID_INT + // temporaryChatMessage.actorId = TEMPORARY_MESSAGE_ID_STRING + // temporaryChatMessage.timestamp = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS + // temporaryChatMessage.message = qMsg.message.toString() + // temporaryChatMessage.tempMessageId = qMsg.id + // temporaryChatMessage.isTempMessage = true + // temporaryChatMessage.parentMessageId = qMsg.replyTo!!.toLong() + // val pos = adapter?.getMessagePositionById(qMsg.replyTo.toString()) + // adapter?.addToStart(temporaryChatMessage, true) + // adapter?.notifyDataSetChanged() + // } + // } messageInputViewModel.messageQueueSizeFlow.observe(this) { size -> if (size == 0) { @@ -719,7 +719,6 @@ class ChatActivity : withCredentials = credentials!!, withUrl = urlForChatting ) - messageInputViewModel.getTempMessagesFromMessageQueue(currentConversation!!.internalId) } } else { Log.w( @@ -3864,7 +3863,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 == TEMPORARY_MESSAGE_ID_STRING + // CONTENT_TYPE_TEMP -> message.id == TEMPORARY_MESSAGE_ID_STRING // CONTENT_TYPE_TEMP -> message.readStatus == ReadStatus.FAILED CONTENT_TYPE_DECK_CARD -> message.isDeckCard() @@ -4013,27 +4012,27 @@ class ChatActivity : } override fun editTemporaryMessage(id: Int, newMessage: String) { - messageInputViewModel.editQueuedMessage(currentConversation!!.internalId, id, newMessage) - adapter?.notifyDataSetChanged() // TODO optimize this + // messageInputViewModel.editQueuedMessage(currentConversation!!.internalId, id, newMessage) + // adapter?.notifyDataSetChanged() // TODO optimize this } override fun deleteTemporaryMessage(id: Int) { - messageInputViewModel.removeFromQueue(currentConversation!!.internalId, id) - var i = 0 - val max = messageInputViewModel.messageQueueSizeFlow.value?.plus(1) - for (item in adapter?.items!!) { - if (i > max!! && max < 1) break - if (item.item is ChatMessage && - (item.item as ChatMessage).isTempMessage && - (item.item as ChatMessage).tempMessageId == id - ) { - val index = adapter?.items!!.indexOf(item) - adapter?.items!!.removeAt(index) - adapter?.notifyItemRemoved(index) - break - } - i++ - } + // messageInputViewModel.removeFromQueue(currentConversation!!.internalId, id) + // var i = 0 + // val max = messageInputViewModel.messageQueueSizeFlow.value?.plus(1) + // for (item in adapter?.items!!) { + // if (i > max!! && max < 1) break + // if (item.item is ChatMessage && + // (item.item as ChatMessage).isTempMessage && + // (item.item as ChatMessage).tempMessageId == id + // ) { + // val index = adapter?.items!!.indexOf(item) + // adapter?.items!!.removeAt(index) + // adapter?.notifyItemRemoved(index) + // break + // } + // i++ + // } } private fun logConversationInfos(methodName: String) { 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 b97ca345b..dba84eaed 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt @@ -158,7 +158,6 @@ class MessageInputFragment : Fragment() { override fun onResume() { super.onResume() - chatActivity.messageInputViewModel.restoreMessageQueue(conversationInternalId) } override fun onDestroyView() { @@ -199,7 +198,7 @@ class MessageInputFragment : Fragment() { wasOnline = !binding.fragmentConnectionLost.isShown val connectionGained = (!wasOnline && isOnline) Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained") - handleMessageQueue(isOnline) + // handleMessageQueue(isOnline) handleUI(isOnline, connectionGained) }.collect() } @@ -292,22 +291,22 @@ class MessageInputFragment : Fragment() { } } - private fun handleMessageQueue(isOnline: Boolean) { - if (isOnline) { - chatActivity.messageInputViewModel.switchToMessageQueue(false) - chatActivity.messageInputViewModel.sendAndEmptyMessageQueue( - conversationInternalId, - chatActivity.conversationUser!!.getCredentials(), - ApiUtils.getUrlForChat( - chatActivity.chatApiVersion, - chatActivity.conversationUser!!.baseUrl!!, - chatActivity.roomToken - ) - ) - } else { - chatActivity.messageInputViewModel.switchToMessageQueue(true) - } - } + // private fun handleMessageQueue(isOnline: Boolean) { + // if (isOnline) { + // chatActivity.messageInputViewModel.switchToMessageQueue(false) + // chatActivity.messageInputViewModel.sendAndEmptyMessageQueue( + // conversationInternalId, + // chatActivity.conversationUser!!.getCredentials(), + // ApiUtils.getUrlForChat( + // chatActivity.chatApiVersion, + // chatActivity.conversationUser!!.baseUrl!!, + // chatActivity.roomToken + // ) + // ) + // } else { + // chatActivity.messageInputViewModel.switchToMessageQueue(true) + // } + // } private fun restoreState() { if (binding.fragmentMessageInputView.inputEditText.text.isEmpty()) { 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 c00e89546..8bc2f9e88 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 @@ -55,16 +55,16 @@ class MessageInputViewModel @Inject constructor( chatRepository = chatMessageRepository } - data class QueuedMessage( - val id: Int, - var message: CharSequence? = null, - val displayName: String? = null, - val replyTo: Int? = null, - val sendWithoutNotification: Boolean? = null - ) + // data class QueuedMessage( + // val id: Int, + // var message: CharSequence? = null, + // val displayName: String? = null, + // val replyTo: Int? = null, + // val sendWithoutNotification: Boolean? = null + // ) - private var isQueueing: Boolean = false - private var messageQueue: MutableList = mutableListOf() + // private var isQueueing: Boolean = false + // private var messageQueue: MutableList = mutableListOf() override fun onResume(owner: LifecycleOwner) { super.onResume(owner) @@ -129,13 +129,13 @@ class MessageInputViewModel @Inject constructor( val isVoicePreviewPlaying: LiveData get() = _isVoicePreviewPlaying - private val _messageQueueSizeFlow = MutableStateFlow(messageQueue.size) + private val _messageQueueSizeFlow = MutableStateFlow(666) val messageQueueSizeFlow: LiveData get() = _messageQueueSizeFlow.asLiveData() - private val _messageQueueFlow: MutableLiveData> = MutableLiveData() - val messageQueueFlow: LiveData> - get() = _messageQueueFlow + // private val _messageQueueFlow: MutableLiveData> = MutableLiveData() + // val messageQueueFlow: LiveData> + // get() = _messageQueueFlow private val _callStartedFlow: MutableLiveData> = MutableLiveData() val callStartedFlow: LiveData> @@ -171,16 +171,16 @@ class MessageInputViewModel @Inject constructor( } } - if (isQueueing) { - val tempID = System.currentTimeMillis().toInt() - val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification) - messageQueue = appPreferences.getMessageQueue(internalId) - messageQueue.add(qMsg) - appPreferences.saveMessageQueue(internalId, messageQueue) - _messageQueueSizeFlow.update { messageQueue.size } - _messageQueueFlow.postValue(listOf(qMsg)) - return - } + // if (isQueueing) { + // val tempID = System.currentTimeMillis().toInt() + // val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification) + // messageQueue = appPreferences.getMessageQueue(internalId) + // messageQueue.add(qMsg) + // appPreferences.saveMessageQueue(internalId, messageQueue) + // _messageQueueSizeFlow.update { messageQueue.size } + // _messageQueueFlow.postValue(listOf(qMsg)) + // return + // } viewModelScope.launch { chatRepository.sendChatMessage( @@ -268,68 +268,68 @@ class MessageInputViewModel @Inject constructor( _getRecordingTime.postValue(time) } - fun sendAndEmptyMessageQueue(internalId: String, credentials: String, url: String) { - if (isQueueing) return - messageQueue.clear() - - val queue = appPreferences.getMessageQueue(internalId) - appPreferences.saveMessageQueue(internalId, null) // empties the queue - while (queue.size > 0) { - val msg = queue.removeAt(0) - sendChatMessage( - internalId, - credentials, - url, - msg.message!!, - msg.displayName!!, - msg.replyTo!!, - msg.sendWithoutNotification!! - ) - sleep(DELAY_BETWEEN_QUEUED_MESSAGES) - } - _messageQueueSizeFlow.tryEmit(0) - } - - fun getTempMessagesFromMessageQueue(internalId: String) { - val queue = appPreferences.getMessageQueue(internalId) - val list = mutableListOf() - for (msg in queue) { - list.add(msg) - } - _messageQueueFlow.postValue(list) - } - - fun switchToMessageQueue(shouldQueue: Boolean) { - isQueueing = shouldQueue - } - - fun restoreMessageQueue(internalId: String) { - messageQueue = appPreferences.getMessageQueue(internalId) - _messageQueueSizeFlow.tryEmit(messageQueue.size) - } - - fun removeFromQueue(internalId: String, id: Int) { - val queue = appPreferences.getMessageQueue(internalId) - for (qMsg in queue) { - if (qMsg.id == id) { - queue.remove(qMsg) - break - } - } - appPreferences.saveMessageQueue(internalId, queue) - _messageQueueSizeFlow.tryEmit(queue.size) - } - - fun editQueuedMessage(internalId: String, id: Int, newMessage: String) { - val queue = appPreferences.getMessageQueue(internalId) - for (qMsg in queue) { - if (qMsg.id == id) { - qMsg.message = newMessage - break - } - } - appPreferences.saveMessageQueue(internalId, queue) - } + // fun sendAndEmptyMessageQueue(internalId: String, credentials: String, url: String) { + // if (isQueueing) return + // messageQueue.clear() + // + // val queue = appPreferences.getMessageQueue(internalId) + // appPreferences.saveMessageQueue(internalId, null) // empties the queue + // while (queue.size > 0) { + // val msg = queue.removeAt(0) + // sendChatMessage( + // internalId, + // credentials, + // url, + // msg.message!!, + // msg.displayName!!, + // msg.replyTo!!, + // msg.sendWithoutNotification!! + // ) + // sleep(DELAY_BETWEEN_QUEUED_MESSAGES) + // } + // _messageQueueSizeFlow.tryEmit(0) + // } + // + // fun getTempMessagesFromMessageQueue(internalId: String) { + // val queue = appPreferences.getMessageQueue(internalId) + // val list = mutableListOf() + // for (msg in queue) { + // list.add(msg) + // } + // _messageQueueFlow.postValue(list) + // } + // + // fun switchToMessageQueue(shouldQueue: Boolean) { + // isQueueing = shouldQueue + // } + // + // fun restoreMessageQueue(internalId: String) { + // messageQueue = appPreferences.getMessageQueue(internalId) + // _messageQueueSizeFlow.tryEmit(messageQueue.size) + // } + // + // fun removeFromQueue(internalId: String, id: Int) { + // val queue = appPreferences.getMessageQueue(internalId) + // for (qMsg in queue) { + // if (qMsg.id == id) { + // queue.remove(qMsg) + // break + // } + // } + // appPreferences.saveMessageQueue(internalId, queue) + // _messageQueueSizeFlow.tryEmit(queue.size) + // } + // + // fun editQueuedMessage(internalId: String, id: Int, newMessage: String) { + // val queue = appPreferences.getMessageQueue(internalId) + // for (qMsg in queue) { + // if (qMsg.id == id) { + // qMsg.message = newMessage + // break + // } + // } + // appPreferences.saveMessageQueue(internalId, queue) + // } fun showCallStartedIndicator(recent: ChatMessage, show: Boolean) { _callStartedFlow.postValue(Pair(recent, show)) diff --git a/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java index 6f273ab32..8679f6504 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java @@ -192,7 +192,6 @@ public class AccountRemovalWorker extends Worker { if (user.getId() != null) { String username = user.getUsername(); try { - appPreferences.deleteAllMessageQueuesFor(user.getUserId()); userManager.deleteUser(user.getId()); Log.d(TAG, "deleted user: " + username); } catch (Throwable e) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java index a9265ae8e..beb152a69 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java @@ -175,12 +175,6 @@ public interface AppPreferences { int getLastKnownId(String internalConversationId, int defaultValue); - void saveMessageQueue(String internalConversationId, List queue); - - List getMessageQueue(String internalConversationId); - - void deleteAllMessageQueuesFor(String userId); - void saveVoiceMessagePlaybackSpeedPreferences(Map speeds); Map readVoiceMessagePlaybackSpeedPreferences(); diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferencesImpl.kt b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferencesImpl.kt index c1e611b9a..742b27c26 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferencesImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferencesImpl.kt @@ -501,75 +501,75 @@ class AppPreferencesImpl(val context: Context) : AppPreferences { return if (lastReadId.isNotEmpty()) lastReadId.toInt() else defaultValue } - override fun saveMessageQueue( - internalConversationId: String, - queue: MutableList? - ) { - runBlocking { - async { - var queueStr = "" - queue?.let { - for (msg in queue) { - val msgStr = "${msg.id},${msg.message},${msg.replyTo},${msg.displayName},${ - msg - .sendWithoutNotification - }^" - queueStr += msgStr - } - } - writeString(internalConversationId + MESSAGE_QUEUE, queueStr) - } - } - } + // override fun saveMessageQueue( + // internalConversationId: String, + // queue: MutableList? + // ) { + // runBlocking { + // async { + // var queueStr = "" + // queue?.let { + // for (msg in queue) { + // val msgStr = "${msg.id},${msg.message},${msg.replyTo},${msg.displayName},${ + // msg + // .sendWithoutNotification + // }^" + // queueStr += msgStr + // } + // } + // writeString(internalConversationId + MESSAGE_QUEUE, queueStr) + // } + // } + // } + // + // @Suppress("Detekt.TooGenericExceptionCaught") + // override fun getMessageQueue(internalConversationId: String): MutableList { + // val queueStr = + // runBlocking { async { readString(internalConversationId + MESSAGE_QUEUE).first() } }.getCompleted() + // + // val queue: MutableList = mutableListOf() + // if (queueStr.isEmpty()) return queue + // + // for (msgStr in queueStr.split("^")) { + // try { + // if (msgStr.isNotEmpty()) { + // val msgArray = msgStr.split(",") + // val id = msgArray[ID].toInt() + // val message = msgArray[MESSAGE_INDEX] + // val replyTo = msgArray[REPLY_TO_INDEX].toInt() + // val displayName = msgArray[DISPLAY_NAME_INDEX] + // val silent = msgArray[SILENT_INDEX].toBoolean() + // + // val qMsg = MessageInputViewModel.QueuedMessage(id, message, displayName, replyTo, silent) + // queue.add(qMsg) + // } + // } catch (e: IndexOutOfBoundsException) { + // Log.e(TAG, "Message string: $msgStr\n Queue String: $queueStr \n$e") + // } + // } + // + // return queue + // } - @Suppress("Detekt.TooGenericExceptionCaught") - override fun getMessageQueue(internalConversationId: String): MutableList { - val queueStr = - runBlocking { async { readString(internalConversationId + MESSAGE_QUEUE).first() } }.getCompleted() - - val queue: MutableList = mutableListOf() - if (queueStr.isEmpty()) return queue - - for (msgStr in queueStr.split("^")) { - try { - if (msgStr.isNotEmpty()) { - val msgArray = msgStr.split(",") - val id = msgArray[ID].toInt() - val message = msgArray[MESSAGE_INDEX] - val replyTo = msgArray[REPLY_TO_INDEX].toInt() - val displayName = msgArray[DISPLAY_NAME_INDEX] - val silent = msgArray[SILENT_INDEX].toBoolean() - - val qMsg = MessageInputViewModel.QueuedMessage(id, message, displayName, replyTo, silent) - queue.add(qMsg) - } - } catch (e: IndexOutOfBoundsException) { - Log.e(TAG, "Message string: $msgStr\n Queue String: $queueStr \n$e") - } - } - - return queue - } - - override fun deleteAllMessageQueuesFor(userId: String) { - runBlocking { - async { - val keyList = mutableListOf>() - val preferencesMap = context.dataStore.data.first().asMap() - for (preference in preferencesMap) { - if (preference.key.name.contains("$userId@")) { - keyList.add(preference.key) - } - } - - for (key in keyList) { - context.dataStore.edit { - it.remove(key) - } - } - } - } - } + // override fun deleteAllMessageQueuesFor(userId: String) { + // runBlocking { + // async { + // val keyList = mutableListOf>() + // val preferencesMap = context.dataStore.data.first().asMap() + // for (preference in preferencesMap) { + // if (preference.key.name.contains("$userId@")) { + // keyList.add(preference.key) + // } + // } + // + // for (key in keyList) { + // context.dataStore.edit { + // it.remove(key) + // } + // } + // } + // } + // } override fun saveVoiceMessagePlaybackSpeedPreferences(speeds: Map) { Json.encodeToString(speeds).let {