Skip to content

Commit

Permalink
Merge pull request #107 from squidowl/fix/text-input-persistence
Browse files Browse the repository at this point in the history
Fix/text input persistence
  • Loading branch information
tarkah authored Jul 6, 2023
2 parents e1e39ae + d3caadb commit 5f4d552
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
24 changes: 20 additions & 4 deletions src/buffer/input_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,40 @@ 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],
) -> Element<'a, Message> {
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(),
}
}

Expand All @@ -49,7 +54,14 @@ impl State {
history: &mut history::Manager,
) -> (Command<Message>, Option<Event>) {
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);
}
Expand All @@ -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)
}
}
}

Expand Down
56 changes: 29 additions & 27 deletions src/widget/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@ 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,
{
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()
}
Expand All @@ -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<dyn Fn(String) -> Message + 'a>,
on_submit: Box<dyn Fn(data::Input) -> Message + 'a>,
on_completion: Message,
on_completion: Box<dyn Fn(String) -> Message + 'a>,
}

#[derive(Default)]
pub struct State {
input: String,
error: Option<String>,
completion: Completion,
selected_history: Option<usize>,
Expand All @@ -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
Expand All @@ -94,31 +97,29 @@ 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());
return None;
}
};

state.input.clear();

Some((self.on_submit)(input))
} else {
None
}
}
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
}
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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())
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 5f4d552

Please sign in to comment.