diff --git a/crates/ely-lok/src/view/lane.rs b/crates/ely-lok/src/view/lane.rs index 28654f6..6920473 100644 --- a/crates/ely-lok/src/view/lane.rs +++ b/crates/ely-lok/src/view/lane.rs @@ -23,7 +23,8 @@ pub(super) struct Job { /// What came back from the lane. enum Landed { - Input(u64, bool, (io::Result>, Option)), + /// Sequence, whether it edits, whether it switched part, outcome. + Input(u64, bool, bool, (io::Result>, Option)), Tile(Job, io::Result), } @@ -46,6 +47,7 @@ impl LokView { input = input_queue.next() => { let Some((seq, input, sent)) = input else { break }; let (waited, edits) = (sent.elapsed().as_millis(), input.edits()); + let switched = matches!(input, super::input::Input::Part(_)); let outcome = super::input::run(&worker, &doc, input); let took = sent.elapsed().as_millis(); if took > SLOW_MS { @@ -53,7 +55,7 @@ impl LokView { } else { log::debug!("lok: input {seq} waited {waited}, took {took} ms"); } - Landed::Input(seq, edits, outcome) + Landed::Input(seq, edits, switched, outcome) } job = tile_queue.next() => { let Some(job) = job else { break }; @@ -96,8 +98,12 @@ impl LokView { let mut reported = false; for landed in batch { match landed { - Landed::Input(seq, edits, outcome) => { + Landed::Input(seq, edits, switched, outcome) => { self.applied = seq; + // Same tile keys, another slide or sheet. + if switched { + self.invalidate(cx); + } self.edited += u64::from(edits); let (outcome, now) = outcome; if edits { diff --git a/crates/ely-lok/src/view/tests/input.rs b/crates/ely-lok/src/view/tests/input.rs index ce3f6cf..e0cd362 100644 --- a/crates/ely-lok/src/view/tests/input.rs +++ b/crates/ely-lok/src/view/tests/input.rs @@ -269,3 +269,44 @@ fn the_clipboard_moves_html_tables_and_images() { let xml = std::fs::read_to_string(&out).expect("the save reads"); assert!(xml.contains(" + + + One + Two + +"#; + +#[test] +fn switching_slides_repaints_the_shown_tiles() { + let Some(install) = crate::client::tests::install() else { + eprintln!("SKIP: no pinned LOK build"); + return; + }; + let mut cx = TestAppContext::single(); + let (view, _) = cx.update(|app| live_view_of(app, &install, "deck.fodp", DECK)); + let before = cx.update(|app| { + view.update(app, |view, cx| { + let side = view.geom.tile_pixels() as usize; + let tile = crate::Tile { generation: view.generation, pixels: vec![0; side * side * 4] }; + view.finish_tile((0, 0), view.geom, Ok(tile), cx); + let image = Arc::clone(&view.tiles[&(0, 0)].image); + view.show_part(1); + image + }) + }); + flush(&cx); + cx.update(|app| { + let entry = &view.read(app).tiles[&(0, 0)]; + assert!( + entry.stale || !Arc::ptr_eq(&entry.image, &before), + "the first slide's tile must not stay" + ); + }); +}