menu: состав пунктов точно по дизайну (+Уведомления/Настройки)
По дизайну выдвижного меню: Файлы/Календарь/Контакты/Карточки/Заметки + Bitrix/1C/Личный кабинет + Уведомления/Настройки. Убраны Почта/Конференции/ Задачи/Поддержка (остаются в нижней панели). - F7AppMenuItem: опц. localIcon (ImageVector); нативные пункты рисуются в круглом бейдже с зелёной обводкой (стиль glass) вместо серверной SVG; - Уведомления → NotificationsSheet, Настройки → настройки активного таба, обработка по label в AppScaffold.onItemClick.
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
package ru.forbion.f7cloud.mobile.ui
|
package ru.forbion.f7cloud.mobile.ui
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Notifications
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import ru.forbion.f7cloud.core.designsystem.F7AppMenuItem
|
import ru.forbion.f7cloud.core.designsystem.F7AppMenuItem
|
||||||
|
|
||||||
enum class AppTab(
|
enum class AppTab(
|
||||||
@@ -29,16 +32,14 @@ private data class AppMenuEntry(
|
|||||||
val webPath: String? = null,
|
val webPath: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Состав меню — по дизайну выдвижного меню (Почта/Конференции/Задачи/Поддержка — только
|
||||||
|
// в нижней панели; Уведомления/Настройки добавлены как нативные пункты, см. appMenuItems).
|
||||||
private val coreAppMenuEntries = listOf(
|
private val coreAppMenuEntries = listOf(
|
||||||
AppMenuEntry(AppTab.Mail, "Почта", "mail-glass.svg"),
|
|
||||||
AppMenuEntry(AppTab.Files, "Файлы", "files-glass.svg"),
|
AppMenuEntry(AppTab.Files, "Файлы", "files-glass.svg"),
|
||||||
AppMenuEntry(AppTab.Calendar, "Календарь", "calendar-glass.svg"),
|
AppMenuEntry(AppTab.Calendar, "Календарь", "calendar-glass.svg"),
|
||||||
AppMenuEntry(AppTab.Contacts, "Контакты", "contact-glass.svg"),
|
AppMenuEntry(AppTab.Contacts, "Контакты", "contact-glass.svg"),
|
||||||
AppMenuEntry(AppTab.Talk, "Конференции", "spreed-glass.svg"),
|
|
||||||
AppMenuEntry(AppTab.Deck, "Карточки", "deck-glass.svg"),
|
AppMenuEntry(AppTab.Deck, "Карточки", "deck-glass.svg"),
|
||||||
AppMenuEntry(AppTab.Tasks, "Задачи", "task-glass.svg"),
|
|
||||||
AppMenuEntry(null, "Заметки", "notes-glass.svg", webPath = "/apps/notes/"),
|
AppMenuEntry(null, "Заметки", "notes-glass.svg", webPath = "/apps/notes/"),
|
||||||
AppMenuEntry(AppTab.Support, "Поддержка", "icon-header-f7support.svg"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class AppMenuExternalSite(
|
data class AppMenuExternalSite(
|
||||||
@@ -71,7 +72,22 @@ fun appMenuItems(
|
|||||||
externalUrl = site.openUrl,
|
externalUrl = site.openUrl,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return core + external
|
// Нативные пункты по дизайну — действия обрабатываются в AppScaffold по label
|
||||||
|
val native = listOf(
|
||||||
|
F7AppMenuItem(
|
||||||
|
label = "Уведомления",
|
||||||
|
iconUrl = "",
|
||||||
|
selected = false,
|
||||||
|
localIcon = Icons.Filled.Notifications,
|
||||||
|
),
|
||||||
|
F7AppMenuItem(
|
||||||
|
label = "Настройки",
|
||||||
|
iconUrl = "",
|
||||||
|
selected = false,
|
||||||
|
localIcon = Icons.Filled.Settings,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return core + external + native
|
||||||
}
|
}
|
||||||
|
|
||||||
fun appTabFromMenuIndex(index: Int): AppTab? {
|
fun appTabFromMenuIndex(index: Int): AppTab? {
|
||||||
|
|||||||
@@ -637,24 +637,42 @@ fun AppScaffold(
|
|||||||
onItemClick = { index ->
|
onItemClick = { index ->
|
||||||
val item = appMenuItemsList.getOrNull(index) ?: return@F7AppMenuSheet
|
val item = appMenuItemsList.getOrNull(index) ?: return@F7AppMenuSheet
|
||||||
val external = item.externalUrl
|
val external = item.externalUrl
|
||||||
val isPersonalCabinet = item.label.trim().equals("Личный кабинет", ignoreCase = true)
|
val label = item.label.trim()
|
||||||
if (isPersonalCabinet) {
|
when {
|
||||||
// Профиль — нативная панель вместо веб-ЛК forbion
|
// Профиль — нативная панель вместо веб-ЛК forbion
|
||||||
menuOpen = false
|
label.equals("Личный кабинет", ignoreCase = true) -> {
|
||||||
profileOpen = true
|
menuOpen = false
|
||||||
} else if (!external.isNullOrBlank()) {
|
profileOpen = true
|
||||||
runCatching {
|
|
||||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(external)))
|
|
||||||
}
|
}
|
||||||
menuOpen = false
|
// Нативные пункты по дизайну меню
|
||||||
} else {
|
label.equals("Уведомления", ignoreCase = true) -> {
|
||||||
appTabFromMenuIndex(index)?.let { tab ->
|
menuOpen = false
|
||||||
if (tab != activeTab) {
|
notificationsOpen = true
|
||||||
pushTabHistory(activeTab)
|
}
|
||||||
activeTab = tab
|
label.equals("Настройки", ignoreCase = true) -> {
|
||||||
|
menuOpen = false
|
||||||
|
when (activeTab) {
|
||||||
|
AppTab.Mail -> mailSettingsOpen = true
|
||||||
|
AppTab.Calendar -> calendarSettingsRequest++
|
||||||
|
AppTab.Files -> filesSettingsOpen = true
|
||||||
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menuOpen = false
|
!external.isNullOrBlank() -> {
|
||||||
|
runCatching {
|
||||||
|
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(external)))
|
||||||
|
}
|
||||||
|
menuOpen = false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
appTabFromMenuIndex(index)?.let { tab ->
|
||||||
|
if (tab != activeTab) {
|
||||||
|
pushTabHistory(activeTab)
|
||||||
|
activeTab = tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuOpen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
+32
-6
@@ -25,8 +25,10 @@ import androidx.compose.foundation.layout.width
|
|||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -40,6 +42,7 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -63,6 +66,9 @@ data class F7AppMenuItem(
|
|||||||
val iconUrl: String,
|
val iconUrl: String,
|
||||||
val selected: Boolean,
|
val selected: Boolean,
|
||||||
val externalUrl: String? = null,
|
val externalUrl: String? = null,
|
||||||
|
// Локальная иконка вместо серверной (для нативных пунктов — Уведомления/Настройки),
|
||||||
|
// рисуется в круглом бейдже с зелёной обводкой под стиль glass-иконок.
|
||||||
|
val localIcon: ImageVector? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -245,12 +251,32 @@ private fun F7AppMenuGridItem(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
) {
|
) {
|
||||||
AsyncImage(
|
val localIcon = item.localIcon
|
||||||
model = item.iconUrl,
|
if (localIcon != null) {
|
||||||
contentDescription = item.label,
|
// Нативный пункт: иконка в круглом бейдже с зелёной обводкой (стиль glass)
|
||||||
modifier = Modifier.size(MenuIconSize),
|
Box(
|
||||||
contentScale = ContentScale.Fit,
|
modifier = Modifier
|
||||||
)
|
.size(MenuIconSize)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(Color.White)
|
||||||
|
.border(1.5.dp, F7Colors.Green30, CircleShape),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
localIcon,
|
||||||
|
contentDescription = item.label,
|
||||||
|
tint = F7Colors.Primary,
|
||||||
|
modifier = Modifier.size(MenuIconSize * 0.46f),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AsyncImage(
|
||||||
|
model = item.iconUrl,
|
||||||
|
contentDescription = item.label,
|
||||||
|
modifier = Modifier.size(MenuIconSize),
|
||||||
|
contentScale = ContentScale.Fit,
|
||||||
|
)
|
||||||
|
}
|
||||||
Text(
|
Text(
|
||||||
text = item.label,
|
text = item.label,
|
||||||
style = MaterialTheme.typography.labelLarge.copy(
|
style = MaterialTheme.typography.labelLarge.copy(
|
||||||
|
|||||||
Reference in New Issue
Block a user