Дизайн Файлов (чанк 1): строка списка по макету (Figma F-18/F-21/F-22)
CI / verify (push) Failing after 1m9s
CI / release (push) Has been skipped

- Имя + расширение инлайн (расширение серым TextSecondary), одна строка —
  вместо имени в 2 строки + мета (размер·дата). По мобильному макету.
- Выбранная строка — светло-зелёный фон (F7Colors.PrimaryLight), скругление.
- Иконка типа 28→24dp. На токенах F7Spacing/F7Radius.
- Строка на существующей загрузке иконок с сервера; локальные ico + офлайн — следом.

feature:files компилируется. Визуальная сверка — на устройстве (side-by-side).
This commit is contained in:
b-dev-mobile
2026-07-08 07:33:27 +00:00
parent 312537cd8a
commit 04227fa5c8
@@ -64,8 +64,13 @@ import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties
import androidx.compose.ui.window.DialogProperties
import coil.compose.AsyncImage
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import ru.forbion.f7cloud.core.designsystem.F7AlertDialog
import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.F7Radius
import ru.forbion.f7cloud.core.designsystem.F7Spacing
import ru.forbion.f7cloud.core.designsystem.F7OutlinedField
import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton
import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton
@@ -775,16 +780,18 @@ fun FilesListRow(
onMenuClick: (Rect) -> Unit,
) {
var menuAnchor by remember { mutableStateOf<Rect?>(null) }
val displayName = if (showExtensions || item.isDirectory) {
item.name
} else {
item.name.substringBeforeLast('.', item.name)
}
// Имя + расширение (расширение серым, инлайн) — по макету моб. Файлов (F-18/F-22).
val hasExt = !item.isDirectory && item.name.contains('.')
val baseName = if (hasExt) item.name.substringBeforeLast('.') else item.name
val extension = if (hasExt && showExtensions) "." + item.name.substringAfterLast('.') else ""
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(F7Radius.md))
// выбранная строка — светло-зелёный фон (макет F-21)
.background(if (selected) F7Colors.PrimaryLight else Color.Transparent)
.clickable(onClick = onOpenClick)
.padding(horizontal = 4.dp, vertical = 10.dp),
.padding(horizontal = F7Spacing.sm, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Checkbox(
@@ -795,37 +802,25 @@ fun FilesListRow(
AsyncImage(
model = FileIcons.iconUrl(serverUrl, item.name, item.isDirectory),
contentDescription = null,
modifier = Modifier.size(28.dp),
modifier = Modifier.size(24.dp),
contentScale = ContentScale.Fit,
)
Column(
Text(
text = buildAnnotatedString {
append(baseName)
if (extension.isNotEmpty()) {
withStyle(SpanStyle(color = F7Colors.TextSecondary)) { append(" $extension") }
}
},
modifier = Modifier
.weight(1f)
.padding(horizontal = 8.dp),
) {
Text(
text = displayName,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
val meta = buildList {
if (!item.isDirectory && item.size != null && item.size > 0) {
add(formatFileSize(item.size))
}
item.lastModified?.let { add(formatModified(it)) }
}.joinToString(" · ")
if (meta.isNotBlank()) {
Text(
text = meta,
style = MaterialTheme.typography.bodySmall,
color = F7Colors.TextSecondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
.padding(horizontal = F7Spacing.sm),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
color = F7Colors.TextPrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Box(
modifier = Modifier
.size(36.dp)