Merge branch 'main' of git.arirex.me:iris/ai-app
This commit is contained in:
commit
6d12388063
2 files changed
+30
-13
No files matched your search
@@ -620,6 +620,21 @@ machine belongs in `~/.claude/TOOLCHAIN.md` (toolchain versions) or
|
|||||||
toggle and used to force both places back to zero the moment the
|
toggle and used to force both places back to zero the moment the
|
||||||
platform says the keyboard is gone, whatever the animated value still
|
platform says the keyboard is gone, whatever the animated value still
|
||||||
claims.
|
claims.
|
||||||
|
**The guard is a boolean; the inset itself must never be read in the
|
||||||
|
composable body.** That correction first shipped as a `padding(bottom =
|
||||||
|
... imeInsets.getBottom(this) ...)` computed in `SessionScreen`, which
|
||||||
|
subscribes the whole screen to a value that changes every frame of the
|
||||||
|
animation: measured on the emulator at **16 full recompositions of
|
||||||
|
`SessionScreen` per keyboard open, against 1**, and it put the
|
||||||
|
transcript's position behind a recomposition while the composer's stayed
|
||||||
|
a draw-phase read of the same frame, so the two were only together while
|
||||||
|
that recomposition kept landing inside the frame. It is `.then(if (imeVisible) Modifier.imePadding() else
|
||||||
|
Modifier)` instead -- `imePadding` reads the inset in the layout phase,
|
||||||
|
which is what the comment above the transcript box means by "the whole of
|
||||||
|
what the keyboard re-measures", and dropping the modifier is the same
|
||||||
|
coercion to zero that the boolean was added for. The counter to check is
|
||||||
|
`session screen recomposed` in the debug button's report, which should
|
||||||
|
move by one across a keyboard open, not by the number of frames it took.
|
||||||
- **The keyboard pans the window unless the activity opts into resize.**
|
- **The keyboard pans the window unless the activity opts into resize.**
|
||||||
Without `android:windowSoftInputMode="adjustResize"`, opening the IME
|
Without `android:windowSoftInputMode="adjustResize"`, opening the IME
|
||||||
slides the whole window up (top bar off screen) instead of resizing —
|
slides the whole window up (top bar off screen) instead of resizing —
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ 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.ime
|
||||||
|
import androidx.compose.foundation.layout.imePadding
|
||||||
import androidx.compose.foundation.layout.isImeVisible
|
import androidx.compose.foundation.layout.isImeVisible
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -1220,19 +1221,20 @@ fun SessionScreen(settings: ServerSettings, summary: SessionSummary, onBack: ()
|
|||||||
// message -- and then the keyboard's, per frame of its animation. This modifier
|
// message -- and then the keyboard's, per frame of its animation. This modifier
|
||||||
// is the whole of what the keyboard re-measures: the box's own size never
|
// is the whole of what the keyboard re-measures: the box's own size never
|
||||||
// changes, so nothing above it is touched.
|
// changes, so nothing above it is touched.
|
||||||
.padding(
|
.padding(bottom = with(LocalDensity.current) { composerHeight.toDp() })
|
||||||
bottom =
|
// The keyboard's room, and only while the platform says there is a keyboard --
|
||||||
with(LocalDensity.current) { composerHeight.toDp() } +
|
// dropping the modifier is what coerces the stuck-open animated value to zero,
|
||||||
// Not the `imePadding()` modifier: it trusts the same animated
|
// the same guard the composer's translation applies below. It has to stay a
|
||||||
// value `imeVisible` exists to correct, so it is exactly as prone
|
// *modifier* rather than a padding computed here: `imePadding` reads the inset
|
||||||
// to sticking open. Coerced to zero the moment the platform says
|
// in the layout phase, so a keyboard frame re-measures this box and nothing
|
||||||
// the keyboard is gone, whatever the animation still claims.
|
// else, while reading `imeInsets` in this composable body subscribes the whole
|
||||||
if (imeVisible) {
|
// of `SessionScreen` to a value that changes every frame of the animation.
|
||||||
with(LocalDensity.current) { imeInsets.getBottom(this).toDp() }
|
// That cost 16 full recompositions of this screen per keyboard open, against
|
||||||
} else {
|
// one, and it made the transcript's position depend on a recomposition landing
|
||||||
0.dp
|
// inside the frame that the inset changed -- which the composer's does not,
|
||||||
}
|
// since its translation is re-read in that frame's draw phase. When the
|
||||||
)
|
// recomposition misses, the transcript trails the composer up the screen.
|
||||||
|
.then(if (imeVisible) Modifier.imePadding() else Modifier)
|
||||||
) {
|
) {
|
||||||
Box(Modifier.fillMaxSize()) {
|
Box(Modifier.fillMaxSize()) {
|
||||||
TranscriptList(
|
TranscriptList(
|
||||||
|
|||||||
Reference in new issue
Block a user