change(room permissions): fix some role&permissions inconsistencies after last changes
This commit is contained in:
parent
a0d6fddf73
commit
4c2aa0ba33
5 changed files with 47 additions and 29 deletions
|
|
@ -36,6 +36,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
|
||||||
import io.element.android.libraries.matrix.api.room.powerlevels.usersWithRole
|
import io.element.android.libraries.matrix.api.room.powerlevels.usersWithRole
|
||||||
import io.element.android.libraries.matrix.api.room.toMatrixUser
|
import io.element.android.libraries.matrix.api.room.toMatrixUser
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
import io.element.android.libraries.matrix.ui.model.powerLevelOf
|
||||||
import io.element.android.libraries.matrix.ui.model.roleOf
|
import io.element.android.libraries.matrix.ui.model.roleOf
|
||||||
import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator
|
import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
|
@ -124,9 +125,10 @@ class ChangeRolesPresenter(
|
||||||
|
|
||||||
val roomInfo by room.roomInfoFlow.collectAsState()
|
val roomInfo by room.roomInfoFlow.collectAsState()
|
||||||
fun canChangeMemberRole(userId: UserId): Boolean {
|
fun canChangeMemberRole(userId: UserId): Boolean {
|
||||||
val currentUserRole = roomInfo.roleOf(room.sessionId)
|
val currentUserPowerLevel = roomInfo.powerLevelOf(room.sessionId)
|
||||||
val otherUserRole = roomInfo.roleOf(userId)
|
val otherUserPowerLevel = roomInfo.powerLevelOf(userId)
|
||||||
return currentUserRole.powerLevel > otherUserRole.powerLevel
|
return currentUserPowerLevel > otherUserPowerLevel &&
|
||||||
|
currentUserPowerLevel >= role.powerLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleEvent(event: ChangeRolesEvent) {
|
fun handleEvent(event: ChangeRolesEvent) {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
|
||||||
import io.element.android.libraries.matrix.api.room.powerlevels.userCountWithRole
|
import io.element.android.libraries.matrix.api.room.powerlevels.userCountWithRole
|
||||||
import io.element.android.libraries.matrix.ui.model.roleOf
|
import io.element.android.libraries.matrix.ui.model.roleOf
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
@ -49,7 +50,16 @@ class RolesAndPermissionsPresenter(
|
||||||
room.userCountWithRole { role -> role is RoomMember.Role.Admin || role is RoomMember.Role.Owner }
|
room.userCountWithRole { role -> role is RoomMember.Role.Admin || role is RoomMember.Role.Owner }
|
||||||
}.collectAsState(null)
|
}.collectAsState(null)
|
||||||
|
|
||||||
val canDemoteSelf = remember { derivedStateOf { roomInfo.roleOf(room.sessionId) !is RoomMember.Role.Owner } }
|
val availableDemoteActions by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
val currentRole = roomInfo.roleOf(room.sessionId)
|
||||||
|
when (currentRole) {
|
||||||
|
is RoomMember.Role.Admin -> persistentListOf(DemoteActions.ToModerator, DemoteActions.ToMember)
|
||||||
|
is RoomMember.Role.Moderator -> persistentListOf(DemoteActions.ToMember)
|
||||||
|
else -> persistentListOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
val changeOwnRoleAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
val changeOwnRoleAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||||
val resetPermissionsAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
val resetPermissionsAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||||
|
|
||||||
|
|
@ -78,7 +88,7 @@ class RolesAndPermissionsPresenter(
|
||||||
roomSupportsOwnerRole = roomInfo.privilegedCreatorRole,
|
roomSupportsOwnerRole = roomInfo.privilegedCreatorRole,
|
||||||
adminCount = adminCount,
|
adminCount = adminCount,
|
||||||
moderatorCount = moderatorCount,
|
moderatorCount = moderatorCount,
|
||||||
canDemoteSelf = canDemoteSelf.value,
|
availableDemoteActions = availableDemoteActions,
|
||||||
changeOwnRoleAction = changeOwnRoleAction.value,
|
changeOwnRoleAction = changeOwnRoleAction.value,
|
||||||
resetPermissionsAction = resetPermissionsAction.value,
|
resetPermissionsAction = resetPermissionsAction.value,
|
||||||
eventSink = ::handleEvent,
|
eventSink = ::handleEvent,
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,24 @@
|
||||||
|
|
||||||
package io.element.android.features.rolesandpermissions.impl.root
|
package io.element.android.features.rolesandpermissions.impl.root
|
||||||
|
|
||||||
|
import io.element.android.features.rolesandpermissions.impl.R
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
data class RolesAndPermissionsState(
|
data class RolesAndPermissionsState(
|
||||||
val roomSupportsOwnerRole: Boolean,
|
val roomSupportsOwnerRole: Boolean,
|
||||||
val adminCount: Int?,
|
val adminCount: Int?,
|
||||||
val moderatorCount: Int?,
|
val moderatorCount: Int?,
|
||||||
val canDemoteSelf: Boolean,
|
val availableDemoteActions: ImmutableList<DemoteActions>,
|
||||||
val changeOwnRoleAction: AsyncAction<Unit>,
|
val changeOwnRoleAction: AsyncAction<Unit>,
|
||||||
val resetPermissionsAction: AsyncAction<Unit>,
|
val resetPermissionsAction: AsyncAction<Unit>,
|
||||||
val eventSink: (RolesAndPermissionsEvents) -> Unit,
|
val eventSink: (RolesAndPermissionsEvents) -> Unit,
|
||||||
)
|
) {
|
||||||
|
val canDemoteSelf = availableDemoteActions.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class DemoteActions(val role: RoomMember.Role, val titleRes: Int) {
|
||||||
|
ToModerator(RoomMember.Role.Moderator, R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator),
|
||||||
|
ToMember(RoomMember.Role.User, R.string.screen_room_roles_and_permissions_change_role_demote_to_member)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ package io.element.android.features.rolesandpermissions.impl.root
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
class RolesAndPermissionsStateProvider : PreviewParameterProvider<RolesAndPermissionsState> {
|
class RolesAndPermissionsStateProvider : PreviewParameterProvider<RolesAndPermissionsState> {
|
||||||
override val values: Sequence<RolesAndPermissionsState>
|
override val values: Sequence<RolesAndPermissionsState>
|
||||||
|
|
@ -46,7 +47,7 @@ class RolesAndPermissionsStateProvider : PreviewParameterProvider<RolesAndPermis
|
||||||
moderatorCount = 2,
|
moderatorCount = 2,
|
||||||
resetPermissionsAction = AsyncAction.Failure(IllegalStateException("Failed to reset permissions")),
|
resetPermissionsAction = AsyncAction.Failure(IllegalStateException("Failed to reset permissions")),
|
||||||
),
|
),
|
||||||
aRolesAndPermissionsState(canDemoteSelf = false),
|
aRolesAndPermissionsState(availableDemoteActions = emptyList()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,14 +55,14 @@ internal fun aRolesAndPermissionsState(
|
||||||
roomSupportsOwners: Boolean = true,
|
roomSupportsOwners: Boolean = true,
|
||||||
adminCount: Int = 0,
|
adminCount: Int = 0,
|
||||||
moderatorCount: Int = 0,
|
moderatorCount: Int = 0,
|
||||||
canDemoteSelf: Boolean = true,
|
availableDemoteActions: List<DemoteActions> = listOf(DemoteActions.ToModerator, DemoteActions.ToMember),
|
||||||
changeOwnRoleAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
changeOwnRoleAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
resetPermissionsAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
resetPermissionsAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
eventSink: (RolesAndPermissionsEvents) -> Unit = {},
|
eventSink: (RolesAndPermissionsEvents) -> Unit = {},
|
||||||
) = RolesAndPermissionsState(
|
) = RolesAndPermissionsState(
|
||||||
roomSupportsOwnerRole = roomSupportsOwners,
|
roomSupportsOwnerRole = roomSupportsOwners,
|
||||||
adminCount = adminCount,
|
adminCount = adminCount,
|
||||||
canDemoteSelf = canDemoteSelf,
|
availableDemoteActions = availableDemoteActions.toImmutableList(),
|
||||||
moderatorCount = moderatorCount,
|
moderatorCount = moderatorCount,
|
||||||
changeOwnRoleAction = changeOwnRoleAction,
|
changeOwnRoleAction = changeOwnRoleAction,
|
||||||
resetPermissionsAction = resetPermissionsAction,
|
resetPermissionsAction = resetPermissionsAction,
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ import io.element.android.libraries.designsystem.theme.components.ListSectionHea
|
||||||
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
|
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.designsystem.theme.components.hide
|
import io.element.android.libraries.designsystem.theme.components.hide
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RolesAndPermissionsView(
|
fun RolesAndPermissionsView(
|
||||||
|
|
@ -117,6 +117,7 @@ fun RolesAndPermissionsView(
|
||||||
when (state.changeOwnRoleAction) {
|
when (state.changeOwnRoleAction) {
|
||||||
is AsyncAction.Confirming -> {
|
is AsyncAction.Confirming -> {
|
||||||
ChangeOwnRoleBottomSheet(
|
ChangeOwnRoleBottomSheet(
|
||||||
|
availableDemoteActions = state.availableDemoteActions,
|
||||||
eventSink = state.eventSink,
|
eventSink = state.eventSink,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +137,7 @@ fun RolesAndPermissionsView(
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ChangeOwnRoleBottomSheet(
|
private fun ChangeOwnRoleBottomSheet(
|
||||||
|
availableDemoteActions: ImmutableList<DemoteActions>,
|
||||||
eventSink: (RolesAndPermissionsEvents) -> Unit,
|
eventSink: (RolesAndPermissionsEvents) -> Unit,
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
@ -164,24 +166,17 @@ private fun ChangeOwnRoleBottomSheet(
|
||||||
style = ElementTheme.typography.fontBodyLgRegular,
|
style = ElementTheme.typography.fontBodyLgRegular,
|
||||||
color = ElementTheme.colors.textPrimary,
|
color = ElementTheme.colors.textPrimary,
|
||||||
)
|
)
|
||||||
ListItem(
|
for (demoteAction in availableDemoteActions) {
|
||||||
headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator)) },
|
ListItem(
|
||||||
onClick = {
|
headlineContent = { Text(stringResource(demoteAction.titleRes)) },
|
||||||
sheetState.hide(coroutineScope) {
|
onClick = {
|
||||||
eventSink(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.Moderator))
|
sheetState.hide(coroutineScope) {
|
||||||
}
|
eventSink(RolesAndPermissionsEvents.DemoteSelfTo(demoteAction.role))
|
||||||
},
|
}
|
||||||
style = ListItemStyle.Destructive,
|
},
|
||||||
)
|
style = ListItemStyle.Destructive,
|
||||||
ListItem(
|
)
|
||||||
headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_role_demote_to_member)) },
|
}
|
||||||
onClick = {
|
|
||||||
sheetState.hide(coroutineScope) {
|
|
||||||
eventSink(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.User))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style = ListItemStyle.Destructive,
|
|
||||||
)
|
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = { Text(stringResource(CommonStrings.action_cancel)) },
|
headlineContent = { Text(stringResource(CommonStrings.action_cancel)) },
|
||||||
onClick = ::dismiss,
|
onClick = ::dismiss,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue