[UI] Iterate on selected user rendering.

This commit is contained in:
Benoit Marty 2025-08-18 14:29:43 +02:00 committed by Benoit Marty
parent fcb63c02e1
commit d7d2fe3ffb
2 changed files with 55 additions and 3 deletions

View file

@ -24,7 +24,7 @@ enum class AvatarSize(val dp: Dp) {
UserHeader(96.dp), UserHeader(96.dp),
UserListItem(36.dp), UserListItem(36.dp),
SelectedUser(56.dp), SelectedUser(52.dp),
SelectedRoom(56.dp), SelectedRoom(56.dp),
DmCluster(75.dp), DmCluster(75.dp),

View file

@ -15,19 +15,29 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ripple import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment 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.draw.clip
import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.compound.tokens.generated.CompoundIcons
@ -36,6 +46,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toPx
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -73,22 +84,49 @@ fun SelectedUser(
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val closeRadius = 12.dp.toPx()
val closeOffset = 10.dp.toPx()
Avatar( Avatar(
avatarData = matrixUser.getAvatarData(size = AvatarSize.SelectedUser), avatarData = matrixUser.getAvatarData(size = AvatarSize.SelectedUser),
avatarType = AvatarType.User, avatarType = AvatarType.User,
modifier = Modifier
.graphicsLayer {
compositingStrategy = CompositingStrategy.Offscreen
}
.drawWithContent {
drawContent()
if (canRemove) {
val xOffset = if (isRtl) {
closeOffset
} else {
size.width - closeOffset
}
drawCircle(
color = Color.Black,
center = Offset(
x = xOffset,
y = closeOffset,
),
radius = closeRadius,
blendMode = BlendMode.Clear,
)
}
}
) )
Text( Text(
modifier = Modifier.clipToBounds(), modifier = Modifier.clipToBounds(),
text = matrixUser.getBestName(), text = matrixUser.getBestName(),
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 2, maxLines = 2,
style = ElementTheme.typography.fontBodyMdRegular, style = MaterialTheme.typography.bodyMedium,
color = ElementTheme.colors.textSecondary,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
} }
if (canRemove) { if (canRemove) {
Surface( Surface(
color = ElementTheme.colors.textPrimary, color = ElementTheme.colors.bgActionPrimaryRest,
modifier = Modifier modifier = Modifier
.clip(CircleShape) .clip(CircleShape)
.size(20.dp) .size(20.dp)
@ -121,6 +159,20 @@ internal fun SelectedUserPreview() = ElementPreview {
) )
} }
@PreviewsDayNight
@Composable
internal fun SelectedUserRtlPreview() = CompositionLocalProvider(
LocalLayoutDirection provides LayoutDirection.Rtl,
) {
ElementPreview {
SelectedUser(
aMatrixUser(displayName = "John Doe"),
canRemove = true,
onUserRemove = {},
)
}
}
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun SelectedUserCannotRemovePreview() = ElementPreview { internal fun SelectedUserCannotRemovePreview() = ElementPreview {