Stop composer layout recursion on spaces

This commit is contained in:
iris committed 2026-09-09 19:54:53 -04:00
1 parent 5ece49b8d9
commit e5fee03da8
4 files changed
+86 -14

No files matched your search

+7
View File
@@ -112,6 +112,13 @@ where
// the transcript: measured at 58px of stray text for a 475px message
// in a 417px box.
let content = field
// A wrapping editor occupies the composer's width even when its
// current text is short. Without this inner constraint the vertical
// ScrollArea reports the text's narrow natural width to Pad; settling
// then offers that width back to the editor, where a trailing space
// wraps and doubles its height. The next parent pass restores the
// wide one-line answer, so the two layouts have no fixed point.
.width(rest(1))
// `scrollable_to_end`: what is being typed is at the end, so a
// message longer than the six lines shown holds that end.
.scrollable(Axis::Y, Pin::End)
+34
View File
@@ -225,6 +225,40 @@ fn the_composer_sits_above_a_simulated_ime_inset() {
);
}
/// A trailing space is narrower than the composer's available width but can
/// wrap when the field is measured again in its own reported width. The
/// settling walk must not bounce forever between those one- and two-line
/// answers. On Android that recursion exhausted the native UI thread's stack
/// and ended in SIGSEGV, before Rust's panic hook could write anything.
#[test]
fn a_space_in_the_composer_finishes_layout() {
let (mut h, screen) = opened();
screen.composer.set_bottom_inset(&mut h.rsc, 1000.0);
h.frame(PHONE_FRAME_MS * 2);
h.state.set_focus(Some(screen.composer.field));
screen.composer.field.edit(&mut h.rsc).set_cursor_byte(0);
for text in ["h", "i", " "] {
screen.composer.field.edit(&mut h.rsc).insert(text);
h.frame(PHONE_FRAME_MS);
}
assert_eq!(screen.composer.field.edit(&mut h.rsc).text.text(), "hi ");
let region = h
.render
.window_region(&screen.composer.field, &h.rsc)
.expect("the composer field is drawn");
let size = region.bot_right - region.top_left;
assert!(
size.x > phone_size().x / 2.0,
"the field shrink-wrapped to the short message: {region:?}"
);
assert!(
size.y < 30.0 * PHONE_SCALE,
"the trailing space wrapped onto a second line: {region:?}"
);
}
/// A newline typed into the composer must leave the caret inside the
/// bar's own padding, not flush against its bottom edge.
///