Remove unnecessary Room.updateMembers() calls. (#2564)

* Remove unnecessary `updateMembers` calls.

Some of them can be directly removed since we have a way to automatically get member info updates based on membership changes.

Others can be replaced by a simpler `getUpdatedMember` method. This might still need a full member sync, but it's quite unlikely.
This commit is contained in:
Jorge Martin Espinosa 2024-03-18 15:57:25 +01:00 committed by GitHub
parent 181e49528b
commit 058a79127c
8 changed files with 26 additions and 37 deletions

View file

@ -295,8 +295,6 @@ class MessagesPresenter @AssistedInject constructor(
private fun CoroutineScope.reinviteOtherUser(inviteProgress: MutableState<AsyncData<Unit>>) = launch(dispatchers.io) { private fun CoroutineScope.reinviteOtherUser(inviteProgress: MutableState<AsyncData<Unit>>) = launch(dispatchers.io) {
inviteProgress.value = AsyncData.Loading() inviteProgress.value = AsyncData.Loading()
runCatching { runCatching {
room.updateMembers()
val memberList = when (val memberState = room.membersStateFlow.value) { val memberList = when (val memberState = room.membersStateFlow.value) {
is MatrixRoomMembersState.Ready -> memberState.roomMembers is MatrixRoomMembersState.Ready -> memberState.roomMembers
is MatrixRoomMembersState.Error -> memberState.prevRoomMembers.orEmpty() is MatrixRoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()

View file

@ -26,7 +26,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.Lifecycle
import im.vector.app.features.analytics.plan.Interaction import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
@ -34,7 +33,6 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
@ -92,13 +90,6 @@ class RoomDetailsPresenter @Inject constructor(
} }
} }
// Update room members only when first presenting the node
OnLifecycleEvent { _, event ->
if (event == Lifecycle.Event.ON_CREATE) {
scope.launch { room.updateMembers() }
}
}
val membersState by room.membersStateFlow.collectAsState() val membersState by room.membersStateFlow.collectAsState()
val canInvite by getCanInvite(membersState) val canInvite by getCanInvite(membersState)
val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME) val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME)

View file

@ -80,8 +80,6 @@ class RoomInviteMembersNode @AssistedInject constructor(
body = context.getString(CommonStrings.common_unable_to_invite_message), body = context.getString(CommonStrings.common_unable_to_invite_message),
) )
} }
room.updateMembers()
} }
} }
) )

View file

