Background fetch

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
rapterjet2004 2024-11-22 10:16:02 -06:00
parent 869c8154d7
commit 7035fb053c
No known key found for this signature in database
GPG Key ID: A6A69CFF84968EA1
5 changed files with 69 additions and 4 deletions

View File

@ -64,6 +64,8 @@ interface ChatMessageRepository : LifecycleAwareManager {
withNetworkParams: Bundle withNetworkParams: Bundle
): Job ): Job
suspend fun updateRoomMessages(internalConversationId: String, limit: Int)
/** /**
* Long polls the server for any updates to the chat, if found, it synchronizes * Long polls the server for any updates to the chat, if found, it synchronizes
* the database with the server and emits the new messages to [messageFlow], * the database with the server and emits the new messages to [messageFlow],

View File

@ -10,6 +10,7 @@ package com.nextcloud.talk.chat.data.network
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.core.os.bundleOf
import com.nextcloud.talk.chat.ChatActivity import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.chat.data.ChatMessageRepository import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.chat.data.model.ChatMessage
@ -28,6 +29,8 @@ import com.nextcloud.talk.models.json.chat.ChatOverall
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.utils.CapabilitiesUtil
import com.nextcloud.talk.utils.SpreedFeatures
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import com.nextcloud.talk.utils.message.SendMessageUtils import com.nextcloud.talk.utils.message.SendMessageUtils
@ -292,6 +295,24 @@ class OfflineFirstChatRepository @Inject constructor(
updateUiForLastCommonRead() updateUiForLastCommonRead()
} }
override suspend fun updateRoomMessages(internalConversationId: String, limit: Int) {
val lastKnown = chatDao.getNewestMessageId(internalConversationId)
Log.d(TAG, "---- updateRoomMessages ------------ with lastKnown: $lastKnown")
val fieldMap = getFieldMap(
lookIntoFuture = true,
timeout = 0,
includeLastKnown = false,
setReadMarker = false,
lastKnown = lastKnown.toInt(),
markNotificationAsRead = false
)
val networkParams = bundleOf()
networkParams.putSerializable(BundleKeys.KEY_FIELD_MAP, fieldMap)
sync(networkParams)
}
override fun initMessagePolling(initialMessageId: Long): Job = override fun initMessagePolling(initialMessageId: Long): Job =
scope.launch { scope.launch {
Log.d(TAG, "---- initMessagePolling ------------") Log.d(TAG, "---- initMessagePolling ------------")
@ -430,7 +451,8 @@ class OfflineFirstChatRepository @Inject constructor(
includeLastKnown: Boolean, includeLastKnown: Boolean,
setReadMarker: Boolean, setReadMarker: Boolean,
lastKnown: Int?, lastKnown: Int?,
limit: Int = DEFAULT_MESSAGES_LIMIT limit: Int = DEFAULT_MESSAGES_LIMIT,
markNotificationAsRead: Boolean = true
): HashMap<String, Int> { ): HashMap<String, Int> {
val fieldMap = HashMap<String, Int>() val fieldMap = HashMap<String, Int>()
@ -449,6 +471,11 @@ class OfflineFirstChatRepository @Inject constructor(
fieldMap["lookIntoFuture"] = if (lookIntoFuture) 1 else 0 fieldMap["lookIntoFuture"] = if (lookIntoFuture) 1 else 0
fieldMap["setReadMarker"] = if (setReadMarker) 1 else 0 fieldMap["setReadMarker"] = if (setReadMarker) 1 else 0
val spreedCapabilities = currentUser.capabilities?.spreedCapability!!
if (CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.CHAT_KEEP_NOTIFICATIONS)) {
fieldMap["markNotificationsAsRead"] = if (markNotificationAsRead) 1 else 0
}
return fieldMap return fieldMap
} }

View File

@ -514,6 +514,9 @@ class ConversationsListActivity :
} }
private fun setConversationList(list: List<ConversationModel>) { private fun setConversationList(list: List<ConversationModel>) {
// Refreshes conversation messages in the background asynchronously
conversationsListViewModel.updateRoomMessages(credentials!!, list)
// Update Conversations // Update Conversations
conversationItems.clear() conversationItems.clear()
conversationItemsWithHeader.clear() conversationItemsWithHeader.clear()
@ -828,7 +831,7 @@ class ConversationsListActivity :
if (!hasFilterEnabled()) filterableConversationItems = searchableConversationItems if (!hasFilterEnabled()) filterableConversationItems = searchableConversationItems
adapter!!.updateDataSet(filterableConversationItems, false) adapter!!.updateDataSet(filterableConversationItems, false)
adapter!!.showAllHeaders() adapter!!.showAllHeaders()
binding.swipeRefreshLayoutView?.isEnabled = false binding.swipeRefreshLayoutView.isEnabled = false
searchBehaviorSubject.onNext(true) searchBehaviorSubject.onNext(true)
return true return true
} }
@ -2077,7 +2080,8 @@ class ConversationsListActivity :
private fun onMessageSearchError(throwable: Throwable) { private fun onMessageSearchError(throwable: Throwable) {
handleHttpExceptions(throwable) handleHttpExceptions(throwable)
binding.swipeRefreshLayoutView?.isRefreshing = false binding.swipeRefreshLayoutView.isRefreshing = false
showErrorDialog()
} }
fun updateFilterState(mention: Boolean, unread: Boolean) { fun updateFilterState(mention: Boolean, unread: Boolean) {

View File

@ -10,21 +10,28 @@ import android.util.Log
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.viewModelScope
import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository
import com.nextcloud.talk.invitation.data.InvitationsModel import com.nextcloud.talk.invitation.data.InvitationsModel
import com.nextcloud.talk.invitation.data.InvitationsRepository import com.nextcloud.talk.invitation.data.InvitationsRepository
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import io.reactivex.Observer 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.Dispatchers
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class ConversationsListViewModel @Inject constructor( class ConversationsListViewModel @Inject constructor(
private val repository: OfflineConversationsRepository, private val repository: OfflineConversationsRepository,
private val chatRepository: ChatMessageRepository,
var userManager: UserManager var userManager: UserManager
) : ) :
ViewModel() { ViewModel() {
@ -88,6 +95,30 @@ class ConversationsListViewModel @Inject constructor(
repository.getRooms() repository.getRooms()
} }
fun updateRoomMessages(
credentials: String,
list: List<ConversationModel>
) {
val current = list.associateWith { model ->
val unreadMessages = model.unreadMessages
unreadMessages
}
val baseUrl = userManager.currentUser.blockingGet().baseUrl!!
viewModelScope.launch(Dispatchers.IO) {
for ((model, unreadMessages) in current) {
if (unreadMessages > 0) {
updateRoomMessage(model, unreadMessages, credentials, baseUrl)
}
}
}
}
private suspend fun updateRoomMessage(model: ConversationModel, limit: Int, credentials: String, baseUrl: String) {
val urlForChatting = ApiUtils.getUrlForChat(1, baseUrl, model.token) // FIXME v1?
chatRepository.setData(model, credentials, urlForChatting)
chatRepository.updateRoomMessages(model.internalId, limit)
}
inner class FederatedInvitationsObserver : Observer<InvitationsModel> { inner class FederatedInvitationsObserver : Observer<InvitationsModel> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
// unused atm // unused atm

View File

@ -56,7 +56,8 @@ enum class SpreedFeatures(val value: String) {
DELETE_MESSAGES_UNLIMITED("delete-messages-unlimited"), DELETE_MESSAGES_UNLIMITED("delete-messages-unlimited"),
BAN_V1("ban-v1"), BAN_V1("ban-v1"),
EDIT_MESSAGES_NOTE_TO_SELF("edit-messages-note-to-self"), EDIT_MESSAGES_NOTE_TO_SELF("edit-messages-note-to-self"),
ARCHIVE_CONVERSATIONS("archived-conversations-v2") ARCHIVE_CONVERSATIONS("archived-conversations-v2"),
CHAT_KEEP_NOTIFICATIONS("chat-keep-notifications")
} }
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")