fix(ui): remove redundant bottom dock imePadding and restore constant bottom clear margins

This commit is contained in:
Bruno Deanoz 2026-06-18 16:35:42 +02:00
parent cbcbd4f76b
commit e13f6798db
2 changed files with 6 additions and 20 deletions

View file

@ -21,13 +21,10 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@ -132,12 +129,6 @@ fun EmptyHero(userName: String, onPick: (String) -> Unit, modifier: Modifier = M
now.format(DateTimeFormatter.ofPattern("EEE, d. MMMM · HH:mm", Locale.GERMAN)) now.format(DateTimeFormatter.ofPattern("EEE, d. MMMM · HH:mm", Locale.GERMAN))
} }
// Query soft-keyboard height dynamically to dynamically expand the bottom spacer.
// This allows suggestion pills to push upwards cleanly above the keyboard & floating input,
// completely preventing any overlaps without squeezing the greeting, date, or Kaizen orb.
val imeBottom = WindowInsets.ime.asPaddingValues().calculateBottomPadding()
val bottomSpacerHeight = remember(imeBottom) { 142.dp + imeBottom }
Column( Column(
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
@ -155,7 +146,7 @@ fun EmptyHero(userName: String, onPick: (String) -> Unit, modifier: Modifier = M
Text(dateLine, color = cs.onSurfaceVariant.copy(alpha = 0.7f), fontSize = 13.sp) Text(dateLine, color = cs.onSurfaceVariant.copy(alpha = 0.7f), fontSize = 13.sp)
Spacer(Modifier.height(32.dp)) Spacer(Modifier.height(32.dp))
SuggestionPills(onPick) SuggestionPills(onPick)
Spacer(Modifier.height(bottomSpacerHeight)) // Dynamically expands to push layout out of the floating bottom dock Spacer(Modifier.height(142.dp)) // Clear the floating bottom dock
} }
} }

View file

@ -5,13 +5,9 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
@ -83,11 +79,10 @@ fun ChatScreen(userName: String = "Bruno") {
MeshBackground { MeshBackground {
Box(Modifier.fillMaxSize()) { Box(Modifier.fillMaxSize()) {
val imeBottom = WindowInsets.ime.asPaddingValues().calculateBottomPadding()
// 1. Scrollable Chat Content // 1. Scrollable Chat Content
// Stretches to the full screen, allowing bubbles to scroll cleanly behind the floating glass panels. // Stretches to the full screen, allowing bubbles to scroll cleanly behind the floating glass panels.
// No root imePadding() here to prevent double-resizing/pushing bugs on standard Android windows. // Since the OS physically resizes the window when the keyboard opens, the Box container shrinks natively,
// placing the bottom dock exactly on top of the keyboard. We use constant Paddings to clear the docks.
if (messages.isEmpty()) { if (messages.isEmpty()) {
EmptyHero( EmptyHero(
userName = userName, userName = userName,
@ -95,13 +90,12 @@ fun ChatScreen(userName: String = "Bruno") {
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) )
} else { } else {
val bottomPadding = remember(imeBottom) { 152.dp + imeBottom }
LazyColumn( LazyColumn(
state = listState, state = listState,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues( contentPadding = PaddingValues(
top = 92.dp, // Leaves luxurious room for the floating KaizenHeader + status bars top = 92.dp, // Leaves luxurious room for the floating KaizenHeader + status bars
bottom = bottomPadding, // Dynamically expands as the keyboard rises to keep messages clear of the floating dock bottom = 152.dp, // Leaves luxurious room for the floating ModePills + ChatInput + bottom margins
start = 16.dp, start = 16.dp,
end = 16.dp end = 16.dp
), ),
@ -119,11 +113,12 @@ fun ChatScreen(userName: String = "Bruno") {
) )
// 3. Floating Bottom Control Dock // 3. Floating Bottom Control Dock
// Positioned at the bottom of the window. When the keyboard is active, the OS resizes the window
// and this dock naturally sits exactly on top of the keyboard without any double-padding.
Column( Column(
modifier = Modifier modifier = Modifier
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)
.navigationBarsPadding() .navigationBarsPadding()
.imePadding() // Only the bottom controls float up, perfectly placing them above the keyboard
) { ) {
ModePillsRow(selected = selectedMode, onSelect = { selectedMode = it; haptics.tick() }) ModePillsRow(selected = selectedMode, onSelect = { selectedMode = it; haptics.tick() })
Spacer(Modifier.height(10.dp)) Spacer(Modifier.height(10.dp))