Adapt 'change roles' screens to the new creator/owner role (#5076)

* Replace `RoomMember.Role.CREATOR` with `RoomMember.Role.Owner` - Make `RoomMember.Role` a sealed interface instead

* Adapt room member role mapping to include the power level to distinguish between admins and owners

* Use new `RoomMember.Role` sealed interface through the app

* Change how `MembersByRole` groups members to add owners to the admins section

* Adapt the `ChangeRoles` screen to the new roles:
    - Owners can't modify other owner's roles.
    - They can modify the roles of any other user, without confirmation.

* Adapt 'roles and permissions' screen:
    - Owners can't demote themselves.
    - The admin count also counts owners.

* Add more tests and screenshots

* Add owners to its own section in the 'change roles' screen

* Update screenshots

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa 2025-07-29 16:07:16 +02:00 committed by GitHub
parent 4534229e84
commit 51f67741ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 663 additions and 301 deletions

View file

@ -22,14 +22,14 @@ fun RoomInfo.getAvatarData(size: AvatarSize) = AvatarData(
/**
* Returns the role of the user in the room.
* If the user is a creator, returns [RoomMember.Role.CREATOR].
* If the user is a creator, returns [RoomMember.Role.Owner].
* Otherwise, checks the power levels and returns the corresponding role.
* If no specific power level is set for the user, defaults to [RoomMember.Role.USER].
* If no specific power level is set for the user, defaults to [RoomMember.Role.User].
*/
fun RoomInfo.roleOf(userId: UserId): RoomMember.Role {
return if (creators.contains(userId)) {
RoomMember.Role.CREATOR
RoomMember.Role.Owner(isCreator = true)
} else {
roomPowerLevels?.roleOf(userId) ?: RoomMember.Role.USER
roomPowerLevels?.roleOf(userId) ?: RoomMember.Role.User
}
}

View file

@ -99,7 +99,7 @@ fun BaseRoom.canHandleKnockRequestsAsState(updateKey: Long): State<Boolean> {
fun BaseRoom.userPowerLevelAsState(updateKey: Long): State<Long> {
return produceState(initialValue = 0, key1 = updateKey) {
value = userRole(sessionId)
.getOrDefault(RoomMember.Role.USER)
.getOrDefault(RoomMember.Role.User)
.powerLevel
}
}
@ -108,7 +108,7 @@ fun BaseRoom.userPowerLevelAsState(updateKey: Long): State<Long> {
fun BaseRoom.isOwnUserAdmin(): Boolean {
val roomInfo by roomInfoFlow.collectAsState()
val role = roomInfo.roleOf(sessionId)
return role == RoomMember.Role.ADMIN || role == RoomMember.Role.CREATOR
return role == RoomMember.Role.Admin || role is RoomMember.Role.Owner
}
@Composable