diff --git a/CHANGELOG.md b/CHANGELOG.md index 617dbcd..5f9da99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. Проверено сборкой | контракты не менялись | низкий: только вид месяца diff --git a/app/build.gradle b/app/build.gradle index 5831516..f0e770c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 diff --git a/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7AppMenuSheet.kt b/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7AppMenuSheet.kt index 3ccb614..d178a2d 100644 --- a/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7AppMenuSheet.kt +++ b/core/designsystem/src/main/java/ru/forbion/f7cloud/core/designsystem/F7AppMenuSheet.kt @@ -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( ) } } + } } } }