Design: iterate on Room List item

This commit is contained in:
Benoit Marty 2023-06-21 17:31:05 +02:00 committed by Benoit Marty
parent 23adc32cd2
commit 7d69e9a4dd
2 changed files with 102 additions and 88 deletions

View file

@ -24,8 +24,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
@ -37,7 +36,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
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.geometry.Rect import androidx.compose.ui.geometry.Rect
@ -70,7 +68,7 @@ import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate
import io.element.android.libraries.designsystem.theme.roomListRoomName import io.element.android.libraries.designsystem.theme.roomListRoomName
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
private val minHeight = 72.dp private val minHeight = 84.dp
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@ -81,40 +79,31 @@ internal fun RoomSummaryRow(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val clickModifier = if (room.isPlaceholder) { val clickModifier = if (room.isPlaceholder) {
modifier Modifier
} else { } else {
modifier.combinedClickable( Modifier.combinedClickable(
onClick = { onClick(room) }, onClick = { onClick(room) },
onLongClick = { onLongClick(room) }, onLongClick = { onLongClick(room) },
indication = rememberRipple(), indication = rememberRipple(),
interactionSource = remember { MutableInteractionSource() } interactionSource = remember { MutableInteractionSource() }
) )
} }
Box(
Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.heightIn(min = minHeight) .heightIn(min = minHeight)
.then(clickModifier) .then(clickModifier)
) {
DefaultRoomSummaryRow(room = room)
}
}
@Composable
internal fun DefaultRoomSummaryRow(
room: RoomListRoomSummary,
) {
Row(
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp, vertical = 11.dp)
.defaultMinSize(minHeight = 84.dp)
.height(IntrinsicSize.Min), .height(IntrinsicSize.Min),
verticalAlignment = CenterVertically
) { ) {
Avatar( Avatar(
room.avatarData, room
modifier = Modifier.placeholder( .avatarData,
modifier = Modifier
.align(Alignment.CenterVertically)
.placeholder(
visible = room.isPlaceholder, visible = room.isPlaceholder,
shape = CircleShape, shape = CircleShape,
color = ElementTheme.colors.roomListPlaceHolder(), color = ElementTheme.colors.roomListPlaceHolder(),
@ -122,47 +111,43 @@ internal fun DefaultRoomSummaryRow(
) )
Column( Column(
modifier = Modifier modifier = Modifier
.padding(start = 12.dp, end = 4.dp, top = 12.dp, bottom = 12.dp) .fillMaxWidth()
.alignByBaseline() .padding(start = 16.dp)
.weight(1f)
) { ) {
Row(modifier = Modifier.fillMaxWidth()) {
NameAndTimestampRow(room = room)
}
Row(modifier = Modifier.fillMaxWidth()) {
LastMessageAndIndicatorRow(room = room)
}
}
}
}
@Composable
private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
// Name // Name
Text( Text(
modifier = Modifier.placeholder( modifier = Modifier
.weight(1f)
.padding(end = 16.dp)
.placeholder(
visible = room.isPlaceholder, visible = room.isPlaceholder,
shape = TextPlaceholderShape, shape = TextPlaceholderShape,
color = ElementTheme.colors.roomListPlaceHolder(), color = ElementTheme.colors.roomListPlaceHolder(),
), ),
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
style = MaterialTheme.typography.bodyMedium,
text = room.name, text = room.name,
color = MaterialTheme.roomListRoomName(), color = MaterialTheme.roomListRoomName(),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
// Last Message // Timestamp
val attributedLastMessage = (room.lastMessage as? AnnotatedString)
?: AnnotatedString(room.lastMessage.orEmpty().toString())
Text( Text(
modifier = Modifier.placeholder(
visible = room.isPlaceholder,
shape = TextPlaceholderShape,
color = ElementTheme.colors.roomListPlaceHolder(),
),
text = attributedLastMessage,
color = MaterialTheme.roomListRoomMessage(),
fontSize = 14.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
// Timestamp and Unread
Column(
modifier = Modifier modifier = Modifier
.alignByBaseline(), .placeholder(
) {
Text(
modifier = Modifier.placeholder(
visible = room.isPlaceholder, visible = room.isPlaceholder,
shape = TextPlaceholderShape, shape = TextPlaceholderShape,
color = ElementTheme.colors.roomListPlaceHolder(), color = ElementTheme.colors.roomListPlaceHolder(),
@ -171,18 +156,39 @@ internal fun DefaultRoomSummaryRow(
text = room.timestamp ?: "", text = room.timestamp ?: "",
color = MaterialTheme.roomListRoomMessageDate(), color = MaterialTheme.roomListRoomMessageDate(),
) )
Spacer(Modifier.size(4.dp)) }
@Composable
private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
// Last Message
val attributedLastMessage = (room.lastMessage as? AnnotatedString)
?: AnnotatedString(room.lastMessage.orEmpty().toString())
Text(
modifier = Modifier
.weight(1f)
.padding(end = 28.dp)
.placeholder(
visible = room.isPlaceholder,
shape = TextPlaceholderShape,
color = ElementTheme.colors.roomListPlaceHolder(),
),
text = attributedLastMessage,
color = MaterialTheme.roomListRoomMessage(),
fontSize = 14.sp,
style = MaterialTheme.typography.bodySmall,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
// Unread
val unreadIndicatorColor = val unreadIndicatorColor =
if (room.hasUnread) MaterialTheme.roomListUnreadIndicator() else Color.Transparent if (room.hasUnread) MaterialTheme.roomListUnreadIndicator() else Color.Transparent
Box( Box(
modifier = Modifier modifier = Modifier
.padding(top = 3.dp)
.size(12.dp) .size(12.dp)
.clip(CircleShape) .clip(CircleShape)
.background(unreadIndicatorColor) .background(unreadIndicatorColor),
.align(Alignment.End),
) )
}
}
} }
val TextPlaceholderShape = PercentRectangleSizeShape(0.5f) val TextPlaceholderShape = PercentRectangleSizeShape(0.5f)

View file

@ -29,7 +29,15 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSu
aRoomListRoomSummary().copy(hasUnread = true), aRoomListRoomSummary().copy(hasUnread = true),
aRoomListRoomSummary().copy(timestamp = "88:88"), aRoomListRoomSummary().copy(timestamp = "88:88"),
aRoomListRoomSummary().copy(timestamp = "88:88", hasUnread = true), aRoomListRoomSummary().copy(timestamp = "88:88", hasUnread = true),
aRoomListRoomSummary().copy(isPlaceholder = true), aRoomListRoomSummary().copy(isPlaceholder = true, timestamp = "88:88"),
aRoomListRoomSummary().copy(
name = "A very long room name that should be truncated",
lastMessage = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
" ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" +
"modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
timestamp = "yesterday",
hasUnread = true,
),
) )
} }