iris: move text state into shared resources

This commit is contained in:
iris committed 2026-09-12 14:18:12 -04:00
1 parent 4cbe7baea0
commit a8093b002b
26 files changed
+686 -467

No files matched your search

+3 -3
View File
@@ -56,7 +56,7 @@ impl DesktopAppState for Client {
let screen = match ai_app::ui::fixture::open(rsc, &mut ui_state) {
Ok(opened) => {
if let Some(message) = message_argv() {
opened.screen.composer.field.edit(rsc).set(&message);
(opened.screen.composer.field)(rsc).set(&message);
}
if let Some(text) = typed_argv() {
let field = opened.screen.composer.field;
@@ -66,8 +66,8 @@ impl DesktopAppState for Client {
ctx.update(move |state: &mut Client, rsc| {
state.set_focus(Some(field));
let end = rsc[field].text().len();
let mut edit = field.edit(rsc);
if edit.text.caret().is_none() {
let edit = field(rsc);
if edit.caret().is_none() {
edit.set_cursor_byte(end);
}
edit.insert(&ch.to_string());
+7 -7
View File
@@ -144,7 +144,7 @@ impl BenchClient {
.any();
ui_state.set_root(rsc, tree);
let font = rsc.ui.text.font_diagnostics();
let font = rsc.ui.text.borrow_mut().font_diagnostics();
log::info!(
"iris fonts: {} families found, default={:?} mono={:?}, resolved regular={:?} \
bold={:?} italic={:?} mono={:?}",
@@ -400,7 +400,7 @@ impl BenchClient {
fn show_diagnostics(&mut self, rsc: &mut Rsc) {
let report = self.diagnostics_text(rsc);
self.report_display.edit(rsc).set(&report);
self.report_display(rsc).set(&report);
self.last_report = Some(report);
}
@@ -423,7 +423,7 @@ impl BenchClient {
/// the keyboard-open capture (which only logs it), so the two can
/// never drift into reporting different things.
fn diagnostics_text(&self, rsc: &mut Rsc) -> String {
let font = rsc.ui.text.font_diagnostics();
let font = rsc.ui.text.borrow_mut().font_diagnostics();
let frame_report = match self.android_state().frame_report.report() {
Some(stats) => format!("{stats}"),
None => "no frames recorded yet".to_string(),
@@ -481,7 +481,7 @@ impl BenchClient {
}
self.running = true;
self.android_state_mut().frame_report.reset();
self.report_display.edit(rsc).set("Running benchmark...");
self.report_display(rsc).set("Running benchmark...");
let platform = self.platform.clone();
let stream_tail = self.stream_tail.clone();
@@ -620,7 +620,7 @@ impl BenchClient {
{rss_line}\n{battery}"
);
log::info!("iris bench report: {report}");
state.report_display.edit(rsc).set(&report);
state.report_display(rsc).set(&report);
state.last_report = Some(report);
});
});
@@ -776,7 +776,7 @@ async fn run_type_phase(
let text = typed.clone();
ctx.update(move |state: &mut BenchClient, rsc| {
if let Some(screen) = &state.screen {
screen.composer.field.edit(rsc).set(&text);
(screen.composer.field)(rsc).set(&text);
}
});
tokio::time::sleep(Duration::from_millis(TYPE_CHAR_MS)).await;
@@ -787,7 +787,7 @@ async fn run_type_phase(
let text = typed.clone();
ctx.update(move |state: &mut BenchClient, rsc| {
if let Some(screen) = &state.screen {
screen.composer.field.edit(rsc).set(&text);
(screen.composer.field)(rsc).set(&text);
}
});
tokio::time::sleep(Duration::from_millis(TYPE_CHAR_MS)).await;
+3 -3
View File
@@ -245,19 +245,19 @@ impl TranscriptClient {
let in_progress = self
.screen
.as_ref()
.map(|screen| screen.composer.field.edit(rsc).text.text().to_string())
.map(|screen| (screen.composer.field)(rsc).text().to_string())
.filter(|t| !t.is_empty());
let rows = group_tool_runs(&self.items);
let (screen, tree) = ui::build_tree(rsc, rows);
if let Some(text) = in_progress {
screen.composer.field.edit(rsc).set(&text);
(screen.composer.field)(rsc).set(&text);
}
if let Some(session_id) = self.session_id.clone() {
let field = screen.composer.field;
rsc.register_event(field, Submit, move |ctx, rsc| {
let text = field.edit(rsc).take();
let text = field(rsc).take();
let text = text.trim().to_string();
if !text.is_empty() {
ctx.state.send_message(session_id.clone(), text);
+3 -3
View File
@@ -290,19 +290,19 @@ impl Client {
let in_progress = self
.screen
.as_ref()
.map(|screen| screen.composer.field.edit(rsc).text.text().to_string())
.map(|screen| (screen.composer.field)(rsc).text().to_string())
.filter(|t| !t.is_empty());
let rows = group_tool_runs(&self.items);
let (screen, tree) = crate::ui::build_tree(rsc, rows);
if let Some(text) = in_progress {
screen.composer.field.edit(rsc).set(&text);
(screen.composer.field)(rsc).set(&text);
}
if let Some(session_id) = self.selected.clone() {
let field = screen.composer.field;
rsc.register_event(field, Submit, move |ctx, rsc| {
let text = field.edit(rsc).take();
let text = field(rsc).take();
let text = text.trim().to_string();
if !text.is_empty() {
ctx.state.send_message(session_id.clone(), text);
+1 -2
View File
@@ -6,8 +6,7 @@ const APPROX_LINE_HEIGHT_DP: f32 = 24.0;
const FIELD_PAD_DP: f32 = 12.0;
/// `field` is exposed so the caller can read its content on submit
/// (`field.edit(rsc).text()`) and clear it afterward
/// (`field.edit(rsc).set("")`).
/// (`field(rsc).text()`) and clear it afterward (`field(rsc).set("")`).
pub struct Composer {
pub field: WeakWidget<TextEdit>,
/// The bar's own outer padding -- only `bottom` is ever changed, by
+18
View File
@@ -532,6 +532,24 @@ mod apply_tests {
out
}
#[test]
fn registering_a_font_after_drawing_invalidates_its_text_owner() {
let mut rsc = TestRsc {
ui: Ui::default(),
events: EventManager::default(),
};
rsc.ui.resize((800.0, 600.0));
let root = wtext("already shaped").add_strong(&mut rsc).any();
rsc.draw(&root);
assert!(!rsc.widgets().has_updates());
rsc.ui.register_font("late-icons", ICON_FONT).unwrap();
assert!(rsc.widgets().has_updates());
rsc.draw(&root);
assert!(!rsc.widgets().has_updates());
}
fn cost_of_one_delta(paragraphs: usize) -> (u64, u64) {
let mut rsc = TestRsc {
ui: Ui::default(),
+5 -5
View File
@@ -197,14 +197,14 @@ fn a_space_in_the_composer_finishes_layout() {
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);
(screen.composer.field)(&mut h.rsc).set_cursor_byte(0);
for text in ["h", "i", " "] {
screen.composer.field.edit(&mut h.rsc).insert(text);
(screen.composer.field)(&mut h.rsc).insert(text);
h.frame(PHONE_FRAME_MS);
}
assert_eq!(screen.composer.field.edit(&mut h.rsc).text.text(), "hi ");
assert_eq!(&*(screen.composer.field)(&mut h.rsc).text(), "hi ");
let region = h
.rsc
.ui
@@ -232,9 +232,9 @@ fn a_newline_leaves_the_caret_inside_the_composers_padding() {
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);
(screen.composer.field)(&mut h.rsc).set_cursor_byte(0);
for _ in 0..12 {
screen.composer.field.edit(&mut h.rsc).insert("a\n");
(screen.composer.field)(&mut h.rsc).insert("a\n");
h.frame(PHONE_FRAME_MS);
}
let render_handle = h.rsc.ui.render_state();