Room admins can change user roles (#2423)
Allow Admins to modify room member roles: - Add a 'roles and permissions' option for each room. - Allow promoting users to admins, adding or removing moderators, and demote yourself if you're and admin. --------- Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
parent
1d892b4bc8
commit
b9d902e3fe
110 changed files with 2398 additions and 160 deletions
|
|
@ -51,6 +51,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
@Composable
|
||||
fun SelectedUser(
|
||||
matrixUser: MatrixUser,
|
||||
canRemove: Boolean,
|
||||
onUserRemoved: (MatrixUser) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -70,24 +71,26 @@ fun SelectedUser(
|
|||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
}
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.size(20.dp)
|
||||
.align(Alignment.TopEnd)
|
||||
.clickable(
|
||||
indication = rememberRipple(),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = { onUserRemoved(matrixUser) }
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Close(),
|
||||
contentDescription = stringResource(id = CommonStrings.action_remove),
|
||||
tint = MaterialTheme.colorScheme.onPrimary,
|
||||
modifier = Modifier.padding(2.dp)
|
||||
)
|
||||
if (canRemove) {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.size(20.dp)
|
||||
.align(Alignment.TopEnd)
|
||||
.clickable(
|
||||
indication = rememberRipple(),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = { onUserRemoved(matrixUser) }
|
||||
),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Close(),
|
||||
contentDescription = stringResource(id = CommonStrings.action_remove),
|
||||
tint = MaterialTheme.colorScheme.onPrimary,
|
||||
modifier = Modifier.padding(2.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,6 +100,17 @@ fun SelectedUser(
|
|||
internal fun SelectedUserPreview() = ElementPreview {
|
||||
SelectedUser(
|
||||
aMatrixUser(),
|
||||
canRemove = true,
|
||||
onUserRemoved = {},
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun SelectedUserCannotRemovePreview() = ElementPreview {
|
||||
SelectedUser(
|
||||
aMatrixUser(),
|
||||
canRemove = false,
|
||||
onUserRemoved = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,11 +46,12 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
import kotlin.math.floor
|
||||
|
||||
@Composable
|
||||
fun SelectedUsersList(
|
||||
fun SelectedUsersRowList(
|
||||
selectedUsers: ImmutableList<MatrixUser>,
|
||||
onUserRemoved: (MatrixUser) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
autoScroll: Boolean = false,
|
||||
canDeselect: (MatrixUser) -> Boolean = { true },
|
||||
contentPadding: PaddingValues = PaddingValues(0.dp),
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
|
@ -105,11 +106,12 @@ fun SelectedUsersList(
|
|||
.fillMaxWidth(),
|
||||
contentPadding = contentPadding,
|
||||
) {
|
||||
itemsIndexed(selectedUsers.toList()) { index, matrixUser ->
|
||||
itemsIndexed(selectedUsers.toList()) { index, selectedUser ->
|
||||
Layout(
|
||||
content = {
|
||||
SelectedUser(
|
||||
matrixUser = matrixUser,
|
||||
matrixUser = selectedUser,
|
||||
canRemove = canDeselect(selectedUser),
|
||||
onUserRemoved = onUserRemoved,
|
||||
)
|
||||
},
|
||||
|
|
@ -133,7 +135,7 @@ fun SelectedUsersList(
|
|||
internal fun SelectedUsersListPreview() = ElementPreview {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
// Two users that will be visible with no scrolling
|
||||
SelectedUsersList(
|
||||
SelectedUsersRowList(
|
||||
selectedUsers = aMatrixUserList().take(2).toImmutableList(),
|
||||
onUserRemoved = {},
|
||||
modifier = Modifier
|
||||
|
|
@ -143,7 +145,7 @@ internal fun SelectedUsersListPreview() = ElementPreview {
|
|||
|
||||
// Multiple users that don't fit, so will be spaced out per the measure policy
|
||||
for (i in 0..5) {
|
||||
SelectedUsersList(
|
||||
SelectedUsersRowList(
|
||||
selectedUsers = aMatrixUserList().take(6).toImmutableList(),
|
||||
onUserRemoved = {},
|
||||
modifier = Modifier
|
||||
|
|
@ -18,9 +18,12 @@ package io.element.android.libraries.matrix.ui.room
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.produceState
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canSendMessage
|
||||
|
|
@ -45,3 +48,10 @@ fun MatrixRoom.canRedactOtherAsState(updateKey: Long): State<Boolean> {
|
|||
value = canRedactOther().getOrElse { false }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MatrixRoom.isOwnUserAdmin(): Boolean {
|
||||
val roomInfo by roomInfoFlow.collectAsState(initial = null)
|
||||
val powerLevel = roomInfo?.userPowerLevels?.get(sessionId) ?: 0L
|
||||
return RoomMember.Role.forPowerLevel(powerLevel) == RoomMember.Role.ADMIN
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue