menu: лончер приложений → bottom-sheet на пол-экрана (v0.5.116/124)
F7AppMenuSheet был fillMaxSize с непрозрачным фоном (закрывал весь экран). Теперь выезжает снизу и занимает ~пол-экрана: якорь BottomCenter, fillMaxHeight(0.6f), скруглённый верх 20dp + тень, ручка-хендл, лёгкий скрим над листом (тап закрывает), зазор под нижнюю панель, сетка иконок скроллится. Экран под меню виден сверху. Бамп версии 0.5.115→0.5.116.
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
Формат: `ГГГГ-ММ-ДД | версия | изменение | контракты | риск`
|
||||
|
||||
- 2026-07-08 | v0.5.116 (124) | Меню-лончер (сетка приложений) → bottom-sheet на пол-экрана (требование владельца «выходить снизу вверх только на пол экрана»). `F7AppMenuSheet` был `fillMaxSize` с непрозрачным фоном → закрывал весь экран. Теперь: якорь снизу (`Alignment.BottomCenter`), высота `fillMaxHeight(0.6f)`, скруглённый верх (20dp) + тень, ручка-хендл, лёгкий скрим (0.18) над листом с тапом-для-закрытия, зазор `BottomBarReserve` под нижнюю панель, сетка иконок скроллится (`weight(1f)`). Экран под меню теперь виден сверху. Компилируется | контракты не менялись | низкий: только оверлей меню
|
||||
|
||||
- 2026-07-08 | v0.5.115 (123) | Бамп версии под дизайн-веху (0.5.114→0.5.115, code 122→123, стиль проекта: патч +1 / code +1). До этого Этапы 0/1 + весь дизайн ошибочно шли одной WIP-линией 0.5.114 (122) — теперь ревью-сборки дизайна помечены отдельной версией. Дальше — бампить на каждую заметную веху/ревью-сборку | версионирование | нет: только versionCode/Name
|
||||
|
||||
- 2026-07-08 | v0.5.114 (122) | Дизайн Календаря (месячная сетка): по «Календарь · Месяц» — дни недели вынесены в серые пилюли; сетка стала безрамочной с тонкими гридлайнами (0.5dp Grey3) вместо скруглённых боксов; номер дня сверху-слева; сегодня — белое число в зелёном круге; событие — зелёная пилюля PrimaryLight (до 2 шт + «+N») вместо одного превью/точки. Компактная мобильная модель (месяц сверху + список событий выбранного дня снизу) сохранена — не десктопная таблица. `CalendarMonthGrid`/`CalendarDayCell`, убран неиспользуемый параметр daysWithEvents. Проверено сборкой | контракты не менялись | низкий: только вид месяца
|
||||
|
||||
+2
-2
@@ -39,8 +39,8 @@ android {
|
||||
applicationId 'ru.forbion.f7cloud.mobile'
|
||||
minSdk 26
|
||||
targetSdk 36
|
||||
versionCode 123
|
||||
versionName '0.5.115'
|
||||
versionCode 124
|
||||
versionName '0.5.116'
|
||||
missingDimensionStrategy 'default', 'f7'
|
||||
multiDexEnabled true
|
||||
|
||||
|
||||
+74
-31
@@ -9,10 +9,12 @@ import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@@ -35,6 +37,7 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
@@ -51,6 +54,10 @@ private val BottomBarReserve: Dp = 90.dp
|
||||
private val MenuIconSize = 62.dp
|
||||
private val MenuGridGap = 20.dp
|
||||
|
||||
// Меню-лист выезжает снизу и занимает ~пол-экрана (не весь), по требованию владельца
|
||||
private const val MenuSheetHeightFraction = 0.6f
|
||||
private val MenuSheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)
|
||||
|
||||
data class F7AppMenuItem(
|
||||
val label: String,
|
||||
val iconUrl: String,
|
||||
@@ -78,41 +85,76 @@ fun F7AppMenuSheet(
|
||||
}
|
||||
val base = serverUrl.trimEnd('/')
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(tween(250)) + slideInVertically(
|
||||
animationSpec = tween(350),
|
||||
initialOffsetY = { it },
|
||||
),
|
||||
exit = fadeOut(tween(200)) + slideOutVertically(
|
||||
animationSpec = tween(300),
|
||||
targetOffsetY = { it },
|
||||
),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(bottom = BottomBarReserve)
|
||||
.navigationBarsPadding()
|
||||
.background(F7Colors.Background)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 8.dp),
|
||||
Box(modifier = modifier.fillMaxSize()) {
|
||||
// Затемнение над листом — тап закрывает меню (лист занимает только низ экрана)
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(tween(200)),
|
||||
exit = fadeOut(tween(200)),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
F7AppMenuSearchField(
|
||||
serverUrl = base,
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.18f))
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null,
|
||||
onClick = onDismiss,
|
||||
),
|
||||
)
|
||||
}
|
||||
// Сам лист — выезжает снизу вверх на ~пол-экрана, скруглённый верх + тень
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(tween(250)) + slideInVertically(
|
||||
animationSpec = tween(350),
|
||||
initialOffsetY = { it },
|
||||
),
|
||||
exit = fadeOut(tween(200)) + slideOutVertically(
|
||||
animationSpec = tween(300),
|
||||
targetOffsetY = { it },
|
||||
),
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 24.dp),
|
||||
)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(4),
|
||||
horizontalArrangement = Arrangement.spacedBy(MenuGridGap),
|
||||
verticalArrangement = Arrangement.spacedBy(MenuGridGap),
|
||||
contentPadding = PaddingValues(horizontal = 2.dp),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
.fillMaxHeight(MenuSheetHeightFraction)
|
||||
.padding(bottom = BottomBarReserve)
|
||||
.navigationBarsPadding()
|
||||
.shadow(16.dp, MenuSheetShape, clip = false)
|
||||
.clip(MenuSheetShape)
|
||||
.background(F7Colors.Background)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
) {
|
||||
// Ручка-хендл
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 2.dp, bottom = 10.dp)
|
||||
.width(40.dp)
|
||||
.height(4.dp)
|
||||
.clip(RoundedCornerShape(2.dp))
|
||||
.background(F7Colors.Border),
|
||||
)
|
||||
F7AppMenuSearchField(
|
||||
serverUrl = base,
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 20.dp),
|
||||
)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(4),
|
||||
horizontalArrangement = Arrangement.spacedBy(MenuGridGap),
|
||||
verticalArrangement = Arrangement.spacedBy(MenuGridGap),
|
||||
contentPadding = PaddingValues(horizontal = 2.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = filteredItems,
|
||||
key = { index, item -> "${item.label}-$index" },
|
||||
@@ -132,6 +174,7 @@ fun F7AppMenuSheet(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user