Feat: entretien de la codebase
This commit is contained in:
@@ -2,7 +2,7 @@ use cagire_markdown::{CodeHighlighter, MarkdownTheme};
|
||||
use ratatui::layout::{Constraint, Layout, Rect};
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::{Line as RLine, Span};
|
||||
use ratatui::widgets::{Block, Borders, List, ListItem, Padding, Paragraph, Wrap};
|
||||
use ratatui::widgets::{Block, Borders, Padding, Paragraph, Wrap};
|
||||
use ratatui::Frame;
|
||||
#[cfg(not(feature = "desktop"))]
|
||||
use tui_big_text::{BigText, PixelSize};
|
||||
@@ -12,6 +12,7 @@ use crate::model::docs::{get_topic, DocEntry, DOCS};
|
||||
use crate::state::HelpFocus;
|
||||
use crate::theme;
|
||||
use crate::views::highlight;
|
||||
use crate::widgets::{render_search_bar, CategoryItem, CategoryList};
|
||||
|
||||
use DocEntry::{Section, Topic};
|
||||
|
||||
@@ -100,80 +101,28 @@ pub fn render(frame: &mut Frame, app: &App, area: Rect) {
|
||||
|
||||
fn render_topics(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let theme = theme::get();
|
||||
let focused = app.ui.help_focus == HelpFocus::Topics;
|
||||
|
||||
let visible_height = area.height.saturating_sub(2) as usize;
|
||||
let total_items = DOCS.len();
|
||||
|
||||
// Find the visual index of the selected topic (including sections)
|
||||
let selected_visual_idx = {
|
||||
let mut visual = 0;
|
||||
let mut topic_count = 0;
|
||||
for entry in DOCS.iter() {
|
||||
if let Topic(_, _) = entry {
|
||||
if topic_count == app.ui.help_topic {
|
||||
break;
|
||||
}
|
||||
topic_count += 1;
|
||||
}
|
||||
visual += 1;
|
||||
}
|
||||
visual
|
||||
};
|
||||
|
||||
// Calculate scroll to keep selection visible (centered when possible)
|
||||
let scroll = if selected_visual_idx < visible_height / 2 {
|
||||
0
|
||||
} else if selected_visual_idx > total_items.saturating_sub(visible_height / 2) {
|
||||
total_items.saturating_sub(visible_height)
|
||||
} else {
|
||||
selected_visual_idx.saturating_sub(visible_height / 2)
|
||||
};
|
||||
|
||||
// Count topics before the scroll offset to track topic_idx correctly
|
||||
let mut topic_idx = DOCS
|
||||
let items: Vec<CategoryItem> = DOCS
|
||||
.iter()
|
||||
.take(scroll)
|
||||
.filter(|e| matches!(e, Topic(_, _)))
|
||||
.count();
|
||||
|
||||
let items: Vec<ListItem> = DOCS
|
||||
.iter()
|
||||
.skip(scroll)
|
||||
.take(visible_height)
|
||||
.map(|entry| match entry {
|
||||
Section(name) => {
|
||||
let style = Style::new().fg(theme.ui.text_dim);
|
||||
ListItem::new(format!("─ {name} ─")).style(style)
|
||||
}
|
||||
Topic(name, _) => {
|
||||
let selected = topic_idx == app.ui.help_topic;
|
||||
let style = if selected {
|
||||
Style::new()
|
||||
.fg(theme.dict.category_selected)
|
||||
.add_modifier(Modifier::BOLD)
|
||||
} else {
|
||||
Style::new().fg(theme.ui.text_primary)
|
||||
};
|
||||
let prefix = if selected { "> " } else { " " };
|
||||
topic_idx += 1;
|
||||
ListItem::new(format!("{prefix}{name}")).style(style)
|
||||
}
|
||||
Section(name) => CategoryItem {
|
||||
label: name,
|
||||
is_section: true,
|
||||
},
|
||||
Topic(name, _) => CategoryItem {
|
||||
label: name,
|
||||
is_section: false,
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
|
||||
let focused = app.ui.help_focus == HelpFocus::Topics;
|
||||
let border_color = if focused {
|
||||
theme.dict.border_focused
|
||||
} else {
|
||||
theme.dict.border_normal
|
||||
};
|
||||
let list = List::new(items).block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::new().fg(border_color))
|
||||
.title("Topics"),
|
||||
);
|
||||
frame.render_widget(list, area);
|
||||
CategoryList::new(&items, app.ui.help_topic)
|
||||
.focused(focused)
|
||||
.title("Topics")
|
||||
.selected_color(theme.dict.category_selected)
|
||||
.normal_color(theme.ui.text_primary)
|
||||
.render(frame, area);
|
||||
}
|
||||
|
||||
const WELCOME_TOPIC: usize = 0;
|
||||
@@ -237,7 +186,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let content_area = if has_search_bar {
|
||||
let [content, search] =
|
||||
Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).areas(md_area);
|
||||
render_search_bar(frame, app, search);
|
||||
render_search_bar(frame, search, &app.ui.help_search_query, app.ui.help_search_active);
|
||||
content
|
||||
} else {
|
||||
md_area
|
||||
@@ -292,18 +241,6 @@ fn wrapped_line_count(line: &RLine, width: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_search_bar(frame: &mut Frame, app: &App, area: Rect) {
|
||||
let theme = theme::get();
|
||||
let style = if app.ui.help_search_active {
|
||||
Style::new().fg(theme.search.active)
|
||||
} else {
|
||||
Style::new().fg(theme.search.inactive)
|
||||
};
|
||||
let cursor = if app.ui.help_search_active { "█" } else { "" };
|
||||
let text = format!(" /{}{cursor}", app.ui.help_search_query);
|
||||
frame.render_widget(Paragraph::new(text).style(style), area);
|
||||
}
|
||||
|
||||
fn highlight_line<'a>(line: RLine<'a>, query: &str) -> RLine<'a> {
|
||||
let theme = theme::get();
|
||||
let mut result: Vec<Span<'a>> = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user