mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
LR-VIEW-PHOTOGRID: follow test over five seeds; comment the mode switch and the names
The random-edit test now runs five seeds instead of one. A grid-mode change re-reading every photo, and the group names growing unpruned, are now said in the comments (the "a day or two at most" claim was wrong for capture-time edits). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d184b3ef50
commit
53ee38431d
@@ -150,6 +150,8 @@ impl ListRead {
|
||||
/// than photos of its own, such as a stack): read it whole then.
|
||||
fn follow(self, stats: &mut GridStats, cat: &Catalog, ids: &Arc<[PhotoId]>, dates: Option<(SortKey, GroupBy)>, shaped: bool) -> Option<ListRead> {
|
||||
if self.dates != dates || self.shapes.is_some() != shaped {
|
||||
// (a switch between the photo grid and the square grid reads every photo once, on
|
||||
// purpose: the other mode's data was never read, so there is nothing to follow)
|
||||
return None;
|
||||
}
|
||||
let touched: HashSet<PhotoId> = cat.touched_since(self.revision)?.into_iter().collect();
|
||||
@@ -157,7 +159,9 @@ impl ListRead {
|
||||
return None;
|
||||
}
|
||||
let mut r = ListRead::new(ids.clone(), cat.revision, dates, shaped);
|
||||
// (the groups' names go on: an import adds a day or two at most)
|
||||
// (the groups' names go on, unpruned: pruning would renumber every photo's group; they are
|
||||
// only reset by a whole read, and grow by a short string per day or month an edit puts a
|
||||
// photo in that no photo was in before)
|
||||
r.names = self.names;
|
||||
r.named = self.named;
|
||||
let mut was = 0;
|
||||
|
||||
@@ -285,74 +285,77 @@ fn a_batch_of_new_photos_or_an_edit_to_one_is_read_photo_by_photo() {
|
||||
/// the list changed by the photos the edit touched, else read whole.
|
||||
#[test]
|
||||
fn a_grid_followed_through_edits_shows_what_a_grid_made_afresh_shows() {
|
||||
let mut h = grid(ViewMode::PhotoGrid);
|
||||
let mut dice = 11u64;
|
||||
let mut roll = |sides: u64| {
|
||||
dice = lightcraft_catalog::mix64(dice);
|
||||
dice % sides
|
||||
};
|
||||
for step in 0..120 {
|
||||
let vis = h.app.session.visible().to_vec();
|
||||
if vis.is_empty() {
|
||||
// (no picks shown: back to every photo)
|
||||
h.app.session.filter.flag = None;
|
||||
continue;
|
||||
}
|
||||
let id = vis[roll(vis.len() as u64) as usize].0;
|
||||
let n = roll(1000);
|
||||
match roll(12) {
|
||||
0 => {
|
||||
let ops: Vec<Op> =
|
||||
(0..1 + roll(20)).map(|k| photo(&mut h, n * 100 + k, &format!("2026-{:02}-{:02}T10:00:00", 1 + n % 12, 1 + k % 28))).collect();
|
||||
h.app.session.commit("Import", Op::Batch { ops }).unwrap();
|
||||
for seed in [11u64, 12, 13, 14, 15] {
|
||||
let mut h = grid(ViewMode::PhotoGrid);
|
||||
let mut dice = seed;
|
||||
let mut roll = |sides: u64| {
|
||||
dice = lightcraft_catalog::mix64(dice);
|
||||
dice % sides
|
||||
};
|
||||
for step in 0..120 {
|
||||
let vis = h.app.session.visible().to_vec();
|
||||
if vis.is_empty() {
|
||||
// (no picks shown: back to every photo)
|
||||
h.app.session.filter.flag = None;
|
||||
continue;
|
||||
}
|
||||
1 => {
|
||||
let _ = h.app.session.commit("Delete", Op::SetDeleted { id: PhotoId(id), deleted: true });
|
||||
}
|
||||
2 => {
|
||||
let _ = h
|
||||
.app
|
||||
.session
|
||||
.commit("Capture time", Op::SetCaptured { id: PhotoId(id), captured: Some(format!("2026-{:02}-03T10:00:00", 1 + n % 12)) });
|
||||
}
|
||||
3 => {
|
||||
h.app.session.execute("library.select", &json!({"ids": [id]})).unwrap();
|
||||
let r = h.app.session.execute("photo.rotateRight", &json!({}));
|
||||
assert!(r.is_ok(), "{r:?}");
|
||||
}
|
||||
4 => {
|
||||
let mut d = (*h.app.session.catalog.photo(PhotoId(id)).unwrap().develop).clone();
|
||||
d.crop.geometry.rect = lightcraft_geom::Rect::new(0.1, 0.0, 0.9 - 0.1 * (n % 4) as f64, 1.0);
|
||||
h.app
|
||||
.session
|
||||
.commit("Crop", Op::SetDevelop { id: PhotoId(id), settings: std::sync::Arc::new(d), label: "Crop".into(), edited: None })
|
||||
.unwrap();
|
||||
}
|
||||
5 => h.app.session.commit("Rating", Op::SetRating { id: PhotoId(id), rating: (n % 6) as u8 }).unwrap(),
|
||||
6 => {
|
||||
let key = ["captureDate", "fileName", "importDate"][n as usize % 3];
|
||||
let r = h.app.session.execute("library.sort", &json!({"key": key, "ascending": n.is_multiple_of(2)}));
|
||||
assert!(r.is_ok(), "{r:?}");
|
||||
}
|
||||
7 => {
|
||||
// a stack: an edit to more than its photos, read whole
|
||||
let other = vis[n as usize % vis.len()].0;
|
||||
let _ = h.app.session.execute("stack.group", &json!({"ids": [id, other], "top": id, "collapsed": n.is_multiple_of(2)}));
|
||||
}
|
||||
8 => {
|
||||
let _ = h.app.session.execute("edit.undo", &json!({}));
|
||||
}
|
||||
9 => {
|
||||
// picks, for the filter below to show some
|
||||
for k in 0..1 + n % 40 {
|
||||
let p = vis[(n as usize * 7 + k as usize * 13) % vis.len()];
|
||||
h.app.session.commit("Flag", Op::SetFlag { id: p, flag: lightcraft_catalog::Flag::Pick }).unwrap();
|
||||
let id = vis[roll(vis.len() as u64) as usize].0;
|
||||
let n = roll(1000);
|
||||
match roll(12) {
|
||||
0 => {
|
||||
let ops: Vec<Op> = (0..1 + roll(20))
|
||||
.map(|k| photo(&mut h, n * 100 + k, &format!("2026-{:02}-{:02}T10:00:00", 1 + n % 12, 1 + k % 28)))
|
||||
.collect();
|
||||
h.app.session.commit("Import", Op::Batch { ops }).unwrap();
|
||||
}
|
||||
1 => {
|
||||
let _ = h.app.session.commit("Delete", Op::SetDeleted { id: PhotoId(id), deleted: true });
|
||||
}
|
||||
2 => {
|
||||
let _ = h
|
||||
.app
|
||||
.session
|
||||
.commit("Capture time", Op::SetCaptured { id: PhotoId(id), captured: Some(format!("2026-{:02}-03T10:00:00", 1 + n % 12)) });
|
||||
}
|
||||
3 => {
|
||||
h.app.session.execute("library.select", &json!({"ids": [id]})).unwrap();
|
||||
let r = h.app.session.execute("photo.rotateRight", &json!({}));
|
||||
assert!(r.is_ok(), "{r:?}");
|
||||
}
|
||||
4 => {
|
||||
let mut d = (*h.app.session.catalog.photo(PhotoId(id)).unwrap().develop).clone();
|
||||
d.crop.geometry.rect = lightcraft_geom::Rect::new(0.1, 0.0, 0.9 - 0.1 * (n % 4) as f64, 1.0);
|
||||
h.app
|
||||
.session
|
||||
.commit("Crop", Op::SetDevelop { id: PhotoId(id), settings: std::sync::Arc::new(d), label: "Crop".into(), edited: None })
|
||||
.unwrap();
|
||||
}
|
||||
5 => h.app.session.commit("Rating", Op::SetRating { id: PhotoId(id), rating: (n % 6) as u8 }).unwrap(),
|
||||
6 => {
|
||||
let key = ["captureDate", "fileName", "importDate"][n as usize % 3];
|
||||
let r = h.app.session.execute("library.sort", &json!({"key": key, "ascending": n.is_multiple_of(2)}));
|
||||
assert!(r.is_ok(), "{r:?}");
|
||||
}
|
||||
7 => {
|
||||
// a stack: an edit to more than its photos, read whole
|
||||
let other = vis[n as usize % vis.len()].0;
|
||||
let _ = h.app.session.execute("stack.group", &json!({"ids": [id, other], "top": id, "collapsed": n.is_multiple_of(2)}));
|
||||
}
|
||||
8 => {
|
||||
let _ = h.app.session.execute("edit.undo", &json!({}));
|
||||
}
|
||||
9 => {
|
||||
// picks, for the filter below to show some
|
||||
for k in 0..1 + n % 40 {
|
||||
let p = vis[(n as usize * 7 + k as usize * 13) % vis.len()];
|
||||
h.app.session.commit("Flag", Op::SetFlag { id: p, flag: lightcraft_catalog::Flag::Pick }).unwrap();
|
||||
}
|
||||
}
|
||||
10 => h.app.ui.view = if h.app.ui.view == ViewMode::PhotoGrid { ViewMode::SquareGrid } else { ViewMode::PhotoGrid },
|
||||
_ => h.app.session.filter.flag = n.is_multiple_of(2).then_some(lightcraft_catalog::Flag::Pick),
|
||||
}
|
||||
10 => h.app.ui.view = if h.app.ui.view == ViewMode::PhotoGrid { ViewMode::SquareGrid } else { ViewMode::PhotoGrid },
|
||||
_ => h.app.session.filter.flag = n.is_multiple_of(2).then_some(lightcraft_catalog::Flag::Pick),
|
||||
h.step();
|
||||
assert_as_made_afresh(&mut h, &format!("seed {seed}, after step {step}"));
|
||||
}
|
||||
h.step();
|
||||
assert_as_made_afresh(&mut h, &format!("after step {step}"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user