diff --git a/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersStateProvider.kt b/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersStateProvider.kt index c8e7d9e6e5..59405004fe 100644 --- a/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersStateProvider.kt +++ b/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersStateProvider.kt @@ -61,12 +61,12 @@ fun aSelectUsersState() = SelectUsersState( fun aSetOfSelectedUsers() = persistentSetOf( MatrixUser(id = UserId("@someone:matrix.org")), - MatrixUser(id = UserId("@someone:matrix.org"), username = "someone"), + MatrixUser(id = UserId("@other:matrix.org"), username = "other"), ) fun aListOfResults() = persistentListOf( MatrixUser(id = UserId("@someone:matrix.org")), - MatrixUser(id = UserId("@someone:matrix.org"), username = "someone"), + MatrixUser(id = UserId("@other:matrix.org"), username = "other"), MatrixUser( id = UserId("@someone_with_a_very_long_matrix_identifier:a_very_long_domain.org"), username = "hey, I am someone with a very long display name" diff --git a/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersView.kt b/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersView.kt index 0c29e35f15..8d2c3ae71d 100644 --- a/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersView.kt +++ b/features/selectusers/api/src/main/kotlin/io/element/android/features/selectusers/api/SelectUsersView.kt @@ -55,6 +55,7 @@ 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.SearchBar import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.ui.components.CheckableMatrixUserRow import io.element.android.libraries.matrix.ui.components.MatrixUserRow import io.element.android.libraries.matrix.ui.model.MatrixUser import io.element.android.libraries.matrix.ui.model.getBestName @@ -177,11 +178,29 @@ fun SearchUserBar( } LazyColumn { - items(results) { - SearchUserResultItem( - matrixUser = it, - onClick = { onUserSelected(it) } - ) + if (isMultiSelectionEnabled) { + items(results) { matrixUser -> + SearchMultipleUsersResultItem( + modifier = Modifier.fillMaxWidth(), + matrixUser = matrixUser, + isUserSelected = selectedUsers.find { it.id == matrixUser.id } != null, + onCheckedChange = { checked -> + if (checked) { + onUserSelected(matrixUser) + } else { + onUserDeselected(matrixUser) + } + } + ) + } + } else { + items(results) { matrixUser -> + SearchSingleUserResultItem( + modifier = Modifier.fillMaxWidth(), + matrixUser = matrixUser, + onClick = { onUserSelected(matrixUser) } + ) + } } } }, @@ -189,7 +208,23 @@ fun SearchUserBar( } @Composable -fun SearchUserResultItem( +fun SearchMultipleUsersResultItem( + matrixUser: MatrixUser, + isUserSelected: Boolean, + modifier: Modifier = Modifier, + onCheckedChange: (Boolean) -> Unit, +) { + CheckableMatrixUserRow( + checked = isUserSelected, + modifier = modifier, + matrixUser = matrixUser, + avatarSize = AvatarSize.Custom(36.dp), + onCheckedChange = onCheckedChange, + ) +} + +@Composable +fun SearchSingleUserResultItem( matrixUser: MatrixUser, modifier: Modifier = Modifier, onClick: () -> Unit = {}, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt new file mode 100644 index 0000000000..67969f8e2e --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.Checkbox +import io.element.android.libraries.matrix.ui.model.MatrixUser + +@Composable +fun CheckableMatrixUserRow( + checked: Boolean, + matrixUser: MatrixUser, + modifier: Modifier = Modifier, + avatarSize: AvatarSize = matrixUser.avatarData.size, + onCheckedChange: (Boolean) -> Unit = {}, + enabled: Boolean = true, +) { + + Row( + modifier = modifier + .fillMaxWidth() + .clickable { + onCheckedChange(!checked) + }, + verticalAlignment = Alignment.CenterVertically, + ) { + MatrixUserRow( + modifier = Modifier.weight(1f), + matrixUser = matrixUser, + avatarSize = avatarSize, + isClickEnabled = false, + ) + + Checkbox( + checked = checked, + onCheckedChange = onCheckedChange, + enabled = enabled, + ) + } +} + +@Preview +@Composable +internal fun CheckableMatrixUserRowLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = + ElementPreviewLight { ContentToPreview(matrixUser) } + +@Preview +@Composable +internal fun CheckableMatrixUserRowDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = + ElementPreviewDark { ContentToPreview(matrixUser) } + +@Composable +private fun ContentToPreview(matrixUser: MatrixUser) { + Column { + CheckableMatrixUserRow(checked = true, matrixUser) + CheckableMatrixUserRow(checked = false, matrixUser) + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt index 035f2d3824..768c803850 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt @@ -20,7 +20,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme @@ -46,12 +45,12 @@ fun MatrixUserRow( matrixUser: MatrixUser, modifier: Modifier = Modifier, avatarSize: AvatarSize = matrixUser.avatarData.size, + isClickEnabled: Boolean = true, onClick: () -> Unit = {}, ) { Row( modifier = modifier - .clickable(onClick = onClick) - .fillMaxWidth() + .let { if (isClickEnabled) it.clickable(onClick = onClick) else it } .padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 8.dp) .height(IntrinsicSize.Min), verticalAlignment = Alignment.CenterVertically