@ -67,7 +67,9 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
} }
} }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
room.updateMembers() // Update room member info when opening this screen
// We don't need to assign the result as it will be automatically propagated by `room.getRoomMemberAsState`
room.getUpdatedMember(roomMemberId)
} }
fun handleEvents(event: RoomMemberDetailsEvents) { fun handleEvents(event: RoomMemberDetailsEvents) {
@ -133,7 +135,7 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
.fold( .fold(
onSuccess = { onSuccess = {
isBlockedState.value = AsyncData.Success(true) isBlockedState.value = AsyncData.Success(true)
room.updateMembers() room.getUpdatedMember(userId)
}, },
onFailure = { onFailure = {
isBlockedState.value = AsyncData.Failure(it, false) isBlockedState.value = AsyncData.Failure(it, false)
@ -147,7 +149,7 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
.fold( .fold(
onSuccess = { onSuccess = {
isBlockedState.value = AsyncData.Success(false) isBlockedState.value = AsyncData.Success(false)
room.updateMembers() room.getUpdatedMember(userId)
}, },
onFailure = { onFailure = {
isBlockedState.value = AsyncData.Failure(it, true) isBlockedState.value = AsyncData.Failure(it, true)

View file

@ -19,9 +19,6 @@ package io.element.android.features.roomdetails.impl.rolesandpermissions
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -33,10 +30,8 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -69,22 +64,12 @@ class RolesAndPermissionsNode @AssistedInject constructor(
override fun onBuilt() { override fun onBuilt() {
super.onBuilt() super.onBuilt()
// Reload members when the user sees this screen
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME) {
lifecycleScope.launch { room.updateMembers() }
}
}
})
// If the user is not an admin anymore, exit this section since they won't have permissions to use it // If the user is not an admin anymore, exit this section since they won't have permissions to use it
lifecycleScope.launch { lifecycleScope.launch {
room.membersStateFlow room.roomInfoFlow
.map { state -> .filter { info ->
state.roomMembers().orEmpty().find { it.userId == room.sessionId } info.userPowerLevels[room.sessionId] != RoomMember.Role.ADMIN.powerLevel
} }
.filter { it?.role != RoomMember.Role.ADMIN }
.take(1) .take(1)
.onEach { navigateUp() } .onEach { navigateUp() }
.collect() .collect()

View file

@ -86,6 +86,11 @@ interface MatrixRoom : Closeable {
*/ */
suspend fun updateMembers() suspend fun updateMembers()
/**
* Will return an updated member or an error.
*/
suspend fun getUpdatedMember(userId: UserId): Result<RoomMember>
suspend fun updateRoomNotificationSettings(): Result<Unit> suspend fun updateRoomNotificationSettings(): Result<Unit>
val syncUpdateFlow: StateFlow<Long> val syncUpdateFlow: StateFlow<Long>

View file

@ -230,6 +230,12 @@ class RustMatrixRoom(
roomMemberListFetcher.fetchRoomMembers(source = source) roomMemberListFetcher.fetchRoomMembers(source = source)
} }
override suspend fun getUpdatedMember(userId: UserId): Result<RoomMember> = withContext(roomDispatcher) {
runCatching {
RoomMemberMapper.map(innerRoom.member(userId.value))
}
}
override suspend fun userDisplayName(userId: UserId): Result<String?> = withContext(roomDispatcher) { override suspend fun userDisplayName(userId: UserId): Result<String?> = withContext(roomDispatcher) {
runCatching { runCatching {
innerRoom.memberDisplayName(userId.value) innerRoom.memberDisplayName(userId.value)

View file

@ -91,7 +91,7 @@ class FakeMatrixRoom(
private var userDisplayNameResult = Result.success<String?>(null) private var userDisplayNameResult = Result.success<String?>(null)
private var userAvatarUrlResult = Result.success<String?>(null) private var userAvatarUrlResult = Result.success<String?>(null)
private var userRoleResult = Result.success(RoomMember.Role.USER) private var userRoleResult = Result.success(RoomMember.Role.USER)
private var updateMembersResult: Result<Unit> = Result.success(Unit) private var getRoomMemberResult = Result.failure<RoomMember>(IllegalStateException("Member not found"))
private var joinRoomResult = Result.success(Unit) private var joinRoomResult = Result.success(Unit)
private var inviteUserResult = Result.success(Unit) private var inviteUserResult = Result.success(Unit)
private var canInviteResult = Result.success(true) private var canInviteResult = Result.success(true)
@ -195,6 +195,10 @@ class FakeMatrixRoom(
override suspend fun updateMembers() = Unit override suspend fun updateMembers() = Unit
override suspend fun getUpdatedMember(userId: UserId): Result<RoomMember> {
return getRoomMemberResult
}
override suspend fun updateRoomNotificationSettings(): Result<Unit> = simulateLongTask { override suspend fun updateRoomNotificationSettings(): Result<Unit> = simulateLongTask {
val notificationSettings = notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow() val notificationSettings = notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow()
roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(notificationSettings) roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(notificationSettings)
@ -532,8 +536,8 @@ class FakeMatrixRoom(
membersStateFlow.value = state membersStateFlow.value = state
} }
fun givenUpdateMembersResult(result: Result<Unit>) { fun givenGetRoomMemberResult(result: Result<RoomMember>) {
updateMembersResult = result getRoomMemberResult = result
} }
fun givenUserDisplayNameResult(displayName: Result<String?>) { fun givenUserDisplayNameResult(displayName: Result<String?>) {