From 8a3192f623b9fb672228a8111a1f1d12463101d6 Mon Sep 17 00:00:00 2001 From: DWAA1660 Date: Thu, 12 Nov 2026 11:11:22 -0700 Subject: [PATCH] fix(ui-egui): Save picture never writes over an existing file Draw > Save picture always wrote `ink-picture.svg`, replacing whatever was there: a picture saved earlier and kept, or another file of the owner's under that name (#158). It now writes the first free name of `ink-picture.svg`, `ink-picture-2.svg`, ... and opens it with `create_new`, so a taken name is never written over. The window already says where the picture went. Fixes #158 Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/inkpad.rs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/crates/ui-egui/src/inkpad.rs b/crates/ui-egui/src/inkpad.rs index b96cbe9..09d39e9 100644 --- a/crates/ui-egui/src/inkpad.rs +++ b/crates/ui-egui/src/inkpad.rs @@ -167,13 +167,30 @@ impl Pad { /// Writes it again as a plain picture, beside the ink, for sending somewhere else. /// Returns where it was written. + /// + /// The picture goes into a file of its own, `ink-picture.svg` or the first of + /// `ink-picture-2.svg`, `ink-picture-3.svg` … that is free. A file already there may be a + /// picture saved earlier and kept on purpose, or something else of the owner's under that + /// name, and is never written over (issue #158). pub fn save_plain(&self) -> std::io::Result { - let plain = self.file.with_file_name("ink-picture.svg"); - if let Some(parent) = plain.parent() { - std::fs::create_dir_all(parent)?; + let folder = self.file.parent().map(Path::to_path_buf).unwrap_or_default(); + std::fs::create_dir_all(&folder)?; + let text = svg::write(&self.drawing, svg::Flavour::Plain); + for n in 1usize..=10_000 { + let name = if n == 1 { "ink-picture.svg".to_string() } else { format!("ink-picture-{n}.svg") }; + let plain = folder.join(name); + // `create_new` refuses a name that is taken, even one taken a moment ago. + match std::fs::OpenOptions::new().write(true).create_new(true).open(&plain) { + Ok(mut file) => { + use std::io::Write; + file.write_all(text.as_bytes())?; + return Ok(plain); + } + Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => continue, + Err(e) => return Err(e), + } } - std::fs::write(&plain, svg::write(&self.drawing, svg::Flavour::Plain))?; - Ok(plain) + Err(std::io::Error::new(std::io::ErrorKind::AlreadyExists, "every ink-picture name in this folder is taken")) } /// Moves the strokes of an old inserted sheet onto the page, and says how many came. @@ -843,6 +860,15 @@ mod tests { let text = std::fs::read_to_string(&plain).expect("read"); assert!(text.contains("