From fa6ccc6ae577a0c13894ba66ecc30b40529e9a1c Mon Sep 17 00:00:00 2001 From: AnhNgoo <110978888+AnhNgoo@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:10:46 +0700 Subject: [PATCH 1/3] fix(engine): set default workbook author (#2448) --- crates/engine/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index f0676c772..789769dee 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -547,6 +547,7 @@ impl Session { pub fn new_workbook(&mut self) -> usize { let n = (1..).find(|n| !self.docs.iter().any(|d| d.title == format!("Book{n}") && d.path.is_none())).unwrap_or(1); let mut wb = Workbook::new(); + wb.props.author = self.prefs.user_name.clone(); for _ in 1..self.prefs.sheets_in_new_workbook.clamp(1, 255) { let name = wb.next_sheet_name(); wb.sheets.push(Arc::new(gridcraft_model::Sheet::new(name))); From a81cb0f21ef84d80cc40e31203ecd8e91d64d3dd Mon Sep 17 00:00:00 2001 From: AnhNgoo <110978888+AnhNgoo@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:22:31 +0700 Subject: [PATCH 2/3] test(engine): cover default workbook author and preservation --- crates/engine/tests/it/main.rs | 1 + crates/engine/tests/it/workbook_author.rs | 50 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 crates/engine/tests/it/workbook_author.rs diff --git a/crates/engine/tests/it/main.rs b/crates/engine/tests/it/main.rs index 4c91e58ac..95220c68f 100644 --- a/crates/engine/tests/it/main.rs +++ b/crates/engine/tests/it/main.rs @@ -28,4 +28,5 @@ mod sparse_clear_invalidation; mod stored_list_shape; mod table_resize_overlap; mod table_total_row_last_row; +mod workbook_author; mod wrap_row_height; diff --git a/crates/engine/tests/it/workbook_author.rs b/crates/engine/tests/it/workbook_author.rs new file mode 100644 index 000000000..7af8b5d68 --- /dev/null +++ b/crates/engine/tests/it/workbook_author.rs @@ -0,0 +1,50 @@ +//! Regression tests for the default author of newly created workbooks. + +use gridcraft_engine::{DocState, Session, Trust, io, model::Workbook}; + +#[test] +fn new_workbook_stamps_the_configured_user_name_at_creation() { + let mut session = Session::new(); + + session.prefs.user_name = "Ada Lovelace".into(); + let first = session.new_workbook(); + + assert_eq!(session.documents()[first].wb.props.author, "Ada Lovelace"); + + // Changing the preference must not rewrite an existing workbook. + session.prefs.user_name = "Grace Hopper".into(); + + assert_eq!(session.documents()[first].wb.props.author, "Ada Lovelace"); + + // A new workbook uses the preference as it exists at creation. + let second = session.new_workbook(); + + assert_eq!(session.documents()[second].wb.props.author, "Grace Hopper"); + + assert_eq!(session.documents()[first].wb.props.author, "Ada Lovelace"); +} + +#[test] +fn opening_and_resaving_preserves_the_existing_workbook_author() { + // An existing XLSX has its own author metadata. + let mut source = Workbook::new(); + source.props.author = "Original Spreadsheet Author".into(); + + let bytes = io::save_bytes(&source, "source.xlsx").unwrap(); + let (opened, _) = io::open_bytes("source.xlsx", &bytes).unwrap(); + + let mut session = Session::new(); + session.prefs.user_name = "Current GridCraft User".into(); + + session.add_document(DocState::new(opened, None, "source".into(), Trust::FromFile)); + + // Opening an existing workbook must not replace its author. + assert_eq!(session.doc().unwrap().wb.props.author, "Original Spreadsheet Author"); + + // The original author must survive another XLSX save and reopen. + let saved = io::save_bytes(&session.doc().unwrap().wb, "saved.xlsx").unwrap(); + + let (reopened, _) = io::open_bytes("saved.xlsx", &saved).unwrap(); + + assert_eq!(reopened.props.author, "Original Spreadsheet Author"); +} From c22f46628cdc2408e67c9f7de21bd48d775a47ac Mon Sep 17 00:00:00 2001 From: AnhNgoo <110978888+AnhNgoo@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:47:42 +0700 Subject: [PATCH 3/3] fix(desktop): load preferences before creating startup workbook --- apps/gridcraft/src/main.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/gridcraft/src/main.rs b/apps/gridcraft/src/main.rs index 988bf738b..805867267 100644 --- a/apps/gridcraft/src/main.rs +++ b/apps/gridcraft/src/main.rs @@ -311,15 +311,16 @@ fn main() -> eframe::Result<()> { { log::warn!("sample {s}: {e}"); } - if session.documents().is_empty() { - session.new_workbook(); - } let mut app = SheetApp::new(session, services()); app.watch_desktop_theme(); app.start_update_check(); - app.after_engine(); // Show warnings from the sample. let control_port = control_port; load_prefs(&mut app); + // Stamp the startup workbook's author from the persisted user name. + if app.session.documents().is_empty() { + app.session.new_workbook(); + } + app.after_engine(); // Show warnings from the sample. // Files named on the command line (a double-click on Windows and Linux) open as File › Open // opens them: a password-protected one asks for its password, and errors are shown, not // only logged. Each replaces the untouched blank Book1, as a file opened from Finder does.