No reload flash when the rescan finds nothing new
The scan's final set_list replaced the whole model unconditionally: generation bump + painted-state clear + set_vec, so Slint recreated every row and every visible thumbnail flashed out and back — even when the rescan changed nothing (the normal warm start). Now: - unchanged list -> status line only, model untouched - displayed list is a prefix of the final one (cold-start fill) -> append the tail rows in place (no row recreation) - genuine change -> full replacement (the correct signal there)
This commit is contained in:
parent
16526a402a
commit
835659131e
46
src/lib.rs
46
src/lib.rs
|
|
@ -1184,10 +1184,50 @@ fn scan_thread(weak: &slint::Weak<Main>) {
|
||||||
let n = entries.len();
|
let n = entries.len();
|
||||||
let ms = t0.elapsed().as_millis();
|
let ms = t0.elapsed().as_millis();
|
||||||
log::info!("gallery: scan {n} files ({ins}+ {upd}~ {del}-) in {ms} ms");
|
log::info!("gallery: scan {n} files ({ins}+ {upd}~ {del}-) in {ms} ms");
|
||||||
|
let status = format!("{n} files ({ins}+ {upd}~ {del}–) in {ms} ms");
|
||||||
|
|
||||||
// Final list: set_list bumps the generation + re-anchors the viewport;
|
// Scan finished: touch the model ONLY if what's on screen actually
|
||||||
// the next tick fills it (warm start: disk-cache hits, nearly free).
|
// changed. A full set_list bumps the generation (drops in-flight +
|
||||||
set_list(weak, entries, format!("{n} files ({ins}+ {upd}~ {del}–) in {ms} ms"));
|
// painted state) and replaces the list model — Slint recreates every
|
||||||
|
// row and every visible thumbnail flashes out and back, even when the
|
||||||
|
// rescan found nothing new. The normal warm start must be a no-op.
|
||||||
|
let same = |a: &Entry, b: &Entry| a.path == b.path && a.mtime == b.mtime && a.size == b.size;
|
||||||
|
let cur: Vec<Entry> = state().entries.lock().unwrap().clone();
|
||||||
|
if cur.len() == entries.len() && cur.iter().zip(&entries).all(|(a, b)| same(a, b)) {
|
||||||
|
log::info!("gallery: rescan unchanged — keeping live list (no reload)");
|
||||||
|
set_status(weak, status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Progressive-fill case (cold start): the displayed list is the final
|
||||||
|
// list's prefix — append the tail in place instead of replacing (no row
|
||||||
|
// recreation, no flash, no generation bump).
|
||||||
|
if entries.len() > cur.len()
|
||||||
|
&& entries[..cur.len()].iter().zip(&cur).all(|(a, b)| same(a, b))
|
||||||
|
{
|
||||||
|
let tail: Vec<Entry> = entries[cur.len()..].to_vec();
|
||||||
|
let full = entries;
|
||||||
|
log::info!(
|
||||||
|
"gallery: rescan added {} — extending list in place",
|
||||||
|
tail.len()
|
||||||
|
);
|
||||||
|
let weak = weak.clone();
|
||||||
|
let _ = slint::invoke_from_event_loop(move || {
|
||||||
|
let Some(w) = weak.upgrade() else { return };
|
||||||
|
let Some(app) = STATE.get() else { return };
|
||||||
|
*app.entries.lock().unwrap() = full;
|
||||||
|
if let Some(m) = w.get_items().as_any().downcast_ref::<VecModel<Item>>() {
|
||||||
|
let at = m.row_count();
|
||||||
|
for (i, it) in chunk(&tail).into_iter().enumerate() {
|
||||||
|
m.insert(at + i, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.set_status(status.into());
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Genuine change (files added mid-list, modified, removed): full
|
||||||
|
// replacement — the one case where the flash is the correct signal.
|
||||||
|
set_list(weak, entries, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A clone of `AndroidApp` kept for the app's whole lifetime so the Java side
|
/// A clone of `AndroidApp` kept for the app's whole lifetime so the Java side
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user