fix: rely only on RoomMember Role values instead of using the powerLevel.

This commit is contained in:
ganfra 2025-12-01 16:08:11 +01:00
parent f265a47243
commit be90afe22b
10 changed files with 84 additions and 122 deletions

View file

@ -79,15 +79,4 @@ data class RoomInfo(
) {
val aliases: List<RoomAlias>
get() = listOfNotNull(canonicalAlias) + alternativeAliases
/**
* Returns the list of users with the given [role] in this room.
*/
fun usersWithRole(role: RoomMember.Role): List<UserId> {
return if (role is RoomMember.Role.Owner && role.isCreator) {
this.creators
} else {
this.roomPowerLevels?.usersWithRole(role).orEmpty().toList()
}
}
}

View file

@ -15,17 +15,16 @@ import io.element.android.libraries.matrix.api.room.activeRoomMembers
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
/**
* Return a flow of the list of active room members who have the given role.
* Return a flow of the list of active room members who match the predicate.
*/
fun BaseRoom.usersWithRole(role: RoomMember.Role): Flow<ImmutableList<RoomMember>> {
// Ensure the room members flow is ready
fun BaseRoom.usersWithRole(predicate: (RoomMember.Role) -> Boolean): Flow<ImmutableList<RoomMember>> {
// Wait until members are ready to avoid returning empty lists initially
val readyMembersFlow = membersStateFlow
.onStart {
if (membersStateFlow.value is RoomMembersState.Unknown) {
@ -34,12 +33,17 @@ fun BaseRoom.usersWithRole(role: RoomMember.Role): Flow<ImmutableList<RoomMember
}
.filter { it is RoomMembersState.Ready }
return roomInfoFlow
.map { roomInfo -> roomInfo.usersWithRole(role) }
.combine(readyMembersFlow) { powerLevels, membersState ->
membersState.activeRoomMembers()
.filter { powerLevels.contains(it.userId) }
.toImmutableList()
}
.distinctUntilChanged()
return readyMembersFlow.map { membersState ->
membersState
.activeRoomMembers()
.filter({ predicate(it.role) })
.toImmutableList()
}.distinctUntilChanged()
}
/**
* Return the number of active room members who match the predicate.
*/
fun BaseRoom.userCountWithRole(predicate: (RoomMember.Role) -> Boolean): Flow<Int> {
return usersWithRole(predicate).map { it.size }
}

View file

@ -35,19 +35,6 @@ data class RoomPowerLevels(
return users[userId] ?: 0L
}
/**
* Returns the set of [UserId]s that have the given role in the room.
*
* **WARNING**: This method must not be used with a creator role. It'll result in a runtime error.
*/
fun usersWithRole(role: RoomMember.Role): Set<UserId> {
return if (role is RoomMember.Role.Owner && role.isCreator) {
error("RoomPowerLevels.usersWithRole should not be used with a creator role, use roomInfo.creators instead")
} else {
users.filterValues { RoomMember.Role.forPowerLevel(it) == role }.keys
}
}
/**
* Returns the role of the user in the room based on their power level.
* If the user is not found, returns null.