Invite list: various layout tweaks
- Larger avatar - Include the MXID in the inviter - Show inviter avatar to the left instead of inline (This may be weird in some translations, but it's what design wants and is consistent with iOS) - Pad the name/alias if the notification dot is present
This commit is contained in:
parent
30e4fad93c
commit
b1824c04e5
3 changed files with 46 additions and 56 deletions
|
|
@ -17,13 +17,13 @@
|
||||||
package io.element.android.features.invitelist.impl.components
|
package io.element.android.features.invitelist.impl.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
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.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
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
|
||||||
|
|
@ -31,18 +31,13 @@ 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.foundation.text.InlineTextContent
|
|
||||||
import androidx.compose.foundation.text.appendInlineContent
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.Placeholder
|
|
||||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
|
@ -64,8 +59,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
import io.element.android.libraries.designsystem.theme.noFontPadding
|
||||||
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
|
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
|
||||||
import io.element.android.libraries.ui.strings.R as StringR
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
private val minHeight = 72.dp
|
private val minHeight = 72.dp
|
||||||
|
|
@ -104,15 +99,17 @@ internal fun DefaultInviteSummaryRow(
|
||||||
verticalAlignment = Alignment.Top
|
verticalAlignment = Alignment.Top
|
||||||
) {
|
) {
|
||||||
Avatar(
|
Avatar(
|
||||||
invite.roomAvatarData,
|
invite.roomAvatarData.copy(size = AvatarSize.Custom(52.dp)),
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 4.dp)
|
.padding(start = 16.dp, end = 4.dp)
|
||||||
.alignByBaseline()
|
.alignByBaseline()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
) {
|
) {
|
||||||
|
val bonusPadding = if (invite.isNew) 12.dp else 0.dp
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
Text(
|
Text(
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
|
|
@ -120,7 +117,9 @@ internal fun DefaultInviteSummaryRow(
|
||||||
text = invite.roomName,
|
text = invite.roomName,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
style = noFontPadding,
|
||||||
|
modifier = Modifier.padding(end = bonusPadding),
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID or Alias
|
// ID or Alias
|
||||||
|
|
@ -131,7 +130,8 @@ internal fun DefaultInviteSummaryRow(
|
||||||
text = it,
|
text = it,
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.padding(end = bonusPadding),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,47 +173,36 @@ internal fun DefaultInviteSummaryRow(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SenderRow(sender: InviteSender) {
|
private fun SenderRow(sender: InviteSender) {
|
||||||
Text(
|
Row(
|
||||||
text = buildAnnotatedString {
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
val placeholder = "$"
|
|
||||||
val text = stringResource(R.string.screen_invites_invited_you, placeholder)
|
|
||||||
val nameIndex = text.indexOf(placeholder)
|
|
||||||
|
|
||||||
// Text before the placeholder
|
|
||||||
append(text.take(nameIndex))
|
|
||||||
|
|
||||||
// Avatar and display name
|
|
||||||
appendInlineContent("avatar")
|
|
||||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)) {
|
|
||||||
append(sender.displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text after the placeholder
|
|
||||||
append(text.drop(nameIndex + placeholder.length))
|
|
||||||
},
|
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
|
||||||
fontSize = 14.sp,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
modifier = Modifier.padding(top = 12.dp),
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
inlineContent = persistentMapOf(
|
) {
|
||||||
"avatar" to InlineTextContent(
|
Avatar(
|
||||||
with(LocalDensity.current) {
|
avatarData = sender.avatarData.copy(size = AvatarSize.Custom(16.dp)),
|
||||||
Placeholder(20.dp.toSp(), 20.dp.toSp(), PlaceholderVerticalAlign.Center)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.fillMaxHeight()
|
|
||||||
.padding(end = 4.dp)
|
|
||||||
) {
|
|
||||||
Avatar(
|
|
||||||
avatarData = sender.avatarData.copy(size = AvatarSize.Custom(16.dp)),
|
|
||||||
modifier = Modifier.align(Alignment.Center)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
Text(
|
||||||
|
text = buildAnnotatedString {
|
||||||
|
val placeholder = "$"
|
||||||
|
val text = stringResource(R.string.screen_invites_invited_you, placeholder, sender.userId.value)
|
||||||
|
val nameIndex = text.indexOf(placeholder)
|
||||||
|
|
||||||
|
// Text before the placeholder
|
||||||
|
append(text.take(nameIndex))
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
withStyle(SpanStyle(fontWeight = FontWeight.Medium, color = MaterialTheme.colorScheme.primary)) {
|
||||||
|
append(sender.displayName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text after the placeholder
|
||||||
|
append(text.drop(nameIndex + placeholder.length))
|
||||||
|
},
|
||||||
|
style = noFontPadding,
|
||||||
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ open class InviteListInviteSummaryProvider : PreviewParameterProvider<InviteList
|
||||||
override val values: Sequence<InviteListInviteSummary>
|
override val values: Sequence<InviteListInviteSummary>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
aInviteListInviteSummary(),
|
aInviteListInviteSummary(),
|
||||||
aInviteListInviteSummary().copy(roomAlias = "#someroom:example.com"),
|
aInviteListInviteSummary().copy(roomAlias = "#someroom-with-a-long-alias:example.com"),
|
||||||
|
aInviteListInviteSummary().copy(roomAlias = "#someroom-with-a-long-alias:example.com", isNew = true),
|
||||||
aInviteListInviteSummary().copy(roomName = "Alice", sender = null),
|
aInviteListInviteSummary().copy(roomName = "Alice", sender = null),
|
||||||
aInviteListInviteSummary().copy(isNew = true)
|
aInviteListInviteSummary().copy(isNew = true)
|
||||||
)
|
)
|
||||||
|
|
@ -32,9 +33,9 @@ open class InviteListInviteSummaryProvider : PreviewParameterProvider<InviteList
|
||||||
|
|
||||||
fun aInviteListInviteSummary() = InviteListInviteSummary(
|
fun aInviteListInviteSummary() = InviteListInviteSummary(
|
||||||
roomId = RoomId("!room1:example.com"),
|
roomId = RoomId("!room1:example.com"),
|
||||||
roomName = "Some room",
|
roomName = "Some room with a long name that will truncate",
|
||||||
sender = InviteSender(
|
sender = InviteSender(
|
||||||
userId = UserId("@alice:example.org"),
|
userId = UserId("@alice-with-a-long-mxid:example.org"),
|
||||||
displayName = "Alice"
|
displayName = "Alice with a long name"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@
|
||||||
<string name="screen_invites_decline_direct_chat_message">"Are you sure you want to decline to chat with %1$s?"</string>
|
<string name="screen_invites_decline_direct_chat_message">"Are you sure you want to decline to chat with %1$s?"</string>
|
||||||
<string name="screen_invites_decline_direct_chat_title">"Decline chat"</string>
|
<string name="screen_invites_decline_direct_chat_title">"Decline chat"</string>
|
||||||
<string name="screen_invites_empty_list">"No Invites"</string>
|
<string name="screen_invites_empty_list">"No Invites"</string>
|
||||||
<string name="screen_invites_invited_you">"%1$s invited you"</string>
|
<string name="screen_invites_invited_you">"%1$s (%2$s) invited you"</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue