mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Fix #3455: Home recent reopen focuses existing document
## Summary document.open with a path that is already open in another tab now activates that document instead of reading the file again and opening a second window, matching Illustrator Home › Recent Files when the file is already open. The result includes activated: true; unsaved edits and the active tab are kept. ## Tests open_same_path_activates_existing_document in cmd::fileio::tests. Closes storytold/vectorcraft#3455 Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
This commit is contained in:
committed by
bflatastic
co-authored by
nrq6993-a11y
parent
e5b732baf5
commit
11eb27b127
@@ -369,6 +369,11 @@ pub fn open_bytes(s: &mut Session, name: &str, bytes: &[u8], path: Option<String
|
||||
|
||||
/// [`open_bytes`] with the `document.open` options in `p` ([`LoadOptions::from_params`]).
|
||||
pub fn open_bytes_with(s: &mut Session, name: &str, bytes: &[u8], path: Option<String>, p: &Value) -> Result<Value> {
|
||||
if let Some(path) = path.as_deref()
|
||||
&& let Some(index) = document_index_for_path(s, path)
|
||||
{
|
||||
return activate_open_document(s, index);
|
||||
}
|
||||
let update_links = s.prefs.update_links == "automatically";
|
||||
open_read(s, read_for_open(name, bytes, path, p, update_links)?)
|
||||
}
|
||||
@@ -704,3 +709,22 @@ fn same_file(a: &str, b: &str) -> bool {
|
||||
_ => a == b,
|
||||
}
|
||||
}
|
||||
|
||||
/// The open document whose saved path is the same file as `path`, if any.
|
||||
fn document_index_for_path(s: &Session, path: &str) -> Option<usize> {
|
||||
s.documents().iter().position(|st| st.path.as_deref().is_some_and(|p| same_file(p, path)))
|
||||
}
|
||||
|
||||
/// Bring an already-open document to the front instead of reading the file again (Home › Recent).
|
||||
fn activate_open_document(s: &mut Session, index: usize) -> Result<Value> {
|
||||
s.set_active(index);
|
||||
let st = &s.documents()[index];
|
||||
Ok(json!({
|
||||
"index": index,
|
||||
"title": st.title(),
|
||||
"format": st.format,
|
||||
"warnings": [],
|
||||
"restored": false,
|
||||
"activated": true,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -363,6 +363,25 @@ fn templates_open_untitled() {
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_same_path_activates_existing_document() {
|
||||
let mut s = Session::new();
|
||||
let dir = tmp_dir("reopen");
|
||||
let path = dir.join("doc.vectorcraft").to_string_lossy().to_string();
|
||||
let mut fresh = Session::new();
|
||||
fresh.execute("file.new", &json!({"width": 100, "height": 100})).unwrap();
|
||||
std::fs::write(&path, b64(&fresh.execute("document.serialize", &json!({})).unwrap())).unwrap();
|
||||
s.execute("document.open", &json!({"path": path})).unwrap();
|
||||
assert_eq!(s.documents().len(), 1);
|
||||
s.execute("shape.rectangle", &json!({"x": 1, "y": 2, "width": 10, "height": 10})).unwrap();
|
||||
let r = s.execute("document.open", &json!({"path": path})).unwrap();
|
||||
assert_eq!(r["activated"], true);
|
||||
assert_eq!(s.documents().len(), 1);
|
||||
assert_eq!(s.active_index(), Some(0));
|
||||
assert_eq!(s.doc().unwrap().doc.layers[0].children().unwrap().len(), 1);
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_exts_cover_every_readable_format() {
|
||||
for f in FORMATS.iter().filter(|f| f.read) {
|
||||
|
||||
Reference in New Issue
Block a user