feat: word list UI implemented
This commit is contained in:
@@ -46,9 +46,4 @@ fn main() -> io::Result<()> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::new(
|
|
||||||
io::ErrorKind::Interrupted,
|
|
||||||
"Exit with abnormal procedure.",
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use ratatui::{
|
|||||||
layout::{Constraint, Direction, Flex, Layout},
|
layout::{Constraint, Direction, Flex, Layout},
|
||||||
style::{Color, Style},
|
style::{Color, Style},
|
||||||
text::Text,
|
text::Text,
|
||||||
widgets::{Block, Borders, Paragraph},
|
widgets::{Block, Borders, List, ListDirection, ListItem, ListState, Padding, Paragraph},
|
||||||
};
|
};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
@@ -22,10 +22,14 @@ pub enum UiState {
|
|||||||
DELETE,
|
DELETE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Preferences {
|
||||||
|
help: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
state: UiState,
|
state: UiState,
|
||||||
file_database: FileDatabase,
|
file_database: FileDatabase,
|
||||||
scroll_position: usize,
|
list_state: ListState,
|
||||||
word_list: Vec<Word>,
|
word_list: Vec<Word>,
|
||||||
word_filter: Option<String>,
|
word_filter: Option<String>,
|
||||||
lang_filter: Option<String>,
|
lang_filter: Option<String>,
|
||||||
@@ -39,7 +43,7 @@ impl App {
|
|||||||
Self {
|
Self {
|
||||||
state: UiState::LIST,
|
state: UiState::LIST,
|
||||||
file_database: db,
|
file_database: db,
|
||||||
scroll_position: 0,
|
list_state: ListState::default().with_selected(Some(0)),
|
||||||
word_list: wl,
|
word_list: wl,
|
||||||
word_filter: None,
|
word_filter: None,
|
||||||
lang_filter: None,
|
lang_filter: None,
|
||||||
@@ -58,7 +62,7 @@ impl App {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, frame: &mut Frame) {
|
fn draw(&mut self, frame: &mut Frame) {
|
||||||
let main_layout = Layout::default()
|
let main_layout = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.spacing(0)
|
.spacing(0)
|
||||||
@@ -109,13 +113,35 @@ impl App {
|
|||||||
filters_layout[1],
|
filters_layout[1],
|
||||||
);
|
);
|
||||||
|
|
||||||
frame.render_widget(
|
let word_key_list_items: Vec<ListItem> = self
|
||||||
Paragraph::new("Word list").block(Block::new().borders(Borders::ALL).title("Entries")),
|
.word_list
|
||||||
words_layout[0],
|
.clone()
|
||||||
);
|
.iter()
|
||||||
|
.map(|w| ListItem::new(w.key.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let word_key_list = List::new(word_key_list_items)
|
||||||
|
.direction(ListDirection::TopToBottom)
|
||||||
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Entries")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.padding(Padding::horizontal(1)),
|
||||||
|
)
|
||||||
|
.highlight_style(Style::default().fg(Color::default()))
|
||||||
|
.highlight_symbol("> ")
|
||||||
|
.style(Style::default().fg(Color::DarkGray));
|
||||||
|
frame.render_stateful_widget(word_key_list, words_layout[0], &mut self.list_state);
|
||||||
|
|
||||||
|
let scroll_position: usize = {
|
||||||
|
if let Some(i) = self.list_state.selected() {
|
||||||
|
i
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
// PERF: do not clone
|
// PERF: do not clone
|
||||||
let selected_word = self.word_list.clone().into_iter().nth(self.scroll_position);
|
let selected_word = self.word_list.clone().into_iter().nth(scroll_position);
|
||||||
if let Some(w) = selected_word {
|
if let Some(w) = selected_word {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(w.description).block(Block::new().borders(Borders::ALL)),
|
Paragraph::new(w.description).block(Block::new().borders(Borders::ALL)),
|
||||||
@@ -123,7 +149,7 @@ impl App {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let help_text = Text::raw("(f)ilter | lan(g) | (d)elete | (e)dit | (a)dd | (q)uit ")
|
let help_text = Text::raw("(f)ilter | (l)ang | (d)elete | (e)dit | (a)dd | (q)uit ")
|
||||||
.style(Style::new().fg(Color::DarkGray));
|
.style(Style::new().fg(Color::DarkGray));
|
||||||
let help_area = help_layout[0].centered(
|
let help_area = help_layout[0].centered(
|
||||||
Constraint::Length(help_text.width() as u16),
|
Constraint::Length(help_text.width() as u16),
|
||||||
@@ -148,7 +174,7 @@ impl App {
|
|||||||
self.file_database.get_all_words()
|
self.file_database.get_all_words()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.scroll_position = 0;
|
self.list_state.select(Some(0));
|
||||||
self.word_list = word_list;
|
self.word_list = word_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +210,7 @@ impl App {
|
|||||||
if c == 'f' || c == '/' {
|
if c == 'f' || c == '/' {
|
||||||
self.state = UiState::FILTERWORD;
|
self.state = UiState::FILTERWORD;
|
||||||
}
|
}
|
||||||
if c == 'g' {
|
if c == 'l' {
|
||||||
self.state = UiState::FILTERLANG;
|
self.state = UiState::FILTERLANG;
|
||||||
}
|
}
|
||||||
if c == 'd' {
|
if c == 'd' {
|
||||||
@@ -198,14 +224,10 @@ impl App {
|
|||||||
}
|
}
|
||||||
// Movement
|
// Movement
|
||||||
if c == 'j' {
|
if c == 'j' {
|
||||||
if self.scroll_position > 0 {
|
self.list_state.select_next();
|
||||||
self.scroll_position -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if c == 'k' {
|
if c == 'k' {
|
||||||
if self.scroll_position < self.word_list.len() - 1 {
|
self.list_state.select_previous();
|
||||||
self.scroll_position += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +245,18 @@ impl App {
|
|||||||
self.update_word_list();
|
self.update_word_list();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UiState::FILTERLANG => {}
|
UiState::FILTERLANG => {
|
||||||
|
if let Some(l) = &self.lang_filter {
|
||||||
|
if l.len() <= 1 {
|
||||||
|
self.lang_filter = None;
|
||||||
|
} else {
|
||||||
|
let mut new_l = l.clone();
|
||||||
|
new_l.pop();
|
||||||
|
self.lang_filter = Some(new_l);
|
||||||
|
}
|
||||||
|
self.update_word_list();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
event::KeyCode::Esc => {
|
event::KeyCode::Esc => {
|
||||||
|
|||||||
Reference in New Issue
Block a user