From bf22400798cb3c945ef4b3ec4ec9e20c1537dd30 Mon Sep 17 00:00:00 2001 From: temportalflux Date: Sun, 21 Jun 2026 15:56:17 -0400 Subject: [PATCH] identify issue with state storage, where it cannot be accessed outside of element painting (aka in action handlers) --- .../src/editable_text/input_element.rs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/crates/gpui_elements/src/editable_text/input_element.rs b/crates/gpui_elements/src/editable_text/input_element.rs index 72e8a42787..6137bed03c 100644 --- a/crates/gpui_elements/src/editable_text/input_element.rs +++ b/crates/gpui_elements/src/editable_text/input_element.rs @@ -11,17 +11,21 @@ use gpui::{ Styled, TextAlign, TextStyle, Window, WrappedLine, fill, point, px, size, }; use smallvec::SmallVec; -use std::{ops::Range, sync::Arc}; +use std::{cell::RefCell, ops::Range, rc::Rc, sync::Arc}; #[track_caller] -pub fn input() -> TextInputElement { +pub fn input(id: impl Into) -> TextInputElement { + let element_id = id.into(); let mut this = TextInputElement { placeholder: None, interactivity: Interactivity::new(), - init_storage: InitStorage::default(), + state_key: Rc::new(RefCell::new((element_id.clone(), InitStorage::default()))), }; + this.interactivity.element_id = Some(element_id); + this = this.key_context(DEFAULT_INPUT_CONTEXT); this.register_actions(); + this } @@ -29,7 +33,7 @@ pub fn input() -> TextInputElement { pub struct TextInputElement { placeholder: Option, interactivity: Interactivity, - init_storage: InitStorage, + state_key: Rc>, } impl InteractiveElement for TextInputElement { @@ -54,11 +58,10 @@ impl IntoElement for TextInputElement { impl EditableInputActionElement for TextInputElement {} impl super::StateBackedElement for TextInputElement { type State = TextInputState; - type InitProps = (Option, InitStorage); + type InitProps = Rc>; fn init_props(&self) -> Self::InitProps { - let element_id = self.interactivity.element_id.clone(); - (element_id, self.init_storage.clone()) + self.state_key.clone() } fn get_or_init_state( @@ -66,15 +69,13 @@ impl super::StateBackedElement for TextInputElement { window: &mut Window, cx: &mut App, ) -> Entity { + let (element_id, init_storage) = init_props.borrow().clone(); + println!("get_or_init_state {element_id:?}"); + // TODO: This can only be called during layout, prepaint, or paint. It cannot be called during an action handler, which occurs between frames. // Get the state from the app using the element's id as the key. // If it doesnt exist, initialize a new state with the user's desired storage medium. - // TODO: how to best garuntee an element id? - let element_id = init_props - .0 - .clone() - .expect("user MUST assign an element id"); window.use_keyed_state(element_id, cx, |_window, cx| { - TextInputState::new(init_props.1.exec(cx), cx) + TextInputState::new(init_storage.exec(cx), cx) }) } } @@ -145,6 +146,8 @@ impl Element for TextInputElement { let state = self.get_state(window, cx); + self.interactivity + .track_focus(state.read(cx).focus_handle(cx)); let layout_id = self.interactivity.request_layout( global_id, inspector_id,