Fix meal planner editor
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package dev.ulfrx.recipe.ui.screens.mealplaneditor
|
package dev.ulfrx.recipe.ui.screens.mealplaneditor
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -41,6 +42,7 @@ import dev.ulfrx.recipe.ui.theme.RecipeTheme
|
|||||||
import kotlinx.datetime.LocalDate
|
import kotlinx.datetime.LocalDate
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
import recipe.composeapp.generated.resources.Res
|
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_ingredients
|
||||||
import recipe.composeapp.generated.resources.meal_plan_editor_section_servings
|
import recipe.composeapp.generated.resources.meal_plan_editor_section_servings
|
||||||
import recipe.composeapp.generated.resources.meal_plan_editor_section_slot
|
import recipe.composeapp.generated.resources.meal_plan_editor_section_slot
|
||||||
@@ -94,94 +96,96 @@ internal fun MealPlanEditorContent(
|
|||||||
editing.addedIngredients.mapTo(mutableSetOf()) { it.ingredientId }
|
editing.addedIngredients.mapTo(mutableSetOf()) { it.ingredientId }
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Box(modifier = Modifier.fillMaxSize().background(RecipeTheme.colors.background)) {
|
||||||
modifier =
|
Column(
|
||||||
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(
|
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxSize()
|
||||||
.height(topChromeHeight)
|
.verticalScroll(scrollState, enabled = !addPanelOpen),
|
||||||
.padding(horizontal = spacing.lg + topChromeHeight + spacing.sm),
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
) {
|
) {
|
||||||
RecipeTitle(title = editing.recipe.title)
|
Spacer(Modifier.height(topChromeInset))
|
||||||
}
|
// Title sits in a row whose vertical bounds match the floating chrome
|
||||||
Spacer(Modifier.height(spacing.xl))
|
// (back/add buttons) so at scroll=0 it reads as the centre of the
|
||||||
RecipeCalendarPill(
|
// toolbar. Horizontal inset clears the chrome buttons — they are
|
||||||
selectedDate = editing.selectedDate,
|
// square pills of [topChromeHeight] anchored at spacing.lg.
|
||||||
expanded = editing.calendarExpanded,
|
Box(
|
||||||
onExpandedChange = onSetCalendarExpanded,
|
modifier =
|
||||||
onSelectDate = onSelectDate,
|
Modifier
|
||||||
onSelectionShift = onSelectDate,
|
.fillMaxWidth()
|
||||||
expandDirection = CalendarPillExpandDirection.Down,
|
.height(topChromeHeight)
|
||||||
glass = false,
|
.padding(horizontal = spacing.lg + topChromeHeight + spacing.sm),
|
||||||
tint = RecipeTheme.colors.surface,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = Modifier.padding(horizontal = spacing.lg),
|
) {
|
||||||
)
|
RecipeTitle(recipeTitle = editing.recipe.title)
|
||||||
|
}
|
||||||
SectionContainer {
|
Spacer(Modifier.height(spacing.xl))
|
||||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_slot))
|
RecipeCalendarPill(
|
||||||
Spacer(Modifier.height(spacing.sm))
|
selectedDate = editing.selectedDate,
|
||||||
MealSlotChipsRow(
|
expanded = editing.calendarExpanded,
|
||||||
allSlots = MealSlot.entries,
|
onExpandedChange = onSetCalendarExpanded,
|
||||||
allowedSlots = editing.recipe.allowedSlots,
|
onSelectDate = onSelectDate,
|
||||||
selectedSlot = editing.selectedSlot,
|
onSelectionShift = onSelectDate,
|
||||||
onSelectSlot = onSelectSlot,
|
expandDirection = CalendarPillExpandDirection.Down,
|
||||||
|
glass = false,
|
||||||
|
tint = RecipeTheme.colors.surface,
|
||||||
|
modifier = Modifier.padding(horizontal = spacing.lg),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
SectionContainer {
|
SectionContainer {
|
||||||
SectionTitle(text = stringResource(Res.string.nutrition_label))
|
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_slot))
|
||||||
Spacer(Modifier.height(spacing.sm))
|
Spacer(Modifier.height(spacing.sm))
|
||||||
NutritionSummary(
|
MealSlotChipsRow(
|
||||||
nutrition = scaledNutrition,
|
allSlots = MealSlot.entries,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
allowedSlots = editing.recipe.allowedSlots,
|
||||||
)
|
selectedSlot = editing.selectedSlot,
|
||||||
}
|
onSelectSlot = onSelectSlot,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
SectionContainer {
|
SectionContainer {
|
||||||
ServingsRow(
|
SectionTitle(text = stringResource(Res.string.nutrition_label))
|
||||||
servings = editing.servings,
|
Spacer(Modifier.height(spacing.sm))
|
||||||
onServingsChange = onSetServings,
|
NutritionSummary(
|
||||||
)
|
nutrition = scaledNutrition,
|
||||||
}
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
SectionContainer {
|
SectionContainer {
|
||||||
SectionTitle(text = stringResource(Res.string.meal_plan_editor_section_ingredients))
|
ServingsRow(
|
||||||
Spacer(Modifier.height(spacing.sm))
|
servings = editing.servings,
|
||||||
IngredientEditorList(
|
onServingsChange = onSetServings,
|
||||||
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))
|
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
|
@Composable
|
||||||
private fun RecipeTitle(
|
private fun RecipeTitle(
|
||||||
title: String,
|
recipeTitle: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
BasicText(
|
Column(
|
||||||
text = title,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
style =
|
|
||||||
RecipeTheme.typography.body.copy(
|
|
||||||
color = RecipeTheme.colors.content,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
|
||||||
fontSize = RecipeTitleSize,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
),
|
|
||||||
modifier = modifier,
|
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,
|
frost = 0.dp,
|
||||||
),
|
),
|
||||||
button = RecipeGlassStyle(
|
button = RecipeGlassStyle(
|
||||||
refraction = 0.5f,
|
refraction = 0.3f,
|
||||||
curve = 0.4f,
|
curve = 0.2f,
|
||||||
edge = 0.03f,
|
edge = 0.03f,
|
||||||
dispersion = 0.5f,
|
dispersion = 0.5f,
|
||||||
saturation = 1f,
|
saturation = 1f,
|
||||||
contrast = 1f,
|
contrast = 0.85f,
|
||||||
frost = 15.dp,
|
frost = 5.dp,
|
||||||
tint = colors.surfaceGlass,
|
|
||||||
),
|
),
|
||||||
panel = RecipeGlassStyle(
|
panel = RecipeGlassStyle(
|
||||||
refraction = 0f,
|
refraction = 0f,
|
||||||
|
|||||||
Reference in New Issue
Block a user