design(mail): список, навигация, sender-card 1:1 по живой теме

_mobile-mail.css:
- Карточка письма: r8 (было 12), фон #FDFDFD, нижняя граница #E6E6E6 +
  тень #CBCBCB, отправитель 16/500, тема 14/600 чёрный-50%, ДОБАВЛЕНА
  превью-строка письма (14/500 чёрный-50%, 1 строка), дата 14/500,
  зазор между карточками 2px (был 8).
- Навигация: панель 90% ширины, фон #FBFBFB, имя папки 14/500 (без
  жирнения активной), счётчик 16/500 серым без фона, разделитель
  #E6E6E6 под шапкой аккаунта.
- Sender-card сообщения: аватар 40 (был 44), имя 16/500.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
b-dev-mobile
2026-07-09 21:09:11 +00:00
parent 1bc568b059
commit bbfb6ae424
2 changed files with 51 additions and 24 deletions
@@ -32,6 +32,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MenuDefaults import androidx.compose.material3.MenuDefaults
@@ -46,6 +47,7 @@ import androidx.compose.runtime.setValue
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.drawBehind
import androidx.compose.ui.draw.shadow import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -328,8 +330,8 @@ fun MailNavigationSidebar(
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.fillMaxWidth(0.8f) .fillMaxWidth(0.9f)
.background(F7Colors.Surface) .background(F7Colors.Background)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding(horizontal = 12.dp, vertical = 12.dp), .padding(horizontal = 12.dp, vertical = 12.dp),
) { ) {
@@ -422,7 +424,10 @@ fun MailNavigationSidebar(
expanded = !collapsed, expanded = !collapsed,
onToggleExpanded = { onToggleAccountCollapsed(account.id) }, onToggleExpanded = { onToggleAccountCollapsed(account.id) },
) )
Spacer(Modifier.height(4.dp)) HorizontalDivider(
modifier = Modifier.padding(bottom = 8.dp),
color = F7Colors.Border,
)
} }
if (!collapsed) { if (!collapsed) {
accountFolders.forEach { folder -> accountFolders.forEach { folder ->
@@ -533,14 +538,17 @@ private fun MailSidebarRow(
title, title,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Medium, fontWeight = FontWeight.Medium,
color = F7Colors.TextPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
if (unread != null && unread > 0) { if (unread != null && unread > 0) {
// Живая тема: счётчик 16/500, серый, без фона
Text( Text(
unread.toString(), unread.toString(),
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
color = F7Colors.TextSecondary, color = F7Colors.TextSecondary,
) )
} }
@@ -598,7 +606,9 @@ fun MailEnvelopeRow(
val sender = message.fromEmail.takeIf { it.isNotBlank() } val sender = message.fromEmail.takeIf { it.isNotBlank() }
?: message.from.takeIf { it.isNotBlank() && !it.equals("Unknown", ignoreCase = true) } ?: message.from.takeIf { it.isNotBlank() && !it.equals("Unknown", ignoreCase = true) }
?: "Неизвестный" ?: "Неизвестный"
val mutedColor = F7Colors.TextSecondary // Живая тема (_mobile-mail.css): карточка #FDFDFD r8, нижняя граница #E6E6E6 + тень #CBCBCB,
// отправитель 16/500 чёрный, тема 14/600 и превью/дата 14/500 — чёрный 50%.
val fadedColor = Color(0x80151515)
val subject = message.subject.ifBlank { "(без темы)" } val subject = message.subject.ifBlank { "(без темы)" }
Box( Box(
@@ -606,14 +616,21 @@ fun MailEnvelopeRow(
.fillMaxWidth() .fillMaxWidth()
.shadow( .shadow(
elevation = 1.dp, elevation = 1.dp,
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(8.dp),
spotColor = Color(0x14000000), spotColor = Color(0xFFCBCBCB),
) )
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(8.dp))
.background(MailCardSurface) .background(MailCardSurface)
.border(1.dp, F7Colors.Border.copy(alpha = 0.45f), RoundedCornerShape(12.dp)) .drawBehind {
drawLine(
color = Color(0xFFE6E6E6),
start = androidx.compose.ui.geometry.Offset(0f, size.height - 0.5f),
end = androidx.compose.ui.geometry.Offset(size.width, size.height - 0.5f),
strokeWidth = 1.dp.toPx(),
)
}
.clickable(onClick = onClick) .clickable(onClick = onClick)
.padding(12.dp), .padding(8.dp),
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -624,7 +641,7 @@ fun MailEnvelopeRow(
email = message.fromEmail, email = message.fromEmail,
modifier = Modifier.size(40.dp), modifier = Modifier.size(40.dp),
) )
Spacer(Modifier.width(10.dp)) Spacer(Modifier.width(8.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -634,15 +651,15 @@ fun MailEnvelopeRow(
sender, sender,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
fontWeight = if (unread) FontWeight.SemiBold else FontWeight.Medium, fontWeight = FontWeight.Medium,
color = F7Colors.TextPrimary, color = F7Colors.TextPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
Text( Text(
formatEnvelopeDate(message.dateInt), formatEnvelopeDate(message.dateInt),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.bodyMedium,
color = mutedColor, color = fadedColor,
) )
if (message.flags.flagged) { if (message.flags.flagged) {
Spacer(Modifier.width(4.dp)) Spacer(Modifier.width(4.dp))
@@ -654,18 +671,27 @@ fun MailEnvelopeRow(
) )
} }
} }
Spacer(Modifier.height(4.dp))
Text( Text(
subject, subject,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.SemiBold,
color = mutedColor, color = fadedColor,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
if (message.preview.isNotBlank()) {
Text(
message.preview,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
color = fadedColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
// Теги письма цветными пилюлями (макет «Список сообщений») // Теги письма цветными пилюлями (макет «Список сообщений»)
if (message.tags.isNotEmpty()) { if (message.tags.isNotEmpty()) {
Spacer(Modifier.height(6.dp)) Spacer(Modifier.height(4.dp))
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
message.tags.take(4).forEach { MailTagChip(it) } message.tags.take(4).forEach { MailTagChip(it) }
} }
@@ -987,15 +1013,15 @@ fun MailMessageSenderCard(
MailAvatar( MailAvatar(
name = fromName, name = fromName,
email = fromEmail, email = fromEmail,
modifier = Modifier.size(44.dp), modifier = Modifier.size(40.dp),
) )
Spacer(Modifier.width(10.dp)) Spacer(Modifier.width(8.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
displayName, displayName,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.Medium,
color = F7Colors.TextPrimary, color = F7Colors.TextPrimary,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -680,7 +680,8 @@ private fun MailInboxScreen(
LazyColumn( LazyColumn(
state = listState, state = listState,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp), // Живая тема: зазор между карточками писем 2px
verticalArrangement = Arrangement.spacedBy(2.dp),
) { ) {
items( items(
listItems, listItems,