fix(tui): use updated v_offset after params_changed in ensure_viewport_cache (#24)
The loading branch of ensure_viewport_cache captured v_offset before the params_changed block, which could reassign self.v_offset. This caused the viewport to use a stale offset when loading + width/format changed together. Remove the stale local variable and read self.v_offset directly, consistent with the non-loading branch. Add regression test.
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user