diff --git a/feature/files/src/main/assets/chrome/comment-icon-black.svg b/feature/files/src/main/assets/chrome/comment-icon-black.svg
new file mode 100644
index 0000000..912f948
--- /dev/null
+++ b/feature/files/src/main/assets/chrome/comment-icon-black.svg
@@ -0,0 +1,13 @@
+
diff --git a/feature/files/src/main/assets/chrome/folder-white.svg b/feature/files/src/main/assets/chrome/folder-white.svg
new file mode 100644
index 0000000..17290f8
--- /dev/null
+++ b/feature/files/src/main/assets/chrome/folder-white.svg
@@ -0,0 +1,4 @@
+
diff --git a/feature/files/src/main/assets/chrome/people-icon-black.svg b/feature/files/src/main/assets/chrome/people-icon-black.svg
new file mode 100644
index 0000000..b30723d
--- /dev/null
+++ b/feature/files/src/main/assets/chrome/people-icon-black.svg
@@ -0,0 +1,13 @@
+
diff --git a/feature/files/src/main/assets/chrome/plus-white.svg b/feature/files/src/main/assets/chrome/plus-white.svg
new file mode 100644
index 0000000..ea9a2b5
--- /dev/null
+++ b/feature/files/src/main/assets/chrome/plus-white.svg
@@ -0,0 +1,11 @@
+
diff --git a/feature/files/src/main/assets/chrome/star-gray.svg b/feature/files/src/main/assets/chrome/star-gray.svg
new file mode 100644
index 0000000..78bb9ba
--- /dev/null
+++ b/feature/files/src/main/assets/chrome/star-gray.svg
@@ -0,0 +1,10 @@
+
diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesComponents.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesComponents.kt
index 345cf97..6ab9015 100644
--- a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesComponents.kt
+++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesComponents.kt
@@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -27,11 +28,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowForward
-import androidx.compose.material.icons.filled.ChatBubbleOutline
import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.filled.Group
-import androidx.compose.material.icons.filled.Star
-import androidx.compose.material.icons.filled.StarBorder
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Icon
import androidx.compose.material3.CheckboxDefaults
@@ -105,6 +102,7 @@ fun FilesNavigationSidebar(
onToggleTreePath: (String) -> Unit,
onToggleSection: (String) -> Unit,
onWebOnlyClick: (String) -> Unit,
+ onCreateClick: (() -> Unit)? = null,
) {
val base = serverUrl.trimEnd('/')
AnimatedVisibility(
@@ -126,11 +124,18 @@ fun FilesNavigationSidebar(
Column(
modifier = Modifier
.fillMaxHeight()
- .fillMaxWidth(0.86f)
- .background(F7Colors.Surface)
+ .fillMaxWidth(0.9f)
+ .background(F7Colors.Background)
.verticalScroll(rememberScrollState())
- .padding(horizontal = 12.dp, vertical = 12.dp),
+ .padding(start = 10.dp, top = 10.dp, end = 16.dp, bottom = 26.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp),
) {
+ onCreateClick?.let { create ->
+ FilesSidebarCreateButton(
+ onClick = create,
+ modifier = Modifier.padding(bottom = 4.dp),
+ )
+ }
FilesSidebarRow(
serverUrl = base,
iconPath = "files/folder-gray.svg",
@@ -233,11 +238,13 @@ fun FilesNavigationSidebar(
}
if (usage.isNotBlank()) {
Spacer(Modifier.height(8.dp))
+ // Живая тема: квота по центру, серым 16/20, без прогресс-бара.
Text(
text = "Использовано $usage",
- style = MaterialTheme.typography.bodySmall,
+ style = MaterialTheme.typography.bodyLarge,
color = F7Colors.TextSecondary,
- modifier = Modifier.padding(horizontal = 8.dp),
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth(),
)
}
}
@@ -307,6 +314,56 @@ private fun FilesTreeNodeRows(
}
}
+/**
+ * Градиентная кнопка «Создать или загрузить» сверху панели (живая тема: 40dp, r100,
+ * градиент 104°, белая папка слева, разделитель и плюс справа).
+ */
+@Composable
+fun FilesSidebarCreateButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .height(40.dp)
+ .clip(RoundedCornerShape(F7Radius.pill))
+ .background(
+ Brush.linearGradient(listOf(Color(0xFFC0FF7B), Color(0xFF7CBC3D))),
+ )
+ .clickable(onClick = onClick)
+ .padding(horizontal = 14.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ AsyncImage(
+ model = FileIcons.chromeAsset("folder-white.svg"),
+ contentDescription = null,
+ modifier = Modifier.size(16.dp),
+ )
+ Text(
+ text = "Создать или загрузить",
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 12.dp),
+ style = MaterialTheme.typography.bodyLarge,
+ fontWeight = FontWeight.Medium,
+ color = Color(0xFFFDFDFD),
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ Box(
+ modifier = Modifier
+ .width(2.dp)
+ .height(40.dp)
+ .background(Color.White),
+ )
+ AsyncImage(
+ model = FileIcons.chromeAsset("plus-white.svg"),
+ contentDescription = "Создать",
+ modifier = Modifier
+ .padding(start = 14.dp)
+ .size(16.dp),
+ )
+ }
+}
+
@Composable
private fun FilesSidebarRow(
serverUrl: String,
@@ -315,36 +372,34 @@ private fun FilesSidebarRow(
selected: Boolean = false,
onClick: () -> Unit,
) {
+ // Живая тема: строка minHeight 40, r8, иконка 20 серым, текст 16/20 #151515,
+ // активная — фон #ECF9DE; правых «⋮» в навигации нет.
Row(
modifier = Modifier
.fillMaxWidth()
+ .heightIn(min = 40.dp)
.clip(RoundedCornerShape(8.dp))
- .background(if (selected) Color(0xFFE8F5E0) else Color.Transparent)
+ .background(if (selected) F7Colors.PrimaryLight else Color.Transparent)
.clickable(onClick = onClick)
- .padding(horizontal = 8.dp, vertical = 10.dp),
+ .padding(horizontal = 8.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
AsyncImage(
model = "$serverUrl/themes/forbion/images/$iconPath",
contentDescription = null,
- modifier = Modifier.size(18.dp),
+ modifier = Modifier.size(20.dp),
contentScale = ContentScale.Fit,
)
- Spacer(Modifier.width(10.dp))
+ Spacer(Modifier.width(8.dp))
Text(
text = title,
modifier = Modifier.weight(1f),
- style = MaterialTheme.typography.bodyMedium,
- fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal,
+ style = MaterialTheme.typography.bodyLarge,
+ fontWeight = FontWeight.Medium,
+ color = F7Colors.TextPrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
- AsyncImage(
- model = "$serverUrl/themes/forbion/images/files/dots-vertic-gray.svg",
- contentDescription = null,
- modifier = Modifier.size(16.dp),
- contentScale = ContentScale.Fit,
- )
}
}
@@ -366,16 +421,12 @@ private fun FilesSidebarChildRow(
Text(
text = title,
modifier = Modifier.weight(1f),
- style = MaterialTheme.typography.bodyMedium,
+ style = MaterialTheme.typography.bodyLarge,
+ fontWeight = FontWeight.Medium,
+ color = F7Colors.TextPrimary,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
- AsyncImage(
- model = "$serverUrl/themes/forbion/images/files/dots-vertic-gray.svg",
- contentDescription = null,
- modifier = Modifier.size(16.dp),
- contentScale = ContentScale.Fit,
- )
}
}
@@ -392,22 +443,23 @@ private fun FilesSidebarExpandableSection(
Row(
modifier = Modifier
.fillMaxWidth()
+ .heightIn(min = 40.dp)
.clip(RoundedCornerShape(8.dp))
.clickable(onClick = onToggle)
- .padding(horizontal = 8.dp, vertical = 10.dp),
+ .padding(horizontal = 8.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
AsyncImage(
model = "$serverUrl/themes/forbion/images/$iconPath",
contentDescription = null,
- modifier = Modifier.size(18.dp),
+ modifier = Modifier.size(20.dp),
contentScale = ContentScale.Fit,
)
- Spacer(Modifier.width(10.dp))
+ Spacer(Modifier.width(8.dp))
Text(
text = title,
modifier = Modifier.weight(1f),
- style = MaterialTheme.typography.bodyMedium,
+ style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
)
Text(text = if (expanded) "▴" else "▾", color = F7Colors.TextSecondary)
@@ -744,47 +796,60 @@ private fun FilesHeaderColumn(
}
}
+/**
+ * Панель выделения по живой теме: 40dp, чекбокс 16 «выбрать все», «Выбрать все» чёрным +
+ * «(Выбран N)» серым, справа — пилюля «Действия» 25dp (без иконки).
+ */
@Composable
fun FilesBulkActionsBar(
serverUrl: String,
selectedCount: Int,
+ allSelected: Boolean = false,
+ onToggleSelectAll: (() -> Unit)? = null,
onActionsClick: (Rect) -> Unit,
) {
var anchorBounds by remember { mutableStateOf(null) }
- val base = serverUrl.trimEnd('/')
Row(
modifier = Modifier
.fillMaxWidth()
- .padding(bottom = 8.dp),
+ .height(40.dp)
+ .padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
+ F7ThemeCheckbox(checked = allSelected, onToggle = { onToggleSelectAll?.invoke() })
Text(
- text = "Выбрано $selectedCount",
+ text = buildAnnotatedString {
+ append("Выбрать все ")
+ withStyle(SpanStyle(color = F7Colors.TextSecondary)) {
+ append("(Выбран $selectedCount)")
+ }
+ },
+ modifier = Modifier.weight(1f),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
+ color = F7Colors.TextPrimary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
)
- Row(
+ Box(
modifier = Modifier
+ .height(25.dp)
.clip(RoundedCornerShape(100.dp))
+ .background(F7Colors.Background)
.border(1.dp, F7Colors.Border, RoundedCornerShape(100.dp))
- .clickable {
- anchorBounds?.let(onActionsClick)
- }
+ .clickable { anchorBounds?.let(onActionsClick) }
.onGloballyPositioned { coords ->
anchorBounds = coords.boundsInWindow()
}
- .padding(horizontal = 12.dp, vertical = 8.dp),
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(6.dp),
+ .padding(horizontal = 8.dp),
+ contentAlignment = Alignment.Center,
) {
- AsyncImage(
- model = "$base/themes/forbion/images/files/dots-vertic-gray.svg",
- contentDescription = null,
- modifier = Modifier.size(14.dp),
- contentScale = ContentScale.Fit,
+ Text(
+ "Действия",
+ style = MaterialTheme.typography.bodyMedium,
+ color = F7Colors.TextPrimary,
)
- Text("Действия", style = MaterialTheme.typography.bodyMedium)
}
}
}
@@ -929,12 +994,14 @@ fun FileActionMenuPopup(
properties = PopupProperties(focusable = true),
) {
Surface(
- modifier = Modifier.widthIn(min = 260.dp, max = 320.dp),
- shape = RoundedCornerShape(12.dp),
- shadowElevation = 8.dp,
+ modifier = Modifier
+ .widthIn(min = 280.dp, max = 340.dp)
+ .border(1.dp, F7Colors.Border, RoundedCornerShape(8.dp)),
+ shape = RoundedCornerShape(8.dp),
+ shadowElevation = 4.dp,
color = Color.White,
) {
- Column(modifier = Modifier.padding(vertical = 6.dp)) {
+ Column(modifier = Modifier.padding(4.dp)) {
entries.forEachIndexed { index, entry ->
if (entry.destructive && index > 0) {
HorizontalDivider(
@@ -945,18 +1012,20 @@ fun FileActionMenuPopup(
Row(
modifier = Modifier
.fillMaxWidth()
+ .heightIn(min = 25.dp)
+ .clip(RoundedCornerShape(6.dp))
.clickable {
onDismiss()
onAction(entry.action)
}
- .padding(horizontal = 14.dp, vertical = 11.dp),
+ .padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(12.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
AsyncImage(
model = "$base/themes/forbion/images/${entry.iconPath}",
contentDescription = null,
- modifier = Modifier.size(18.dp),
+ modifier = Modifier.size(16.dp),
contentScale = ContentScale.Fit,
)
Text(
@@ -1006,12 +1075,14 @@ fun FilesBulkActionMenuPopup(
properties = PopupProperties(focusable = true),
) {
Surface(
- modifier = Modifier.widthIn(min = 240.dp, max = 300.dp),
- shape = RoundedCornerShape(12.dp),
- shadowElevation = 8.dp,
+ modifier = Modifier
+ .widthIn(min = 240.dp, max = 300.dp)
+ .border(1.dp, F7Colors.Border, RoundedCornerShape(8.dp)),
+ shape = RoundedCornerShape(8.dp),
+ shadowElevation = 4.dp,
color = Color.White,
) {
- Column(modifier = Modifier.padding(vertical = 6.dp)) {
+ Column(modifier = Modifier.padding(4.dp)) {
entries.forEachIndexed { index, (action, label, icon) ->
if (index == entries.lastIndex) {
HorizontalDivider(
@@ -1063,25 +1134,26 @@ fun FilesDetailsSheet(
) {
if (item == null) return
var commentDraft by remember(item.relativePath) { mutableStateOf("") }
- androidx.compose.ui.window.Dialog(onDismissRequest = onDismiss) {
+ // Живая тема: панель на весь экран, фон #FBFBFB, без скруглений.
+ androidx.compose.ui.window.Dialog(
+ onDismissRequest = onDismiss,
+ properties = androidx.compose.ui.window.DialogProperties(usePlatformDefaultWidth = false),
+ ) {
Surface(
- modifier = Modifier
- .fillMaxWidth()
- .fillMaxHeight(0.92f),
- shape = RoundedCornerShape(16.dp),
- color = F7Colors.Surface,
+ modifier = Modifier.fillMaxSize(),
+ color = F7Colors.Background,
) {
Column(
modifier = Modifier
.fillMaxSize()
- .padding(20.dp),
+ .padding(horizontal = 16.dp, vertical = 12.dp),
) {
- // Крестик закрытия — правый верхний угол (по макету)
+ // Крестик 40dp — правый верхний угол
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
Box(
modifier = Modifier
- .size(28.dp)
- .clip(CircleShape)
+ .size(40.dp)
+ .clip(RoundedCornerShape(8.dp))
.clickable(onClick = onDismiss),
contentAlignment = Alignment.Center,
) {
@@ -1093,75 +1165,81 @@ fun FilesDetailsSheet(
)
}
}
+ // Заголовок 18/600 + звезда 20 справа (живая тема)
Row(
modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.spacedBy(12.dp),
- verticalAlignment = Alignment.Top,
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ verticalAlignment = Alignment.CenterVertically,
) {
- Column(modifier = Modifier.weight(1f)) {
+ Text(
+ item.name,
+ modifier = Modifier.weight(1f),
+ style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),
+ fontWeight = FontWeight.SemiBold,
+ color = F7Colors.TextPrimary,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ AsyncImage(
+ model = FileIcons.chromeAsset(
+ if (item.favorite) "star-green-full.svg" else "star-gray.svg",
+ ),
+ contentDescription = "Избранное",
+ modifier = Modifier
+ .size(20.dp)
+ .clickable(onClick = onToggleFavorite),
+ )
+ }
+ Spacer(Modifier.height(8.dp))
+ // Чип владельца (пилюля 25dp) слева, «дата / размер» серым справа
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Row(
+ modifier = Modifier
+ .height(25.dp)
+ .clip(RoundedCornerShape(100.dp))
+ .background(F7Colors.Background)
+ .border(1.dp, F7Colors.Border, RoundedCornerShape(100.dp))
+ .padding(horizontal = 4.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ Box(
+ modifier = Modifier
+ .size(16.dp)
+ .clip(CircleShape)
+ .background(F7Colors.PrimaryLight),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ ownerLabel.firstOrNull()?.uppercaseChar()?.toString() ?: "?",
+ style = MaterialTheme.typography.labelSmall,
+ color = F7Colors.Primary,
+ fontWeight = FontWeight.SemiBold,
+ )
+ }
Text(
- item.name,
- style = MaterialTheme.typography.titleLarge,
- fontWeight = FontWeight.SemiBold,
- maxLines = 2,
+ ownerLabel,
+ style = MaterialTheme.typography.labelMedium,
+ color = F7Colors.TextPrimary,
+ maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
- Spacer(Modifier.height(8.dp))
- // Чип владельца (аватар-инициал + логин) — по макету
- Row(
- modifier = Modifier
- .clip(RoundedCornerShape(100.dp))
- .background(F7Colors.SurfaceMuted)
- .padding(start = 4.dp, end = 10.dp, top = 4.dp, bottom = 4.dp),
- verticalAlignment = Alignment.CenterVertically,
- horizontalArrangement = Arrangement.spacedBy(6.dp),
- ) {
- Box(
- modifier = Modifier
- .size(20.dp)
- .clip(CircleShape)
- .background(F7Colors.PrimaryLight),
- contentAlignment = Alignment.Center,
- ) {
- Text(
- ownerLabel.firstOrNull()?.uppercaseChar()?.toString() ?: "?",
- style = MaterialTheme.typography.labelSmall,
- color = F7Colors.Primary,
- fontWeight = FontWeight.SemiBold,
- )
- }
- Text(
- ownerLabel,
- style = MaterialTheme.typography.bodySmall,
- color = F7Colors.TextSecondary,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- )
- }
}
- Column(horizontalAlignment = Alignment.End) {
- val dateSize = buildList {
- item.lastModified?.let {
- add(SimpleDateFormat("d MMMM", Locale("ru")).format(Date(it)))
- }
- item.size?.let { add(formatFileSize(it)) }
+ Spacer(Modifier.weight(1f))
+ val dateSize = buildList {
+ item.lastModified?.let {
+ add(SimpleDateFormat("d MMMM", Locale("ru")).format(Date(it)))
}
- if (dateSize.isNotEmpty()) {
- Text(
- dateSize.joinToString(" / "),
- style = MaterialTheme.typography.bodySmall,
- color = F7Colors.TextSecondary,
- )
- Spacer(Modifier.height(8.dp))
- }
- Icon(
- if (item.favorite) Icons.Filled.Star else Icons.Filled.StarBorder,
- contentDescription = "Избранное",
- tint = if (item.favorite) F7Colors.Primary else F7Colors.TextSecondary,
- modifier = Modifier
- .size(24.dp)
- .clip(CircleShape)
- .clickable(onClick = onToggleFavorite),
+ item.size?.let { add(formatFileSize(it)) }
+ }
+ if (dateSize.isNotEmpty()) {
+ Text(
+ dateSize.joinToString(" / "),
+ style = MaterialTheme.typography.bodyMedium,
+ color = F7Colors.TextSecondary,
)
}
}
@@ -1171,14 +1249,14 @@ fun FilesDetailsSheet(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
FilesDetailsTabPill(
- icon = Icons.Filled.ChatBubbleOutline,
+ iconAsset = "comment-icon-black.svg",
contentDescription = "Обсуждение",
selected = tab == FileDetailsTab.Events,
onClick = { onTabChange(FileDetailsTab.Events) },
modifier = Modifier.weight(1f),
)
FilesDetailsTabPill(
- icon = Icons.Filled.Group,
+ iconAsset = "people-icon-black.svg",
contentDescription = "Общий доступ",
selected = tab == FileDetailsTab.Sharing,
onClick = { onTabChange(FileDetailsTab.Sharing) },
@@ -1229,27 +1307,31 @@ fun FilesDetailsSheet(
@Composable
private fun FilesDetailsTabPill(
- icon: androidx.compose.ui.graphics.vector.ImageVector,
+ iconAsset: String,
contentDescription: String,
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
- val shape = RoundedCornerShape(14.dp)
+ // Живая тема: пилюля 30dp r100; активная — фон #ECF9DE, рамка #70B62B 20%; иконка темы 16.
+ val shape = RoundedCornerShape(100.dp)
Box(
modifier = modifier
- .height(40.dp)
+ .height(30.dp)
.clip(shape)
- .background(if (selected) F7Colors.PrimaryLight else F7Colors.Surface)
- .border(1.dp, if (selected) Color.Transparent else F7Colors.Border, shape)
+ .background(if (selected) F7Colors.PrimaryLight else F7Colors.Background)
+ .border(
+ 1.dp,
+ if (selected) F7Colors.Primary.copy(alpha = 0.2f) else F7Colors.Border,
+ shape,
+ )
.clickable(onClick = onClick),
contentAlignment = Alignment.Center,
) {
- Icon(
- icon,
+ AsyncImage(
+ model = FileIcons.chromeAsset(iconAsset),
contentDescription = contentDescription,
- tint = if (selected) F7Colors.Primary else F7Colors.TextSecondary,
- modifier = Modifier.size(20.dp),
+ modifier = Modifier.size(16.dp),
)
}
}
diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt
index 72ea273..4be5336 100644
--- a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt
+++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt
@@ -191,9 +191,8 @@ fun FilesScreen(
FilesViewToggleButton(viewMode) {
viewMode = if (viewMode == FilesViewMode.List) FilesViewMode.Grid else FilesViewMode.List
}
- // Создание (загрузка/новая папка) — раньше вызывалось из нижней панели,
- // теперь кнопка в шапке (нижняя панель стала навигационной)
- F7CreateButton(onClick = { showCreateMenu = true }, size = 40.dp)
+ // Кнопки создания в шапке нет (живая тема): «Создать или загрузить» —
+ // градиентная кнопка сверху панели навигации.
}
// Хлебные крошки
val crumbSegments = state.currentPath.split("/").filter { it.isNotBlank() }
@@ -203,9 +202,15 @@ fun FilesScreen(
onSegmentClick = { i -> vm.navigateToPath(session, crumbSegments.take(i + 1).joinToString("/")) },
)
if (selectionMode) {
+ val allSelected = displayItems.isNotEmpty() &&
+ state.selectedPaths.size >= displayItems.size
FilesBulkActionsBar(
serverUrl = session.serverUrl,
selectedCount = state.selectedPaths.size,
+ allSelected = allSelected,
+ onToggleSelectAll = {
+ if (allSelected) vm.clearSelection() else vm.selectAllVisible()
+ },
onActionsClick = { rect ->
bulkMenuAnchor = rect
bulkMenuOpen = true
@@ -323,6 +328,10 @@ fun FilesScreen(
vm.showWebOnlyMessage(title)
onSidebarOpenChange(false)
},
+ onCreateClick = {
+ onSidebarOpenChange(false)
+ showCreateMenu = true
+ },
)
FilesCreateMenu(