forked from GitHub-Mirror/riotX-android
User Account Data: fix sync issues with direct invites
This commit is contained in:
parent
087cc0e6e3
commit
4b4156996d
@ -34,14 +34,10 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
|
|||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
|
||||||
import im.vector.matrix.android.internal.database.query.find
|
import im.vector.matrix.android.internal.database.query.find
|
||||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
||||||
import im.vector.matrix.android.internal.database.query.isDirect
|
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
|
||||||
import im.vector.matrix.android.internal.session.mapWithProgress
|
import im.vector.matrix.android.internal.session.mapWithProgress
|
||||||
import im.vector.matrix.android.internal.session.notification.DefaultPushRuleService
|
import im.vector.matrix.android.internal.session.notification.DefaultPushRuleService
|
||||||
import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask
|
import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask
|
||||||
@ -69,9 +65,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
private val tokenStore: SyncTokenStore,
|
private val tokenStore: SyncTokenStore,
|
||||||
private val pushRuleService: DefaultPushRuleService,
|
private val pushRuleService: DefaultPushRuleService,
|
||||||
private val processForPushTask: ProcessEventForPushTask,
|
private val processForPushTask: ProcessEventForPushTask,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
|
||||||
private val credentials: Credentials,
|
private val credentials: Credentials,
|
||||||
private val directChatsHelper: DirectChatsHelper,
|
|
||||||
private val taskExecutor: TaskExecutor) {
|
private val taskExecutor: TaskExecutor) {
|
||||||
|
|
||||||
sealed class HandlingStrategy {
|
sealed class HandlingStrategy {
|
||||||
@ -192,21 +186,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
|||||||
val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events)
|
val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events)
|
||||||
roomEntity.addOrUpdate(chunkEntity)
|
roomEntity.addOrUpdate(chunkEntity)
|
||||||
}
|
}
|
||||||
val myUserStateEvent = RoomMembers(realm, roomId).getStateEvent(credentials.userId)
|
roomSummaryUpdater.update(realm, roomId, Membership.INVITE)
|
||||||
val inviterId = myUserStateEvent?.sender
|
|
||||||
val myUserRoomMember: RoomMember? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
|
||||||
val isDirect = myUserRoomMember?.isDirect
|
|
||||||
if (isDirect == true && inviterId != null) {
|
|
||||||
val isAlreadyDirect = RoomSummaryEntity.isDirect(realm, roomId)
|
|
||||||
if (!isAlreadyDirect) {
|
|
||||||
val directChatsMap = directChatsHelper.getDirectChats(include = Pair(inviterId, roomId))
|
|
||||||
val updateUserAccountParams = UpdateUserAccountDataTask.DirectChatParams(
|
|
||||||
directMessages = directChatsMap
|
|
||||||
)
|
|
||||||
updateUserAccountDataTask.configureWith(updateUserAccountParams).executeBy(taskExecutor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roomSummaryUpdater.update(realm, roomId, Membership.INVITE, isDirect = isDirect, directUserId = inviterId)
|
|
||||||
return roomEntity
|
return roomEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,23 @@
|
|||||||
package im.vector.matrix.android.internal.session.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.isDirect
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
import im.vector.matrix.android.internal.session.reportSubtask
|
import im.vector.matrix.android.internal.session.reportSubtask
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
|
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
||||||
|
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
@ -88,9 +100,7 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
|||||||
measureTimeMillis {
|
measureTimeMillis {
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) {
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) {
|
||||||
Timber.v("Handle accountData")
|
Timber.v("Handle accountData")
|
||||||
if (syncResponse.accountData != null) {
|
userAccountDataSyncHandler.handle(syncResponse.accountData, syncResponse.rooms?.invite)
|
||||||
userAccountDataSyncHandler.handle(syncResponse.accountData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
Timber.v("Finish handling accountData in $it ms")
|
Timber.v("Finish handling accountData in $it ms")
|
||||||
@ -98,7 +108,6 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
|||||||
|
|
||||||
Timber.v("On sync completed")
|
Timber.v("On sync completed")
|
||||||
cryptoSyncHandler.onSyncCompleted(syncResponse)
|
cryptoSyncHandler.onSyncCompleted(syncResponse)
|
||||||
|
|
||||||
}
|
}
|
||||||
Timber.v("Finish handling sync in $measure ms")
|
Timber.v("Finish handling sync in $measure ms")
|
||||||
syncResponse
|
syncResponse
|
||||||
|
@ -17,28 +17,45 @@
|
|||||||
package im.vector.matrix.android.internal.session.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
|
||||||
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
|
||||||
|
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
||||||
|
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.Realm
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy) {
|
internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy,
|
||||||
|
private val credentials: Credentials,
|
||||||
|
private val directChatsHelper: DirectChatsHelper,
|
||||||
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
|
private val taskExecutor: TaskExecutor) {
|
||||||
|
|
||||||
fun handle(accountData: UserAccountDataSync) {
|
fun handle(accountData: UserAccountDataSync?, invites: Map<String, InvitedRoomSync>?) {
|
||||||
accountData.list.forEach {
|
accountData?.list?.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is UserAccountDataDirectMessages -> handleDirectChatRooms(it)
|
is UserAccountDataDirectMessages -> handleDirectChatRooms(it)
|
||||||
else -> return@forEach
|
else -> return@forEach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
monarchy.doWithRealm { realm ->
|
||||||
|
synchronizeWithServerIfNeeded(realm, invites)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleDirectChatRooms(directMessages: UserAccountDataDirectMessages) {
|
private fun handleDirectChatRooms(directMessages: UserAccountDataDirectMessages) {
|
||||||
monarchy.runTransactionSync { realm ->
|
monarchy.runTransactionSync { realm ->
|
||||||
|
|
||||||
val oldDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
val oldDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
||||||
oldDirectRooms.forEach {
|
oldDirectRooms.forEach {
|
||||||
it.isDirect = false
|
it.isDirect = false
|
||||||
@ -57,4 +74,39 @@ internal class UserAccountDataSyncHandler @Inject constructor(private val monarc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we get some direct chat invites, we synchronize the user account data including those.
|
||||||
|
private fun synchronizeWithServerIfNeeded(realm: Realm, invites: Map<String, InvitedRoomSync>?) {
|
||||||
|
if (invites.isNullOrEmpty()) return
|
||||||
|
|
||||||
|
val directChats = directChatsHelper.getDirectChats()
|
||||||
|
val directChatInvites = HashMap<String, MutableList<String>>().apply {
|
||||||
|
directChats.forEach { (inviterId, roomIds) ->
|
||||||
|
put(inviterId, ArrayList(roomIds))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var hasUpdate = false
|
||||||
|
invites.forEach { (roomId, _) ->
|
||||||
|
val myUserStateEvent = RoomMembers(realm, roomId).getStateEvent(credentials.userId)
|
||||||
|
val inviterId = myUserStateEvent?.sender
|
||||||
|
val myUserRoomMember: RoomMember? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
||||||
|
val isDirect = myUserRoomMember?.isDirect
|
||||||
|
if (inviterId != null && inviterId != credentials.userId && isDirect == true) {
|
||||||
|
directChatInvites.getOrPut(inviterId, { arrayListOf() }).apply {
|
||||||
|
if (contains(roomId)) {
|
||||||
|
Timber.v("Direct chats already include room $roomId with user $inviterId")
|
||||||
|
} else {
|
||||||
|
this.add(roomId)
|
||||||
|
hasUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasUpdate) {
|
||||||
|
val updateUserAccountParams = UpdateUserAccountDataTask.DirectChatParams(
|
||||||
|
directMessages = directChatInvites
|
||||||
|
)
|
||||||
|
updateUserAccountDataTask.configureWith(updateUserAccountParams).executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
internal class DirectChatsHelper @Inject constructor(@SessionDatabase private val realmConfiguration: RealmConfiguration) {
|
internal class DirectChatsHelper @Inject constructor(@SessionDatabase private val realmConfiguration: RealmConfiguration) {
|
||||||
|
|
||||||
fun getDirectChats(include: Pair<String, String>? = null, filterRoomId: String? = null): Map<String, List<String>> {
|
fun getDirectChats(filterRoomId: String? = null): Map<String, List<String>> {
|
||||||
return Realm.getInstance(realmConfiguration).use { realm ->
|
return Realm.getInstance(realmConfiguration).use { realm ->
|
||||||
val currentDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
val currentDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
||||||
val directChatsMap = mutableMapOf<String, MutableList<String>>()
|
val directChatsMap = mutableMapOf<String, MutableList<String>>()
|
||||||
@ -37,15 +37,6 @@ internal class DirectChatsHelper @Inject constructor(@SessionDatabase private va
|
|||||||
add(directRoom.roomId)
|
add(directRoom.roomId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (include != null) {
|
|
||||||
directChatsMap.getOrPut(include.first, { arrayListOf() }).apply {
|
|
||||||
if (contains(include.second)) {
|
|
||||||
Timber.v("Direct chats already include room ${include.second} with user ${include.first}")
|
|
||||||
} else {
|
|
||||||
add(include.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
directChatsMap
|
directChatsMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user