Fix meal planner editor
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package dev.ulfrx.recipe.ui.screens.mealplaneditor
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -41,6 +42,7 @@ import dev.ulfrx.recipe.ui.theme.RecipeTheme
|
||||
import kotlinx.datetime.LocalDate
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import recipe.composeapp.generated.resources.Res
|
||||
import recipe.composeapp.generated.resources.meal_plan_editor_title
|
||||
import recipe.composeapp.generated.resources.meal_plan_editor_section_ingredients
|
||||
import recipe.composeapp.generated.resources.meal_plan_editor_section_servings
|
||||
import recipe.composeapp.generated.resources.meal_plan_editor_section_slot
|
||||
@@ -94,94 +96,96 @@ internal fun MealPlanEditorContent(
|
||||
editing.addedIngredients.mapTo(mutableSetOf()) { it.ingredientId }
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState, enabled = !addPanelOpen),
|
||||
) {
|
||||
Spacer(Modifier.height(topChromeInset))
|
||||
// Title sits in a row whose vertical bounds match the floating chrome
|
||||
// (back/add buttons) so at scroll=0 it reads as the centre of the
|
||||
// toolbar. Horizontal inset clears the chrome buttons — they are
|
||||
// square pills of [topChromeHeight] anchored at spacing.lg.
|
||||
Box(
|
||||
Box(modifier = Modifier.fillMaxSize().background(RecipeTheme.colors.background)) {
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(topChromeHeight)
|
||||
.padding(horizontal = spacing.lg + topChromeHeight + spacing.sm),
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState, enabled = !addPanelOpen),
|
||||
) {
|
||||
RecipeTitle(title = editing.recipe.title)
|
||||
}
|
||||
Spacer(Modifier.height(spacing.xl))
|
||||
RecipeCalendarPill(
|
||||
selectedDate = editing.selectedDate,
|
||||
expanded = editing.calendarExpanded,
|
||||
onExpandedChange = onSetCalendarExpanded,
|
||||
onSelectDate = onSelectDate,
|
||||
onSelectionShift = onSelectDate,
|
||||
expandDirection = CalendarPillExpandDirection.Down,
|
||||
glass = false,
|
||||
tint = RecipeTheme.colors.surface,
|
||||
modifier = Modifier.padding(horizontal = spacing.lg),
|
||||
)
|
||||
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_slot))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
MealSlotChipsRow(
|
||||
allSlots = MealSlot.entries,
|
||||
allowedSlots = editing.recipe.allowedSlots,
|
||||
selectedSlot = editing.selectedSlot,
|
||||
onSelectSlot = onSelectSlot,
|
||||
Spacer(Modifier.height(topChromeInset))
|
||||
// Title sits in a row whose vertical bounds match the floating chrome
|
||||
// (back/add buttons) so at scroll=0 it reads as the centre of the
|
||||
// toolbar. Horizontal inset clears the chrome buttons — they are
|
||||
// square pills of [topChromeHeight] anchored at spacing.lg.
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(topChromeHeight)
|
||||
.padding(horizontal = spacing.lg + topChromeHeight + spacing.sm),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
RecipeTitle(recipeTitle = editing.recipe.title)
|
||||
}
|
||||
Spacer(Modifier.height(spacing.xl))
|
||||
RecipeCalendarPill(
|
||||
selectedDate = editing.selectedDate,
|
||||
expanded = editing.calendarExpanded,
|
||||
onExpandedChange = onSetCalendarExpanded,
|
||||
onSelectDate = onSelectDate,
|
||||
onSelectionShift = onSelectDate,
|
||||
expandDirection = CalendarPillExpandDirection.Down,
|
||||
glass = false,
|
||||
tint = RecipeTheme.colors.surface,
|
||||
modifier = Modifier.padding(horizontal = spacing.lg),
|
||||
)
|
||||
}
|
||||
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.nutrition_label))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
NutritionSummary(
|
||||
nutrition = scaledNutrition,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_slot))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
MealSlotChipsRow(
|
||||
allSlots = MealSlot.entries,
|
||||
allowedSlots = editing.recipe.allowedSlots,
|
||||
selectedSlot = editing.selectedSlot,
|
||||
onSelectSlot = onSelectSlot,
|
||||
)
|
||||
}
|
||||
|
||||
SectionContainer {
|
||||
ServingsRow(
|
||||
servings = editing.servings,
|
||||
onServingsChange = onSetServings,
|
||||
)
|
||||
}
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.nutrition_label))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
NutritionSummary(
|
||||
nutrition = scaledNutrition,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_ingredients))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
IngredientEditorList(
|
||||
recipeIngredients = editing.recipe.ingredients,
|
||||
addedIngredients = editing.addedIngredients,
|
||||
excludedIngredientIds = editing.excludedIngredients,
|
||||
substitutions = editing.substitutions,
|
||||
servings = editing.servings,
|
||||
onSelectSubstitution = onSelectSubstitution,
|
||||
onRemoveRecipeIngredient = onRemoveRecipeIngredient,
|
||||
onRemoveAddedIngredient = onRemoveAddedIngredient,
|
||||
onRestoreRemoved = onRestoreRemoved,
|
||||
)
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
AddIngredientPanel(
|
||||
catalog = catalog,
|
||||
usedIngredientIds = usedIngredientIds,
|
||||
onPick = onAddIngredient,
|
||||
keyboardClearance = keyboardReserve + spacing.sm,
|
||||
autoFocusEnabled = addPanelOpen,
|
||||
keyboardAnimationDurationMillis = keyboardTransition.animationDurationMillis,
|
||||
onOpenChange = { addPanelOpen = it },
|
||||
)
|
||||
}
|
||||
SectionContainer {
|
||||
ServingsRow(
|
||||
servings = editing.servings,
|
||||
onServingsChange = onSetServings,
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(bottomInset + spacing.xxl))
|
||||
SectionContainer {
|
||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_ingredients))
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
IngredientEditorList(
|
||||
recipeIngredients = editing.recipe.ingredients,
|
||||
addedIngredients = editing.addedIngredients,
|
||||
excludedIngredientIds = editing.excludedIngredients,
|
||||
substitutions = editing.substitutions,
|
||||
servings = editing.servings,
|
||||
onSelectSubstitution = onSelectSubstitution,
|
||||
onRemoveRecipeIngredient = onRemoveRecipeIngredient,
|
||||
onRemoveAddedIngredient = onRemoveAddedIngredient,
|
||||
onRestoreRemoved = onRestoreRemoved,
|
||||
)
|
||||
Spacer(Modifier.height(spacing.sm))
|
||||
AddIngredientPanel(
|
||||
catalog = catalog,
|
||||
usedIngredientIds = usedIngredientIds,
|
||||
onPick = onAddIngredient,
|
||||
keyboardClearance = keyboardReserve + spacing.sm,
|
||||
autoFocusEnabled = addPanelOpen,
|
||||
keyboardAnimationDurationMillis = keyboardTransition.animationDurationMillis,
|
||||
onOpenChange = { addPanelOpen = it },
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(bottomInset + spacing.xxl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,22 +228,48 @@ private fun SectionContainer(content: @Composable () -> Unit) {
|
||||
|
||||
@Composable
|
||||
private fun RecipeTitle(
|
||||
title: String,
|
||||
recipeTitle: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BasicText(
|
||||
text = title,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style =
|
||||
RecipeTheme.typography.body.copy(
|
||||
color = RecipeTheme.colors.content,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
fontSize = RecipeTitleSize,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
Column(
|
||||
modifier = modifier,
|
||||
)
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
BasicText(
|
||||
text = stringResource(Res.string.meal_plan_editor_title),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style =
|
||||
RecipeTheme.typography.body.copy(
|
||||
color = RecipeTheme.colors.content,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = RecipeTitleSize,
|
||||
lineHeight = RecipeTitleLineHeight,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
Spacer(Modifier.height(RecipeTitleGap))
|
||||
BasicText(
|
||||
text = recipeTitle,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style =
|
||||
RecipeTheme.typography.body.copy(
|
||||
color = RecipeTheme.colors.contentMuted,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = RecipeSubtitleSize,
|
||||
lineHeight = RecipeSubtitleLineHeight,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val RecipeTitleSize = 14.sp
|
||||
private val RecipeTitleSize = 16.sp
|
||||
private val RecipeTitleLineHeight = 17.sp
|
||||
private val RecipeTitleGap = 4.dp
|
||||
private val RecipeSubtitleSize = 11.sp
|
||||
private val RecipeSubtitleLineHeight = 14.sp
|
||||
|
||||
@@ -35,14 +35,13 @@ fun recipeGlassFor(colors: RecipeColors): RecipeGlass =
|
||||
frost = 0.dp,
|
||||
),
|
||||
button = RecipeGlassStyle(
|
||||
refraction = 0.5f,
|
||||
curve = 0.4f,
|
||||
refraction = 0.3f,
|
||||
curve = 0.2f,
|
||||
edge = 0.03f,
|
||||
dispersion = 0.5f,
|
||||
saturation = 1f,
|
||||
contrast = 1f,
|
||||
frost = 15.dp,
|
||||
tint = colors.surfaceGlass,
|
||||
contrast = 0.85f,
|
||||
frost = 5.dp,
|
||||
),
|
||||
panel = RecipeGlassStyle(
|
||||
refraction = 0f,
|
||||
|
||||
Reference in New Issue
Block a user