diff --git a/src/app/commands/fileops.rs b/src/app/commands/fileops.rs index a6ef731d0..6b98a3d44 100644 --- a/src/app/commands/fileops.rs +++ b/src/app/commands/fileops.rs @@ -211,7 +211,7 @@ impl OpenCADStudio { if let Some(id) = self.main_window { return Some(Task::done(Message::WindowCloseRequested(id))); } - return Some(iced::exit()); + return Some(self.exit_app()); } // ── Frame-budget HUD (Phase 5.3) ─────────────────────────────── diff --git a/src/app/update/dialog.rs b/src/app/update/dialog.rs index fc2b96079..0ed6eefe3 100644 --- a/src/app/update/dialog.rs +++ b/src/app/update/dialog.rs @@ -186,7 +186,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven self.pending_close = Some(crate::app::PendingClose::Quit); } else { let close_win = self.close_unsaved_dialog_window(); - return Task::batch(vec![close_win, iced::exit()]); + return Task::batch(vec![close_win, self.exit_app()]); } } None => {} @@ -252,7 +252,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven self.pending_close = Some(crate::app::PendingClose::Quit); } else { let close_win = self.close_unsaved_dialog_window(); - return Task::batch(vec![close_win, iced::exit()]); + return Task::batch(vec![close_win, self.exit_app()]); } } None => {} @@ -299,7 +299,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven self.pending_close = Some(crate::app::PendingClose::Quit); return self.open_unsaved_dialog_window(); } else { - return iced::exit(); + return self.exit_app(); } } Err(e) => { diff --git a/src/app/update/file.rs b/src/app/update/file.rs index bf56d6662..ed14dba89 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -550,6 +550,8 @@ pub(super) fn on_open_file(&mut self) -> Task { self.command_line .push_output(&format!("Saved: {}", path.display())); self.tabs[i].dirty = false; + // A clean save supersedes any autosave recovery copy. + let _ = std::fs::remove_file(path.with_extension("sv$")); } Err(e) => self.command_line.push_error(&format!("Save failed: {e}")), } @@ -615,6 +617,8 @@ pub(super) fn on_open_file(&mut self) -> Task { .push_output(&format!("Saved: {}", path.display())); self.tabs[i].current_path = Some(path.clone()); self.tabs[i].dirty = false; + // A clean save supersedes any autosave recovery copy. + let _ = std::fs::remove_file(path.with_extension("sv$")); if self.save_dialog_for_unsaved { let next = self.update(Message::UnsavedPickedSavePath(Some(path))); return Task::batch([close, next]); @@ -712,6 +716,23 @@ pub(super) fn on_open_file(&mut self) -> Task { Task::none() } + /// Delete the `.sv$` autosave recovery files for all open drawings. They + /// exist only to survive a crash, so a clean save or exit removes them. + pub(in crate::app) fn cleanup_autosaves(&self) { + #[cfg(not(target_arch = "wasm32"))] + for t in &self.tabs { + if let Some(path) = &t.current_path { + let _ = std::fs::remove_file(path.with_extension("sv$")); + } + } + } + + /// Remove the autosave recovery files, then quit the application. + pub(in crate::app) fn exit_app(&self) -> Task { + self.cleanup_autosaves(); + iced::exit() + } + pub(super) fn on_page_setup_commit(&mut self) -> Task { let i = self.active_tab; let layout_name = self.tabs[i].scene.current_layout.clone(); diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 69088eb19..526476e2c 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -809,7 +809,7 @@ impl OpenCADStudio { self.pending_close = Some(super::PendingClose::Quit); return self.open_unsaved_dialog_window(); } - return iced::exit(); + return self.exit_app(); } Task::none() } @@ -818,7 +818,7 @@ impl OpenCADStudio { // Only the main window exists now; all dialogs are in-canvas // modals (Plan B). Closing it exits. if self.main_window == Some(id) { - return iced::exit(); + return self.exit_app(); } Task::none() }