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 fde154a284
commit 883d834284
8 changed files with 26 additions and 37 deletions
@@ -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()
@@ -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)
@@ -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()
} }
} }
) )
@@ -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)
@@ -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()
@@ -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>
@@ -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)
@@ -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?>) {