diff --git a/ATTRIBUTION.toml b/ATTRIBUTION.toml
index cc007dc7..616c4bae 100644
--- a/ATTRIBUTION.toml
+++ b/ATTRIBUTION.toml
@@ -7,7 +7,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Greek UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "d7ad8f46f105638aff5b91423fe74077af5bf1f3246eeb9e066df8e4df0e222e"
+sha256 = "f158bd9cc2557593365171f28f76fc38b95e7ce07faf2ff8b651d99a540f82a6"
# ATTRIBUTION.toml: one entry per asset (AGENTS.md §1). The source of truth for provenance and licences.
# ATTRIBUTION.md is generated from this file: `cargo xtask assets --write`. Checked by `cargo xtask assets` (part of `xtask ci`).
@@ -30,7 +30,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Simplified Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "7df6e3aebce85e8eaac46465ab46d0c8447f314cdcdbe41ba4fc0188a2105f14"
+sha256 = "26c2f0ead5f4dd87d946ba11b4c2b8d442e87d54b2ec8dc15f7abfe187eccc3f"
[[asset]]
path = "crates/ui-egui/src/i18n/zh-hant.tsv"
@@ -41,7 +41,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Traditional Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "49eccf2decfc53724250e685bb448c41ccadcf6906fa56ba9b13d8047329ab99"
+sha256 = "658f1c4a24029fd767cabecb8f8f3be2eacc0d09f710eae0e7aceb03cc628f32"
[[asset]]
path = "crates/ui-egui/src/i18n/cs.tsv"
@@ -52,7 +52,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Czech UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "6abec13d351d38a12e4634f64bbf6b884c8102af1f97da7e08cbcd29de14a5ba"
+sha256 = "640636e260b8bc726d40d6d7101698640de5028df0d67935a16741491fb3cb5f"
[[asset]]
path = "crates/ui-egui/src/i18n/pt-br.tsv"
@@ -63,7 +63,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Brazilian Portuguese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "afa953e566e7b9533df28845b52a768f77c7d8aa254cd3bbe1928ddf28019efa"
+sha256 = "bf92cc2ebf7a1a7ae1f7c4fd270ca7643530bc6f8b38d5cba4da3594498f2889"
[[asset]]
path = "crates/ui-egui/src/i18n/es.tsv"
@@ -74,7 +74,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "1de0258b9b1ea7c375ef71d8c4cbeeebbc0f976cb6aead04bdd1d06d18f7c717"
+sha256 = "7c12f6bf221a654ce22e77fc723e621daf8dd52ceafd6bff075b7b070d484aa2"
[[asset]]
path = "crates/ui-egui/src/i18n/fr.tsv"
@@ -85,7 +85,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "French UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "59ac5e705d8d74273ce774cb2dd8020313277ae2a376ae2967031d60ae590745"
+sha256 = "3d16bf1a86f7d8108ec64569e18db00eafba174092f27ca93c8281ffb93a8c39"
[[asset]]
path = "crates/ui-egui/src/i18n/de.tsv"
@@ -96,7 +96,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "36e814e0bec4fab77c7a0face806fa14269c1964b9850d19765d4b41b4503300"
+sha256 = "64cfe3444b8c0cf1bc91938567b52ed52fccd9124e2a567f8ac2d710510b7c30"
[[asset]]
path = "crates/ui-egui/src/i18n/te.tsv"
@@ -107,7 +107,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Telugu UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "22c8d5335c7b7be2e7a735e94b076ab9aead4817335953387f1122691b00e04e"
+sha256 = "7e1c2cebada9fd1d065d10496e77e6c0ae4b08ef9145292b1ce216fe476036ba"
[[asset]]
path = "crates/ui-egui/src/i18n/it.tsv"
@@ -118,7 +118,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Italian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "3c2740ffdf370e1dc1cd3fbfd4da05185a0d247233fcb143c63c2f560a072cd2"
+sha256 = "4ed39c62cf09008372d5f079458bb7ab80ed62786c58e8193ded3d35e8fea521"
[[asset]]
path = "crates/ui-egui/src/i18n/pl.tsv"
@@ -129,7 +129,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Polish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "755fadd87a23d56ff3319ed58b4651b386603a86ceed1a74919403a9a1f5698b"
+sha256 = "92ceee115cfb37b94dd7c5aad674896d3529b1f5637b1fd9529458b7d91ab8df"
[[asset]]
path = "crates/ui-egui/src/i18n/ru.tsv"
@@ -140,7 +140,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Russian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "3455f5598efb906ad12921cb9264761d7eb8f180d26ef02e8c3ab041d5f63f76"
+sha256 = "1e1524a817f7ee2b53aa7d48e0d755173578060d2fae9fa3d9c7ecd18ec3b0f0"
[[asset]]
path = "crates/ui-egui/src/i18n/hu.tsv"
@@ -151,7 +151,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Hungarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "0f9ae32a12fd0285d5e11a523019f410894533669a20ba16ad6ded4907ee8f55"
+sha256 = "faee788eefd418d93caded400a81ea33a5ec5ea20ae62bf36f344a694027c7b5"
[[asset]]
path = "crates/ui-egui/src/i18n/bg.tsv"
@@ -162,7 +162,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Bulgarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "3e1386f1e8c6412a5a685b127b4871c5ea5e7e1c91428a1a402dca61b785f103"
+sha256 = "d88ae2bc2ad294ef9daa783768feb9827c3a90bf60f0c022cf714ddd8d5e2606"
[[asset]]
path = "crates/ui-egui/src/i18n/kk.tsv"
@@ -173,7 +173,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Kazakh UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "134d6c9787407e8634c2749adcf40c8f15f89e6262e902547f8ef0022e548f72"
+sha256 = "203245e46fdddd99a6e9c2fac1b05db6f6e3a3347369a2d0dc5846dcd0293c32"
[[asset]]
path = "crates/ui-egui/src/i18n/ja.tsv"
@@ -184,7 +184,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Japanese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "6dfc2b9e312a888fd0a11426129d38654e40f59888c2c90b1be1751b5893daa3"
+sha256 = "d9e8acae91cb85b22abd2f8e7d285709d200f8b9b60e09370e3c1919328607c0"
[[asset]]
path = "crates/ui-egui/src/i18n/uk.tsv"
@@ -195,7 +195,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Ukrainian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "46f7addc24737c5700b8dff69392d16b24c67b92f0bf92444b806f3f9e107195"
+sha256 = "bcb35726d63d4f154df5a389d3be46b53b6de9836e79d79b5fb13cd5aa9c5157"
[[asset]]
path = "crates/ui-egui/src/i18n/ar.tsv"
@@ -206,7 +206,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "a680284dc350985b9f0742e258ff6e8d05e2d30513a0d9444c915d250ba1ed9a"
+sha256 = "7550018b4737b4ee689d38c31b5ea2093e26a18ccd717661b80a68778a0fb652"
[[asset]]
path = "crates/ui-egui/src/i18n/tr.tsv"
@@ -217,7 +217,7 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Turkish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "1a1db9cd9a6d3ba59eeb739a8961e57183320dd11ca9f8750c6683ed5bc243a3"
+sha256 = "45580772203b30915881c8945d33e6edc6363d7b5583fc0eff5acface163b37b"
[[asset]]
path = "assets/icons/accessibility.svg"
@@ -3328,4 +3328,4 @@ licence = "MIT OR Apache-2.0"
licence_file = "LICENSE-MIT"
kind = "translation"
usage = "Slovene UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
-sha256 = "499b2ea8dbb49c4d59f4ac360e72a64ac4f3eb2760521c4e9b8f135297180823"
+sha256 = "a9c8fd94278a41acda913e7d3242da627701207a1ac187f2bf2b5a9fddcf6aa8"
diff --git a/README.md b/README.md
index fce87cf3..b20179ff 100644
--- a/README.md
+++ b/README.md
@@ -133,6 +133,8 @@ Search the whole document as you type, step through matches with ⌘G
## Navigate long documents
+Right-click a PDF tab to close it, reopen the last closed file-backed tab, or reveal its file. Closing still asks about unsaved changes. Reopening reads the saved file from disk; it does not restore discarded edits. Reveal selects the file in Explorer or Finder. On Linux and FreeBSD it requests `org.freedesktop.FileManager1.ShowItems`, falling back to opening the containing directory with `xdg-open` when that service is unavailable. Reopen and Reveal are unavailable on the web; Reveal is also unavailable for pathless documents.
+
Bookmarks, page thumbnails and the document's own page labels (i, ii, 1, 2…) keep you oriented in long documents. Search bookmark titles in the Bookmarks panel to find nested entries even when their parents are collapsed. Matches keep their ancestors for context; Clear restores the unfiltered tree without changing its expansion state.
diff --git a/crates/ui-egui/src/chrome.rs b/crates/ui-egui/src/chrome.rs
index d83e1bee..1f2d2371 100644
--- a/crates/ui-egui/src/chrome.rs
+++ b/crates/ui-egui/src/chrome.rs
@@ -88,6 +88,7 @@ pub fn tab_strip(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
data.insert_temp(id, state);
changed
});
+ let mut action = None;
let mut close = None;
ui.scope(|ui| {
ui.style_mut().always_scroll_the_only_direction = true;
@@ -119,12 +120,34 @@ pub fn tab_strip(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
if changed && app.active == Some(i) && !app.combine_showing() {
response.scroll_to_me(Some(Align::Center));
}
+ let id = app.views[i].id;
+ let reveal = cfg!(not(target_arch = "wasm32")) && doc.path.is_some();
+ response.context_menu(|ui| {
+ if ui.button(tl!("Close Tab")).clicked() {
+ action = Some(crate::tab_context::Action::Close(id));
+ ui.close();
+ }
+ if ui.add_enabled(!app.closed_tabs.is_empty(), egui::Button::new(tl!("Reopen Closed Tab"))).clicked() {
+ action = Some(crate::tab_context::Action::Reopen);
+ ui.close();
+ }
+ let label = if cfg!(target_os = "macos") { tl!("Reveal in Finder") } else { tl!("Reveal in File Explorer") };
+ if ui.add_enabled(reveal, egui::Button::new(label)).clicked() {
+ action = Some(crate::tab_context::Action::Reveal(id));
+ ui.close();
+ }
+ });
if response.clicked() {
app.active = Some(i);
}
}
- if let Some(i) = close {
- app.request_close_tab(i);
+ if let Some(i) = close
+ && let Some(view) = app.views.get(i)
+ {
+ action.get_or_insert(crate::tab_context::Action::Close(view.id));
+ }
+ if let Some(action) = action {
+ app.tab_action(action);
}
if app.combine_tab.open {
// After the document tabs; its index can't clash with theirs.
diff --git a/crates/ui-egui/src/i18n/ar.tsv b/crates/ui-egui/src/i18n/ar.tsv
index b3881170..29702ad4 100644
--- a/crates/ui-egui/src/i18n/ar.tsv
+++ b/crates/ui-egui/src/i18n/ar.tsv
@@ -2337,6 +2337,12 @@ animation effects Off معطّلة
Ink sensitivity حساسية الحبر
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. لم يُعثر على توقيع داخل الإطار. حرّك الإطار فوق التوقيع أو ارفع حساسية الحبر.
Couldn't use the photo: {e} تعذّر استخدام الصورة: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab إغلاق علامة التبويب
+ Reopen Closed Tab إعادة فتح علامة التبويب المغلقة
+ Reveal in Finder إظهار في Finder
+ Reveal in File Explorer إظهار في مستكشف الملفات
Other colour… لون آخر…
Recent colours الألوان الأخيرة
Couldn't follow linked PDF: {reason} تعذّر فتح ملف PDF المرتبط: {reason}
diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv
index efc6a483..719f3129 100644
--- a/crates/ui-egui/src/i18n/bg.tsv
+++ b/crates/ui-egui/src/i18n/bg.tsv
@@ -2279,6 +2279,12 @@ animation effects Off Изключени
Ink sensitivity Чувствителност към мастило
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. В рамката не е открит подпис. Преместете рамката върху подписа или увеличете чувствителността към мастило.
Couldn't use the photo: {e} Снимката не може да се използва: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Затваряне на раздела
+ Reopen Closed Tab Отваряне на затворения раздел
+ Reveal in Finder Показване във Finder
+ Reveal in File Explorer Показване във файловия мениджър
Other colour… Друг цвят…
Recent colours Последни цветове
Couldn't follow linked PDF: {reason} Свързаният PDF не можа да бъде отворен: {reason}
diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv
index 42d6afc9..1d4f057c 100644
--- a/crates/ui-egui/src/i18n/cs.tsv
+++ b/crates/ui-egui/src/i18n/cs.tsv
@@ -2390,6 +2390,12 @@ animation effects Off Vypnuto
Ink sensitivity Citlivost na inkoust
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. V rámečku nebyl nalezen žádný podpis. Přesuňte rámeček na podpis nebo zvyšte citlivost na inkoust.
Couldn't use the photo: {e} Fotografii nelze použít: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Zavřít kartu
+ Reopen Closed Tab Znovu otevřít zavřenou kartu
+ Reveal in Finder Zobrazit ve Finderu
+ Reveal in File Explorer Zobrazit v Průzkumníku souborů
Other colour… Jiná barva…
Recent colours Nedávné barvy
Couldn't follow linked PDF: {reason} Odkazovaný PDF nelze otevřít: {reason}
diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv
index bf81b3d5..e99ed095 100644
--- a/crates/ui-egui/src/i18n/de.tsv
+++ b/crates/ui-egui/src/i18n/de.tsv
@@ -2317,6 +2317,12 @@ animation effects Off Aus
Ink sensitivity Tintenempfindlichkeit
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Im Rahmen wurde keine Unterschrift gefunden. Ziehen Sie den Rahmen über die Unterschrift oder erhöhen Sie die Tintenempfindlichkeit.
Couldn't use the photo: {e} Das Foto kann nicht verwendet werden: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Tab schließen
+ Reopen Closed Tab Geschlossenen Tab wieder öffnen
+ Reveal in Finder Im Finder anzeigen
+ Reveal in File Explorer Im Datei-Explorer anzeigen
Other colour… Andere Farbe…
Recent colours Zuletzt verwendete Farben
Couldn't follow linked PDF: {reason} Verknüpfte PDF konnte nicht geöffnet werden: {reason}
diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv
index b9e3cc6f..a2ddff0b 100644
--- a/crates/ui-egui/src/i18n/el.tsv
+++ b/crates/ui-egui/src/i18n/el.tsv
@@ -2321,6 +2321,12 @@ animation effects Off Ανενεργά
Ink sensitivity Ευαισθησία μελανιού
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Δεν βρέθηκε υπογραφή στο πλαίσιο. Μετακινήστε το πλαίσιο πάνω από την υπογραφή ή αυξήστε την ευαισθησία μελανιού.
Couldn't use the photo: {e} Δεν ήταν δυνατή η χρήση της φωτογραφίας: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Κλείσιμο καρτέλας
+ Reopen Closed Tab Επαναφορά κλειστής καρτέλας
+ Reveal in Finder Εμφάνιση στο Finder
+ Reveal in File Explorer Εμφάνιση στη διαχείριση αρχείων
Other colour… Άλλο χρώμα…
Recent colours Πρόσφατα χρώματα
Reading colours Χρώματα ανάγνωσης
diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv
index 518a55e1..47c03919 100644
--- a/crates/ui-egui/src/i18n/es.tsv
+++ b/crates/ui-egui/src/i18n/es.tsv
@@ -2435,6 +2435,12 @@ animation effects Off Desactivados
Ink sensitivity Sensibilidad de la tinta
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. No se encontró ninguna firma en el marco. Mueva el marco sobre la firma o aumente la sensibilidad de la tinta.
Couldn't use the photo: {e} No se puede usar la foto: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Cerrar pestaña
+ Reopen Closed Tab Reabrir pestaña cerrada
+ Reveal in Finder Mostrar en Finder
+ Reveal in File Explorer Mostrar en el explorador de archivos
Other colour… Otro color…
Recent colours Colores recientes
Reading colours Colores de lectura
diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv
index 514a6c55..d605b850 100644
--- a/crates/ui-egui/src/i18n/fr.tsv
+++ b/crates/ui-egui/src/i18n/fr.tsv
@@ -2316,6 +2316,12 @@ animation effects Off Désactivés
Ink sensitivity Sensibilité à l’encre
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Aucune signature trouvée dans le cadre. Placez le cadre sur la signature ou augmentez la sensibilité à l’encre.
Couldn't use the photo: {e} Impossible d’utiliser la photo : {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Fermer l’onglet
+ Reopen Closed Tab Rouvrir l’onglet fermé
+ Reveal in Finder Afficher dans le Finder
+ Reveal in File Explorer Afficher dans l’explorateur de fichiers
Other colour… Autre couleur…
Recent colours Couleurs récentes
Couldn't follow linked PDF: {reason} Impossible de suivre le PDF lié : {reason}
diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv
index 274ec00f..28e24cd9 100644
--- a/crates/ui-egui/src/i18n/hu.tsv
+++ b/crates/ui-egui/src/i18n/hu.tsv
@@ -2315,6 +2315,12 @@ animation effects Off Ki
Ink sensitivity Tintaérzékenység
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. A keretben nem található aláírás. Húzza a keretet az aláírásra, vagy növelje a tintaérzékenységet.
Couldn't use the photo: {e} A fénykép nem használható: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Lap bezárása
+ Reopen Closed Tab Bezárt lap újranyitása
+ Reveal in Finder Megjelenítés a Finderben
+ Reveal in File Explorer Megjelenítés a fájlkezelőben
Other colour… Egyéb szín…
Recent colours Legutóbbi színek
Couldn't follow linked PDF: {reason} A hivatkozott PDF nem nyitható meg: {reason}
diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv
index 69aa38b3..7f81eab8 100644
--- a/crates/ui-egui/src/i18n/it.tsv
+++ b/crates/ui-egui/src/i18n/it.tsv
@@ -2325,6 +2325,12 @@ animation effects Off Disattivati
Ink sensitivity Sensibilità all’inchiostro
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Nessuna firma trovata nella cornice. Sposta la cornice sulla firma o aumenta la sensibilità all’inchiostro.
Couldn't use the photo: {e} Impossibile usare la foto: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Chiudi scheda
+ Reopen Closed Tab Riapri scheda chiusa
+ Reveal in Finder Mostra nel Finder
+ Reveal in File Explorer Mostra in Esplora file
Other colour… Altro colore…
Recent colours Colori recenti
Couldn't follow linked PDF: {reason} Impossibile aprire il PDF collegato: {reason}
diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv
index 049a5898..33e434e5 100644
--- a/crates/ui-egui/src/i18n/ja.tsv
+++ b/crates/ui-egui/src/i18n/ja.tsv
@@ -2316,6 +2316,12 @@ animation effects Off オフ
Ink sensitivity インクの感度
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. 枠内に署名が見つかりません。枠を署名に合わせるか、インクの感度を上げてください。
Couldn't use the photo: {e} 写真を使用できません: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab タブを閉じる
+ Reopen Closed Tab 閉じたタブを再度開く
+ Reveal in Finder Finderで表示
+ Reveal in File Explorer ファイルエクスプローラーで表示
Other colour… その他の色…
Recent colours 最近使った色
Couldn't follow linked PDF: {reason} リンク先の PDF を開けませんでした: {reason}
diff --git a/crates/ui-egui/src/i18n/kk.tsv b/crates/ui-egui/src/i18n/kk.tsv
index 08ea0d3d..d198b3db 100644
--- a/crates/ui-egui/src/i18n/kk.tsv
+++ b/crates/ui-egui/src/i18n/kk.tsv
@@ -2304,6 +2304,12 @@ animation effects Off Өшірулі
Ink sensitivity Сия сезімталдығы
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Жақтауда қолтаңба табылмады. Жақтауды қолтаңбаның үстіне жылжытыңыз немесе сия сезімталдығын арттырыңыз.
Couldn't use the photo: {e} Суретті пайдалану мүмкін болмады: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Қойындыны жабу
+ Reopen Closed Tab Жабылған қойындыны қайта ашу
+ Reveal in Finder Finder ішінде көрсету
+ Reveal in File Explorer Файл шолғышында көрсету
Other colour… Басқа түс…
Recent colours Соңғы түстер
Reading colours Оқу түстері
diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv
index e0c73082..8fb27b3f 100644
--- a/crates/ui-egui/src/i18n/pl.tsv
+++ b/crates/ui-egui/src/i18n/pl.tsv
@@ -2285,6 +2285,12 @@ animation effects Off Wyłączone
Ink sensitivity Czułość na atrament
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. W ramce nie znaleziono podpisu. Przesuń ramkę na podpis lub zwiększ czułość na atrament.
Couldn't use the photo: {e} Nie można użyć zdjęcia: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Zamknij kartę
+ Reopen Closed Tab Otwórz ponownie zamkniętą kartę
+ Reveal in Finder Pokaż w Finderze
+ Reveal in File Explorer Pokaż w Eksploratorze plików
Other colour… Inny kolor…
Recent colours Ostatnie kolory
Reading colours Kolory do czytania
diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv
index 87527d0f..bdcaf04c 100644
--- a/crates/ui-egui/src/i18n/pt-br.tsv
+++ b/crates/ui-egui/src/i18n/pt-br.tsv
@@ -2330,6 +2330,12 @@ animation effects Off Desativados
Ink sensitivity Sensibilidade à tinta
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Nenhuma assinatura encontrada no quadro. Mova o quadro sobre a assinatura ou aumente a sensibilidade à tinta.
Couldn't use the photo: {e} Não foi possível usar a foto: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Fechar aba
+ Reopen Closed Tab Reabrir aba fechada
+ Reveal in Finder Mostrar no Finder
+ Reveal in File Explorer Mostrar no explorador de arquivos
Other colour… Outra cor…
Recent colours Cores recentes
Couldn't follow linked PDF: {reason} Não foi possível abrir o PDF vinculado: {reason}
diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv
index 11ee72d6..fcb886e5 100644
--- a/crates/ui-egui/src/i18n/ru.tsv
+++ b/crates/ui-egui/src/i18n/ru.tsv
@@ -2229,6 +2229,12 @@ animation effects Off Выкл
Ink sensitivity Чувствительность к чернилам
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. В рамке не найдена подпись. Наведите рамку на подпись или увеличьте чувствительность к чернилам.
Couldn't use the photo: {e} Не удалось использовать фото: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Закрыть вкладку
+ Reopen Closed Tab Открыть закрытую вкладку
+ Reveal in Finder Показать в Finder
+ Reveal in File Explorer Показать в проводнике
Other colour… Другой цвет…
Recent colours Недавние цвета
Couldn't follow linked PDF: {reason} Не удалось открыть связанный PDF: {reason}
diff --git a/crates/ui-egui/src/i18n/sl.tsv b/crates/ui-egui/src/i18n/sl.tsv
index a7963948..71acd021 100644
--- a/crates/ui-egui/src/i18n/sl.tsv
+++ b/crates/ui-egui/src/i18n/sl.tsv
@@ -2321,6 +2321,12 @@ animation effects Off Izklopljeni
Ink sensitivity Občutljivost za črnilo
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. V okvirju ni bilo najdenega podpisa. Premaknite okvir nad podpis ali povečajte občutljivost za črnilo.
Couldn't use the photo: {e} Fotografije ni bilo mogoče uporabiti: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Zapri zavihek
+ Reopen Closed Tab Znova odpri zaprti zavihek
+ Reveal in Finder Prikaži v Finderju
+ Reveal in File Explorer Prikaži v upravljalniku datotek
Other colour… Druga barva…
Recent colours Nedavne barve
Couldn't follow linked PDF: {reason} Povezanega PDF-ja ni bilo mogoče odpreti: {reason}
diff --git a/crates/ui-egui/src/i18n/te.tsv b/crates/ui-egui/src/i18n/te.tsv
index 646cb032..55aeea98 100644
--- a/crates/ui-egui/src/i18n/te.tsv
+++ b/crates/ui-egui/src/i18n/te.tsv
@@ -2218,6 +2218,12 @@ animation effects Off ఆఫ్
Ink sensitivity ఇంక్ సున్నితత్వం
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. ఫ్రేమ్లో సంతకం కనబడలేదు. ఫ్రేమ్ను సంతకం మీదకు జరపండి లేదా ఇంక్ సున్నితత్వాన్ని పెంచండి.
Couldn't use the photo: {e} ఫోటోను ఉపయోగించలేకపోయాం: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab ట్యాబ్ను మూసివేయి
+ Reopen Closed Tab మూసివేసిన ట్యాబ్ను మళ్లీ తెరువు
+ Reveal in Finder Finderలో చూపు
+ Reveal in File Explorer ఫైల్ ఎక్స్ప్లోరర్లో చూపు
Other colour… ఇతర రంగు…
Recent colours ఇటీవలి రంగులు
Reading colours చదవడానికి రంగులు
diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv
index e721c004..2cf8ba8f 100644
--- a/crates/ui-egui/src/i18n/tr.tsv
+++ b/crates/ui-egui/src/i18n/tr.tsv
@@ -2302,6 +2302,12 @@ animation effects Off Kapalı
Ink sensitivity Mürekkep hassasiyeti
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. Çerçevede imza bulunamadı. Çerçeveyi imzanın üzerine taşıyın veya mürekkep hassasiyetini artırın.
Couldn't use the photo: {e} Fotoğraf kullanılamadı: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Sekmeyi kapat
+ Reopen Closed Tab Kapatılan sekmeyi yeniden aç
+ Reveal in Finder Finder’da göster
+ Reveal in File Explorer Dosya Gezgini’nde göster
Other colour… Diğer renk…
Recent colours Son kullanılan renkler
Reading colours Okuma renkleri
diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv
index 99ecf468..f35aadb6 100644
--- a/crates/ui-egui/src/i18n/uk.tsv
+++ b/crates/ui-egui/src/i18n/uk.tsv
@@ -2338,6 +2338,12 @@ animation effects Off Вимкнено
Ink sensitivity Чутливість до чорнила
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. У рамці не знайдено підпису. Наведіть рамку на підпис або збільште чутливість до чорнила.
Couldn't use the photo: {e} Не вдалося використати фото: {e}
+
+# PDF tab context menu (#1233)
+ Close Tab Закрити вкладку
+ Reopen Closed Tab Відкрити закриту вкладку
+ Reveal in Finder Показати у Finder
+ Reveal in File Explorer Показати у файловому провіднику
Other colour… Інший колір…
Recent colours Нещодавні кольори
Couldn't follow linked PDF: {reason} Не вдалося відкрити пов’язаний PDF: {reason}
diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv
index 6dff6d70..f313fe45 100644
--- a/crates/ui-egui/src/i18n/zh-hans.tsv
+++ b/crates/ui-egui/src/i18n/zh-hans.tsv
@@ -2280,6 +2280,12 @@ animation effects Off 关
Ink sensitivity 墨迹灵敏度
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. 框内未找到签名。请将框移到签名上,或提高墨迹灵敏度。
Couldn't use the photo: {e} 无法使用该照片:{e}
+
+# PDF tab context menu (#1233)
+ Close Tab 关闭标签页
+ Reopen Closed Tab 重新打开已关闭的标签页
+ Reveal in Finder 在 Finder 中显示
+ Reveal in File Explorer 在文件资源管理器中显示
Other colour… 其他颜色…
Recent colours 最近使用的颜色
Couldn't follow linked PDF: {reason} 无法打开链接的 PDF:{reason}
diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv
index 0b9751bd..437c07ae 100644
--- a/crates/ui-egui/src/i18n/zh-hant.tsv
+++ b/crates/ui-egui/src/i18n/zh-hant.tsv
@@ -2179,6 +2179,12 @@ animation effects Off 關
Ink sensitivity 墨跡靈敏度
No signature was found in the frame. Move the frame over the signature or raise the ink sensitivity. 框內找不到簽名。請將框移到簽名上,或提高墨跡靈敏度。
Couldn't use the photo: {e} 無法使用此相片:{e}
+
+# PDF tab context menu (#1233)
+ Close Tab 關閉分頁
+ Reopen Closed Tab 重新開啟已關閉的分頁
+ Reveal in Finder 在 Finder 中顯示
+ Reveal in File Explorer 在檔案總管中顯示
Other colour… 其他顏色…
Recent colours 最近使用的顏色
Reading colours 閱讀色彩
diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs
index a7283211..80a524ef 100644
--- a/crates/ui-egui/src/lib.rs
+++ b/crates/ui-egui/src/lib.rs
@@ -122,6 +122,7 @@ mod recovery;
pub mod scroll_speed;
#[cfg(not(target_arch = "wasm32"))]
mod system_fonts;
+mod tab_context;
pub mod theme;
pub mod ui_scale;
pub mod updates;
@@ -434,6 +435,7 @@ pub struct PdfCraftApp {
pub(crate) pending_panel_reveals: Vec,
pub session: Session,
pub views: Vec,
+ pub(crate) closed_tabs: Vec,
/// `None` shows the Home tab.
pub active: Option,
pub mode: Mode,
@@ -784,6 +786,7 @@ impl PdfCraftApp {
Self {
session: Session::new(),
views: Vec::new(),
+ closed_tabs: Vec::new(),
active: None,
mode: Mode::AllTools,
default_mode: Mode::AllTools,
@@ -1430,6 +1433,13 @@ impl PdfCraftApp {
return;
}
let id = self.views.remove(index).id;
+ #[cfg(not(target_arch = "wasm32"))]
+ if let Some(path) = self.session.get(id).and_then(|d| d.path.clone()) {
+ if self.closed_tabs.len() == 10 {
+ self.closed_tabs.remove(0);
+ }
+ self.closed_tabs.push(path);
+ }
self.forget_recovery(id);
self.session.close(id);
self.active = match self.active {
diff --git a/crates/ui-egui/src/tab_context.rs b/crates/ui-egui/src/tab_context.rs
new file mode 100644
index 00000000..b9802e69
--- /dev/null
+++ b/crates/ui-egui/src/tab_context.rs
@@ -0,0 +1,275 @@
+//! PDF-tab actions. Closed history contains paths only, never bytes or passwords.
+use pdfcraft_engine::DocId;
+
+pub(crate) enum Action {
+ Close(DocId),
+ Reopen,
+ Reveal(DocId),
+}
+
+impl crate::PdfCraftApp {
+ pub(crate) fn tab_action(&mut self, action: Action) {
+ match action {
+ Action::Close(id) => {
+ if let Some(i) = self.views.iter().position(|v| v.id == id) {
+ self.request_close_tab(i);
+ }
+ }
+ Action::Reopen => {
+ #[cfg(not(target_arch = "wasm32"))]
+ if let Some(path) = self.closed_tabs.last().cloned() {
+ // A tab may already have been reopened through File > Open.
+ if let Some(index) = self.views.iter().position(|v| self.session.get(v.id).is_some_and(|d| d.path.as_deref() == Some(&path))) {
+ self.active = Some(index);
+ self.closed_tabs.pop();
+ } else {
+ let tabs = self.views.len();
+ self.open_path(&path);
+ // open_path reports errors through notifications, not a Result.
+ // Keep the entry until an actual document tab has been opened.
+ if self.views.len() > tabs {
+ self.closed_tabs.pop();
+ }
+ }
+ }
+ }
+ Action::Reveal(id) => {
+ #[cfg(not(target_arch = "wasm32"))]
+ if let Some(path) = self.session.get(id).and_then(|d| d.path.clone())
+ && let Err(e) = reveal(std::path::Path::new(&path))
+ {
+ self.notify_error(e);
+ }
+ #[cfg(target_arch = "wasm32")]
+ let _ = id;
+ }
+ }
+ }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn reveal(path: &std::path::Path) -> Result<(), String> {
+ // Absolute paths also prevent a filename starting with '-' becoming an option.
+ let path = std::path::absolute(path).map_err(|e| e.to_string())?;
+ if !path.try_exists().map_err(|e| e.to_string())? {
+ return Err("The file no longer exists".into());
+ }
+ let platform = std::env::consts::OS;
+ let run = |program: &str, args: &[std::ffi::OsString]| {
+ std::process::Command::new(program).args(args).output().map(|o| o.status.success()).map_err(|e| e.to_string())
+ };
+ if matches!(platform, "linux" | "freebsd") {
+ // `dbus-send --print-reply` waits up to 2 s for the file manager (then xdg-open may run),
+ // so it runs off the UI thread; a failure there is only logged.
+ let spawned = std::thread::Builder::new().name("pdfcraft-reveal".into()).spawn(move || {
+ if let Err(e) = reveal_via(platform, &path, run) {
+ log::warn!("reveal {}: {e}", path.display());
+ }
+ });
+ return spawned.map(|_| ()).map_err(|e| e.to_string());
+ }
+ reveal_via(platform, &path, run)
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn reveal_via(
+ platform: &str,
+ path: &std::path::Path,
+ mut run: impl FnMut(&str, &[std::ffi::OsString]) -> Result,
+) -> Result<(), String> {
+ let (program, args) = reveal_command(platform, path)?;
+ if run(program, &args).unwrap_or(false) {
+ return Ok(());
+ }
+ if matches!(platform, "linux" | "freebsd") {
+ // FileManager1 is optional. If absent, open the containing folder with xdg-open.
+ let parent = path.parent().ok_or("The file has no parent directory")?;
+ if run("xdg-open", &[parent.as_os_str().into()])? {
+ return Ok(());
+ }
+ }
+ Err("Could not reveal the file in the system file manager".into())
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn reveal_command(platform: &str, path: &std::path::Path) -> Result<(&'static str, Vec), String> {
+ match platform {
+ "windows" => {
+ // Explorer uses /select,