From d7c985b7546328b26e60802059bf848d16e2cd20 Mon Sep 17 00:00:00 2001 From: shreeraj Date: Thu, 29 Oct 2026 22:10:54 +0530 Subject: [PATCH] Fix crash when terminal is resized taller near the bottom of the graph --- CHANGELOG.md | 4 ++++ src/widgets/graph_view.rs | 47 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e16f8e..afb4633 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Crash when the terminal is resized taller while scrolled near the bottom + ## [0.2.1] - 2026-10-24 diff --git a/src/widgets/graph_view.rs b/src/widgets/graph_view.rs index f112c99..50ee346 100644 --- a/src/widgets/graph_view.rs +++ b/src/widgets/graph_view.rs @@ -152,11 +152,14 @@ impl StatefulWidget for GraphView<'_> { } let list_height = list_area.height as usize; - let mut start = state.offset; + // The view may have grown since the last render + let mut start = state + .offset + .min(state.graph_lines.len().saturating_sub(list_height)); let height = std::cmp::min( list_height, - state.graph_lines.len().saturating_sub(state.offset), + state.graph_lines.len().saturating_sub(start), ); let mut end = start + height; @@ -310,3 +313,43 @@ impl Widget for GraphView<'_> { StatefulWidget::render(self, area, buf, &mut state); } } + +#[cfg(test)] +mod tests { + use super::*; + + fn state(lines: usize) -> GraphViewState { + GraphViewState { + graph_lines: (0..lines).map(|i| format!("* {}", i)).collect(), + text_lines: (0..lines).map(|i| format!("commit {}", i)).collect(), + indices: (0..lines).collect(), + selected: Some(lines - 1), + ..Default::default() + } + } + + fn render(state: &mut GraphViewState, height: u16) { + let area = Rect::new(0, 0, 40, height); + let mut buf = Buffer::empty(area); + let widget = GraphView::default() + .block(Block::bordered()) + .highlight_symbol("> ", "+ "); + StatefulWidget::render(widget, area, &mut buf, state); + } + + #[test] + fn resize_taller_at_bottom_does_not_panic() { + let mut state = state(100); + render(&mut state, 10); + render(&mut state, 20); + assert_eq!(state.offset, 100 - 18); + } + + #[test] + fn resize_taller_than_graph_resets_offset() { + let mut state = state(30); + render(&mut state, 10); + render(&mut state, 50); + assert_eq!(state.offset, 0); + } +}