mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #3502 from nrq6993-a11y/stream/vc-feat1-3455-home-reopen-focus
Fix #3455: Home recent reopen focuses existing document
This commit is contained in:
@@ -3094,7 +3094,7 @@ fn recent(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
for path in files {
|
||||
if recent_row(ui, &path).clicked() {
|
||||
// A failure is reported to the user there.
|
||||
let _ = crate::io::open_reporting(app, &path);
|
||||
let _ = crate::io::open_recent_reporting(app, &path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +214,44 @@ pub fn open_reporting(app: &mut VectorcraftApp, path: &str) -> Result<Value, Str
|
||||
r
|
||||
}
|
||||
|
||||
/// Home › Recent Files and File › Open Recent: focus an already-open tab for that path instead of
|
||||
/// calling `document.open` again (#3455).
|
||||
pub fn open_recent_reporting(app: &mut VectorcraftApp, path: &str) -> Result<Value, String> {
|
||||
if let Some(r) = try_activate_open_document(app, path)? {
|
||||
return Ok(r);
|
||||
}
|
||||
open_reporting(app, path)
|
||||
}
|
||||
|
||||
fn try_activate_open_document(app: &mut VectorcraftApp, path: &str) -> Result<Option<Value>, String> {
|
||||
let Some(index) = document_index_for_path(app, path) else {
|
||||
return Ok(None);
|
||||
};
|
||||
let st = &app.session.documents()[index];
|
||||
let r = json!({
|
||||
"index": index,
|
||||
"title": st.title(),
|
||||
"format": st.format,
|
||||
"warnings": [],
|
||||
"restored": false,
|
||||
"activated": true,
|
||||
});
|
||||
app.run("document.activate", json!({ "index": index }))?;
|
||||
opened(app, &r);
|
||||
Ok(Some(r))
|
||||
}
|
||||
|
||||
fn document_index_for_path(app: &VectorcraftApp, path: &str) -> Option<usize> {
|
||||
app.session.documents().iter().position(|st| st.path.as_deref().is_some_and(|p| same_open_path(p, path)))
|
||||
}
|
||||
|
||||
fn same_open_path(a: &str, b: &str) -> bool {
|
||||
match (std::fs::canonicalize(a), std::fs::canonicalize(b)) {
|
||||
(Ok(a), Ok(b)) => a == b,
|
||||
_ => a == b,
|
||||
}
|
||||
}
|
||||
|
||||
fn read(app: &VectorcraftApp, path: &str) -> Result<Vec<u8>, String> {
|
||||
app.services.read.as_ref().ok_or("no file reader")?(path)
|
||||
}
|
||||
|
||||
@@ -1266,7 +1266,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
|
||||
"file.cancelExport" => Ok(io::cancel_exports(app)),
|
||||
"file.exportInBackground" => Ok(io::hide_exports(app)),
|
||||
id if id.starts_with("file.openRecent") => match recent_slot(app, id).cloned() {
|
||||
Some(path) => io::open_reporting(app, &path),
|
||||
Some(path) => io::open_recent_reporting(app, &path),
|
||||
None => Err("no such recent file".into()),
|
||||
},
|
||||
"type.findFont" => {
|
||||
|
||||
@@ -297,3 +297,31 @@ fn home_scrolls_in_a_short_window() {
|
||||
visible_home_texts(&mut app, &ctx, size, 4.1, vec![press(false)]);
|
||||
assert_eq!(app.session.documents().len(), 1, "the card opened its preset");
|
||||
}
|
||||
|
||||
/// Home › Recent Files and File › Open Recent focus an open tab instead of opening a second copy
|
||||
/// (#3455); `document.open` is unchanged.
|
||||
#[test]
|
||||
fn home_recent_reopen_focuses_an_already_open_document() {
|
||||
let services = crate::Services {
|
||||
read: Some(Box::new(|p: &str| std::fs::read(p).map_err(|e| e.to_string()))),
|
||||
write: Some(Box::new(|p: &str, b: &[u8]| std::fs::write(p, b).map_err(|e| e.to_string()))),
|
||||
..Default::default()
|
||||
};
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), services);
|
||||
let d = std::env::temp_dir().join(format!("vc-home-reopen-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
let path = d.join("doc.vectorcraft").to_string_lossy().to_string();
|
||||
app.run("file.new", json!({"width": 100, "height": 100})).unwrap();
|
||||
app.run("shape.rectangle", json!({"x": 1, "y": 2, "width": 10, "height": 10})).unwrap();
|
||||
app.run("file.saveAs", json!({"path": path})).unwrap();
|
||||
app.run("file.new", json!({})).unwrap();
|
||||
assert_eq!(app.session.documents().len(), 2);
|
||||
assert_eq!(app.session.active_index(), Some(1));
|
||||
let r = crate::io::open_recent_reporting(&mut app, &path).unwrap();
|
||||
assert_eq!(r["activated"], true);
|
||||
assert_eq!(app.session.documents().len(), 2);
|
||||
assert_eq!(app.session.active_index(), Some(0));
|
||||
assert_eq!(app.session.doc().unwrap().doc.layers[0].children().unwrap().len(), 1);
|
||||
let _ = std::fs::remove_dir_all(d);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user