mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 03:29:28 +01:00
Implement queued messages for offline support
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
parent
3d2df9bb94
commit
569be55395
@ -73,6 +73,7 @@ import com.nextcloud.talk.utils.text.Spans
|
|||||||
import com.otaliastudios.autocomplete.Autocomplete
|
import com.otaliastudios.autocomplete.Autocomplete
|
||||||
import com.stfalcon.chatkit.commons.models.IMessage
|
import com.stfalcon.chatkit.commons.models.IMessage
|
||||||
import com.vanniktech.emoji.EmojiPopup
|
import com.vanniktech.emoji.EmojiPopup
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -141,6 +142,11 @@ class MessageInputFragment : Fragment() {
|
|||||||
saveState()
|
saveState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
chatActivity.messageInputViewModel.restoreMessageQueue(chatActivity.roomToken)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
if (mentionAutocomplete != null && mentionAutocomplete!!.isPopupShowing) {
|
if (mentionAutocomplete != null && mentionAutocomplete!!.isPopupShowing) {
|
||||||
@ -178,12 +184,19 @@ class MessageInputFragment : Fragment() {
|
|||||||
val connectionGained = (!wasOnline && isOnline)
|
val connectionGained = (!wasOnline && isOnline)
|
||||||
wasOnline = !binding.fragmentMessageInputView.isShown
|
wasOnline = !binding.fragmentMessageInputView.isShown
|
||||||
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
|
Log.d(TAG, "isOnline: $isOnline\nwasOnline: $wasOnline\nconnectionGained: $connectionGained")
|
||||||
|
delay(500)
|
||||||
// FIXME timeout exception - maybe something to do with the room?
|
handleMessageQueue(isOnline)
|
||||||
// handleMessageQueue(isOnline)
|
|
||||||
handleUI(isOnline, connectionGained)
|
handleUI(isOnline, connectionGained)
|
||||||
}.collect()
|
}.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chatActivity.messageInputViewModel.messageQueueSizeFlow.observe(viewLifecycleOwner) { size ->
|
||||||
|
if (size > 0) {
|
||||||
|
binding.fragmentConnectionLost.text = getString(R.string.connection_lost_queued, size)
|
||||||
|
} else {
|
||||||
|
binding.fragmentConnectionLost.text = getString(R.string.connection_lost_sent_messages_are_queued)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleUI(isOnline: Boolean, connectionGained: Boolean) {
|
private fun handleUI(isOnline: Boolean, connectionGained: Boolean) {
|
||||||
@ -220,12 +233,9 @@ class MessageInputFragment : Fragment() {
|
|||||||
binding.fragmentConnectionLost.clearAnimation()
|
binding.fragmentConnectionLost.clearAnimation()
|
||||||
binding.fragmentConnectionLost.visibility = View.GONE
|
binding.fragmentConnectionLost.visibility = View.GONE
|
||||||
binding.fragmentConnectionLost.setBackgroundColor(resources.getColor(R.color.hwSecurityRed))
|
binding.fragmentConnectionLost.setBackgroundColor(resources.getColor(R.color.hwSecurityRed))
|
||||||
binding.fragmentConnectionLost.text =
|
|
||||||
getString(R.string.connection_lost_sent_messages_are_queued)
|
|
||||||
binding.fragmentConnectionLost.visibility = View.VISIBLE
|
binding.fragmentConnectionLost.visibility = View.VISIBLE
|
||||||
binding.fragmentMessageInputView.attachmentButton.isEnabled = false
|
binding.fragmentMessageInputView.attachmentButton.isEnabled = false
|
||||||
binding.fragmentMessageInputView.recordAudioButton.isEnabled = false
|
binding.fragmentMessageInputView.recordAudioButton.isEnabled = false
|
||||||
binding.fragmentMessageInputView.messageInput.isEnabled = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import androidx.lifecycle.LifecycleOwner
|
|||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
|
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
|
||||||
import com.nextcloud.talk.chat.data.io.AudioRecorderManager
|
import com.nextcloud.talk.chat.data.io.AudioRecorderManager
|
||||||
import com.nextcloud.talk.chat.data.io.MediaPlayerManager
|
import com.nextcloud.talk.chat.data.io.MediaPlayerManager
|
||||||
@ -26,6 +27,8 @@ import io.reactivex.Observer
|
|||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MessageInputViewModel @Inject constructor(
|
class MessageInputViewModel @Inject constructor(
|
||||||
@ -51,7 +54,7 @@ class MessageInputViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private var isQueueing: Boolean = false
|
private var isQueueing: Boolean = false
|
||||||
private val 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)
|
||||||
@ -119,6 +122,10 @@ class MessageInputViewModel @Inject constructor(
|
|||||||
val isVoicePreviewPlaying: LiveData<Boolean>
|
val isVoicePreviewPlaying: LiveData<Boolean>
|
||||||
get() = _isVoicePreviewPlaying
|
get() = _isVoicePreviewPlaying
|
||||||
|
|
||||||
|
private val _messageQueueSizeFlow = MutableStateFlow(messageQueue.size)
|
||||||
|
val messageQueueSizeFlow: LiveData<Int>
|
||||||
|
get() = _messageQueueSizeFlow.asLiveData()
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun sendChatMessage(
|
fun sendChatMessage(
|
||||||
roomToken: String,
|
roomToken: String,
|
||||||
@ -132,6 +139,7 @@ class MessageInputViewModel @Inject constructor(
|
|||||||
if (isQueueing) {
|
if (isQueueing) {
|
||||||
messageQueue.add(QueuedMessage(message, displayName, replyTo, sendWithoutNotification))
|
messageQueue.add(QueuedMessage(message, displayName, replyTo, sendWithoutNotification))
|
||||||
dataStore.saveMessageQueue(roomToken, messageQueue)
|
dataStore.saveMessageQueue(roomToken, messageQueue)
|
||||||
|
_messageQueueSizeFlow.update { messageQueue.size }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,4 +267,9 @@ class MessageInputViewModel @Inject constructor(
|
|||||||
fun switchToMessageQueue(shouldQueue: Boolean) {
|
fun switchToMessageQueue(shouldQueue: Boolean) {
|
||||||
isQueueing = shouldQueue
|
isQueueing = shouldQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun restoreMessageQueue(roomToken: String) {
|
||||||
|
messageQueue = dataStore.getMessageQueue(roomToken)
|
||||||
|
_messageQueueSizeFlow.tryEmit(messageQueue.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
|
|||||||
var queueStr = ""
|
var queueStr = ""
|
||||||
queue?.let {
|
queue?.let {
|
||||||
for (msg in queue) {
|
for (msg in queue) {
|
||||||
val msgStr = "[${msg.message},${msg.replyTo},${msg.displayName},${msg.sendWithoutNotification}]"
|
val msgStr = "${msg.message},${msg.replyTo},${msg.displayName},${msg.sendWithoutNotification}^"
|
||||||
queueStr += msgStr
|
queueStr += msgStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -500,18 +500,20 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
|
|||||||
val queue: MutableList<MessageInputViewModel.QueuedMessage> = mutableListOf()
|
val queue: MutableList<MessageInputViewModel.QueuedMessage> = mutableListOf()
|
||||||
if (queueStr.isEmpty()) return queue
|
if (queueStr.isEmpty()) return queue
|
||||||
|
|
||||||
for (msgStr in queueStr.split("]")) {
|
for (msgStr in queueStr.split("^")) {
|
||||||
try {
|
try {
|
||||||
val msgArray = msgStr.replace("[", "").split(",")
|
if (msgStr.isNotEmpty()) {
|
||||||
val message = msgArray[MESSAGE_INDEX]
|
val msgArray = msgStr.split(",")
|
||||||
val replyTo = msgArray[REPLY_TO_INDEX].toInt()
|
val message = msgArray[MESSAGE_INDEX]
|
||||||
val displayName = msgArray[DISPLY_NAME_INDEX]
|
val replyTo = msgArray[REPLY_TO_INDEX].toInt()
|
||||||
val silent = msgArray[SILENT_INDEX].toBoolean()
|
val displayName = msgArray[DISPLY_NAME_INDEX]
|
||||||
|
val silent = msgArray[SILENT_INDEX].toBoolean()
|
||||||
|
|
||||||
val qMsg = MessageInputViewModel.QueuedMessage(message, displayName, replyTo, silent)
|
val qMsg = MessageInputViewModel.QueuedMessage(message, displayName, replyTo, silent)
|
||||||
queue.add(qMsg)
|
queue.add(qMsg)
|
||||||
|
}
|
||||||
} catch (e: IndexOutOfBoundsException) {
|
} catch (e: IndexOutOfBoundsException) {
|
||||||
Log.e(TAG, "Message string: $msgStr\n $e")
|
Log.e(TAG, "Message string: $msgStr\n Queue String: $queueStr \n$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,6 +802,7 @@ How to translate with transifex:
|
|||||||
<string name="show_banned_participants">Show banned participants</string>
|
<string name="show_banned_participants">Show banned participants</string>
|
||||||
<string name="bans_list">Bans list</string>
|
<string name="bans_list">Bans list</string>
|
||||||
<string name="connection_lost_sent_messages_are_queued">Connection lost - Sent messages are queued</string>
|
<string name="connection_lost_sent_messages_are_queued">Connection lost - Sent messages are queued</string>
|
||||||
|
<string name="connection_lost_queued">Connection lost - %1$d are queued</string>
|
||||||
<string name="connection_established">Connection established</string>
|
<string name="connection_established">Connection established</string>
|
||||||
<string name="message_deleted_by_you">Message deleted by you</string>
|
<string name="message_deleted_by_you">Message deleted by you</string>
|
||||||
<string name="unban">Unban</string>
|
<string name="unban">Unban</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user