248 lines
9.8 KiB
Rust
248 lines
9.8 KiB
Rust
use std::io;
|
|
|
|
use crossterm::event::{self, Event};
|
|
|
|
use crate::modules::{
|
|
source::{Word, WordSource},
|
|
ui::app::{AddState, App, UiState},
|
|
};
|
|
|
|
pub fn handle_user_input(app: &mut App) -> io::Result<()> {
|
|
if let Event::Key(key) = event::read()? {
|
|
match key.code {
|
|
event::KeyCode::Char(c) => {
|
|
match app.state {
|
|
UiState::DELETE => {
|
|
if c == 'y' || c == 'Y' || c == 's' || c == 'S' {
|
|
// delete word
|
|
let scroll_position: usize = {
|
|
if let Some(i) = app.list_state.selected() {
|
|
i
|
|
} else {
|
|
0
|
|
}
|
|
};
|
|
let selected_word =
|
|
app.word_list.clone().into_iter().nth(scroll_position);
|
|
if let Some(w) = selected_word {
|
|
// TODO: manage result with some notification context
|
|
let _ = app.file_database.remove_word(&w.key);
|
|
app.update_word_list();
|
|
if scroll_position > 0 {
|
|
app.list_state.select(Some(scroll_position - 1));
|
|
}
|
|
app.state = UiState::LIST;
|
|
}
|
|
} else {
|
|
app.state = UiState::LIST;
|
|
}
|
|
}
|
|
UiState::FILTERWORD => {
|
|
if let Some(mut prev_word) = app.word_filter.clone() {
|
|
prev_word.push(c);
|
|
app.word_filter = Some(prev_word);
|
|
} else {
|
|
app.word_filter = Some(c.to_string());
|
|
}
|
|
app.update_word_list();
|
|
}
|
|
UiState::FILTERLANG => {
|
|
if let Some(mut prev_lang) = app.lang_filter.clone() {
|
|
prev_lang.push(c);
|
|
app.lang_filter = Some(prev_lang);
|
|
} else {
|
|
app.lang_filter = Some(c.to_string());
|
|
}
|
|
app.update_word_list();
|
|
}
|
|
UiState::ADD => match app.add_state {
|
|
AddState::KEY => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.key.push(c);
|
|
app.word_to_add = Some(prev_word);
|
|
} else {
|
|
app.word_to_add = Some(Word {
|
|
key: c.to_string(),
|
|
description: "".to_string(),
|
|
lang: "".to_string(),
|
|
});
|
|
}
|
|
}
|
|
AddState::DESCRIPTION => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.description.push(c);
|
|
app.word_to_add = Some(prev_word);
|
|
} else {
|
|
app.word_to_add = Some(Word {
|
|
key: c.to_string(),
|
|
description: "".to_string(),
|
|
lang: "".to_string(),
|
|
});
|
|
}
|
|
}
|
|
AddState::LANG => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.lang.push(c);
|
|
app.word_to_add = Some(prev_word);
|
|
} else {
|
|
app.word_to_add = Some(Word {
|
|
key: c.to_string(),
|
|
description: "".to_string(),
|
|
lang: "".to_string(),
|
|
});
|
|
}
|
|
}
|
|
},
|
|
_ => {
|
|
// Quit
|
|
if c == 'q' || c == 'x' {
|
|
app.exit = true;
|
|
}
|
|
// State change
|
|
if c == 'f' || c == '/' {
|
|
app.state = UiState::FILTERWORD;
|
|
}
|
|
if c == 'l' {
|
|
app.state = UiState::FILTERLANG;
|
|
}
|
|
if c == 'd' {
|
|
app.state = UiState::DELETE;
|
|
}
|
|
if c == 'e' {
|
|
app.state = UiState::EDIT;
|
|
}
|
|
if c == 'a' {
|
|
app.state = UiState::ADD;
|
|
}
|
|
// Movement
|
|
if c == 'j' {
|
|
let scroll_position: usize = {
|
|
if let Some(i) = app.list_state.selected() {
|
|
i
|
|
} else {
|
|
0
|
|
}
|
|
};
|
|
if scroll_position < app.word_list.len() - 1 {
|
|
app.list_state.select_next();
|
|
app.description_scroll = 0;
|
|
}
|
|
}
|
|
if c == 'G' {
|
|
app.list_state.select_last();
|
|
}
|
|
if c == 'k' {
|
|
app.list_state.select_previous();
|
|
app.description_scroll = 0;
|
|
}
|
|
if c == 'J' {
|
|
app.description_scroll += 1;
|
|
}
|
|
if c == 'K' {
|
|
if app.description_scroll > 0 {
|
|
app.description_scroll -= 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
event::KeyCode::Enter => match app.state {
|
|
UiState::ADD => {
|
|
if let Some(w) = app.word_to_add.clone()
|
|
&& w.key.len() > 0
|
|
{
|
|
let res = app.file_database.insert_word(w);
|
|
match res {
|
|
Ok(_) => {
|
|
app.update_word_list();
|
|
app.word_to_add = None;
|
|
app.state = get_next_ui_state(app.state);
|
|
}
|
|
Err(_) => app.state = get_next_ui_state(app.state),
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
},
|
|
event::KeyCode::Tab => match app.state {
|
|
UiState::ADD => {
|
|
app.add_state = get_next_add_state(app.add_state);
|
|
}
|
|
_ => {
|
|
app.state = get_next_ui_state(app.state);
|
|
}
|
|
},
|
|
event::KeyCode::Backspace => match app.state {
|
|
UiState::FILTERWORD => {
|
|
app.word_filter = remove_last_char(&app.word_filter);
|
|
app.update_word_list();
|
|
}
|
|
UiState::FILTERLANG => {
|
|
app.lang_filter = remove_last_char(&app.lang_filter);
|
|
app.update_word_list();
|
|
}
|
|
UiState::ADD => match app.add_state {
|
|
AddState::KEY => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.key.pop();
|
|
app.word_to_add = Some(prev_word);
|
|
}
|
|
}
|
|
AddState::DESCRIPTION => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.description.pop();
|
|
app.word_to_add = Some(prev_word);
|
|
}
|
|
}
|
|
AddState::LANG => {
|
|
if let Some(mut prev_word) = app.word_to_add.clone() {
|
|
prev_word.lang.pop();
|
|
app.word_to_add = Some(prev_word);
|
|
}
|
|
}
|
|
},
|
|
_ => {}
|
|
},
|
|
event::KeyCode::Esc => {
|
|
app.state = UiState::LIST;
|
|
}
|
|
_ => return Ok(()),
|
|
}
|
|
app.last_key = Some(key);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn remove_last_char(input: &Option<String>) -> Option<String> {
|
|
if let Some(l) = input {
|
|
if l.len() <= 1 {
|
|
None
|
|
} else {
|
|
let mut new_l = l.clone();
|
|
new_l.pop();
|
|
Some(new_l)
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn get_next_add_state(current: AddState) -> AddState {
|
|
if current == AddState::KEY {
|
|
AddState::LANG
|
|
} else if current == AddState::LANG {
|
|
AddState::DESCRIPTION
|
|
} else {
|
|
AddState::KEY
|
|
}
|
|
}
|
|
|
|
fn get_next_ui_state(current: UiState) -> UiState {
|
|
match current {
|
|
UiState::LIST => UiState::FILTERWORD,
|
|
UiState::FILTERWORD => UiState::FILTERLANG,
|
|
UiState::FILTERLANG => UiState::LIST,
|
|
_ => UiState::LIST,
|
|
}
|
|
}
|