mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-27 20:06:53 -06:00
M7: keep saved document titles in sync with filenames
This commit is contained in:
@@ -542,7 +542,8 @@ fn load_with(
|
||||
return Ok((figcraft_format::Loaded { issues: warnings, ..doc.into() }, true));
|
||||
}
|
||||
let mut loaded = figcraft_format::load_bytes_with_versions(bytes).map_err(|e| EngineError::Other(e.to_string()))?;
|
||||
if loaded.doc.name.is_empty() {
|
||||
// Older files saved an untouched default title even after the user chose a filename.
|
||||
if loaded.doc.name.is_empty() || loaded.doc.name == "Untitled" {
|
||||
loaded.doc.name = file_stem(name_hint);
|
||||
}
|
||||
Ok((loaded, false))
|
||||
@@ -853,8 +854,14 @@ fn save_to(s: &mut Session, path: String) -> Result<Value> {
|
||||
}
|
||||
let i = crate::branches::file_tab(s);
|
||||
let ds = s.docs.get_mut(i).ok_or(EngineError::NoDocument)?;
|
||||
let bytes = file_bytes(ds)?;
|
||||
let mut snapshot = FileSnapshot::of(ds);
|
||||
let follows_path = ds.path.as_deref().map_or(ds.doc.name == "Untitled", |old| ds.doc.name == file_stem(old));
|
||||
if follows_path && ds.path.as_deref() != Some(path.as_str()) {
|
||||
Arc::make_mut(&mut snapshot.doc).name = file_stem(&path);
|
||||
}
|
||||
let bytes = snapshot.encode()?;
|
||||
write(&path, &bytes)?;
|
||||
ds.doc = snapshot.doc;
|
||||
ds.path = Some(path.clone());
|
||||
ds.mark_saved();
|
||||
ds.revision += 1;
|
||||
|
||||
@@ -1062,7 +1062,9 @@ impl Session {
|
||||
};
|
||||
let Some(ds) = self.docs.iter_mut().find(|d| d.uid == uid) else { return };
|
||||
let changed = !Arc::ptr_eq(&ds.doc, &bdoc);
|
||||
if changed {
|
||||
// Saving may adopt the chosen filename as the document title. The encoded snapshot is
|
||||
// already final; normalising it again would detach it from the saved baseline.
|
||||
if changed && !matches!(spec.id, "file.save" | "file.saveAs") {
|
||||
normalize(ds.doc_mut(), &bdoc);
|
||||
}
|
||||
let edit = changed && ds.interaction.is_none();
|
||||
|
||||
@@ -265,7 +265,7 @@ fn revert_offline_file_works_while_another_file_is_live_and_after_leaving() {
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let offline_path = saved_file(&mut s);
|
||||
s.execute("file.revert", &json!({})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().name, "Untitled");
|
||||
assert_eq!(s.doc().unwrap().name, offline_path.file_stem().unwrap().to_string_lossy());
|
||||
assert!(!s.ds().unwrap().is_dirty());
|
||||
assert_eq!(s.ds().unwrap().versions.len(), 1);
|
||||
assert_eq!(s.live_of(uid).doc_uid, Some(uid));
|
||||
@@ -273,7 +273,7 @@ fn revert_offline_file_works_while_another_file_is_live_and_after_leaving() {
|
||||
s.execute("doc.switch", &json!({"index": 0})).unwrap();
|
||||
s.execute("collab.leave", &json!({})).unwrap();
|
||||
s.execute("file.revert", &json!({})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().name, "Untitled");
|
||||
assert_eq!(s.doc().unwrap().name, path.file_stem().unwrap().to_string_lossy());
|
||||
assert!(!s.ds().unwrap().is_dirty());
|
||||
assert_eq!(s.ds().unwrap().versions.len(), 1);
|
||||
assert_eq!(s.live().doc_uid, None);
|
||||
|
||||
@@ -89,6 +89,46 @@ fn assert_save_state_unchanged(s: &Session, before: &DocState, recent: &[String]
|
||||
assert_eq!(s.prefs.recent_files, recent);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_native_save_uses_chosen_filename_for_an_untitled_document() {
|
||||
let mut files = SaveFiles::new();
|
||||
let path = files.path("Redis.figcraft");
|
||||
let copy = files.path("Redis copy.figcraft");
|
||||
let manual_copy = files.path("Other.figcraft");
|
||||
let mut s = Session::new();
|
||||
s.execute("file.saveAs", &json!({"path": path.to_string_lossy()})).unwrap();
|
||||
assert_eq!(s.ds().unwrap().doc.name, "Redis");
|
||||
assert!(!s.ds().unwrap().is_dirty());
|
||||
assert_eq!(figcraft_format::load_bytes(&std::fs::read(&path).unwrap()).unwrap().0.name, "Redis");
|
||||
|
||||
let mut reopened = Session::empty();
|
||||
reopened.execute("file.open", &json!({"path": path.to_string_lossy()})).unwrap();
|
||||
assert_eq!(reopened.ds().unwrap().doc.name, "Redis");
|
||||
|
||||
s.execute("file.saveAs", &json!({"path": copy.to_string_lossy()})).unwrap();
|
||||
assert_eq!(s.ds().unwrap().doc.name, "Redis copy");
|
||||
s.execute("file.rename", &json!({"name": "Chosen title"})).unwrap();
|
||||
s.execute("file.saveAs", &json!({"path": manual_copy.to_string_lossy()})).unwrap();
|
||||
assert_eq!(s.ds().unwrap().doc.name, "Chosen title");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opening_an_older_file_uses_its_filename_only_for_the_default_title() {
|
||||
let mut files = SaveFiles::new();
|
||||
let old_path = files.path("Redis.figcraft");
|
||||
let named_path = files.path("Other.figcraft");
|
||||
let mut original = Session::new();
|
||||
std::fs::write(&old_path, crate::cmd::file::file_bytes(original.ds().unwrap()).unwrap()).unwrap();
|
||||
original.execute("file.rename", &json!({"name": "Chosen title"})).unwrap();
|
||||
std::fs::write(&named_path, crate::cmd::file::file_bytes(original.ds().unwrap()).unwrap()).unwrap();
|
||||
|
||||
let mut reopened = Session::empty();
|
||||
reopened.execute("file.open", &json!({"path": old_path.to_string_lossy()})).unwrap();
|
||||
assert_eq!(reopened.ds().unwrap().doc.name, "Redis");
|
||||
reopened.execute("file.open", &json!({"path": named_path.to_string_lossy()})).unwrap();
|
||||
assert_eq!(reopened.ds().unwrap().doc.name, "Chosen title");
|
||||
}
|
||||
|
||||
fn read_fig(path: &std::path::Path, result: &Value) -> figcraft_doc::Document {
|
||||
let bytes = std::fs::read(path).unwrap();
|
||||
assert_eq!(result["format"], "fig");
|
||||
|
||||
Reference in New Issue
Block a user