From 47877c4076581c698cca3762c942c670af6b8719 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Dec 2022 15:55:47 +0100 Subject: [PATCH] Create a MatrixUserRow composable --- .../x/features/roomlist/RoomListScreen.kt | 5 +- .../x/features/roomlist/RoomListViewModel.kt | 3 +- .../designsystem/components/avatar/Avatar.kt | 7 ++ .../element/android/x/matrix/MatrixClient.kt | 7 +- .../x/matrix/ui/components/MatrixUserRow.kt | 101 ++++++++++++++++++ .../android/x/matrix/ui/model/MatrixUser.kt | 6 ++ 6 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/components/MatrixUserRow.kt diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt index f19a4d79d1..022479b7e2 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt @@ -48,6 +48,7 @@ import io.element.android.x.features.roomlist.model.RoomListRoomSummary import io.element.android.x.features.roomlist.model.RoomListViewState import io.element.android.x.features.roomlist.model.stubbedRoomSummaries import io.element.android.x.matrix.core.RoomId +import io.element.android.x.matrix.core.UserId import io.element.android.x.matrix.ui.model.MatrixUser import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -154,7 +155,7 @@ fun PreviewableRoomListContent() { ElementXTheme(darkTheme = false) { RoomListContent( roomSummaries = stubbedRoomSummaries(), - matrixUser = MatrixUser("User#1", avatarData = AvatarData("U")), + matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")), onRoomClicked = {}, filter = "filter", onFilterChanged = {}, @@ -169,7 +170,7 @@ fun PreviewableDarkRoomListContent() { ElementXTheme(darkTheme = true) { RoomListContent( roomSummaries = stubbedRoomSummaries(), - matrixUser = MatrixUser("User#1", avatarData = AvatarData("U")), + matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")), onRoomClicked = {}, filter = "filter", onFilterChanged = {}, diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt index 57a2942d75..72a3e25670 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt @@ -89,7 +89,8 @@ class RoomListViewModel @AssistedInject constructor( AvatarSize.SMALL ) MatrixUser( - username = userDisplayName ?: client.userId().value, + id = client.userId(), + username = userDisplayName, avatarUrl = userAvatarUrl, avatarData = avatarData, ) diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt index 692a67a082..e494849009 100644 --- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import io.element.android.x.designsystem.AvatarGradientEnd @@ -93,3 +94,9 @@ private fun InitialsAvatar( ) } } + +@Preview +@Composable +fun InitialsAvatar() { + InitialsAvatar("A") +} diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt index bda1814a14..55dd355678 100644 --- a/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt +++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt @@ -25,9 +25,6 @@ import io.element.android.x.matrix.room.RoomSummaryDataSource import io.element.android.x.matrix.room.RustRoomSummaryDataSource import io.element.android.x.matrix.session.SessionStore import io.element.android.x.matrix.sync.SlidingSyncObserverProxy -import java.io.Closeable -import java.io.File -import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client @@ -38,6 +35,9 @@ import org.matrix.rustcomponents.sdk.SlidingSyncMode import org.matrix.rustcomponents.sdk.SlidingSyncViewBuilder import org.matrix.rustcomponents.sdk.StoppableSpawn import timber.log.Timber +import java.io.Closeable +import java.io.File +import java.util.concurrent.atomic.AtomicBoolean class MatrixClient internal constructor( private val client: Client, @@ -157,6 +157,7 @@ class MatrixClient internal constructor( } fun userId(): UserId = UserId(client.userId()) + suspend fun loadUserDisplayName(): Result = withContext(dispatchers.io) { runCatching { client.displayName() diff --git a/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/components/MatrixUserRow.kt new file mode 100644 index 0000000000..6fbde8bd64 --- /dev/null +++ b/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/components/MatrixUserRow.kt @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 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.x.matrix.ui.components + +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 +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.unit.dp +import androidx.compose.ui.unit.sp +import io.element.android.x.designsystem.ElementXTheme +import io.element.android.x.designsystem.components.avatar.Avatar +import io.element.android.x.designsystem.components.avatar.AvatarData +import io.element.android.x.matrix.core.UserId +import io.element.android.x.matrix.ui.model.MatrixUser +import io.element.android.x.matrix.ui.model.getBestName + +@Composable +fun MatrixUserRow( + matrixUser: MatrixUser, + modifier: Modifier = Modifier, + onClick: () -> Unit = {}, +) { + Row( + modifier = modifier + .clickable(onClick = onClick) + .fillMaxWidth() + .padding(horizontal = 16.dp) + .height(IntrinsicSize.Min), + verticalAlignment = Alignment.CenterVertically + ) { + Avatar( + matrixUser.avatarData, + ) + Column( + modifier = Modifier + .padding(start = 12.dp, end = 4.dp, top = 12.dp, bottom = 12.dp) + .alignByBaseline() + .weight(1f) + ) { + // Name + Text( + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + text = matrixUser.getBestName(), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + // Id + if (matrixUser.username.isNullOrEmpty().not()) { + Text( + text = matrixUser.id.value, + color = MaterialTheme.colorScheme.secondary, + fontSize = 14.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } +} + +@Preview +@Composable +fun MatrixUserRowPreview() { + ElementXTheme { + MatrixUserRow( + MatrixUser( + id = UserId("@alice:server.org"), + username = "Alice", + avatarUrl = null, + avatarData = AvatarData("Alice") + ) + ) + } +} diff --git a/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/model/MatrixUser.kt b/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/model/MatrixUser.kt index 43dbada195..5aaa69e6e6 100644 --- a/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/model/MatrixUser.kt +++ b/libraries/matrixui/src/main/java/io/element/android/x/matrix/ui/model/MatrixUser.kt @@ -18,10 +18,16 @@ package io.element.android.x.matrix.ui.model import androidx.compose.runtime.Stable import io.element.android.x.designsystem.components.avatar.AvatarData +import io.element.android.x.matrix.core.UserId @Stable data class MatrixUser( + val id: UserId, val username: String? = null, val avatarUrl: String? = null, val avatarData: AvatarData = AvatarData(), ) + +fun MatrixUser.getBestName(): String { + return username?.takeIf { it.isNotEmpty() } ?: id.value +}