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 6b5827555d..b8c22a4a44 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -322,6 +322,7 @@ class ChatActivity : private val onBackPressedCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { + chatViewModel.handleChatOnBackPress() if (currentlyPlayedVoiceMessage != null) { stopMediaPlayer(currentlyPlayedVoiceMessage!!) } @@ -600,10 +601,12 @@ class ChatActivity : val urlForChatting = ApiUtils.getUrlForChat(chatApiVersion, conversationUser?.baseUrl, roomToken) - chatViewModel.loadMessages( - withCredentials = credentials!!, - withUrl = urlForChatting - ) + if (adapter?.isEmpty == true) { + chatViewModel.loadMessages( + withCredentials = credentials!!, + withUrl = urlForChatting + ) + } } is ChatViewModel.GetCapabilitiesErrorState -> { @@ -2718,7 +2721,7 @@ class ChatActivity : withUrl = urlForChatting, withCredentials = credentials!!, withMessageLimit = MESSAGE_PULL_LIMIT, - roomToken = currentConversation!!.token!! + roomToken = currentConversation!!.token ) } 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 010d74e0bd..41268d460d 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 @@ -69,4 +69,9 @@ interface ChatMessageRepository : LifecycleAwareManager { * Gets a individual message. */ suspend fun getMessage(messageId: Long, bundle: Bundle): Flow + + /** + * Destroys unused resources. + */ + fun handleChatOnBackPress() } 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 f45cf97779..05916c7750 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 @@ -31,6 +31,7 @@ import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow @@ -201,8 +202,8 @@ class OfflineFirstChatRepository @Inject constructor( val networkParams = Bundle() - while (!itIsPaused) { - if (!monitor.isOnline.first()) Thread.sleep(500) + while (true) { + if (!monitor.isOnline.first() || itIsPaused) Thread.sleep(HALF_SECOND) // sync database with server (This is a long blocking call because long polling (lookIntoFuture) is set) networkParams.putSerializable(BundleKeys.KEY_FIELD_MAP, fieldMap) @@ -464,9 +465,11 @@ class OfflineFirstChatRepository @Inject constructor( // the parent message is always the newest state, no matter how old the system message is. // that's why we can just take the parent, update it in DB and update the UI messageJson.parentMessage?.let { parentMessageJson -> - val parentMessageEntity = parentMessageJson.asEntity(currentUser.id!!) - chatDao.upsertChatMessage(parentMessageEntity) - _updateMessageFlow.emit(parentMessageEntity.asModel()) + parentMessageJson.message?.let { + val parentMessageEntity = parentMessageJson.asEntity(currentUser.id!!) + chatDao.upsertChatMessage(parentMessageEntity) + _updateMessageFlow.emit(parentMessageEntity.asModel()) + } } } @@ -629,11 +632,16 @@ class OfflineFirstChatRepository @Inject constructor( // unused atm } + override fun handleChatOnBackPress() { + scope.cancel() + } + companion object { val TAG = OfflineFirstChatRepository::class.simpleName private const val HTTP_CODE_OK: Int = 200 private const val HTTP_CODE_NOT_MODIFIED = 304 private const val HTTP_CODE_PRECONDITION_FAILED = 412 + private const val HALF_SECOND = 500L private const val DELAY_TO_ENSURE_MESSAGES_ARE_ADDED: Long = 100 } } diff --git a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt index 447fdd933b..256e9b1147 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt @@ -634,6 +634,10 @@ class ChatViewModel @Inject constructor( _getCapabilitiesViewState.value = GetCapabilitiesStartState } + fun handleChatOnBackPress() { + chatRepository.handleChatOnBackPress() + } + suspend fun getMessageById(url: String, conversationModel: ConversationModel, messageId: Long): Flow = flow { val bundle = Bundle() @@ -642,7 +646,7 @@ class ChatViewModel @Inject constructor( BundleKeys.KEY_CREDENTIALS, userProvider.currentUser.blockingGet().getCredentials() ) - bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversationModel.token!!) + bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversationModel.token) val message = chatRepository.getMessage(messageId, bundle) emit(message.first()) diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt index ce64a6c7b8..7a4b51f030 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt @@ -374,8 +374,8 @@ class ConversationsListActivity : conversationsListViewModel.getRoomsFlow .onEach { list -> // Update Conversations + conversationItems.clear() conversationItemsWithHeader.clear() - conversationItems.clear() // fixme remove this for (conversation in list) { addToConversationItems(conversation) } diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/data/network/OfflineFirstConversationsRepository.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/data/network/OfflineFirstConversationsRepository.kt index 45482ba64f..397a86dca7 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationlist/data/network/OfflineFirstConversationsRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/data/network/OfflineFirstConversationsRepository.kt @@ -9,6 +9,7 @@ package com.nextcloud.talk.conversationlist.data.network import android.util.Log +import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource import com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository import com.nextcloud.talk.data.database.dao.ConversationsDao @@ -19,7 +20,9 @@ import com.nextcloud.talk.data.network.NetworkMonitor import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.models.domain.ConversationModel import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew +import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -29,11 +32,13 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import javax.inject.Inject class OfflineFirstConversationsRepository @Inject constructor( private val dao: ConversationsDao, private val network: ConversationsNetworkDataSource, + private val chatNetworkDataSource: ChatNetworkDataSource, private val monitor: NetworkMonitor, private val currentUserProviderNew: CurrentUserProviderNew ) : OfflineConversationsRepository { @@ -64,7 +69,34 @@ class OfflineFirstConversationsRepository @Inject constructor( scope.launch { val id = user.id!! val model = getConversation(id, roomToken) - model.let { _conversationFlow.emit(model) } + if (model != null) { + _conversationFlow.emit(model) + } else { + chatNetworkDataSource.getRoom(user, roomToken) + .subscribeOn(Schedulers.io()) + ?.observeOn(AndroidSchedulers.mainThread()) + ?.subscribe(object : Observer { + override fun onSubscribe(p0: Disposable) { + // unused atm + } + + override fun onError(e: Throwable) { + // unused atm + } + + override fun onComplete() { + // unused atm + } + + override fun onNext(model: ConversationModel) { + runBlocking { + _conversationFlow.emit(model) + val entityList = listOf(model.asEntity()) + dao.upsertConversations(entityList) + } + } + }) + } } private suspend fun sync(): List? { @@ -107,9 +139,9 @@ class OfflineFirstConversationsRepository @Inject constructor( it.map(ConversationEntity::asModel) }.first() - private suspend fun getConversation(accountId: Long, token: String): ConversationModel { + private suspend fun getConversation(accountId: Long, token: String): ConversationModel? { val entity = dao.getConversationForUser(accountId, token).first() - return entity.asModel() + return entity?.asModel() } companion object { diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt index 666ab69d02..4085d41146 100644 --- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt +++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt @@ -10,11 +10,11 @@ package com.nextcloud.talk.dagger.modules import com.nextcloud.talk.api.NcApi +import com.nextcloud.talk.api.NcApiCoroutines import com.nextcloud.talk.chat.data.ChatMessageRepository import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource import com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository import com.nextcloud.talk.chat.data.network.RetrofitChatNetwork -import com.nextcloud.talk.api.NcApiCoroutines import com.nextcloud.talk.contacts.ContactsRepository import com.nextcloud.talk.contacts.ContactsRepositoryImpl import com.nextcloud.talk.conversation.repository.ConversationRepository @@ -191,10 +191,17 @@ class RepositoryModule { fun provideOfflineFirstConversationsRepository( dao: ConversationsDao, dataSource: ConversationsNetworkDataSource, + chatNetworkDataSource: ChatNetworkDataSource, networkMonitor: NetworkMonitor, currentUserProviderNew: CurrentUserProviderNew ): OfflineConversationsRepository { - return OfflineFirstConversationsRepository(dao, dataSource, networkMonitor, currentUserProviderNew) + return OfflineFirstConversationsRepository( + dao, + dataSource, + chatNetworkDataSource, + networkMonitor, + currentUserProviderNew + ) } @Provides diff --git a/app/src/main/java/com/nextcloud/talk/data/database/dao/ConversationsDao.kt b/app/src/main/java/com/nextcloud/talk/data/database/dao/ConversationsDao.kt index 07dd553553..b6b7ae14fe 100644 --- a/app/src/main/java/com/nextcloud/talk/data/database/dao/ConversationsDao.kt +++ b/app/src/main/java/com/nextcloud/talk/data/database/dao/ConversationsDao.kt @@ -20,7 +20,7 @@ interface ConversationsDao { fun getConversationsForUser(accountId: Long): Flow> @Query("SELECT * FROM Conversations where accountId = :accountId AND token = :token") - fun getConversationForUser(accountId: Long, token: String): Flow + fun getConversationForUser(accountId: Long, token: String): Flow @Upsert fun upsertConversations(conversationEntities: List)