Group: rework a bit how and when we fetch data about groups

This commit is contained in:
ganfra 2020-07-06 18:47:59 +02:00
parent 32d2cea7f8
commit 9ebf87df62
17 changed files with 212 additions and 184 deletions

View file

@ -16,9 +16,20 @@
package im.vector.matrix.android.api.session.group
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to interact within a group.
*/
interface Group {
val groupId: String
/**
* This methods allows you to refresh data about this group. It will be reflected on the GroupSummary.
* The SDK also takes care of refreshing group data every hour.
* @param callback : the matrix callback to be notified of success or failure
* @return a Cancelable to be able to cancel requests.
*/
fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable
}

View file

@ -1,34 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.database.mapper
import im.vector.matrix.android.api.session.group.Group
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.session.group.DefaultGroup
internal object GroupMapper {
fun map(groupEntity: GroupEntity): Group {
return DefaultGroup(
groupEntity.groupId
)
}
}
internal fun GroupEntity.asDomain(): Group {
return GroupMapper.map(this)
}

View file

@ -22,8 +22,7 @@ import io.realm.annotations.PrimaryKey
/**
* This class is used to store group info (groupId and membership) from the sync response.
* Then [im.vector.matrix.android.internal.session.group.GroupSummaryUpdater] observes change and
* makes requests to fetch group information from the homeserver
* Then GetGroupDataTask is called regularly to fetch group information from the homeserver.
*/
internal open class GroupEntity(@PrimaryKey var groupId: String = "")
: RealmObject() {

View file

@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.database.query
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupEntityFields
import im.vector.matrix.android.internal.query.process
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.kotlin.where
@ -28,10 +29,6 @@ internal fun GroupEntity.Companion.where(realm: Realm, groupId: String): RealmQu
.equalTo(GroupEntityFields.GROUP_ID, groupId)
}
internal fun GroupEntity.Companion.where(realm: Realm, membership: Membership? = null): RealmQuery<GroupEntity> {
val query = realm.where<GroupEntity>()
if (membership != null) {
query.equalTo(GroupEntityFields.MEMBERSHIP_STR, membership.name)
}
return query
internal fun GroupEntity.Companion.where(realm: Realm, memberships: List<Membership>): RealmQuery<GroupEntity> {
return realm.where<GroupEntity>().process(GroupEntityFields.MEMBERSHIP_STR, memberships)
}

View file

@ -18,8 +18,10 @@ package im.vector.matrix.android.internal.database.query
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.kotlin.createObject
import io.realm.kotlin.where
internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupId: String? = null): RealmQuery<GroupSummaryEntity> {
@ -34,3 +36,7 @@ internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupIds: List<Str
return realm.where<GroupSummaryEntity>()
.`in`(GroupSummaryEntityFields.GROUP_ID, groupIds.toTypedArray())
}
internal fun GroupSummaryEntity.Companion.getOrCreate(realm: Realm, groupId: String): GroupSummaryEntity {
return where(realm, groupId).findFirst() ?: realm.createObject(groupId)
}

View file

