prepare to replace no-internet-connection message handling (sorry Julius!!)

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2024-12-11 15:27:52 +01:00
parent 3f5f2f024a
commit 0f53244652
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
7 changed files with 211 additions and 220 deletions

View File

@ -120,17 +120,17 @@ class OutcomingTextMessageViewHolder(itemView: View) :
} }
// CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
if (message.sendingFailed) { if (message.sendingFailed) {
updateStatus( updateStatus(
R.drawable.baseline_report_problem_24, R.drawable.baseline_report_problem_24,
"failed" "failed"
) )
// } else if (message.isTempMessage && !networkMonitor.isOnline.first()) { } else if (message.isTempMessage && !networkMonitor.isOnline.first()) {
// updateStatus( updateStatus(
// R.drawable.ic_signal_wifi_off_white_24dp, R.drawable.ic_signal_wifi_off_white_24dp,
// "offline" "offline"
// ) )
} else if (message.isTempMessage) { } else if (message.isTempMessage) {
updateSendingStatus() updateSendingStatus()
} else if(message.readStatus == ReadStatus.READ){ } else if(message.readStatus == ReadStatus.READ){
@ -138,7 +138,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
} else if(message.readStatus == ReadStatus.SENT) { } else if(message.readStatus == ReadStatus.SENT) {
updateStatus(R.drawable.ic_check, context.resources?.getString(R.string.nc_message_sent)) updateStatus(R.drawable.ic_check, context.resources?.getString(R.string.nc_message_sent))
} }
// } }
itemView.setTag(R.string.replyable_message_view_tag, message.replyable) itemView.setTag(R.string.replyable_message_view_tag, message.replyable)

View File

