Never lose work: atomic saves (temporary file, flush, rename) keeping the replaced version as <file>.bak; autosave of unsaved changes into a recovery folder (every 5 min, preference autosave_minutes, and after commands over 1.5 s; skipped when unchanged; entries locked while their app runs); Recover unsaved design? at launch; doc.recovery_list / doc.recover / doc.recovery_discard; kill-mid-save test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 11:37:33 +00:00
1 parent 01b349842c
commit f40356a74f
11 files changed
+679 -1

No files matched your search

+8
View File
@@ -35,6 +35,9 @@ impl eframe::App for App {
fn save(&mut self, storage: &mut dyn eframe::Storage) {
storage.set_string(PREFS_KEY, self.0.prefs());
}
fn on_exit(&mut self) {
solvecraft_ui_egui::recovery_ui::close(&mut self.0);
}
}
/// Where the preferences (theme) are kept in eframe's storage.
@@ -134,6 +137,11 @@ fn main() -> eframe::Result {
let rev = app.session.revision;
app.home.show(rev);
}
// Autosave, and offer what crashed sessions left behind.
if let Some(dir) = solvecraft_engine::recovery::default_dir() {
let every = if app.autosave_minutes > 0.0 { app.autosave_minutes * 60.0 } else { f64::MAX / 4.0 };
solvecraft_ui_egui::recovery_ui::start(&mut app, &dir, std::time::Duration::from_secs_f64(every.min(1e9)));
}
Ok(Box::new(App(app)))
}),
)