@ -21,7 +21,10 @@ import androidx.work.Constraints
import androidx.work.ListenableWorker
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.time.Duration
import java.util.concurrent.TimeUnit
import javax.inject.Inject
internal class WorkManagerProvider @Inject constructor(
@ -39,6 +42,15 @@ internal class WorkManagerProvider @Inject constructor(
OneTimeWorkRequestBuilder<W>()
.addTag(tag)
/**
* Create a PeriodicWorkRequestBuilder, with the Matrix SDK tag
*/
inline fun <reified W : ListenableWorker> matrixPeriodicWorkRequestBuilder(repeatInterval: Long,
repeatIntervalTimeUnit: TimeUnit) =
PeriodicWorkRequestBuilder<W>(repeatInterval, repeatIntervalTimeUnit)
.addTag(tag)
/**
* Cancel all works instantiated by the Matrix SDK for the current session, and not those from the SDK client, or for other sessions
*/

View file

@ -68,7 +68,6 @@ import im.vector.matrix.android.internal.network.token.AccessTokenProvider
import im.vector.matrix.android.internal.network.token.HomeserverAccessTokenProvider
import im.vector.matrix.android.internal.session.call.CallEventProcessor
import im.vector.matrix.android.internal.session.download.DownloadProgressInterceptor
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
import im.vector.matrix.android.internal.session.homeserver.DefaultHomeServerCapabilitiesService
import im.vector.matrix.android.internal.session.identity.DefaultIdentityService
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManager
@ -293,10 +292,6 @@ internal abstract class SessionModule {
@Binds
abstract fun bindNetworkConnectivityChecker(checker: DefaultNetworkConnectivityChecker): NetworkConnectivityChecker
@Binds
@IntoSet
abstract fun bindGroupSummaryUpdater(updater: GroupSummaryUpdater): SessionLifecycleObserver
@Binds
@IntoSet
abstract fun bindEventRedactionProcessor(processor: RedactionEventProcessor): EventInsertLiveProcessor

View file

@ -18,7 +18,9 @@ package im.vector.matrix.android.internal.session.group
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.network.executeRequest
@ -28,11 +30,14 @@ import im.vector.matrix.android.internal.session.group.model.GroupUsers
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.awaitTransaction
import org.greenrobot.eventbus.EventBus
import timber.log.Timber
import javax.inject.Inject
internal interface GetGroupDataTask : Task<GetGroupDataTask.Params, Unit> {
data class Params(val groupId: String)
sealed class Params {
object FetchAllActive : Params()
data class FetchWithIds(val groupIds: List<String>) : Params()
}
}
internal class DefaultGetGroupDataTask @Inject constructor(
@ -41,44 +46,64 @@ internal class DefaultGetGroupDataTask @Inject constructor(
private val eventBus: EventBus
) : GetGroupDataTask {
private data class GroupData(
val groupId: String,
val groupSummary: GroupSummaryResponse,
val groupRooms: GroupRooms,
val groupUsers: GroupUsers
)
override suspend fun execute(params: GetGroupDataTask.Params) {
val groupId = params.groupId
val groupSummary = executeRequest<GroupSummaryResponse>(eventBus) {
apiCall = groupAPI.getSummary(groupId)
val groupIds = when (params) {
is GetGroupDataTask.Params.FetchAllActive -> {
getActiveGroupIds()
}
is GetGroupDataTask.Params.FetchWithIds -> {
params.groupIds
}
}
val groupRooms = executeRequest<GroupRooms>(eventBus) {
apiCall = groupAPI.getRooms(groupId)
Timber.v("Fetch data for group with ids: ${groupIds.joinToString(";")}")
val data = groupIds.map { groupId ->
val groupSummary = executeRequest<GroupSummaryResponse>(eventBus) {
apiCall = groupAPI.getSummary(groupId)
}
val groupRooms = executeRequest<GroupRooms>(eventBus) {
apiCall = groupAPI.getRooms(groupId)
}
val groupUsers = executeRequest<GroupUsers>(eventBus) {
apiCall = groupAPI.getUsers(groupId)
}
GroupData(groupId, groupSummary, groupRooms, groupUsers)
}
val groupUsers = executeRequest<GroupUsers>(eventBus) {
apiCall = groupAPI.getUsers(groupId)
}
insertInDb(groupSummary, groupRooms, groupUsers, groupId)
insertInDb(data)
}
private suspend fun insertInDb(groupSummary: GroupSummaryResponse,
groupRooms: GroupRooms,
groupUsers: GroupUsers,
groupId: String) {
private fun getActiveGroupIds(): List<String> {
return monarchy.fetchAllMappedSync(
{ realm ->
GroupEntity.where(realm, Membership.activeMemberships())
},
{ it.groupId }
)
}
private suspend fun insertInDb(groupDataList: List<GroupData>) {
monarchy
.awaitTransaction { realm ->
val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst()
?: realm.createObject(GroupSummaryEntity::class.java, groupId)
groupDataList.forEach { groupData ->
groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
val name = groupSummary.profile?.name
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: ""
val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupData.groupId)
groupSummaryEntity.roomIds.clear()
groupRooms.rooms.mapTo(groupSummaryEntity.roomIds) { it.roomId }
groupSummaryEntity.avatarUrl = groupData.groupSummary.profile?.avatarUrl ?: ""
val name = groupData.groupSummary.profile?.name
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupData.groupId else name
groupSummaryEntity.shortDescription = groupData.groupSummary.profile?.shortDescription ?: ""
groupSummaryEntity.userIds.clear()
groupUsers.users.mapTo(groupSummaryEntity.userIds) { it.userId }
groupSummaryEntity.roomIds.clear()
groupData.groupRooms.rooms.mapTo(groupSummaryEntity.roomIds) { it.roomId }
groupSummaryEntity.membership = when (groupSummary.user?.membership) {
Membership.JOIN.value -> Membership.JOIN
Membership.INVITE.value -> Membership.INVITE
else -> Membership.LEAVE
groupSummaryEntity.userIds.clear()
groupData.groupUsers.users.mapTo(groupSummaryEntity.userIds) { it.userId }
}
}
}

View file

@ -16,6 +16,20 @@
package im.vector.matrix.android.internal.session.group
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.group.Group
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
internal class DefaultGroup(override val groupId: String) : Group
internal class DefaultGroup(override val groupId: String,
private val taskExecutor: TaskExecutor,
private val getGroupDataTask: GetGroupDataTask) : Group {
override fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable {
val params = GetGroupDataTask.Params.FetchWithIds(listOf(groupId))
return getGroupDataTask.configureWith(params) {
this.callback = callback
}.executeBy(taskExecutor)
}
}

View file

@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.group.GroupService
import im.vector.matrix.android.api.session.group.GroupSummaryQueryParams
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
@ -33,10 +34,15 @@ import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class DefaultGroupService @Inject constructor(@SessionDatabase private val monarchy: Monarchy) : GroupService {
internal class DefaultGroupService @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory) : GroupService {
override fun getGroup(groupId: String): Group? {
return null
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
GroupEntity.where(realm, groupId).findFirst()?.let {
groupFactory.create(groupId)
}
}
}
override fun getGroupSummary(groupId: String): GroupSummary? {

View file

@ -35,7 +35,6 @@ internal class GetGroupDataWorker(context: Context, params: WorkerParameters) :
@JsonClass(generateAdapter = true)
internal data class Params(
override val sessionId: String,
val groupIds: List<String>,
override val lastFailureMessage: String? = null
) : SessionWorkerParams
@ -48,14 +47,11 @@ internal class GetGroupDataWorker(context: Context, params: WorkerParameters) :
val sessionComponent = getSessionComponent(params.sessionId) ?: return Result.success()
sessionComponent.inject(this)
val results = params.groupIds.map { groupId ->
runCatching { fetchGroupData(groupId) }
}
val isSuccessful = results.none { it.isFailure }
return if (isSuccessful) Result.success() else Result.retry()
}
private suspend fun fetchGroupData(groupId: String) {
getGroupDataTask.execute(GetGroupDataTask.Params(groupId))
return runCatching {
getGroupDataTask.execute(GetGroupDataTask.Params.FetchAllActive)
}.fold(
{ Result.success() },
{ Result.retry() }
)
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.group
import im.vector.matrix.android.api.session.group.Group
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.task.TaskExecutor
import javax.inject.Inject
internal interface GroupFactory {
fun create(groupId: String): Group
}
@SessionScope
internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask,
private val taskExecutor: TaskExecutor) :
GroupFactory {
override fun create(groupId: String): Group {
return DefaultGroup(
groupId = groupId,
taskExecutor = taskExecutor,
getGroupDataTask = getGroupDataTask
)
}
}

View file

@ -21,6 +21,8 @@ import dagger.Module
import dagger.Provides
import im.vector.matrix.android.api.session.group.GroupService
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.room.DefaultRoomFactory
import im.vector.matrix.android.internal.session.room.RoomFactory
import retrofit2.Retrofit
@Module
@ -36,6 +38,9 @@ internal abstract class GroupModule {
}
}
@Binds
abstract fun bindGroupFactory(factory: DefaultGroupFactory): GroupFactory
@Binds
abstract fun bindGetGroupDataTask(task: DefaultGetGroupDataTask): GetGroupDataTask

View file

@ -1,93 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.group
import androidx.work.ExistingWorkPolicy
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.awaitTransaction
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.SessionId
import im.vector.matrix.android.internal.di.WorkManagerProvider
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
import io.realm.OrderedCollectionChangeSet
import io.realm.RealmResults
import kotlinx.coroutines.launch
import javax.inject.Inject
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
internal class GroupSummaryUpdater @Inject constructor(
private val workManagerProvider: WorkManagerProvider,
@SessionId private val sessionId: String,
@SessionDatabase private val monarchy: Monarchy)
: RealmLiveEntityObserver<GroupEntity>(monarchy.realmConfiguration) {
override val query = Monarchy.Query { GroupEntity.where(it) }
override fun onChange(results: RealmResults<GroupEntity>) {
/*
// `insertions` for new groups and `changes` to handle left groups
val modifiedGroupEntity = (changeSet.insertions + changeSet.changes)
.asSequence()
.mapNotNull { results[it] }
fetchGroupsData(modifiedGroupEntity
.filter { it.membership == Membership.JOIN || it.membership == Membership.INVITE }
.map { it.groupId }
.toList())
modifiedGroupEntity
.filter { it.membership == Membership.LEAVE }
.map { it.groupId }
.toList()
.also {
observerScope.launch {
deleteGroups(it)
}
}
*/
}
private fun fetchGroupsData(groupIds: List<String>) {
val getGroupDataWorkerParams = GetGroupDataWorker.Params(sessionId, groupIds)
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
val getGroupWork = workManagerProvider.matrixOneTimeWorkRequestBuilder<GetGroupDataWorker>()
.setInputData(workData)
.setConstraints(WorkManagerProvider.workConstraints)
.build()
workManagerProvider.workManager
.beginUniqueWork(GET_GROUP_DATA_WORKER, ExistingWorkPolicy.APPEND, getGroupWork)
.enqueue()
}
/**
* Delete the GroupSummaryEntity of left groups
*/
private suspend fun deleteGroups(groupIds: List<String>) = awaitTransaction(monarchy.realmConfiguration) { realm ->
GroupSummaryEntity.where(realm, groupIds)
.findAll()
.deleteAllFromRealm()
}
}

View file

@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.session.sync
import im.vector.matrix.android.R
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.mapWithProgress
@ -64,29 +66,33 @@ internal class GroupSyncHandler @Inject constructor() {
handleLeftGroup(realm, it.key)
}
}
/** Note: [im.vector.matrix.android.internal.session.group.GroupSummaryUpdater] is observing changes */
realm.insertOrUpdate(groups)
}
private fun handleJoinedGroup(realm: Realm,
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId)
groupEntity.membership = Membership.JOIN
groupSummaryEntity.membership = Membership.JOIN
return groupEntity
}
private fun handleInvitedGroup(realm: Realm,
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId)
groupEntity.membership = Membership.INVITE
groupSummaryEntity.membership = Membership.INVITE
return groupEntity
}
private fun handleLeftGroup(realm: Realm,
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
val groupSummaryEntity = GroupSummaryEntity.getOrCreate(realm, groupId)
groupEntity.membership = Membership.LEAVE
groupSummaryEntity.membership = Membership.LEAVE
return groupEntity
}
}

View file

@ -16,23 +16,34 @@
package im.vector.matrix.android.internal.session.sync
import androidx.work.ExistingPeriodicWorkPolicy
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.R
import im.vector.matrix.android.api.pushrules.PushRuleService
import im.vector.matrix.android.api.pushrules.RuleScope
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.SessionId
import im.vector.matrix.android.internal.di.WorkManagerProvider
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask
import im.vector.matrix.android.internal.session.reportSubtask
import im.vector.matrix.android.internal.session.sync.model.GroupsSyncResponse
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.util.awaitTransaction
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.system.measureTimeMillis
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
internal class SyncResponseHandler @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
@SessionId private val sessionId: String,
private val workManagerProvider: WorkManagerProvider,
private val roomSyncHandler: RoomSyncHandler,
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
private val groupSyncHandler: GroupSyncHandler,
@ -109,10 +120,39 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
checkPushRules(it, isInitialSync)
userAccountDataSyncHandler.synchronizeWithServerIfNeeded(it.invite)
}
syncResponse.groups?.also {
scheduleGroupDataFetchingIfNeeded(it)
}
Timber.v("On sync completed")
cryptoSyncHandler.onSyncCompleted(syncResponse)
}
/**
* At the moment we don't get any group data through the sync, so we poll where every hour.
You can also force to refetch group data using [Group] API.
*/
private fun scheduleGroupDataFetchingIfNeeded(groupsSyncResponse: GroupsSyncResponse) {
val groupIds = ArrayList<String>()
groupIds.addAll(groupsSyncResponse.join.keys)
groupIds.addAll(groupsSyncResponse.invite.keys)
if (groupIds.isEmpty()) {
Timber.v("No new groups to fetch data for.")
return
}
Timber.v("There are ${groupIds.size} new groups to fetch data for.")
val getGroupDataWorkerParams = GetGroupDataWorker.Params(sessionId)
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
val getGroupWork = workManagerProvider.matrixPeriodicWorkRequestBuilder<GetGroupDataWorker>(1, TimeUnit.HOURS)
.setInputData(workData)
.setConstraints(WorkManagerProvider.workConstraints)
.build()
workManagerProvider.workManager
.enqueueUniquePeriodicWork(GET_GROUP_DATA_WORKER, ExistingPeriodicWorkPolicy.REPLACE, getGroupWork)
}
private suspend fun checkPushRules(roomsSyncResponse: RoomsSyncResponse, isInitialSync: Boolean) {
Timber.v("[PushRules] --> checkPushRules")
if (isInitialSync) {

View file

@ -23,6 +23,7 @@ import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.NoOpMatrixCallback
import im.vector.matrix.android.api.query.QueryStringValue
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.groupSummaryQueryParams
@ -88,6 +89,8 @@ class GroupListViewModel @AssistedInject constructor(@Assisted initialState: Gro
private fun handleSelectGroup(action: GroupListAction.SelectGroup) = withState { state ->
if (state.selectedGroup?.groupId != action.groupSummary.groupId) {
// We take care of refreshing group data when selecting to be sure we get all the rooms and users
session.getGroup(action.groupSummary.groupId)?.fetchGroupData(NoOpMatrixCallback())
setState { copy(selectedGroup = action.groupSummary) }
}
}