mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-08 21:10:40 +00:00
Layers: a document opened after a close keeps its thumbnail jobs
Closing a document told the worker to forget every row whose document was not open at that moment. The worker keeps that test until it is idle, so while a job still ran, a document opened afterward had its rows dropped and they stayed without thumbnails. The worker now forgets only the documents that closed.
This commit is contained in:
@@ -266,18 +266,17 @@ impl Thumbs {
|
||||
return;
|
||||
}
|
||||
let open: HashSet<u64> = uids.iter().copied().collect();
|
||||
let closed = self.open_docs.as_ref().is_some_and(|before| before.iter().any(|uid| !open.contains(uid)));
|
||||
let closed: HashSet<u64> = self.open_docs.as_ref().map(|before| before.difference(&open).copied().collect()).unwrap_or_default();
|
||||
let stale =
|
||||
self.entries.keys().chain(self.pending.keys()).any(|key| !open.contains(&key.0)) || self.showing.is_some_and(|uid| !open.contains(&uid));
|
||||
self.entries.retain(|key, _| open.contains(&key.0));
|
||||
self.pending.retain(|key, _| open.contains(&key.0));
|
||||
self.showing = self.showing.filter(|uid| open.contains(uid));
|
||||
if closed {
|
||||
if !closed.is_empty() {
|
||||
// Images finished before now are dropped with the rest of the queue: the open
|
||||
// documents' rows are asked for again.
|
||||
// documents' rows are asked for again. Documents opened later keep their jobs.
|
||||
if let Some(w) = &self.worker {
|
||||
let open = open.clone();
|
||||
w.forget(move |key| !open.contains(&key.0));
|
||||
w.forget(move |key| closed.contains(&key.0));
|
||||
if w.poll().is_none() {
|
||||
self.worker = None;
|
||||
}
|
||||
@@ -536,6 +535,37 @@ mod tests {
|
||||
assert_eq!(done.key.0, next, "no worker keeps the closed document's image");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_document_opened_while_a_job_runs_after_a_close_gets_its_thumbnails() {
|
||||
let ctx = egui::Context::default();
|
||||
let Some(worker) = ThumbWorker::start(&ctx, "test") else { return };
|
||||
let mut thumbs = Thumbs { worker: Some(worker), worker_started: true, ..Default::default() };
|
||||
thumbs.retain_open(&[1, 2]);
|
||||
// A job of document 2 is running.
|
||||
let (started, running) = std::sync::mpsc::channel::<()>();
|
||||
let (release, held) = std::sync::mpsc::channel::<()>();
|
||||
let blocker = (2, NodeId(1));
|
||||
let job: crate::thumb_worker::JobFn = Box::new(move |_| {
|
||||
started.send(()).ok();
|
||||
held.recv().ok();
|
||||
None
|
||||
});
|
||||
assert!(thumbs.worker.as_ref().is_some_and(|w| w.submit(blocker, (blocker, Weak::new(), 1), job)));
|
||||
running.recv().expect("the job starts");
|
||||
// Document 1 closes, then document 3 opens and one of its rows is queued.
|
||||
thumbs.retain_open(&[2]);
|
||||
thumbs.retain_open(&[2, 3]);
|
||||
let opened = (3, NodeId(2));
|
||||
assert!(thumbs.worker.as_ref().is_some_and(|w| w.submit(opened, (opened, Weak::new(), 1), Box::new(|_| None))));
|
||||
// A job of document 2 queued after it marks the end of the queue.
|
||||
let last = (2, NodeId(3));
|
||||
assert!(thumbs.worker.as_ref().is_some_and(|w| w.submit(last, (last, Weak::new(), 1), Box::new(|_| None))));
|
||||
release.send(()).ok();
|
||||
let worker = thumbs.worker.as_ref().expect("the worker is kept");
|
||||
let order: Vec<(u64, NodeId)> = (0..3).map_while(|_| worker.wait().map(|d| d.key.0)).take_while(|key| *key != last).collect();
|
||||
assert_eq!(order, [blocker, opened], "document 3's job comes back before the last one");
|
||||
}
|
||||
|
||||
/// An open zigzag of `anchors` anchors.
|
||||
fn line(anchors: usize) -> PathData {
|
||||
let pts: Vec<Point> = (0..anchors).map(|i| Point::new(i as f64 * 0.01, (i % 2) as f64 * 50.0)).collect();
|
||||
|
||||
Reference in New Issue
Block a user