Space avatar rounded corner has radius of 25% of the width.

This commit is contained in:
Benoit Marty 2025-06-24 11:00:53 +02:00
parent 6e7696a2fe
commit 475b8543de
6 changed files with 27 additions and 26 deletions

View file

@ -11,12 +11,22 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
@Composable @Composable
fun AvatarType.avatarShape(): Shape { fun AvatarType.User.avatarShape() = CircleShape
@Composable
fun AvatarType.Room.avatarShape() = CircleShape
@Composable
fun AvatarType.Space.avatarShape(avatarSize: Dp) = RoundedCornerShape(avatarSize * 0.25f)
@Composable
fun AvatarType.avatarShape(avatarSize: Dp): Shape {
return when (this) { return when (this) {
is AvatarType.Space -> RoundedCornerShape(cornerSize) is AvatarType.Space -> avatarShape(avatarSize)
is AvatarType.Room, is AvatarType.Room -> avatarShape()
AvatarType.User -> CircleShape is AvatarType.User -> avatarShape()
} }
} }

View file

@ -8,7 +8,6 @@
package io.element.android.libraries.designsystem.components.avatar package io.element.android.libraries.designsystem.components.avatar
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.ui.unit.Dp
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -22,7 +21,6 @@ sealed interface AvatarType {
) : AvatarType ) : AvatarType
data class Space( data class Space(
val cornerSize: Dp,
val isTombstoned: Boolean = false, val isTombstoned: Boolean = false,
) : AvatarType ) : AvatarType
} }

View file

@ -57,7 +57,7 @@ internal fun AvatarCluster(
InitialOrImageAvatar( InitialOrImageAvatar(
avatarData = limitedAvatars[0], avatarData = limitedAvatars[0],
hideAvatarImage = hideAvatarImages, hideAvatarImage = hideAvatarImages,
avatarShape = avatarType.avatarShape(), avatarShape = avatarType.avatarShape(limitedAvatars[0].size.dp),
forcedAvatarSize = null, forcedAvatarSize = null,
modifier = modifier, modifier = modifier,
contentDescription = contentDescription, contentDescription = contentDescription,
@ -106,14 +106,7 @@ internal fun AvatarCluster(
InitialOrImageAvatar( InitialOrImageAvatar(
avatarData = heroAvatar, avatarData = heroAvatar,
hideAvatarImage = hideAvatarImages, hideAvatarImage = hideAvatarImages,
avatarShape = avatarType.let { avatarType -> avatarShape = avatarType.avatarShape(heroAvatarSize),
if (avatarType is AvatarType.Space) {
// Reduce corner size for small Space avatars
avatarType.copy(cornerSize = avatarType.cornerSize / 2f)
} else {
avatarType
}
}.avatarShape(),
forcedAvatarSize = heroAvatarSize, forcedAvatarSize = heroAvatarSize,
modifier = Modifier, modifier = Modifier,
contentDescription = contentDescription, contentDescription = contentDescription,
@ -134,7 +127,7 @@ internal fun AvatarClusterPreview() = ElementThemedPreview {
listOf( listOf(
AvatarType.User, AvatarType.User,
AvatarType.Room(), AvatarType.Room(),
AvatarType.Space(8.dp), AvatarType.Space(),
).forEach { avatarType -> ).forEach { avatarType ->
Row( Row(
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)

View file

@ -32,17 +32,18 @@ internal fun SpaceAvatar(
hideAvatarImage: Boolean = false, hideAvatarImage: Boolean = false,
contentDescription: String? = null, contentDescription: String? = null,
) { ) {
val size = forcedAvatarSize ?: avatarData.size.dp
when { when {
avatarType.isTombstoned -> TombstonedRoomAvatar( avatarType.isTombstoned -> TombstonedRoomAvatar(
size = forcedAvatarSize ?: avatarData.size.dp, size = size,
avatarShape = avatarType.avatarShape(), avatarShape = avatarType.avatarShape(size),
modifier = modifier, modifier = modifier,
contentDescription = contentDescription, contentDescription = contentDescription,
) )
else -> InitialOrImageAvatar( else -> InitialOrImageAvatar(
avatarData = avatarData, avatarData = avatarData,
hideAvatarImage = hideAvatarImage, hideAvatarImage = hideAvatarImage,
avatarShape = avatarType.avatarShape(), avatarShape = avatarType.avatarShape(size),
forcedAvatarSize = forcedAvatarSize, forcedAvatarSize = forcedAvatarSize,
modifier = modifier, modifier = modifier,
contentDescription = contentDescription, contentDescription = contentDescription,
@ -62,12 +63,11 @@ internal fun SpaceAvatarPreview() =
) { ) {
SpaceAvatar( SpaceAvatar(
avatarData = anAvatarData(), avatarData = anAvatarData(),
avatarType = AvatarType.Space(cornerSize = 16.dp), avatarType = AvatarType.Space(),
) )
SpaceAvatar( SpaceAvatar(
avatarData = anAvatarData(), avatarData = anAvatarData(),
avatarType = AvatarType.Space( avatarType = AvatarType.Space(
cornerSize = 16.dp,
isTombstoned = true, isTombstoned = true,
), ),
) )

View file

@ -77,7 +77,7 @@ internal fun TextAvatarPreview() = ElementPreview {
listOf( listOf(
AvatarType.User, AvatarType.User,
AvatarType.Room(), AvatarType.Room(),
AvatarType.Space(8.dp), AvatarType.Space(),
).forEach { avatarType -> ).forEach { avatarType ->
TextAvatar( TextAvatar(
text = "AB", text = "AB",
@ -86,7 +86,7 @@ internal fun TextAvatarPreview() = ElementPreview {
background = ElementTheme.colors.bgSubtlePrimary, background = ElementTheme.colors.bgSubtlePrimary,
foreground = ElementTheme.colors.iconPrimary, foreground = ElementTheme.colors.iconPrimary,
), ),
avatarShape = avatarType.avatarShape(), avatarShape = avatarType.avatarShape(40.dp),
contentDescription = null, contentDescription = null,
) )
} }

View file

@ -50,7 +50,7 @@ fun UnsavedAvatar(
) { ) {
val commonModifier = modifier val commonModifier = modifier
.size(avatarSize.dp) .size(avatarSize.dp)
.clip(avatarType.avatarShape()) .clip(avatarType.avatarShape(avatarSize.dp))
if (avatarUri != null) { if (avatarUri != null) {
val context = LocalContext.current val context = LocalContext.current
@ -87,7 +87,7 @@ internal fun UnsavedAvatarPreview() = ElementPreview {
) { ) {
UnsavedAvatar(null, AvatarSize.EditRoomDetails, AvatarType.User) UnsavedAvatar(null, AvatarSize.EditRoomDetails, AvatarType.User)
UnsavedAvatar(Uri.EMPTY, AvatarSize.EditRoomDetails, AvatarType.User) UnsavedAvatar(Uri.EMPTY, AvatarSize.EditRoomDetails, AvatarType.User)
UnsavedAvatar(null, AvatarSize.EditRoomDetails, AvatarType.Space(8.dp)) UnsavedAvatar(null, AvatarSize.EditRoomDetails, AvatarType.Space())
UnsavedAvatar(Uri.EMPTY, AvatarSize.EditRoomDetails, AvatarType.Space(8.dp)) UnsavedAvatar(Uri.EMPTY, AvatarSize.EditRoomDetails, AvatarType.Space())
} }
} }