Fix cursor getting stuck when Enter pressed on last row

move_selection() only clamped at 0, letting the row/col index go past
the last valid item. Selected_cell_key() would then return None, leaving
the cursor in a phantom position with no selectable cell.

Now clamp both row and col against the actual item count so pressing
Enter on the last row keeps the cursor on that row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ed L
2026-03-21 23:05:57 -07:00
parent c9d1313072
commit 413601517d
2 changed files with 140 additions and 28 deletions

View File

@ -899,11 +899,31 @@ impl App {
// ── Motion helpers ─────────────────────────────────────────────────────── // ── Motion helpers ───────────────────────────────────────────────────────
fn move_selection(&mut self, dr: i32, dc: i32) { fn move_selection(&mut self, dr: i32, dc: i32) {
// Compute max row/col from actual item counts so we never go out of bounds.
let row_max = {
let row_cats: Vec<String> = self.model.active_view()
.map(|v| v.categories_on(crate::view::Axis::Row).into_iter().map(String::from).collect())
.unwrap_or_default();
row_cats.first()
.and_then(|c| self.model.category(c))
.map(|c| c.items.len().saturating_sub(1))
.unwrap_or(0)
};
let col_max = {
let col_cats: Vec<String> = self.model.active_view()
.map(|v| v.categories_on(crate::view::Axis::Column).into_iter().map(String::from).collect())
.unwrap_or_default();
col_cats.first()
.and_then(|c| self.model.category(c))
.map(|c| c.items.len().saturating_sub(1))
.unwrap_or(0)
};
if let Some(view) = self.model.active_view_mut() { if let Some(view) = self.model.active_view_mut() {
let (r, c) = view.selected; let (r, c) = view.selected;
view.selected = ( view.selected = (
(r as i32 + dr).max(0) as usize, (r as i32 + dr).clamp(0, row_max as i32) as usize,
(c as i32 + dc).max(0) as usize, (c as i32 + dc).clamp(0, col_max as i32) as usize,
); );
} }
} }

View File

@ -128,29 +128,6 @@
"Number": 3.0 "Number": 3.0
} }
], ],
[
[
[
"Month",
"Janury"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Food"
]
],
{
"Number": 12.0
}
],
[ [
[ [
[ [
@ -196,6 +173,121 @@
{ {
"Number": 5.0 "Number": 5.0
} }
],
[
[
[
"Month",
"February"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Medical"
]
],
{
"Number": 33.0
}
],
[
[
[
"Month",
"February"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Gas"
]
],
{
"Number": 55.0
}
],
[
[
[
"Month",
"February"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Food"
]
],
{
"Number": 4.0
}
],
[
[
[
"Month",
"February"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Clothing"
]
],
{
"Text": "i5"
}
],
[
[
[
"Month",
"Janury"
],
[
"Payer",
"Bernadette"
],
[
"Recipient",
"Bob"
],
[
"Type",
"Food"
]
],
{
"Number": 12.0
}
] ]
], ],
"formulas": [], "formulas": [],
@ -217,8 +309,8 @@
"row_offset": 0, "row_offset": 0,
"col_offset": 0, "col_offset": 0,
"selected": [ "selected": [
1, 6,
1 2
] ]
} }
}, },