From fb4b05fb6f048ff65e8ccd45d6169962cde31236 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sun, 23 Aug 2026 14:15:34 +0200 Subject: [PATCH] Let the date range be opened before there is a date range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pressing "limit to range" did nothing, and the reason was two early returns that sat above the line which shows the controls. If the catalog was not open, or nothing in it carried a capture date, the handler returned before `set_library_range_active`, so no state changed and nothing appeared. Capture dates are read from EXIF as thumbnails load, so a freshly opened library has none — the button was inert on exactly the libraries where someone is most likely to go looking for a date, and it failed by doing nothing at all, which is the hardest failure to report. Underneath that was a smaller mistake with the same shape: whether the controls showed was read from whether a range was set. The fields are how a range gets set, so requiring one before they appear is a door locked from the inside. The panel has its own state now, and the timeline span is a seed for the fields rather than a precondition for them — no span means two empty fields waiting to be typed into, which is a way to choose a range rather than a refusal to offer one. Co-Authored-By: Claude Opus 5 (1M context) --- ui/dr-ui/src/library_ui.rs | 51 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/ui/dr-ui/src/library_ui.rs b/ui/dr-ui/src/library_ui.rs index 819a1df..bb85245 100644 --- a/ui/dr-ui/src/library_ui.rs +++ b/ui/dr-ui/src/library_ui.rs @@ -4640,26 +4640,41 @@ pub fn wire( let ctl = ctl.clone(); window.on_library_toggle_date_range(move || { let Some(w) = weak.upgrade() else { return }; - let on = !ctl.filter.borrow().has_date_range(); + // Whether the *controls* are showing, which is not the same as + // whether a range is set — and reading it from the filter was why + // pressing this did nothing. The fields are how a range gets set, + // so requiring one before they appear is a door locked from the + // inside. + let on = !w.get_library_range_active(); if on { - // The span the axis is currently drawn over, which is what the - // user is looking at when they ask for "this range". - let borrow = ctl.catalog.borrow(); - let Some(catalog) = borrow.as_ref() else { - return; + // Seeded from the span the axis is drawn over, which is what + // the user is looking at when they ask for "this range". + // + // Only a seed. If there is no catalog yet, or nothing in it + // carries a capture date — dates are read from EXIF as + // thumbnails load, so a freshly opened library has none — the + // fields simply open empty and wait to be typed into. This + // used to `return` in both cases, which meant the button + // silently did nothing on exactly the libraries where a person + // is most likely to be looking for a date. + let seeded = { + let borrow = ctl.catalog.borrow(); + borrow + .as_ref() + .and_then(|catalog| catalog_span(catalog, &ctl)) + .map(|span| { + zoomed_span( + span, + *ctl.timeline_zoom.borrow(), + *ctl.timeline_centre.borrow(), + ) + }) }; - let Some(span) = catalog_span(catalog, &ctl) else { - return; - }; - let (from, to) = zoomed_span( - span, - *ctl.timeline_zoom.borrow(), - *ctl.timeline_centre.borrow(), - ); - drop(borrow); - let mut f = ctl.filter.borrow_mut(); - f.captured_from = Some(from); - f.captured_to = Some(to); + if let Some((from, to)) = seeded { + let mut f = ctl.filter.borrow_mut(); + f.captured_from = Some(from); + f.captured_to = Some(to); + } } else { let mut f = ctl.filter.borrow_mut(); f.captured_from = None;