diff --git a/crates/tui/src/app.rs b/crates/tui/src/app.rs index 05548a0..d6eebf5 100644 --- a/crates/tui/src/app.rs +++ b/crates/tui/src/app.rs @@ -246,7 +246,6 @@ impl App { /// Returns (start_logical, offset_in_line) for rendering. pub(crate) fn ensure_viewport_cache(&mut self, width: usize) -> (usize, usize) { let viewport_height = self.content_height as usize; - let v_offset = self.v_offset; if !self.is_loaded() || width == 0 || viewport_height == 0 { return (0, 0); @@ -268,7 +267,7 @@ impl App { // Find start logical line from v_offset let (start_logical, offset_in_line) = if self.is_loading() { - (v_offset.min(self.total_lines().saturating_sub(1)), self.v_sub_offset) + (self.v_offset.min(self.total_lines().saturating_sub(1)), self.v_sub_offset) } else { self.find_logical_line_at_visual_row(self.v_offset, width) }; @@ -2538,6 +2537,42 @@ plain text line assert!(result.is_ok()); } + /// Regression test for issue #24: + /// ensure_viewport_cache must use the updated self.v_offset after params_changed + /// recalculates it, not a stale local captured before the change block. + #[test] + fn test_loading_viewport_cache_uses_updated_v_offset_on_params_changed() { + let content: String = (0..200).map(|i| format!("line{i}\n")).collect(); + let path = make_temp_file(&content); + let result = std::panic::catch_unwind(|| { + let mut app = App::new(); + app.load_file(path.to_str().unwrap()).unwrap(); + assert!(app.is_loading(), "should be in Loading state"); + + app.content_height = 10; + app.ensure_viewport_cache(80); + + app.v_offset = 90; + app.cursor_line = 100; + + let new_width = 40; + app.ensure_viewport_cache(new_width); + + let recomputed_offset = app.v_offset; + assert_ne!( + recomputed_offset, 90, + "v_offset should have been recalculated by params_changed block, still 90" + ); + + assert_eq!( + app.viewport_cache.logical_start, recomputed_offset.min(app.total_lines().saturating_sub(1)), + "logical_start should match the updated v_offset" + ); + }); + cleanup(&path); + assert!(result.is_ok()); + } + fn install_vhi(app: &mut App, heights: &[usize]) { let width = app.get_content_width(); let json_format = app.json_format;