mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-25 14:35:40 +03:00
Follow up bug fixes for offline support
Got join conversation to work Unread message popup should work when entering a conversation now "Delete All Messages" now works without breaking the initMessagePolling linter Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com> Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
822af2c967
commit
ea453dba3e
8 changed files with 77 additions and 18 deletions
|
@ -323,6 +323,7 @@ class ChatActivity :
|
|||
|
||||
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
chatViewModel.handleChatOnBackPress()
|
||||
if (currentlyPlayedVoiceMessage != null) {
|
||||
stopMediaPlayer(currentlyPlayedVoiceMessage!!)
|
||||
}
|
||||
|
@ -601,10 +602,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 -> {
|
||||
|
@ -2717,7 +2720,7 @@ class ChatActivity :
|
|||
withUrl = urlForChatting,
|
||||
withCredentials = credentials!!,
|
||||
withMessageLimit = MESSAGE_PULL_LIMIT,
|
||||
roomToken = currentConversation!!.token!!
|
||||
roomToken = currentConversation!!.token
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -65,4 +65,9 @@ interface ChatMessageRepository : LifecycleAwareManager {
|
|||
* Gets a individual message.
|
||||
*/
|
||||
suspend fun getMessage(messageId: Long, bundle: Bundle): Flow<ChatMessage>
|
||||
|
||||
/**
|
||||
* Destroys unused resources.
|
||||
*/
|
||||
fun handleChatOnBackPress()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -197,8 +198,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)
|
||||
|
@ -457,9 +458,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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,11 +625,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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -626,6 +626,10 @@ class ChatViewModel @Inject constructor(
|
|||
_getCapabilitiesViewState.value = GetCapabilitiesStartState
|
||||
}
|
||||
|
||||
fun handleChatOnBackPress() {
|
||||
chatRepository.handleChatOnBackPress()
|
||||
}
|
||||
|
||||
suspend fun getMessageById(url: String, conversationModel: ConversationModel, messageId: Long): Flow<ChatMessage> =
|
||||
flow {
|
||||
val bundle = Bundle()
|
||||
|
@ -634,7 +638,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())
|
||||
|
|
|
@ -373,8 +373,8 @@ class ConversationsListActivity :
|
|||
conversationsListViewModel.getRoomsFlow
|
||||
.onEach { list ->
|
||||
// Update Conversations
|
||||
conversationItems.clear()
|
||||
conversationItemsWithHeader.clear()
|
||||
conversationItems.clear() // fixme remove this
|
||||
for (conversation in list) {
|
||||
addToConversationItems(conversation)
|
||||
}
|
||||
|
|
|
@ -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<ConversationModel> {
|
||||
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<ConversationEntity>? {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,7 +20,7 @@ interface ConversationsDao {
|
|||
fun getConversationsForUser(accountId: Long): Flow<List<ConversationEntity>>
|
||||
|
||||
@Query("SELECT * FROM Conversations where accountId = :accountId AND token = :token")
|
||||
fun getConversationForUser(accountId: Long, token: String): Flow<ConversationEntity>
|
||||
fun getConversationForUser(accountId: Long, token: String): Flow<ConversationEntity?>
|
||||
|
||||
@Upsert
|
||||
fun upsertConversations(conversationEntities: List<ConversationEntity>)
|
||||
|
|
Loading…
Reference in a new issue