mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-31 21:48:53 -06:00
LRC-SS-LAYOUT: the Slideshow settings page no longer moves when the slide preview finishes rendering
The preview's hint line was drawn only after the render had landed, so the pinned preview block grew by a line on the frame the render arrived (a worker thread, so any frame) and the page below it moved down. A click made in that frame hit the wrong place: the gate's tests_slideshow::playback_settings_drive_the_slideshow_and_bad_ones_are_refused clicked "Random order" and the checkbox never changed. The hint is drawn while the preview is still rendering too. A new test holds the render back, then lets it land, and checks that the page and a control keep their places.
This commit is contained in:
@@ -247,9 +247,14 @@ pub fn preview(app: &mut LightcraftApp, ui: &mut egui::Ui, t: &Tokens, max_h: f3
|
||||
} else {
|
||||
ui.ctx().request_repaint_after(std::time::Duration::from_secs_f64((DEBOUNCE - still).clamp(0.01, DEBOUNCE)));
|
||||
}
|
||||
let say =
|
||||
|ui: &mut egui::Ui| hint(ui, t, "The selected photo as a slide. Playback fills the screen; the aspect preview only changes this preview.");
|
||||
let Some(tex) = app.renderer.textures.get(&Slot::SlidePreview).filter(|tex| tex.photo == id) else {
|
||||
p.rect_filled(rect, 0.0, Color32::from_rgb(s.backdrop_color[0], s.backdrop_color[1], s.backdrop_color[2]));
|
||||
p.text(rect.center(), Align2::CENTER_CENTER, crate::i18n::tr("Rendering…"), t.font(11.5), Color32::from_gray(200));
|
||||
// (the hint too: the render lands on a frame nobody can name, and a line that came with it would push
|
||||
// the pinned preview's block, and the page under it, down while a control is being clicked)
|
||||
say(ui);
|
||||
return;
|
||||
};
|
||||
let drawn = crate::panels::detail::fit_texture_rect(rect, tex.size);
|
||||
@@ -269,7 +274,7 @@ pub fn preview(app: &mut LightcraftApp, ui: &mut egui::Ui, t: &Tokens, max_h: f3
|
||||
p.line_segment([pos2(drawn.left(), gy), pos2(drawn.right(), gy)], stroke);
|
||||
}
|
||||
}
|
||||
hint(ui, t, "The selected photo as a slide. Playback fills the screen; the aspect preview only changes this preview.");
|
||||
say(ui);
|
||||
}
|
||||
|
||||
/// The preview showing title screen `title` (composed off the UI thread like the photo's slide,
|
||||
|
||||
@@ -400,6 +400,29 @@ fn playback_settings_drive_the_slideshow_and_bad_ones_are_refused() {
|
||||
h.settle(SETTLE);
|
||||
}
|
||||
|
||||
/// The slide preview's render lands on a frame nobody can name (a worker thread); the page under it must
|
||||
/// not move when it does, or a click made in that frame lands beside the control aimed at (the gate went
|
||||
/// red on it: `playback_settings_…` clicks "Random order" and the checkbox never changed).
|
||||
#[test]
|
||||
fn the_settings_page_does_not_move_when_the_slide_preview_finishes_rendering() {
|
||||
let mut h = grid();
|
||||
let open = std::rc::Rc::new(std::cell::Cell::new(false));
|
||||
h.app.renderer.set_offload(Box::new(crate::headless::RenderGate::new(open.clone())));
|
||||
run(&mut h, "view.slideshowOptions", json!({}));
|
||||
// (the held render keeps the app "busy", so settle() would wait out its timeout: a second of frames instead)
|
||||
for _ in 0..60 {
|
||||
h.step();
|
||||
}
|
||||
let rect = |h: &Headless, w: &str| h.app.widgets.iter().find(|(id, _)| id == w).map(|(_, r)| *r).unwrap_or_else(|| panic!("{w} is on screen"));
|
||||
let (room, check) = (rect(&h, "settings:pageRoom"), rect(&h, "check:settings.slideshowRandom"));
|
||||
assert!(!h.app.renderer.textures.contains_key(&Slot::SlidePreview), "the render is held back");
|
||||
open.set(true);
|
||||
assert!(h.step_until(SETTLE, |h| h.app.renderer.textures.contains_key(&Slot::SlidePreview)), "the render lands");
|
||||
h.settle(Duration::from_secs(5));
|
||||
assert_eq!(rect(&h, "settings:pageRoom"), room, "the page's room is the same before and after the render");
|
||||
assert_eq!(rect(&h, "check:settings.slideshowRandom"), check, "a control stays where it was drawn");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_click_on_a_control_scrolled_out_of_the_settings_page_is_refused() {
|
||||
// A compact window leaves the lower controls of the Slideshow settings page outside the
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
## 2026-10-24
|
||||
|
||||
### The Slideshow settings page stays put while the preview renders
|
||||
- In Settings ▸ Slideshow, the line under the slide preview ("The selected photo as a slide…") now shows from the first
|
||||
frame instead of only once the preview has finished rendering. Before, it appeared with the render, pushing the page
|
||||
below it down by a line, so a click made in that moment could land beside the control you aimed at.
|
||||
|
||||
### Relative-date filters and smart albums follow the clock
|
||||
- A current view or source count using “in the last” rules now refreshes when the session clock moves into a new
|
||||
minute, even when no catalog edit occurred. This fixes stale photos remaining in the grid and stale counts for
|
||||
|
||||
Reference in New Issue
Block a user