From 6dd265067f3c307272808ec5d8908eb47bcf7d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Forment?= Date: Wed, 25 Feb 2026 23:29:11 +0100 Subject: [PATCH] Fix: boundary fix in help/dict views --- src/services/dict_nav.rs | 3 ++- src/services/help_nav.rs | 3 ++- src/state/ui.rs | 6 +++++- src/views/dict_view.rs | 1 + src/views/help_view.rs | 1 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/services/dict_nav.rs b/src/services/dict_nav.rs index c8be53b..59bcdbe 100644 --- a/src/services/dict_nav.rs +++ b/src/services/dict_nav.rs @@ -96,8 +96,9 @@ pub fn prev_category(ui: &mut UiState) { } pub fn scroll_down(ui: &mut UiState, n: usize) { + let max = ui.dict_max_scroll.get(); let s = ui.dict_scroll_mut(); - *s = s.saturating_add(n); + *s = s.saturating_add(n).min(max); } pub fn scroll_up(ui: &mut UiState, n: usize) { diff --git a/src/services/help_nav.rs b/src/services/help_nav.rs index 1958be8..fcbb648 100644 --- a/src/services/help_nav.rs +++ b/src/services/help_nav.rs @@ -98,8 +98,9 @@ pub fn prev_topic(ui: &mut UiState, n: usize) { } pub fn scroll_down(ui: &mut UiState, n: usize) { + let max = ui.help_max_scroll.get(); let s = ui.help_scroll_mut(); - *s = s.saturating_add(n); + *s = s.saturating_add(n).min(max); } pub fn scroll_up(ui: &mut UiState, n: usize) { diff --git a/src/state/ui.rs b/src/state/ui.rs index a00a8d3..93831ff 100644 --- a/src/state/ui.rs +++ b/src/state/ui.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::time::{Duration, Instant}; use cagire_markdown::ParsedMarkdown; @@ -57,6 +57,8 @@ pub struct UiState { pub dict_scrolls: Vec, pub dict_search_query: String, pub dict_search_active: bool, + pub help_max_scroll: Cell, + pub dict_max_scroll: Cell, pub help_collapsed: Vec, pub help_on_section: Option, pub dict_collapsed: Vec, @@ -107,6 +109,8 @@ impl Default for UiState { dict_scrolls: vec![0; crate::model::categories::category_count()], dict_search_query: String::new(), dict_search_active: false, + help_max_scroll: Cell::new(usize::MAX), + dict_max_scroll: Cell::new(usize::MAX), help_collapsed: vec![false; crate::model::docs::section_count()], help_on_section: None, dict_collapsed: vec![false; crate::model::categories::section_count()], diff --git a/src/views/dict_view.rs b/src/views/dict_view.rs index eb9a3d9..617c355 100644 --- a/src/views/dict_view.rs +++ b/src/views/dict_view.rs @@ -160,6 +160,7 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) { let visible_height = content_area.height.saturating_sub(2) as usize; let total_lines = lines.len(); let max_scroll = total_lines.saturating_sub(visible_height); + app.ui.dict_max_scroll.set(max_scroll); let scroll = app.ui.dict_scroll().min(max_scroll); let title = if is_searching { diff --git a/src/views/help_view.rs b/src/views/help_view.rs index 45137a7..3be3354 100644 --- a/src/views/help_view.rs +++ b/src/views/help_view.rs @@ -223,6 +223,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) { .map(|l| wrapped_line_count(l, content_width)) .sum(); let max_scroll = total_wrapped.saturating_sub(visible_height); + app.ui.help_max_scroll.set(max_scroll); let scroll = app.ui.help_scroll().min(max_scroll); let mut lines = parsed.lines.clone();