Open: opening an already-open file focuses its tab (#1620)

Co-authored-by: GLM <noreply@z.ai>
This commit is contained in:
Eduardo Soares
2026-10-12 22:55:19 -03:00
co-authored by GLM
parent 42cfc6a8f2
commit 95a769eedc
3 changed files with 47 additions and 1 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ impl LastSession {
/// `path` made absolute against the current directory, without resolving links (and without
/// Windows' `\\?\` prefix, which `canonicalize` adds).
#[cfg(not(target_arch = "wasm32"))]
fn absolute(path: &str) -> String {
pub(crate) fn absolute(path: &str) -> String {
std::path::absolute(path).map_or_else(|_| path.to_string(), |p| p.to_string_lossy().into_owned())
}
+16
View File
@@ -1208,8 +1208,24 @@ impl PdfCraftApp {
}
}
/// The tab already showing the file at `path`, if any: its position in `views`. Paths are
/// compared after `absolute` normalization, so another spelling of the same file matches
/// (#1620).
#[cfg(not(target_arch = "wasm32"))]
fn view_showing(&self, path: &str) -> Option<usize> {
let path = crate::last_session::absolute(path);
self.views
.iter()
.position(|v| self.session.get(v.id).and_then(|d| d.path.as_deref()).map(crate::last_session::absolute).as_deref() == Some(path.as_str()))
}
#[cfg(not(target_arch = "wasm32"))]
pub fn open_path(&mut self, path: &str) {
if let Some(i) = self.view_showing(path) {
self.startup_superseded = true;
self.active = Some(i);
return;
}
let name = std::path::Path::new(path).file_name().map(|n| n.to_string_lossy().into_owned()).unwrap_or_else(|| path.to_string());
match std::fs::read(path) {
Ok(bytes) => {
+30
View File
@@ -653,6 +653,36 @@ fn the_last_session_is_off_by_default_and_skips_missing_and_duplicate_files() {
assert!(later.views.is_empty(), "neither opens from the session");
}
#[test]
fn opening_the_same_path_again_focuses_its_tab() {
let pdfs = TempPdfs::new("dedup-open");
let a = pdfs.file("a.pdf", 1);
let b = pdfs.file("b.pdf", 1);
let mut h = session_harness(|_| {});
h.state_mut().open_path(&a);
h.state_mut().open_path(&b);
h.run_steps(2);
assert_eq!(h.state().views.len(), 2, "two different files open two tabs");
h.state_mut().open_path(&a);
h.run_steps(2);
assert_eq!(h.state().views.len(), 2, "opening an open file again adds no tab");
assert_eq!(h.state().active, Some(0), "the existing tab comes to the front");
assert_eq!(open_paths(h.state()), vec![a, b], "the tab order is untouched");
}
#[test]
fn opening_the_same_file_with_a_dot_component_focuses_its_tab() {
let pdfs = TempPdfs::new("dedup-dot");
let a = pdfs.file("a.pdf", 1);
let dotted = format!("{}/./a.pdf", pdfs.0.display());
let mut h = session_harness(|_| {});
h.state_mut().open_path(&a);
h.state_mut().open_path(&dotted);
h.run_steps(2);
assert_eq!(h.state().views.len(), 1, "another spelling of the same file matches");
assert_eq!(h.state().active, Some(0));
}
#[test]
fn save_prompt_stays_inside_the_screen_for_a_long_filename() {
// Issue #161: an unwrapped title carrying a long filename widened the centered modal past