@ -583,21 +583,21 @@ class ChatActivity :
private fun initObservers() { private fun initObservers() {
Log.d(TAG, "initObservers Called") Log.d(TAG, "initObservers Called")
messageInputViewModel.messageQueueFlow.observe(this) { list -> // messageInputViewModel.messageQueueFlow.observe(this) { list ->
list.forEachIndexed { _, qMsg -> // list.forEachIndexed { _, qMsg ->
val temporaryChatMessage = ChatMessage() // val temporaryChatMessage = ChatMessage()
temporaryChatMessage.jsonMessageId = TEMPORARY_MESSAGE_ID_INT // temporaryChatMessage.jsonMessageId = TEMPORARY_MESSAGE_ID_INT
temporaryChatMessage.actorId = TEMPORARY_MESSAGE_ID_STRING // temporaryChatMessage.actorId = TEMPORARY_MESSAGE_ID_STRING
temporaryChatMessage.timestamp = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS // temporaryChatMessage.timestamp = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS
temporaryChatMessage.message = qMsg.message.toString() // temporaryChatMessage.message = qMsg.message.toString()
temporaryChatMessage.tempMessageId = qMsg.id // temporaryChatMessage.tempMessageId = qMsg.id
temporaryChatMessage.isTempMessage = true // temporaryChatMessage.isTempMessage = true
temporaryChatMessage.parentMessageId = qMsg.replyTo!!.toLong() // temporaryChatMessage.parentMessageId = qMsg.replyTo!!.toLong()
val pos = adapter?.getMessagePositionById(qMsg.replyTo.toString()) // val pos = adapter?.getMessagePositionById(qMsg.replyTo.toString())
adapter?.addToStart(temporaryChatMessage, true) // adapter?.addToStart(temporaryChatMessage, true)
adapter?.notifyDataSetChanged() // adapter?.notifyDataSetChanged()
} // }
} // }
messageInputViewModel.messageQueueSizeFlow.observe(this) { size -> messageInputViewModel.messageQueueSizeFlow.observe(this) { size ->
if (size == 0) { if (size == 0) {
@ -719,7 +719,6 @@ class ChatActivity :
withCredentials = credentials!!, withCredentials = credentials!!,
withUrl = urlForChatting withUrl = urlForChatting
) )
messageInputViewModel.getTempMessagesFromMessageQueue(currentConversation!!.internalId)
} }
} else { } else {
Log.w( Log.w(
@ -3864,7 +3863,7 @@ class ChatActivity :
CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage) CONTENT_TYPE_SYSTEM_MESSAGE -> !TextUtils.isEmpty(message.systemMessage)
CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == UNREAD_MESSAGES_MARKER_ID.toString() CONTENT_TYPE_UNREAD_NOTICE_MESSAGE -> message.id == UNREAD_MESSAGES_MARKER_ID.toString()
CONTENT_TYPE_CALL_STARTED -> message.id == "-2" 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_TEMP -> message.readStatus == ReadStatus.FAILED
CONTENT_TYPE_DECK_CARD -> message.isDeckCard() CONTENT_TYPE_DECK_CARD -> message.isDeckCard()
@ -4013,27 +4012,27 @@ class ChatActivity :
} }
override fun editTemporaryMessage(id: Int, newMessage: String) { override fun editTemporaryMessage(id: Int, newMessage: String) {
messageInputViewModel.editQueuedMessage(currentConversation!!.internalId, id, newMessage) // messageInputViewModel.editQueuedMessage(currentConversation!!.internalId, id, newMessage)
adapter?.notifyDataSetChanged() // TODO optimize this // adapter?.notifyDataSetChanged() // TODO optimize this
} }
override fun deleteTemporaryMessage(id: Int) { override fun deleteTemporaryMessage(id: Int) {
messageInputViewModel.removeFromQueue(currentConversation!!.internalId, id) // messageInputViewModel.removeFromQueue(currentConversation!!.internalId, id)
var i = 0 // var i = 0
val max = messageInputViewModel.messageQueueSizeFlow.value?.plus(1) // val max = messageInputViewModel.messageQueueSizeFlow.value?.plus(1)
for (item in adapter?.items!!) { // for (item in adapter?.items!!) {
if (i > max!! && max < 1) break // if (i > max!! && max < 1) break
if (item.item is ChatMessage && // if (item.item is ChatMessage &&
(item.item as ChatMessage).isTempMessage && // (item.item as ChatMessage).isTempMessage &&
(item.item as ChatMessage).tempMessageId == id // (item.item as ChatMessage).tempMessageId == id
) { // ) {
val index = adapter?.items!!.indexOf(item) // val index = adapter?.items!!.indexOf(item)
adapter?.items!!.removeAt(index) // adapter?.items!!.removeAt(index)
adapter?.notifyItemRemoved(index) // adapter?.notifyItemRemoved(index)
break // break
} // }
i++ // i++
} // }
} }
private fun logConversationInfos(methodName: String) { private fun logConversationInfos(methodName: String) {

View File

@ -158,7 +158,6 @@ class MessageInputFragment : Fragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
chatActivity.messageInputViewModel.restoreMessageQueue(conversationInternalId)
} }
override fun onDestroyView() { override fun onDestroyView() {
@ -199,7 +198,7 @@ class MessageInputFragment : Fragment() {
wasOnline = !binding.fragmentConnectionLost.isShown wasOnline = !binding.fragmentConnectionLost.isShown
val connectionGained = (!wasOnline && isOnline) val connectionGained = (!wasOnline && isOnline)
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained") Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
handleMessageQueue(isOnline) // handleMessageQueue(isOnline)
handleUI(isOnline, connectionGained) handleUI(isOnline, connectionGained)
}.collect() }.collect()
} }
@ -292,22 +291,22 @@ class MessageInputFragment : Fragment() {
} }
} }
private fun handleMessageQueue(isOnline: Boolean) { // private fun handleMessageQueue(isOnline: Boolean) {
if (isOnline) { // if (isOnline) {
chatActivity.messageInputViewModel.switchToMessageQueue(false) // chatActivity.messageInputViewModel.switchToMessageQueue(false)
chatActivity.messageInputViewModel.sendAndEmptyMessageQueue( // chatActivity.messageInputViewModel.sendAndEmptyMessageQueue(
conversationInternalId, // conversationInternalId,
chatActivity.conversationUser!!.getCredentials(), // chatActivity.conversationUser!!.getCredentials(),
ApiUtils.getUrlForChat( // ApiUtils.getUrlForChat(
chatActivity.chatApiVersion, // chatActivity.chatApiVersion,
chatActivity.conversationUser!!.baseUrl!!, // chatActivity.conversationUser!!.baseUrl!!,
chatActivity.roomToken // chatActivity.roomToken
) // )
) // )
} else { // } else {
chatActivity.messageInputViewModel.switchToMessageQueue(true) // chatActivity.messageInputViewModel.switchToMessageQueue(true)
} // }
} // }
private fun restoreState() { private fun restoreState() {
if (binding.fragmentMessageInputView.inputEditText.text.isEmpty()) { if (binding.fragmentMessageInputView.inputEditText.text.isEmpty()) {

View File

@ -55,16 +55,16 @@ class MessageInputViewModel @Inject constructor(
chatRepository = chatMessageRepository chatRepository = chatMessageRepository
} }
data class QueuedMessage( // data class QueuedMessage(
val id: Int, // val id: Int,
var message: CharSequence? = null, // var message: CharSequence? = null,
val displayName: String? = null, // val displayName: String? = null,
val replyTo: Int? = null, // val replyTo: Int? = null,
val sendWithoutNotification: Boolean? = null // val sendWithoutNotification: Boolean? = null
) // )
private var isQueueing: Boolean = false // private var isQueueing: Boolean = false
private var messageQueue: MutableList<QueuedMessage> = mutableListOf() // private var messageQueue: MutableList<QueuedMessage> = mutableListOf()
override fun onResume(owner: LifecycleOwner) { override fun onResume(owner: LifecycleOwner) {
super.onResume(owner) super.onResume(owner)
@ -129,13 +129,13 @@ class MessageInputViewModel @Inject constructor(
val isVoicePreviewPlaying: LiveData<Boolean> val isVoicePreviewPlaying: LiveData<Boolean>
get() = _isVoicePreviewPlaying get() = _isVoicePreviewPlaying
private val _messageQueueSizeFlow = MutableStateFlow(messageQueue.size) private val _messageQueueSizeFlow = MutableStateFlow(666)
val messageQueueSizeFlow: LiveData<Int> val messageQueueSizeFlow: LiveData<Int>
get() = _messageQueueSizeFlow.asLiveData() get() = _messageQueueSizeFlow.asLiveData()
private val _messageQueueFlow: MutableLiveData<List<QueuedMessage>> = MutableLiveData() // private val _messageQueueFlow: MutableLiveData<List<QueuedMessage>> = MutableLiveData()
val messageQueueFlow: LiveData<List<QueuedMessage>> // val messageQueueFlow: LiveData<List<QueuedMessage>>
get() = _messageQueueFlow // get() = _messageQueueFlow
private val _callStartedFlow: MutableLiveData<Pair<ChatMessage, Boolean>> = MutableLiveData() private val _callStartedFlow: MutableLiveData<Pair<ChatMessage, Boolean>> = MutableLiveData()
val callStartedFlow: LiveData<Pair<ChatMessage, Boolean>> val callStartedFlow: LiveData<Pair<ChatMessage, Boolean>>
@ -171,16 +171,16 @@ class MessageInputViewModel @Inject constructor(
} }
} }
if (isQueueing) { // if (isQueueing) {
val tempID = System.currentTimeMillis().toInt() // val tempID = System.currentTimeMillis().toInt()
val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification) // val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification)
messageQueue = appPreferences.getMessageQueue(internalId) // messageQueue = appPreferences.getMessageQueue(internalId)
messageQueue.add(qMsg) // messageQueue.add(qMsg)
appPreferences.saveMessageQueue(internalId, messageQueue) // appPreferences.saveMessageQueue(internalId, messageQueue)
_messageQueueSizeFlow.update { messageQueue.size } // _messageQueueSizeFlow.update { messageQueue.size }
_messageQueueFlow.postValue(listOf(qMsg)) // _messageQueueFlow.postValue(listOf(qMsg))
return // return
} // }
viewModelScope.launch { viewModelScope.launch {
chatRepository.sendChatMessage( chatRepository.sendChatMessage(
@ -268,68 +268,68 @@ class MessageInputViewModel @Inject constructor(
_getRecordingTime.postValue(time) _getRecordingTime.postValue(time)
} }
fun sendAndEmptyMessageQueue(internalId: String, credentials: String, url: String) { // fun sendAndEmptyMessageQueue(internalId: String, credentials: String, url: String) {
if (isQueueing) return // if (isQueueing) return
messageQueue.clear() // messageQueue.clear()
//
val queue = appPreferences.getMessageQueue(internalId) // val queue = appPreferences.getMessageQueue(internalId)
appPreferences.saveMessageQueue(internalId, null) // empties the queue // appPreferences.saveMessageQueue(internalId, null) // empties the queue
while (queue.size > 0) { // while (queue.size > 0) {
val msg = queue.removeAt(0) // val msg = queue.removeAt(0)
sendChatMessage( // sendChatMessage(
internalId, // internalId,
credentials, // credentials,
url, // url,
msg.message!!, // msg.message!!,
msg.displayName!!, // msg.displayName!!,
msg.replyTo!!, // msg.replyTo!!,
msg.sendWithoutNotification!! // msg.sendWithoutNotification!!
) // )
sleep(DELAY_BETWEEN_QUEUED_MESSAGES) // sleep(DELAY_BETWEEN_QUEUED_MESSAGES)
} // }
_messageQueueSizeFlow.tryEmit(0) // _messageQueueSizeFlow.tryEmit(0)
} // }
//
fun getTempMessagesFromMessageQueue(internalId: String) { // fun getTempMessagesFromMessageQueue(internalId: String) {
val queue = appPreferences.getMessageQueue(internalId) // val queue = appPreferences.getMessageQueue(internalId)
val list = mutableListOf<QueuedMessage>() // val list = mutableListOf<QueuedMessage>()
for (msg in queue) { // for (msg in queue) {
list.add(msg) // list.add(msg)
} // }
_messageQueueFlow.postValue(list) // _messageQueueFlow.postValue(list)
} // }
//
fun switchToMessageQueue(shouldQueue: Boolean) { // fun switchToMessageQueue(shouldQueue: Boolean) {
isQueueing = shouldQueue // isQueueing = shouldQueue
} // }
//
fun restoreMessageQueue(internalId: String) { // fun restoreMessageQueue(internalId: String) {
messageQueue = appPreferences.getMessageQueue(internalId) // messageQueue = appPreferences.getMessageQueue(internalId)
_messageQueueSizeFlow.tryEmit(messageQueue.size) // _messageQueueSizeFlow.tryEmit(messageQueue.size)
} // }
//
fun removeFromQueue(internalId: String, id: Int) { // fun removeFromQueue(internalId: String, id: Int) {
val queue = appPreferences.getMessageQueue(internalId) // val queue = appPreferences.getMessageQueue(internalId)
for (qMsg in queue) { // for (qMsg in queue) {
if (qMsg.id == id) { // if (qMsg.id == id) {
queue.remove(qMsg) // queue.remove(qMsg)
break // break
} // }
} // }
appPreferences.saveMessageQueue(internalId, queue) // appPreferences.saveMessageQueue(internalId, queue)
_messageQueueSizeFlow.tryEmit(queue.size) // _messageQueueSizeFlow.tryEmit(queue.size)
} // }
//
fun editQueuedMessage(internalId: String, id: Int, newMessage: String) { // fun editQueuedMessage(internalId: String, id: Int, newMessage: String) {
val queue = appPreferences.getMessageQueue(internalId) // val queue = appPreferences.getMessageQueue(internalId)
for (qMsg in queue) { // for (qMsg in queue) {
if (qMsg.id == id) { // if (qMsg.id == id) {
qMsg.message = newMessage // qMsg.message = newMessage
break // break
} // }
} // }
appPreferences.saveMessageQueue(internalId, queue) // appPreferences.saveMessageQueue(internalId, queue)
} // }
fun showCallStartedIndicator(recent: ChatMessage, show: Boolean) { fun showCallStartedIndicator(recent: ChatMessage, show: Boolean) {
_callStartedFlow.postValue(Pair(recent, show)) _callStartedFlow.postValue(Pair(recent, show))

View File

@ -192,7 +192,6 @@ public class AccountRemovalWorker extends Worker {
if (user.getId() != null) { if (user.getId() != null) {
String username = user.getUsername(); String username = user.getUsername();
try { try {
appPreferences.deleteAllMessageQueuesFor(user.getUserId());
userManager.deleteUser(user.getId()); userManager.deleteUser(user.getId());
Log.d(TAG, "deleted user: " + username); Log.d(TAG, "deleted user: " + username);
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -175,12 +175,6 @@ public interface AppPreferences {
int getLastKnownId(String internalConversationId, int defaultValue); int getLastKnownId(String internalConversationId, int defaultValue);
void saveMessageQueue(String internalConversationId, List<MessageInputViewModel.QueuedMessage> queue);
List<MessageInputViewModel.QueuedMessage> getMessageQueue(String internalConversationId);
void deleteAllMessageQueuesFor(String userId);
void saveVoiceMessagePlaybackSpeedPreferences(Map<String, PlaybackSpeed> speeds); void saveVoiceMessagePlaybackSpeedPreferences(Map<String, PlaybackSpeed> speeds);
Map<String, PlaybackSpeed> readVoiceMessagePlaybackSpeedPreferences(); Map<String, PlaybackSpeed> readVoiceMessagePlaybackSpeedPreferences();

View File

@ -501,75 +501,75 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
return if (lastReadId.isNotEmpty()) lastReadId.toInt() else defaultValue return if (lastReadId.isNotEmpty()) lastReadId.toInt() else defaultValue
} }
override fun saveMessageQueue( // override fun saveMessageQueue(
internalConversationId: String, // internalConversationId: String,
queue: MutableList<MessageInputViewModel.QueuedMessage>? // queue: MutableList<MessageInputViewModel.QueuedMessage>?
) { // ) {
runBlocking<Unit> { // runBlocking<Unit> {
async { // async {
var queueStr = "" // var queueStr = ""
queue?.let { // queue?.let {
for (msg in queue) { // for (msg in queue) {
val msgStr = "${msg.id},${msg.message},${msg.replyTo},${msg.displayName},${ // val msgStr = "${msg.id},${msg.message},${msg.replyTo},${msg.displayName},${
msg // msg
.sendWithoutNotification // .sendWithoutNotification
}^" // }^"
queueStr += msgStr // queueStr += msgStr
} // }
} // }
writeString(internalConversationId + MESSAGE_QUEUE, queueStr) // writeString(internalConversationId + MESSAGE_QUEUE, queueStr)
} // }
} // }
} // }
//
// @Suppress("Detekt.TooGenericExceptionCaught")
// override fun getMessageQueue(internalConversationId: String): MutableList<MessageInputViewModel.QueuedMessage> {
// val queueStr =
// runBlocking { async { readString(internalConversationId + MESSAGE_QUEUE).first() } }.getCompleted()
//
// val queue: MutableList<MessageInputViewModel.QueuedMessage> = 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 deleteAllMessageQueuesFor(userId: String) {
override fun getMessageQueue(internalConversationId: String): MutableList<MessageInputViewModel.QueuedMessage> { // runBlocking {
val queueStr = // async {
runBlocking { async { readString(internalConversationId + MESSAGE_QUEUE).first() } }.getCompleted() // val keyList = mutableListOf<Preferences.Key<*>>()
// val preferencesMap = context.dataStore.data.first().asMap()
val queue: MutableList<MessageInputViewModel.QueuedMessage> = mutableListOf() // for (preference in preferencesMap) {
if (queueStr.isEmpty()) return queue // if (preference.key.name.contains("$userId@")) {
// keyList.add(preference.key)
for (msgStr in queueStr.split("^")) { // }
try { // }
if (msgStr.isNotEmpty()) { //
val msgArray = msgStr.split(",") // for (key in keyList) {
val id = msgArray[ID].toInt() // context.dataStore.edit {
val message = msgArray[MESSAGE_INDEX] // it.remove(key)
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<Preferences.Key<*>>()
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<String, PlaybackSpeed>) { override fun saveVoiceMessagePlaybackSpeedPreferences(speeds: Map<String, PlaybackSpeed>) {
Json.encodeToString(speeds).let { Json.encodeToString(speeds).let {