Move and refactor MatrixUser (#381)

Move and refactor MatrixUser

Instead of living in matrixui and having an AvatarData, this can
reside in the matrix module and just have the URL. An extension
method in matrixui can then provide the AvatarData when required.

This removes some small duplication, and pushes the UI-specific
information (i.e., what size of avatar is going to be rendered)
further down the stack. It also aligns the field names with those
used by the rust SDK (e.g. "displayName" instead of "userName").
This commit is contained in:
Chris Smith 2023-05-03 17:30:19 +01:00 committed by GitHub
parent 271c66588a
commit 581c5ab2d2
51 changed files with 125 additions and 215 deletions

View file

@ -1,53 +0,0 @@
/*
* 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.libraries.matrix.ui
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.MatrixClient
import io.element.android.libraries.matrix.ui.model.MatrixUser
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import javax.inject.Inject
class MatrixItemHelper @Inject constructor(
private val client: MatrixClient
) {
/**
* TODO Make username and avatar live...
*/
@OptIn(FlowPreview::class)
fun getCurrentUserData(avatarSize: AvatarSize): Flow<MatrixUser> {
return suspend {
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
val userDisplayName = client.loadUserDisplayName().getOrNull()
val avatarData =
AvatarData(
client.sessionId.value,
userDisplayName,
userAvatarUrl,
avatarSize
)
MatrixUser(
id = client.sessionId,
username = userDisplayName,
avatarData = avatarData,
)
}.asFlow()
}
}

View file

@ -30,14 +30,14 @@ 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
import io.element.android.libraries.matrix.api.user.MatrixUser
@Composable
fun CheckableMatrixUserRow(
checked: Boolean,
matrixUser: MatrixUser,
modifier: Modifier = Modifier,
avatarSize: AvatarSize = matrixUser.avatarData.size,
avatarSize: AvatarSize = AvatarSize.MEDIUM,
onCheckedChange: (Boolean) -> Unit = {},
enabled: Boolean = true,
) {

View file

@ -38,7 +38,8 @@ 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.Text
import io.element.android.libraries.matrix.ui.model.MatrixUser
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.matrix.ui.model.getBestName
@Composable
@ -56,7 +57,7 @@ fun MatrixUserHeader(
horizontalAlignment = Alignment.CenterHorizontally
) {
Avatar(
matrixUser.avatarData.copy(size = AvatarSize.HUGE),
matrixUser.getAvatarData(size = AvatarSize.HUGE),
)
Spacer(modifier = Modifier.height(16.dp))
// Name
@ -69,10 +70,10 @@ fun MatrixUserHeader(
color = MaterialTheme.colorScheme.primary,
)
// Id
if (matrixUser.username.isNullOrEmpty().not()) {
if (matrixUser.displayName.isNullOrEmpty().not()) {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = matrixUser.id.value,
text = matrixUser.userId.value,
color = MaterialTheme.colorScheme.secondary,
fontSize = 14.sp,
maxLines = 1,

View file

@ -17,25 +17,20 @@
package io.element.android.libraries.matrix.ui.components
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.avatar.anAvatarData
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.ui.model.MatrixUser
import io.element.android.libraries.matrix.api.user.MatrixUser
open class MatrixUserProvider : PreviewParameterProvider<MatrixUser> {
override val values: Sequence<MatrixUser>
get() = sequenceOf(
aMatrixUser(),
aMatrixUser().copy(
username = null,
avatarData = anAvatarData().copy(name = null)
),
aMatrixUser().copy(displayName = null),
)
}
fun aMatrixUser(id: String = "@id_of_alice:server.org", userName: String = "Alice") = MatrixUser(
id = UserId(id),
username = userName,
avatarData = anAvatarData(id, userName)
fun aMatrixUser(id: String = "@id_of_alice:server.org", displayName: String = "Alice") = MatrixUser(
userId = UserId(id),
displayName = displayName,
)
fun aMatrixUserList() = listOf(
@ -55,10 +50,7 @@ open class MatrixUserWithNullProvider : PreviewParameterProvider<MatrixUser?> {
override val values: Sequence<MatrixUser?>
get() = sequenceOf(
aMatrixUser(),
aMatrixUser().copy(
username = null,
avatarData = anAvatarData().copy(name = null)
),
aMatrixUser().copy(displayName = null),
null,
)
}

View file

@ -37,14 +37,15 @@ 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.Text
import io.element.android.libraries.matrix.ui.model.MatrixUser
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.matrix.ui.model.getBestName
@Composable
fun MatrixUserRow(
matrixUser: MatrixUser,
modifier: Modifier = Modifier,
avatarSize: AvatarSize = matrixUser.avatarData.size,
avatarSize: AvatarSize = AvatarSize.MEDIUM,
) {
Row(
modifier = modifier
@ -54,7 +55,7 @@ fun MatrixUserRow(
verticalAlignment = Alignment.CenterVertically
) {
Avatar(
matrixUser.avatarData.copy(size = avatarSize),
matrixUser.getAvatarData(size = avatarSize),
)
Column(
modifier = Modifier
@ -70,9 +71,9 @@ fun MatrixUserRow(
color = MaterialTheme.colorScheme.primary,
)
// Id
if (matrixUser.username.isNullOrEmpty().not()) {
if (matrixUser.displayName.isNullOrEmpty().not()) {
Text(
text = matrixUser.id.value,
text = matrixUser.userId.value,
color = MaterialTheme.colorScheme.secondary,
fontSize = 14.sp,
maxLines = 1,

View file

@ -16,20 +16,17 @@
package io.element.android.libraries.matrix.ui.model
import android.os.Parcelable
import androidx.compose.runtime.Immutable
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.parcelize.Parcelize
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.user.MatrixUser
@Parcelize
@Immutable
data class MatrixUser(
val id: UserId,
val username: String? = null,
val avatarData: AvatarData = AvatarData(id.value, username),
) : Parcelable
fun MatrixUser.getAvatarData(size: AvatarSize = AvatarSize.MEDIUM) = AvatarData(
id = userId.value,
name = displayName,
url = avatarUrl,
size = size,
)
fun MatrixUser.getBestName(): String {
return username?.takeIf { it.isNotEmpty() } ?: id.value
return displayName?.takeIf { it.isNotEmpty() } ?: userId.value
}