Adding a view to list the selected users

This commit is contained in:
Maxime NATUREL
2023-03-13 16:17:55 +01:00
committed by Florian Renaud
parent 787a5bc1cb
commit ab538c46be
3 changed files with 97 additions and 5 deletions
@@ -16,7 +16,9 @@
package io.element.android.features.createroom.impl.selectmembers package io.element.android.features.createroom.impl.selectmembers
import io.element.android.libraries.matrix.ui.model.MatrixUser
data class SelectMembersState( data class SelectMembersState(
val selectedUserIds: List<String> = emptyList(), val selectedUsers: List<MatrixUser> = emptyList(),
val eventSink: (SelectMembersEvents) -> Unit, val eventSink: (SelectMembersEvents) -> Unit,
) )
@@ -17,15 +17,28 @@
package io.element.android.features.createroom.impl.selectmembers package io.element.android.features.createroom.impl.selectmembers
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.ui.model.MatrixUser
open class SelectMembersStateProvider : PreviewParameterProvider<SelectMembersState> { open class SelectMembersStateProvider : PreviewParameterProvider<SelectMembersState> {
override val values: Sequence<SelectMembersState> override val values: Sequence<SelectMembersState>
get() = sequenceOf( get() = sequenceOf(
aSelectMembersState(), aSelectMembersState(),
aSelectMembersState().copy(selectedUserIds = listOf("someUserId")) aSelectMembersState().copy(
selectedUsers = listOf(
aMatrixUser(userName = "User"),
aMatrixUser(userName = "User with long name"),
)
)
) )
} }
fun aSelectMembersState() = SelectMembersState( fun aSelectMembersState() = SelectMembersState(
eventSink = {} eventSink = {}
) )
fun aMatrixUser(userName: String): MatrixUser {
return MatrixUser(id = UserId("@id"), username = userName, avatarData = AvatarData("@id", "U", size = AvatarSize.BIG))
}
@@ -16,25 +16,43 @@
package io.element.android.features.createroom.impl.selectmembers package io.element.android.features.createroom.impl.selectmembers
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
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.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.matrix.ui.model.MatrixUser
import io.element.android.libraries.ui.strings.R as StringR import io.element.android.libraries.ui.strings.R as StringR
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -50,18 +68,23 @@ fun SelectMembersView(
Scaffold( Scaffold(
topBar = { topBar = {
SelectMembersViewTopBar( SelectMembersViewTopBar(
hasSelectedUsers = state.selectedUserIds.isNotEmpty(), hasSelectedUsers = state.selectedUsers.isNotEmpty(),
onBackPressed = onBackPressed, onBackPressed = onBackPressed,
onNextPressed = onNextPressed, onNextPressed = onNextPressed,
) )
} }
) { padding -> ) { padding ->
Box( Column(
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
.padding(padding) .padding(padding)
) { ) {
SelectedMembersList(
modifier = Modifier.padding(horizontal = 16.dp),
selectedUsers = state.selectedUsers,
)
// TODO create ViewEvent to add/remove selected user
// TODO create a SearchUserView with multi selection option + callbacks
} }
} }
} }
@@ -99,6 +122,60 @@ fun SelectMembersViewTopBar(
) )
} }
@Composable
fun SelectedMembersList(
selectedUsers: List<MatrixUser>,
modifier: Modifier = Modifier,
onUserRemoved: (MatrixUser) -> Unit = {},
) {
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(24.dp),
) {
items(selectedUsers) { matrixUser ->
SelectedMember(
matrixUser = matrixUser,
onUserRemoved = onUserRemoved,
)
}
}
}
@Composable
fun SelectedMember(
matrixUser: MatrixUser,
modifier: Modifier = Modifier,
onUserRemoved: (MatrixUser) -> Unit,
) {
Box(modifier = modifier.width(56.dp)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Avatar(matrixUser.avatarData)
Text(
text = matrixUser.username.orEmpty(),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.bodyLarge,
)
}
IconButton(
modifier = Modifier
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary)
.size(20.dp)
.align(Alignment.TopEnd),
onClick = { onUserRemoved(matrixUser) }
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(id = StringR.string.action_remove),
tint = MaterialTheme.colorScheme.onPrimary,
)
}
}
}
@Preview @Preview
@Composable @Composable
internal fun ChangeServerViewLightPreview(@PreviewParameter(SelectMembersStateProvider::class) state: SelectMembersState) = internal fun ChangeServerViewLightPreview(@PreviewParameter(SelectMembersStateProvider::class) state: SelectMembersState) =