From c81358db05af9683381109df06a2b17d4ca26b4d Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 6 Jul 2023 10:50:59 -0700 Subject: [PATCH 1/2] Persist text input content outside widget tree --- src/buffer/input_view.rs | 24 ++++++++++++++--- src/widget/input.rs | 56 +++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/buffer/input_view.rs b/src/buffer/input_view.rs index 26774af7..0921a745 100644 --- a/src/buffer/input_view.rs +++ b/src/buffer/input_view.rs @@ -10,12 +10,13 @@ pub enum Event { #[derive(Debug, Clone)] pub enum Message { + Input(String), Send(Input), - CompletionSelected, + Completion(String), } pub fn view<'a>( - state: &State, + state: &'a State, buffer: Buffer, users: &'a [User], history: &'a [String], @@ -23,22 +24,26 @@ pub fn view<'a>( input( state.input_id.clone(), buffer, + &state.input, users, history, + Message::Input, Message::Send, - Message::CompletionSelected, + Message::Completion, ) } #[derive(Debug, Clone)] pub struct State { input_id: input::Id, + input: String, } impl State { pub fn new() -> Self { Self { input_id: input::Id::unique(), + input: String::default(), } } @@ -49,7 +54,14 @@ impl State { history: &mut history::Manager, ) -> (Command, Option) { match message { + Message::Input(input) => { + self.input = input; + + (Command::none(), None) + } Message::Send(input) => { + self.input.clear(); + if let Some(encoded) = input.encoded() { clients.send(input.server(), encoded); } @@ -60,7 +72,11 @@ impl State { (Command::none(), Some(Event::InputSent)) } - Message::CompletionSelected => (input::move_cursor_to_end(self.input_id.clone()), None), + Message::Completion(input) => { + self.input = input; + + (input::move_cursor_to_end(self.input_id.clone()), None) + } } } diff --git a/src/widget/input.rs b/src/widget/input.rs index df5f146b..bfadf924 100644 --- a/src/widget/input.rs +++ b/src/widget/input.rs @@ -15,10 +15,12 @@ pub type Id = text_input::Id; pub fn input<'a, Message>( id: Id, buffer: Buffer, + input: &'a str, users: &'a [User], history: &'a [String], + on_input: impl Fn(String) -> Message + 'a, on_submit: impl Fn(data::Input) -> Message + 'a, - on_completion: Message, + on_completion: impl Fn(String) -> Message + 'a, ) -> Element<'a, Message> where Message: 'a + Clone, @@ -26,10 +28,12 @@ where Input { id, buffer, + input, users, history, + on_input: Box::new(on_input), on_submit: Box::new(on_submit), - on_completion, + on_completion: Box::new(on_completion), } .into() } @@ -52,15 +56,16 @@ pub enum Event { pub struct Input<'a, Message> { id: Id, buffer: Buffer, + input: &'a str, users: &'a [User], history: &'a [String], + on_input: Box Message + 'a>, on_submit: Box Message + 'a>, - on_completion: Message, + on_completion: Box Message + 'a>, } #[derive(Default)] pub struct State { - input: String, error: Option, completion: Completion, selected_history: Option, @@ -81,11 +86,9 @@ where // Reset selected history state.selected_history = None; - state.input = input; + state.completion.process(&input, self.users); - state.completion.process(&state.input, self.users); - - None + Some((self.on_input)(input)) } Event::Send => { // Reset error state @@ -94,13 +97,13 @@ where state.selected_history = None; if let Some(entry) = state.completion.select() { - state.input = entry.complete_input(&state.input); - Some(self.on_completion.clone()) - } else if !state.input.is_empty() { + let new_input = entry.complete_input(self.input); + Some((self.on_completion)(new_input)) + } else if !self.input.is_empty() { state.completion.reset(); // Parse input - let input = match input::parse(self.buffer.clone(), &state.input) { + let input = match input::parse(self.buffer.clone(), self.input) { Ok(input) => input, Err(error) => { state.error = Some(error.to_string()); @@ -108,8 +111,6 @@ where } }; - state.input.clear(); - Some((self.on_submit)(input)) } else { None @@ -117,8 +118,8 @@ where } Event::Tab => { if let Some(entry) = state.completion.tab() { - state.input = entry.complete_input(&state.input); - Some(self.on_completion.clone()) + let new_input = entry.complete_input(self.input); + Some((self.on_completion)(new_input)) } else { None } @@ -133,14 +134,14 @@ where state.selected_history = Some(0); } - state.input = self + let new_input = self .history .get(state.selected_history.unwrap()) .unwrap() .clone(); - state.completion.process(&state.input, self.users); + state.completion.process(&new_input, self.users); - return Some(self.on_completion.clone()); + return Some((self.on_completion)(new_input)); } None @@ -149,16 +150,17 @@ where state.completion.reset(); if let Some(index) = state.selected_history.as_mut() { - if *index == 0 { + let new_input = if *index == 0 { state.selected_history = None; - state.input.clear(); + String::new() } else { *index -= 1; - state.input = self.history.get(*index).unwrap().clone(); - state.completion.process(&state.input, self.users); - } + let new_input = self.history.get(*index).unwrap().clone(); + state.completion.process(&new_input, self.users); + new_input + }; - return Some(self.on_completion.clone()); + return Some((self.on_completion)(new_input)); } None @@ -173,7 +175,7 @@ where theme::TextInput::Default }; - let text_input = text_input("Send message...", &state.input) + let text_input = text_input("Send message...", self.input) .on_input(Event::Input) .on_submit(Event::Send) .id(self.id.clone()) @@ -205,7 +207,7 @@ where .error .as_ref() .map(error) - .or_else(|| state.completion.view(&state.input)) + .or_else(|| state.completion.view(self.input)) .unwrap_or_else(|| row![].into()); anchored_overlay(input, overlay) From d3caadb5fa8973e671cd277c5085602dd53e3977 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 6 Jul 2023 10:52:09 -0700 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24859823..80faa63a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Changed: Fixed: - The last word of a message sometimes dissapeared +- Persist partial text input content when switching away from buffer # 2023.1-alpha1 (2023-06-30)