diff --git a/crates/engine/src/cmd/view.rs b/crates/engine/src/cmd/view.rs index 6135e5df..6f1320e6 100644 --- a/crates/engine/src/cmd/view.rs +++ b/crates/engine/src/cmd/view.rs @@ -138,8 +138,16 @@ fn page_step(s: &mut Session, dir: i64) -> Result { let pages = &ds.doc.pages; let i = pages.iter().position(|p| *p == ds.page).unwrap_or(0) as i64; let n = pages.len() as i64; - let next = (i + dir).clamp(0, n - 1) as usize; - let Some(pg) = pages.get(next).copied() else { return ok() }; + // Dividers never open: step over them, and stay put when only dividers lie ahead. + let mut next = i + dir; + let pg = loop { + let page = usize::try_from(next).ok().and_then(|k| pages.get(k).copied()); + match page { + Some(p) if !ds.doc.is_divider(p) => break p, + Some(_) if dir != 0 && next >= 0 && next < n => next += dir, + _ => break ds.page, + } + }; let ds = s.ds_mut()?; ds.page = pg; ds.selection.clear(); diff --git a/crates/engine/src/panels_behaviour_tests.rs b/crates/engine/src/panels_behaviour_tests.rs index c1016c29..a7b857b6 100644 --- a/crates/engine/src/panels_behaviour_tests.rs +++ b/crates/engine/src/panels_behaviour_tests.rs @@ -414,3 +414,25 @@ fn duplicating_a_layer_named_past_the_counter_does_not_overflow() { assert_eq!(name(&s, dup), "Layer 18446744073709551615 2"); assert!(s.doc().unwrap().validate().is_empty(), "the document still checks out"); } + +#[test] +fn page_navigation_skips_dividers() { + // A trailing divider: Next page stays on the ordinary page. + let mut s = Session::new(); + let first = s.page().unwrap(); + let div = id(&ex(&mut s, "page.add", json!({"name": "-"}))); + assert!(s.execute("page.select", &json!({"id": div})).is_err(), "a divider isn't a page to open"); + let r = ex(&mut s, "view.nextPage", json!({})); + assert_eq!(s.page().unwrap(), first, "Next page doesn't open a trailing divider"); + assert_eq!(id_of(&r["page"]), Some(first), "the result names the current page"); + // A middle divider: Previous page crosses it, Next page crosses it back. + let later = id(&ex(&mut s, "page.add", json!({"name": "Later"}))); + assert_eq!(s.page().unwrap(), later); + let r = ex(&mut s, "view.prevPage", json!({})); + assert_eq!(s.page().unwrap(), first, "Previous page crosses a divider"); + assert_eq!(id_of(&r["page"]), Some(first)); + ex(&mut s, "view.nextPage", json!({})); + assert_eq!(s.page().unwrap(), later, "Next page crosses a divider"); + ex(&mut s, "view.nextPage", json!({})); + assert_eq!(s.page().unwrap(), later, "Next page stops on the last page"); +}