Feat: collapsible help

This commit is contained in:
2026-02-16 23:43:25 +01:00
parent 2d8abe4af9
commit f258358c8f
12 changed files with 597 additions and 119 deletions

View File

@@ -9,7 +9,7 @@ use crate::model::categories::{get_category_name, CatEntry, CATEGORIES};
use crate::model::{Word, WORDS};
use crate::state::DictFocus;
use crate::theme;
use crate::widgets::{render_search_bar, CategoryItem, CategoryList};
use crate::widgets::{render_search_bar, CategoryItem, CategoryList, Selection};
use CatEntry::{Category, Section};
@@ -51,21 +51,38 @@ fn render_categories(frame: &mut Frame, app: &App, area: Rect, dimmed: bool) {
let theme = theme::get();
let focused = app.ui.dict_focus == DictFocus::Categories && !dimmed;
let mut section_idx = 0usize;
let items: Vec<CategoryItem> = CATEGORIES
.iter()
.map(|entry| match entry {
Section(name) => CategoryItem {
label: name,
is_section: true,
},
Section(name) => {
let collapsed = app
.ui
.dict_collapsed
.get(section_idx)
.copied()
.unwrap_or(false);
section_idx += 1;
CategoryItem {
label: name,
is_section: true,
collapsed,
}
}
Category(name) => CategoryItem {
label: name,
is_section: false,
collapsed: false,
},
})
.collect();
let mut list = CategoryList::new(&items, app.ui.dict_category)
let selection = match app.ui.dict_on_section {
Some(s) => Selection::Section(s),
None => Selection::Item(app.ui.dict_category),
};
let mut list = CategoryList::new(&items, selection)
.focused(focused)
.title("Categories");
@@ -91,23 +108,24 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
.collect()
} else {
let category = get_category_name(app.ui.dict_category);
WORDS
.iter()
.filter(|w| w.category == category)
.collect()
WORDS.iter().filter(|w| w.category == category).collect()
};
let show_search = app.ui.dict_search_active || is_searching;
let (search_area, content_area) = if show_search {
let [s, c] =
Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).areas(area);
let [s, c] = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).areas(area);
(Some(s), c)
} else {
(None, area)
};
if let Some(sa) = search_area {
render_search_bar(frame, sa, &app.ui.dict_search_query, app.ui.dict_search_active);
render_search_bar(
frame,
sa,
&app.ui.dict_search_query,
app.ui.dict_search_active,
);
}
let content_width = content_area.width.saturating_sub(2) as usize;
@@ -172,7 +190,11 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
let category = get_category_name(app.ui.dict_category);
format!("{category} ({} words)", words.len())
};
let border_color = if focused { theme.dict.border_focused } else { theme.dict.border_normal };
let border_color = if focused {
theme.dict.border_focused
} else {
theme.dict.border_normal
};
let block = Block::default()
.borders(Borders::ALL)
.border_style(Style::new().fg(border_color))