Main green: revert the start page change (#4295) and fix the format 28 test (#4335)

* Revert "Start page: sample pictures and the existence check of recent files run off the window thread (#4295)"

This reverts commit d9059d8da5.

* Test: an older design is marked format 28 now that 0.18.3 folded face pieces into 29

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bherbruck
2026-10-21 10:52:08 -04:00
committed by GitHub
parent e570c0b4eb
commit 775e5155bb
2 changed files with 10 additions and 69 deletions
@@ -444,6 +444,8 @@ fn a_design_saved_before_pieces_were_numbered_by_place_keeps_their_numbers() {
if let Some(Value::Array(pending)) = file.get_mut("format_pending") {
pending.retain(|c| c != "face-pieces-by-place");
}
// 0.18.3 folded the change into format 29, so a build before it wrote 28.
file["format"] = Value::String(solidcraft_doc::format::format_string(28));
let old = solidcraft_doc::Document::from_json(&file.to_string()).unwrap();
assert!(old.features.iter().all(|f| f.kernel_piece_order), "the features of an older design keep the old numbering");
let mut reopened = Session::new(old);
+8 -69
View File
@@ -47,13 +47,6 @@ pub struct HomeState {
remembering: Option<std::sync::mpsc::Receiver<Made>>,
/// A sample picked before its design was ready.
wanted: Option<usize>,
/// Whether each recent file is there, found off the window thread (a stat of a slow or
/// disconnected drive must not hold up the page); unknown counts as there.
present: HashMap<String, bool>,
#[cfg(not(target_arch = "wasm32"))]
present_asked: std::collections::HashSet<String>,
#[cfg(not(target_arch = "wasm32"))]
present_rx: Vec<std::sync::mpsc::Receiver<(String, bool)>>,
}
impl HomeState {
@@ -267,10 +260,6 @@ fn make(key: &str) -> Made {
fn read_pictures(keys: Vec<String>, tx: &std::sync::mpsc::Sender<Made>) -> Option<Vec<String>> {
let mut cold = Vec::new();
for key in keys {
if let Some(i) = key.strip_prefix("samplepic:").and_then(|i| i.parse::<usize>().ok()) {
tx.send((format!("sample:{i}"), sample_picture(i), None)).ok()?;
continue;
}
match std::panic::catch_unwind(|| picture(&key)).ok().flatten() {
Some(img) => tx.send((key, Some(img), None)).ok()?,
None => cold.push(key),
@@ -438,7 +427,7 @@ pub fn open_sample(app: &mut SolveApp, i: usize) {
/// Is this recent design there to open: in memory, or something the host can bring back?
pub fn available(app: &SolveApp, path: &str) -> bool {
app.home.present.get(path).copied().unwrap_or(true) || app.services.can_restore.as_ref().is_some_and(|can| can(path))
solidcraft_engine::io::vfs::exists(path) || app.services.can_restore.as_ref().is_some_and(|can| can(path))
}
pub fn open_recent(app: &mut SolveApp, path: &str) {
@@ -454,39 +443,6 @@ pub fn open_recent(app: &mut SolveApp, path: &str) {
app.open_path_async(path);
}
/// Find out whether the recent files are there: on a thread, so the page never waits on a drive.
fn ask_present(h: &mut HomeState, ctx: &egui::Context, recent: &[String]) {
#[cfg(not(target_arch = "wasm32"))]
{
let new: Vec<String> = recent.iter().filter(|p| h.present_asked.insert((*p).clone())).cloned().collect();
if !new.is_empty() {
let (tx, rx) = std::sync::mpsc::channel();
let ctx = ctx.clone();
let spawned = std::thread::Builder::new().name("recent-files".into()).spawn(move || {
for p in new {
let there = solidcraft_engine::io::vfs::exists(&p);
if tx.send((p, there)).is_err() {
return;
}
ctx.request_repaint();
}
});
if spawned.is_ok() {
h.present_rx.push(rx);
}
}
for rx in &h.present_rx {
while let Ok((p, there)) = rx.try_recv() {
h.present.insert(p, there);
}
}
}
#[cfg(target_arch = "wasm32")]
for p in recent {
h.present.insert(p.clone(), solidcraft_engine::io::vfs::exists(p));
}
}
/// The page itself (in place of the toolbar, browser and viewport).
pub fn show(app: &mut SolveApp, ui: &mut egui::Ui) {
poll(app, ui.ctx());
@@ -497,23 +453,12 @@ pub fn show(app: &mut SolveApp, ui: &mut egui::Ui) {
for i in 0..samples.len() {
let key = format!("sample:{i}");
if !app.home.thumbs.contains_key(&key) {
// Decoded on the thumbnail thread where there is one; the card shows its placeholder
// until the picture arrives.
#[cfg(not(target_arch = "wasm32"))]
{
app.home.queued.push(format!("samplepic:{i}"));
app.home.thumbs.insert(key, None);
}
#[cfg(target_arch = "wasm32")]
install(&mut app.home, ui.ctx(), &key, sample_picture(i));
}
}
let recent = app.home.recent.clone();
ask_present(&mut app.home, ui.ctx(), &recent);
for p in &recent {
if app.home.present.get(p).copied().unwrap_or(true) {
want(&mut app.home, p);
}
for p in recent.iter().filter(|p| solidcraft_engine::io::vfs::exists(p)) {
want(&mut app.home, p);
}
let mut action: Option<Box<dyn FnOnce(&mut SolveApp)>> = None;
egui::CentralPanel::default().frame(egui::Frame::NONE.fill(t.panel).inner_margin(egui::Margin::symmetric(36, 24))).show(ui, |ui| {
@@ -772,9 +717,6 @@ mod tests {
h.app.services.can_restore = Some(Box::new(|p| p.starts_with("/disk/known/")));
h.app.services.restore_file = Some(Box::new(move |p| sink.borrow_mut().push(p.to_string())));
assert!(available(&h.app, "/disk/known/Bracket.solidcraft"));
// A file is taken to be there until the background check says it is not.
assert!(available(&h.app, "/disk/other/Bracket.solidcraft"));
h.app.home.present.insert("/disk/other/Bracket.solidcraft".into(), false);
assert!(!available(&h.app, "/disk/other/Bracket.solidcraft"));
open_recent(&mut h.app, "/disk/known/Bracket.solidcraft");
assert_eq!(*asked.borrow(), ["/disk/known/Bracket.solidcraft"]);
@@ -928,18 +870,15 @@ mod tests {
}
#[test]
fn first_home_frame_shows_placeholders_and_the_sample_pictures_arrive_without_building_any_model() {
fn first_home_frame_shows_all_samples_without_building_any_models() {
let mut h = crate::scenario::Harness::new();
h.app.home.show(0);
h.frames(1);
assert!(h.app.home.ready_samples() < solidcraft_engine::sample::samples().len(), "the first frame decodes nothing");
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(30);
while h.app.home.ready_samples() < solidcraft_engine::sample::samples().len() && std::time::Instant::now() < deadline {
std::thread::sleep(std::time::Duration::from_millis(10));
h.frames(1);
}
assert_eq!(h.app.home.ready_samples(), solidcraft_engine::sample::samples().len());
assert!(h.app.home.samples.is_empty(), "no sample model was built");
assert!(h.app.home.samples.is_empty());
assert!(h.app.home.queued.is_empty());
#[cfg(not(target_arch = "wasm32"))]
assert!(h.app.home.sample_rx.is_none() && h.app.home.rx.is_none());
}
#[cfg(not(target_arch = "wasm32"))]