From 07a5f3f3a133a46fe0792783a6233b67471decd4 Mon Sep 17 00:00:00 2001 From: mtlcl410 <2368091+mtlcl410@users.noreply.github.com> Date: Sat, 17 Oct 2026 13:08:47 +0800 Subject: [PATCH] M5: the first save after placing a signature asks to lock it into the page (#2149) A Fill & Sign signature stays a removable comment unless Flatten Fill & Sign when saving is on, which sat only in Preferences. The first save after a signature or initials is placed now asks: Lock and save flattens the document's Fill & Sign marks, Keep editable saves as before, Cancel saves nothing, and Don't ask again turns the answer into the preference. The Sign menu carries the same switch. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/app.rs | 4 ++ crates/ui-egui/src/app/prefs.rs | 4 ++ crates/ui-egui/src/dialogs.rs | 39 +++++++++++++ crates/ui-egui/src/editing.rs | 7 +++ crates/ui-egui/src/editing/save.rs | 47 +++++++++++++++ crates/ui-egui/src/i18n/ar.tsv | 7 +++ crates/ui-egui/src/i18n/bg.tsv | 7 +++ crates/ui-egui/src/i18n/cs.tsv | 7 +++ crates/ui-egui/src/i18n/de.tsv | 7 +++ crates/ui-egui/src/i18n/el.tsv | 7 +++ crates/ui-egui/src/i18n/es.tsv | 7 +++ crates/ui-egui/src/i18n/fr.tsv | 7 +++ crates/ui-egui/src/i18n/hu.tsv | 7 +++ crates/ui-egui/src/i18n/it.tsv | 7 +++ crates/ui-egui/src/i18n/ja.tsv | 7 +++ crates/ui-egui/src/i18n/kk.tsv | 7 +++ crates/ui-egui/src/i18n/lt.tsv | 7 +++ crates/ui-egui/src/i18n/pl.tsv | 7 +++ crates/ui-egui/src/i18n/pt-br.tsv | 7 +++ crates/ui-egui/src/i18n/ru.tsv | 7 +++ crates/ui-egui/src/i18n/sl.tsv | 7 +++ crates/ui-egui/src/i18n/te.tsv | 8 +++ crates/ui-egui/src/i18n/tr.tsv | 7 +++ crates/ui-egui/src/i18n/uk.tsv | 7 +++ crates/ui-egui/src/i18n/zh-hans.tsv | 7 +++ crates/ui-egui/src/i18n/zh-hant.tsv | 8 +++ crates/ui-egui/src/lib.rs | 9 +++ crates/ui-egui/src/state.rs | 3 + crates/ui-egui/src/tools/fill_sign.rs | 2 + crates/ui-egui/src/workflows/js_ui.rs | 4 ++ crates/ui-egui/tests/it/fill_sign.rs | 84 ++++++++++++++++++++++++++- docs/target-app-parity.md | 2 +- parity/acrobat-features.toml | 4 +- 33 files changed, 354 insertions(+), 4 deletions(-) diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs index 43d0066e63..29801c4b76 100644 --- a/crates/ui-egui/src/app.rs +++ b/crates/ui-egui/src/app.rs @@ -106,6 +106,10 @@ impl PdfCraftApp { system_text_scale: 1.0, ui_scale_applied: None, flatten_fill_sign_on_save: false, + ask_to_lock_signatures: true, + placed_signatures: Default::default(), + pending_lock: None, + lock_remember: false, fill_text_size: fill_sign::TEXT_SIZE, fill_text_color: [0.0; 3], dialog: None, diff --git a/crates/ui-egui/src/app/prefs.rs b/crates/ui-egui/src/app/prefs.rs index 7bd8943774..5e35547035 100644 --- a/crates/ui-egui/src/app/prefs.rs +++ b/crates/ui-egui/src/app/prefs.rs @@ -101,6 +101,7 @@ impl PdfCraftApp { // Null follows the system's text scaling. "ui_scale": self.ui_scale, "flatten_fill_sign": self.flatten_fill_sign_on_save, + "ask_to_lock_signatures": self.ask_to_lock_signatures, "fill_text_size": self.fill_text_size, "date_format": self.session.date_format(), // Null follows the interface language. @@ -284,6 +285,9 @@ impl PdfCraftApp { if let Some(on) = v["flatten_fill_sign"].as_bool() { self.flatten_fill_sign_on_save = on; } + if let Some(on) = v["ask_to_lock_signatures"].as_bool() { + self.ask_to_lock_signatures = on; + } if let Some(size) = v["fill_text_size"].as_f64().and_then(fill_sign::valid_text_size) { self.fill_text_size = size; } diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 42bed83657..30985fab28 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -50,6 +50,7 @@ struct Pending { revert_now: bool, overwrite_now: bool, overwrite_elsewhere: bool, + lock_answer: Option, summarize_now: bool, optimize_now: bool, duplicate_now: Option, @@ -275,6 +276,11 @@ fn dialog_body(ui: &mut egui::Ui, app: &mut PdfCraftApp, dialog: Dialog, req: &m return false; } } + Dialog::LockSignatures => { + if !dialog_lock_signatures(ui, app, req) { + return false; + } + } Dialog::Revert => { if !dialog_revert(ui, app, req) { return false; @@ -1246,6 +1252,31 @@ fn dialog_summarize_comments(ui: &mut egui::Ui, app: &mut PdfCraftApp, req: &mut false } +/// `Dialog::LockSignatures` content (#2149). Returns `false` when it has its own buttons and no +/// footer is wanted. +fn dialog_lock_signatures(ui: &mut egui::Ui, app: &mut PdfCraftApp, req: &mut Pending) -> bool { + ui.label(egui::RichText::new(tl!("Lock your signature into the page?")).font(theme::semibold(18.0))); + ui.add_space(8.0); + ui.label(tl!("A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page.")); + ui.add_space(8.0); + ui.add(widgets::checkbox(&mut app.lock_remember, tl!("Don't ask again"))); + ui.add_space(12.0); + ui.with_layout(Layout::right_to_left(Align::Center), |ui| { + if widgets::pill_button(ui, tl!("Lock and save"), true).clicked() { + req.lock_answer = Some(true); + req.close = true; + } + if widgets::pill_button(ui, tl!("Keep editable"), false).clicked() { + req.lock_answer = Some(false); + req.close = true; + } + if widgets::pill_button(ui, tl!("Cancel"), false).clicked() { + req.close = true; + } + }); + false +} + /// `Dialog::Revert` content. Returns `false` when it has its own buttons and no footer is wanted. fn dialog_revert(ui: &mut egui::Ui, app: &mut PdfCraftApp, req: &mut Pending) -> bool { let name = app.active_ids().and_then(|(_, id)| app.session.get(id)).map(|d| d.name.clone()).unwrap_or_default(); @@ -1762,6 +1793,14 @@ fn finish_requests(app: &mut PdfCraftApp, dialog: Dialog, modal_closed: bool, re if dialog == Dialog::OverwriteChanged && (modal_closed || req.close) { app.pending_overwrite = None; } + if let Some(lock) = req.lock_answer { + let remember = std::mem::take(&mut app.lock_remember); + app.answer_lock_signatures(lock, remember); + } else if dialog == Dialog::LockSignatures && (modal_closed || req.close) { + // Cancelled or dismissed: nothing is saved. + app.pending_lock = None; + app.lock_remember = false; + } } /// Runs the document actions the dialog asked for. diff --git a/crates/ui-egui/src/editing.rs b/crates/ui-egui/src/editing.rs index b810e2abe5..f753335b72 100644 --- a/crates/ui-egui/src/editing.rs +++ b/crates/ui-egui/src/editing.rs @@ -10,6 +10,7 @@ mod close; mod save; pub use close::CloseRequest; +pub use save::PendingLock; #[cfg(not(target_arch = "wasm32"))] pub use save::PendingOverwrite; #[cfg(target_arch = "wasm32")] @@ -669,12 +670,18 @@ impl PdfCraftApp { fn apply_queued_edit(&mut self, i: usize) -> bool { let Some(edit) = self.views.get_mut(i).and_then(|v| v.pending_edit.take()) else { return true }; let signature_page = self.views.get_mut(i).and_then(|v| v.fill_signature_page.take()); + let doc_id = self.views.get(i).map(|v| v.id); let committed = self.views.get_mut(i).and_then(|v| v.forms.committed.take()); let typed = match (&edit, &committed) { (Edit::SetFieldValue { name, .. }, Some(draft)) => *name == draft.name, _ => false, }; if self.apply_edit(edit) { + if signature_page.is_some() + && let Some(id) = doc_id + { + self.placed_signatures.insert(id); + } // Tab can wrap to the same field (including another widget of that field). // Its new editor was opened before this edit ran, so it still holds the old // value. Refresh from the accepted form before Save can commit that stale draft. diff --git a/crates/ui-egui/src/editing/save.rs b/crates/ui-egui/src/editing/save.rs index f685247c9d..446aba1fc5 100644 --- a/crates/ui-egui/src/editing/save.rs +++ b/crates/ui-egui/src/editing/save.rs @@ -11,6 +11,14 @@ pub struct PendingOverwrite { after: Box, } +/// A save held back by [`Dialog::LockSignatures`](crate::Dialog::LockSignatures) (#2149). +pub struct PendingLock { + pub id: pdfcraft_engine::DocId, + target: SaveTarget, + /// What was to run once the document is written (close its tab, quit). + after: Box, +} + /// Where Save writes. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum SaveTarget { @@ -46,6 +54,13 @@ impl PdfCraftApp { return false; } let Some(id) = self.views.get(index).map(|v| v.id) else { return false }; + // A signature just placed with Fill & Sign is a removable comment unless it is flattened: + // ask once whether to lock it into the page (#2149). + if self.ask_to_lock_signatures && !self.flatten_fill_sign_on_save && self.placed_signatures.contains(&id) { + self.pending_lock = Some(PendingLock { id, target, after: Box::new(after) }); + self.dialog = Some(crate::Dialog::LockSignatures); + return false; + } let Some(doc) = self.session.get(id) else { return false }; let (name, path) = (doc.name.clone(), doc.path.clone()); #[cfg(not(target_arch = "wasm32"))] @@ -154,6 +169,37 @@ impl PdfCraftApp { } } + /// The Lock signatures dialog answered (#2149): lock the document's Fill & Sign marks into + /// its pages first when `lock`, then save as was asked. With `remember`, the answer becomes + /// the preference (flatten on every save, or never ask again). + pub(crate) fn answer_lock_signatures(&mut self, lock: bool, remember: bool) { + let Some(p) = self.pending_lock.take() else { return }; + self.placed_signatures.remove(&p.id); + if remember { + if lock { + self.flatten_fill_sign_on_save = true; + } else { + self.ask_to_lock_signatures = false; + } + } + if lock && !self.flatten_fill_sign_on_save { + let before = self.session.get(p.id).map(|d| d.edit_generation()); + if let Err(e) = self.session.apply(p.id, pdfcraft_engine::Edit::FlattenFillSign) { + self.notify_error(e); + return; + } + if before != self.session.get(p.id).map(|d| d.edit_generation()) + && let Some(doc) = self.session.get(p.id) + && let Some(view) = self.views.iter_mut().find(|v| v.id == p.id) + { + view.document_changed(&doc.info); + } + } + if let Some(index) = self.views.iter().position(|v| v.id == p.id) { + self.save_then(index, p.target, p.after); + } + } + /// Write document `id` to `dest` and make it the document's file. Returns `true` if written. #[cfg(not(target_arch = "wasm32"))] fn save_doc_to(&mut self, id: pdfcraft_engine::DocId, dest: &str, target: SaveTarget) -> bool { @@ -192,6 +238,7 @@ impl PdfCraftApp { match self.session.mark_saved(id, bytes, Some(dest.to_string())) { Ok(()) => { self.forget_recovery(id); + self.placed_signatures.remove(&id); if let Some(doc) = self.session.get(id) && let Some(view) = self.views.iter_mut().find(|v| v.id == id) { diff --git a/crates/ui-egui/src/i18n/ar.tsv b/crates/ui-egui/src/i18n/ar.tsv index 1b08929307..50d633bd33 100644 --- a/crates/ui-egui/src/i18n/ar.tsv +++ b/crates/ui-egui/src/i18n/ar.tsv @@ -2278,6 +2278,13 @@ calendar date December ديسمبر Smaller pages صفحات أصغر Reset page size إعادة ضبط حجم الصفحة Flatten Fill & Sign when saving تسطيح التعبئة والتوقيع عند الحفظ + Lock your signature into the page? هل تريد تثبيت توقيعك في الصفحة؟ + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. التوقيع الموضوع تعليق إلى أن يُثبَّت: يستطيع أي شخص لديه محرر PDF نقله أو إزالته. التثبيت يجعل نصوص التعبئة والتوقيع وعلاماتها وتواقيعها جزءًا من الصفحة. + Don't ask again عدم السؤال مرة أخرى + Lock and save التثبيت والحفظ + Keep editable إبقاؤه قابلًا للتحرير + Lock into the page when saving التثبيت في الصفحة عند الحفظ + Otherwise, ask on the first save after a signature is placed وإلا فاسأل عند أول حفظ بعد وضع توقيع Text, marks and signatures become part of the page. Other comments stay editable. النص والعلامات والتوقيعات تصبح جزءًا من الصفحة. التعليقات الأخرى تبقى قابلة للتحرير. Date format تنسيق التاريخ Fill & Sign dates تواريخ التعبئة والتوقيع diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index e269febf18..56cd2f3fd1 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -138,6 +138,13 @@ Side panels Странични панели Enable Acrobat JavaScript Включи Acrobat JavaScript Flatten Fill & Sign when saving Сплескай „Попълни и подпиши“ при запазване + Lock your signature into the page? Да се заключи ли подписът ви в страницата? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Поставеният подпис е коментар, докато не бъде заключен: всеки с PDF редактор може да го премести или премахне. Заключването прави текста, отметките и подписите от „Попълване и подписване“ част от страницата. + Don't ask again Не питай отново + Lock and save Заключване и запис + Keep editable Да остане редактируем + Lock into the page when saving Заключване в страницата при запис + Otherwise, ask on the first save after a signature is placed Иначе питай при първия запис след поставяне на подпис Text, marks and signatures become part of the page. Other comments stay editable. Текстът, маркировките и подписите стават част от страницата. Другите коментари остават редактируеми. OK OK Cancel Отказ diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 22f6e3e056..89da6a9309 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -2299,6 +2299,13 @@ calendar date December prosince Smaller pages Menší stránky Reset page size Obnovit velikost stránek Flatten Fill & Sign when saving Při ukládání sloučit obsah Vyplnit a podepsat se stránkou + Lock your signature into the page? Zamknout podpis do stránky? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Umístěný podpis je komentář, dokud není zamčen: kdokoli s editorem PDF ho může přesunout nebo odstranit. Zamčení udělá z textu, značek a podpisů Vyplnit a podepsat součást stránky. + Don't ask again Už se neptat + Lock and save Zamknout a uložit + Keep editable Ponechat upravitelné + Lock into the page when saving Při ukládání zamknout do stránky + Otherwise, ask on the first save after a signature is placed Jinak se zeptat při prvním uložení po umístění podpisu Text, marks and signatures become part of the page. Other comments stay editable. Text, značky a podpisy se stanou součástí stránky. Ostatní komentáře zůstanou upravitelné. Date format Formát data Fill & Sign dates Datum pro Vyplnit a podepsat diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 2c9ce7ae36..a80eb7b98d 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -71,6 +71,13 @@ Side panels Seitenleisten Enable Acrobat JavaScript Acrobat-JavaScript aktivieren Flatten Fill & Sign when saving Ausfüllen und unterschreiben beim Speichern reduzieren + Lock your signature into the page? Unterschrift fest in die Seite übernehmen? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Eine platzierte Unterschrift ist ein Kommentar, bis sie fest übernommen wird: Jeder mit einem PDF-Editor kann sie verschieben oder entfernen. Beim Übernehmen werden Text, Markierungen und Unterschriften aus „Ausfüllen und unterschreiben“ Teil der Seite. + Don't ask again Nicht mehr fragen + Lock and save Übernehmen und speichern + Keep editable Bearbeitbar lassen + Lock into the page when saving Beim Speichern fest in die Seite übernehmen + Otherwise, ask on the first save after a signature is placed Andernfalls beim ersten Speichern nach dem Platzieren einer Unterschrift fragen Text, marks and signatures become part of the page. Other comments stay editable. Text, Markierungen und Unterschriften werden Teil der Seite. Andere Kommentare bleiben bearbeitbar. OK OK Join our Discord Unserem Discord beitreten diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index d83bf4aef7..9952012e7a 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -286,6 +286,13 @@ Failed Αποτυχία Page {p} of {n} Σελίδα {p} από {n} Flatten Fill & Sign when saving Ενσωμάτωση συμπληρώσεων και υπογραφών κατά την αποθήκευση + Lock your signature into the page? Κλείδωμα της υπογραφής σας στη σελίδα; + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Μια τοποθετημένη υπογραφή είναι σχόλιο μέχρι να κλειδωθεί: οποιοσδήποτε με επεξεργαστή PDF μπορεί να τη μετακινήσει ή να την αφαιρέσει. Το κλείδωμα κάνει το κείμενο, τα σημάδια και τις υπογραφές της Συμπλήρωσης και υπογραφής μέρος της σελίδας. + Don't ask again Να μην ερωτηθώ ξανά + Lock and save Κλείδωμα και αποθήκευση + Keep editable Να παραμείνει επεξεργάσιμη + Lock into the page when saving Κλείδωμα στη σελίδα κατά την αποθήκευση + Otherwise, ask on the first save after a signature is placed Διαφορετικά, ερώτηση στην πρώτη αποθήκευση μετά την τοποθέτηση υπογραφής Text, marks and signatures become part of the page. Other comments stay editable. Το κείμενο, τα σημάδια και οι υπογραφές γίνονται μέρος της σελίδας. Τα υπόλοιπα σχόλια παραμένουν επεξεργάσιμα. Current page — type a page number or label (such as iv) and press Enter Τρέχουσα σελίδα — πληκτρολογήστε αριθμό ή ετικέτα σελίδας (π.χ. iv) και πατήστε Enter Zoom — type a percentage and press Enter Ζουμ — πληκτρολογήστε ένα ποσοστό και πατήστε Enter diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 131d2dacaf..cb6b90f278 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -94,6 +94,13 @@ Side panels Paneles laterales Enable Acrobat JavaScript Activar Acrobat JavaScript Flatten Fill & Sign when saving Acoplar Rellenar y firmar al guardar + Lock your signature into the page? ¿Fijar su firma en la página? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Una firma colocada es un comentario hasta que se fija: cualquiera con un editor de PDF puede moverla o quitarla. Al fijarla, el texto, las marcas y las firmas de Rellenar y firmar pasan a formar parte de la página. + Don't ask again No volver a preguntar + Lock and save Fijar y guardar + Keep editable Mantener editable + Lock into the page when saving Fijar en la página al guardar + Otherwise, ask on the first save after a signature is placed Si no, preguntar al guardar por primera vez tras colocar una firma Text, marks and signatures become part of the page. Other comments stay editable. El texto, las marcas y las firmas pasan a formar parte de la página. Los demás comentarios siguen siendo editables. OK Aceptar Join our Discord Únete a nuestro Discord diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 1c22cf9d81..2cb821d804 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -71,6 +71,13 @@ Side panels Panneaux latéraux Enable Acrobat JavaScript Activer Acrobat JavaScript Flatten Fill & Sign when saving Aplatir Remplir et signer à l'enregistrement + Lock your signature into the page? Intégrer votre signature à la page ? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Une signature placée reste un commentaire tant qu’elle n’est pas intégrée : n’importe qui avec un éditeur PDF peut la déplacer ou la supprimer. L’intégration rend le texte, les marques et les signatures de Remplir et signer partie de la page. + Don't ask again Ne plus demander + Lock and save Intégrer et enregistrer + Keep editable Garder modifiable + Lock into the page when saving Intégrer à la page à l’enregistrement + Otherwise, ask on the first save after a signature is placed Sinon, demander au premier enregistrement après avoir placé une signature Text, marks and signatures become part of the page. Other comments stay editable. Le texte, les marques et les signatures deviennent partie de la page. Les autres commentaires restent modifiables. OK OK Join our Discord Rejoindre notre Discord diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 47d9c24b40..1b9a0c5d78 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -2255,6 +2255,13 @@ action wizard Start Indítás Smaller pages Kisebb oldalak Reset page size Oldalméret visszaállítása Flatten Fill & Sign when saving Kitöltés és aláírás beégetése mentéskor + Lock your signature into the page? Rögzíti az aláírását az oldalba? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Az elhelyezett aláírás megjegyzés, amíg nincs rögzítve: bárki egy PDF-szerkesztővel áthelyezheti vagy eltávolíthatja. A rögzítés a Kitöltés és aláírás szövegét, jeleit és aláírásait az oldal részévé teszi. + Don't ask again Ne kérdezzen többet + Lock and save Rögzítés és mentés + Keep editable Szerkeszthető marad + Lock into the page when saving Mentéskor rögzítés az oldalba + Otherwise, ask on the first save after a signature is placed Különben kérdezzen rá az aláírás elhelyezése utáni első mentéskor Text, marks and signatures become part of the page. Other comments stay editable. A szöveg, a jelek és az aláírások az oldal részévé válnak. A többi megjegyzés szerkeszthető marad. Date format Dátumformátum Fill & Sign dates Kitöltés és aláírás dátumai diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 0cae8f3e98..eb713baefd 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -2215,6 +2215,13 @@ Files are combined in this order. Leave Pages empty to take every page. I file vengono combinati in quest'ordine. Lascia vuoto Pagine per prendere tutte le pagine. Fill & Sign dates Date di Compila e firma Flatten Fill & Sign when saving Appiattisci Compila e firma al salvataggio + Lock your signature into the page? Bloccare la firma nella pagina? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Una firma inserita è un commento finché non viene bloccata: chiunque abbia un editor PDF può spostarla o rimuoverla. Il blocco rende testo, segni e firme di Compila e firma parte della pagina. + Don't ask again Non chiedere più + Lock and save Blocca e salva + Keep editable Mantieni modificabile + Lock into the page when saving Blocca nella pagina al salvataggio + Otherwise, ask on the first save after a signature is placed Altrimenti, chiedi al primo salvataggio dopo aver inserito una firma H / Space (hold) H / Spazio (tieni premuto) Home / End Home / Fine Inserted text Testo inserito diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index abc616b817..9e151bbc62 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -2270,6 +2270,13 @@ @plural {n} page|{n} pages {n} ページ signature pad Type 入力 Flatten Fill & Sign when saving 保存時に入力と署名を統合する + Lock your signature into the page? 署名をページに固定しますか? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. 配置した署名は固定するまで注釈です。PDF エディターを持つ人なら誰でも移動や削除ができます。固定すると、入力と署名のテキスト、マーク、署名がページの一部になります。 + Don't ask again 今後は確認しない + Lock and save 固定して保存 + Keep editable 編集可能のままにする + Lock into the page when saving 保存時にページに固定 + Otherwise, ask on the first save after a signature is placed それ以外は、署名を配置した後の最初の保存時に確認する Text, marks and signatures become part of the page. Other comments stay editable. テキスト、マーク、署名がページの一部になります。その他のコメントは引き続き編集できます。 Scroll tabs left タブを左にスクロール Scroll tabs right タブを右にスクロール diff --git a/crates/ui-egui/src/i18n/kk.tsv b/crates/ui-egui/src/i18n/kk.tsv index fc6a2d783a..87b0496d70 100644 --- a/crates/ui-egui/src/i18n/kk.tsv +++ b/crates/ui-egui/src/i18n/kk.tsv @@ -2187,6 +2187,13 @@ calendar date December Желтоқсан Smaller pages Кішірек беттер Reset page size Бет өлшемін қалпына келтіру Flatten Fill & Sign when saving Сақтау кезінде «Толтыру және қол қою» мазмұнын жазықтау + Lock your signature into the page? Қолтаңбаңызды бетке бекіту керек пе? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Қойылған қолтаңба бекітілгенге дейін түсініктеме болып қалады: PDF өңдегіші бар кез келген адам оны жылжытып не жоя алады. Бекіту «Толтыру және қол қою» мәтінін, белгілерін және қолтаңбаларын беттің бөлігіне айналдырады. + Don't ask again Қайта сұрамау + Lock and save Бекіту және сақтау + Keep editable Өңделетін күйде қалдыру + Lock into the page when saving Сақтағанда бетке бекіту + Otherwise, ask on the first save after a signature is placed Әйтпесе, қолтаңба қойылғаннан кейінгі алғашқы сақтауда сұрау Text, marks and signatures become part of the page. Other comments stay editable. Мәтін, белгілер мен қолтаңбалар беттің бөлігіне айналады. Басқа түсініктемелер өңделетін күйде қалады. Date format Күн пішімі Fill & Sign dates «Толтыру және қол қою» күндері diff --git a/crates/ui-egui/src/i18n/lt.tsv b/crates/ui-egui/src/i18n/lt.tsv index fd7f431154..725d8ad22e 100644 --- a/crates/ui-egui/src/i18n/lt.tsv +++ b/crates/ui-egui/src/i18n/lt.tsv @@ -590,6 +590,13 @@ Fixed what could be fixed; 1 problem remains Ištaisyta tai, ką buvo galima; liko 1 problema Fixed what could be fixed; {n} problems remain Ištaisyta tai, ką buvo galima; liko problemų: {n} Flatten Fill & Sign when saving Įrašant suplokštinti pildymo ir pasirašymo turinį + Lock your signature into the page? Įtvirtinti parašą puslapyje? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Padėtas parašas yra komentaras, kol neįtvirtintas: bet kas su PDF redaktoriumi gali jį perkelti ar pašalinti. Įtvirtinus užpildymo ir pasirašymo tekstas, žymės ir parašai tampa puslapio dalimi. + Don't ask again Daugiau neklausti + Lock and save Įtvirtinti ir įrašyti + Keep editable Palikti redaguojamą + Lock into the page when saving Įrašant įtvirtinti puslapyje + Otherwise, ask on the first save after a signature is placed Kitaip klausti pirmą kartą įrašant po parašo padėjimo Flip Horizontal Apversti horizontaliai Flip Vertical Apversti vertikaliai Flip horizontal Apversti horizontaliai diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 208dd1c61e..ee94b2085a 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -2249,6 +2249,13 @@ @plural {n} page|{n} pages {n} strona|{n} strony|{n} stron signature pad Type Wpisz Flatten Fill & Sign when saving Spłaszczaj elementy Wypełnij i podpisz przy zapisie + Lock your signature into the page? Utrwalić podpis na stronie? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Umieszczony podpis jest komentarzem, dopóki nie zostanie utrwalony: każdy z edytorem PDF może go przenieść lub usunąć. Utrwalenie sprawia, że tekst, znaki i podpisy z Wypełnij i podpisz stają się częścią strony. + Don't ask again Nie pytaj ponownie + Lock and save Utrwal i zapisz + Keep editable Zachowaj edytowalny + Lock into the page when saving Utrwalaj na stronie przy zapisie + Otherwise, ask on the first save after a signature is placed W przeciwnym razie pytaj przy pierwszym zapisie po umieszczeniu podpisu Text, marks and signatures become part of the page. Other comments stay editable. Tekst, oznaczenia i podpisy stają się częścią strony. Pozostałe komentarze pozostają edytowalne. Scroll tabs left Przewiń karty w lewo Scroll tabs right Przewiń karty w prawo diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index a172a03879..d98d77904e 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -2208,6 +2208,13 @@ action wizard Start Iniciar First Primeiro First commit Primeiro commit Flatten Fill & Sign when saving Nivelar Preencher e assinar ao salvar + Lock your signature into the page? Fixar sua assinatura na página? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Uma assinatura colocada é um comentário até ser fixada: qualquer pessoa com um editor de PDF pode movê-la ou removê-la. Fixar torna o texto, as marcas e as assinaturas de Preencher e assinar parte da página. + Don't ask again Não perguntar novamente + Lock and save Fixar e salvar + Keep editable Manter editável + Lock into the page when saving Fixar na página ao salvar + Otherwise, ask on the first save after a signature is placed Caso contrário, perguntar ao salvar pela primeira vez após colocar uma assinatura H / Space (hold) H / Espaço (manter pressionado) Home / End Home / End Inserted text Texto inserido diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index b45d73ecab..bae4c18a5c 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -91,6 +91,13 @@ Side panels Боковые панели Enable Acrobat JavaScript Включить Acrobat JavaScript Flatten Fill & Sign when saving Расплющить «Заполнить и подписать» при сохранении + Lock your signature into the page? Закрепить подпись на странице? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Размещённая подпись остаётся комментарием, пока не закреплена: любой с редактором PDF может её переместить или удалить. Закрепление делает текст, отметки и подписи из «Заполнить и подписать» частью страницы. + Don't ask again Больше не спрашивать + Lock and save Закрепить и сохранить + Keep editable Оставить редактируемой + Lock into the page when saving Закреплять на странице при сохранении + Otherwise, ask on the first save after a signature is placed Иначе спрашивать при первом сохранении после размещения подписи Text, marks and signatures become part of the page. Other comments stay editable. Текст, пометки и подписи становятся частью страницы. Остальные комментарии можно по-прежнему править. OK OK Join our Discord Присоединяйтесь к нашему Discord diff --git a/crates/ui-egui/src/i18n/sl.tsv b/crates/ui-egui/src/i18n/sl.tsv index c95f6d6bd6..cd08378b90 100644 --- a/crates/ui-egui/src/i18n/sl.tsv +++ b/crates/ui-egui/src/i18n/sl.tsv @@ -2203,6 +2203,13 @@ signature pad Type Vtipkaj Document properties ({key}) Lastnosti dokumenta ({key}) Fill & Sign dates Datumi pri Izpolni in podpiši Flatten Fill & Sign when saving Splošči Izpolni in podpiši ob shranjevanju + Lock your signature into the page? Zakleniti podpis v stran? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Postavljen podpis je komentar, dokler ni zaklenjen: vsak z urejevalnikom PDF ga lahko premakne ali odstrani. Zaklepanje naredi besedilo, oznake in podpise iz Izpolni in podpiši del strani. + Don't ask again Ne sprašuj več + Lock and save Zakleni in shrani + Keep editable Ohrani urejljivo + Lock into the page when saving Ob shranjevanju zakleni v stran + Otherwise, ask on the first save after a signature is placed Sicer vprašaj ob prvem shranjevanju po postavitvi podpisa Font size 0 uses automatic sizing. Velikost pisave 0 pomeni samodejno velikost. Import list… Uvozi seznam… Larger pages Večje strani diff --git a/crates/ui-egui/src/i18n/te.tsv b/crates/ui-egui/src/i18n/te.tsv index 9b81ffb8b9..3c7e4aa7b6 100644 --- a/crates/ui-egui/src/i18n/te.tsv +++ b/crates/ui-egui/src/i18n/te.tsv @@ -2503,6 +2503,14 @@ animation effects Off ఆఫ్ Send backward వెనుకకు పంపు Send to back అందరికంటే వెనుకకు పంపు + Lock your signature into the page? మీ సంతకాన్ని పేజీలో లాక్ చేయాలా? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. ఉంచిన సంతకం లాక్ చేసే వరకు ఒక వ్యాఖ్య మాత్రమే: PDF ఎడిటర్ ఉన్న ఎవరైనా దాన్ని తరలించవచ్చు లేదా తొలగించవచ్చు. లాక్ చేయడం వల్ల నింపి సంతకం చేయి వచనం, గుర్తులు, సంతకాలు పేజీలో భాగమవుతాయి. + Don't ask again మళ్లీ అడగవద్దు + Lock and save లాక్ చేసి సేవ్ చేయి + Keep editable సవరించగలిగేలా ఉంచు + Lock into the page when saving సేవ్ చేసేటప్పుడు పేజీలో లాక్ చేయి + Otherwise, ask on the first save after a signature is placed లేకపోతే, సంతకం ఉంచిన తర్వాత మొదటి సేవ్‌లో అడుగు + # Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed) Today ఈరోజు @plural {n} reply|{n} replies {n} ప్రత్యుత్తరం|{n} ప్రత్యుత్తరాలు diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 6921a6c33e..e62d87e160 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -62,6 +62,13 @@ Side panels Yan paneller Enable Acrobat JavaScript Acrobat JavaScript'i etkinleştir Flatten Fill & Sign when saving Kaydederken Doldur ve İmzala'yı düzleştir + Lock your signature into the page? İmzanız sayfaya sabitlensin mi? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Yerleştirilen imza, sabitlenene kadar bir yorumdur: PDF düzenleyicisi olan herkes onu taşıyabilir veya kaldırabilir. Sabitlemek, Doldur ve İmzala metnini, işaretlerini ve imzalarını sayfanın parçası yapar. + Don't ask again Bir daha sorma + Lock and save Sabitle ve kaydet + Keep editable Düzenlenebilir bırak + Lock into the page when saving Kaydederken sayfaya sabitle + Otherwise, ask on the first save after a signature is placed Aksi halde, imza yerleştirildikten sonraki ilk kayıtta sor Text, marks and signatures become part of the page. Other comments stay editable. Metin, işaretler ve imzalar sayfanın bir parçası olur. Diğer yorumlar düzenlenebilir kalır. OK Tamam Join our Discord Discord'umuza katılın diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index a824769600..863d1a69c1 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -2278,6 +2278,13 @@ calendar date December грудня Smaller pages Менші сторінки Reset page size Скинути розмір сторінок Flatten Fill & Sign when saving Звести «Заповнення й підпис» під час збереження + Lock your signature into the page? Закріпити підпис на сторінці? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. Розміщений підпис є коментарем, доки його не закріплено: будь-хто з редактором PDF може його перемістити або видалити. Закріплення робить текст, позначки й підписи з «Заповнити й підписати» частиною сторінки. + Don't ask again Більше не питати + Lock and save Закріпити й зберегти + Keep editable Залишити редагованим + Lock into the page when saving Закріплювати на сторінці під час збереження + Otherwise, ask on the first save after a signature is placed Інакше питати під час першого збереження після розміщення підпису Text, marks and signatures become part of the page. Other comments stay editable. Текст, позначки й підписи стають частиною сторінки. Інші коментарі залишаються редагованими. Date format Формат дати Fill & Sign dates Дати заповнення й підпису diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 96e9c3bb75..a3eee785a9 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -144,6 +144,13 @@ Side panels 侧边面板 Enable Acrobat JavaScript 启用 Acrobat JavaScript Flatten Fill & Sign when saving 保存时拼合填写与签名 + Lock your signature into the page? 将签名锁定到页面中? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. 放置的签名在锁定前只是注释:任何有 PDF 编辑器的人都能移动或删除它。锁定后,“填写和签名”的文字、标记和签名会成为页面的一部分。 + Don't ask again 不再询问 + Lock and save 锁定并保存 + Keep editable 保持可编辑 + Lock into the page when saving 保存时锁定到页面 + Otherwise, ask on the first save after a signature is placed 否则,在放置签名后首次保存时询问 Text, marks and signatures become part of the page. Other comments stay editable. 文字、标记和签名会成为页面内容。其他注释仍可编辑。 OK 确定 Cancel 取消 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index a1b933b830..3695a90572 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -2544,6 +2544,14 @@ animation effects Off 關 Send backward 下移一層 Send to back 移到最下層 + Lock your signature into the page? 將簽名鎖定到頁面中? + A placed signature is a comment until it is locked: anyone with a PDF editor can move or remove it. Locking makes your Fill & Sign text, marks and signatures part of the page. 放置的簽名在鎖定前只是註解:任何有 PDF 編輯器的人都能移動或移除它。鎖定後,「填寫與簽署」的文字、標記與簽名會成為頁面的一部分。 + Don't ask again 不再詢問 + Lock and save 鎖定並儲存 + Keep editable 保持可編輯 + Lock into the page when saving 儲存時鎖定到頁面 + Otherwise, ask on the first save after a signature is placed 否則,在放置簽名後第一次儲存時詢問 + # Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed) Today 今天 @plural {n} reply|{n} replies {n} 則回覆 diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index fe0138f27f..c847b01337 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -326,6 +326,15 @@ pub struct PdfCraftApp { ui_scale_applied: Option, /// Preferences: bake Fill & Sign marks into the page when saving. Off, so a normal save stays editable. pub flatten_fill_sign_on_save: bool, + /// Ask on the first save after Fill & Sign places a signature or initials whether to lock + /// them into the page (#2149). Off once the user says not to ask again. + pub ask_to_lock_signatures: bool, + /// Documents with a signature or initials placed by Fill & Sign since they were last saved + /// (or asked about). + pub(crate) placed_signatures: std::collections::HashSet, + /// A save waiting behind [`Dialog::LockSignatures`], and its Don't ask again box. + pub(crate) pending_lock: Option, + pub(crate) lock_remember: bool, /// Point size for new Fill & Sign text and dates, kept across launches. pub fill_text_size: f64, /// Colour for new Fill & Sign text and dates, kept across launches. diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs index e3a9c540a6..c034c51a8d 100644 --- a/crates/ui-egui/src/state.rs +++ b/crates/ui-egui/src/state.rs @@ -142,6 +142,9 @@ pub enum Dialog { Revert, /// Save over a file that changed on disk since the document came from it (#2166). OverwriteChanged, + /// Saving a document with a signature just placed by Fill & Sign: lock it into the page + /// first? (#2149) + LockSignatures, /// Link Properties. LinkProps, /// Organize ▸ Extract (options), Rotate Pages. diff --git a/crates/ui-egui/src/tools/fill_sign.rs b/crates/ui-egui/src/tools/fill_sign.rs index 045bb64974..225faca601 100644 --- a/crates/ui-egui/src/tools/fill_sign.rs +++ b/crates/ui-egui/src/tools/fill_sign.rs @@ -398,6 +398,8 @@ pub(crate) fn signature_entries(ui: &mut egui::Ui, app: &mut crate::PdfCraftApp, }); ui.add_space(4.0); } + // Where the signing happens, not only in Preferences (#2149). + ui.add(crate::widgets::checkbox(&mut app.flatten_fill_sign_on_save, tl!("Lock into the page when saving"))); command } diff --git a/crates/ui-egui/src/workflows/js_ui.rs b/crates/ui-egui/src/workflows/js_ui.rs index 70c3f775e9..dce319d637 100644 --- a/crates/ui-egui/src/workflows/js_ui.rs +++ b/crates/ui-egui/src/workflows/js_ui.rs @@ -560,6 +560,10 @@ pub(crate) fn preferences_body(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tok ui.add_space(8.0); ui.label(egui::RichText::new(tl!("Fill & Sign")).font(theme::semibold(13.0))); ui.add(widgets::checkbox(&mut app.flatten_fill_sign_on_save, tl!("Flatten Fill & Sign when saving"))); + ui.add_enabled( + !app.flatten_fill_sign_on_save, + widgets::checkbox(&mut app.ask_to_lock_signatures, tl!("Otherwise, ask on the first save after a signature is placed")), + ); ui.label( egui::RichText::new(tl!("Text, marks and signatures become part of the page. Other comments stay editable.")).small().color(t.text_muted), ); diff --git a/crates/ui-egui/tests/it/fill_sign.rs b/crates/ui-egui/tests/it/fill_sign.rs index ce21bd9f74..1bd6f53ff9 100644 --- a/crates/ui-egui/tests/it/fill_sign.rs +++ b/crates/ui-egui/tests/it/fill_sign.rs @@ -4,7 +4,7 @@ use egui::{Pos2, pos2}; use egui_kittest::Harness; use egui_kittest::kittest::Queryable; use pdfcraft_ui_egui::fill_sign::{FillTool, SavedSig}; -use pdfcraft_ui_egui::{Dialog, PdfCraftApp, QuickTool}; +use pdfcraft_ui_egui::{Dialog, PdfCraftApp, QuickTool, SaveTarget}; const FIXTURE: &[u8] = b"%PDF-1.7 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj @@ -1752,6 +1752,88 @@ fn photos_and_images_dropped_on_the_signature_pad_are_imported_not_opened() { std::fs::remove_file(photo).unwrap(); } +/// #2149: the first save after Fill & Sign places a signature asks whether to lock it into the +/// page. Lock and save flattens it; Keep editable keeps it a comment; Don't ask again becomes +/// the preference; the Sign menu has the switch too. +#[test] +fn the_first_save_after_placing_a_signature_asks_to_lock_it() { + let out = std::env::temp_dir().join(format!("pdfcraft-lock-signature-{}.pdf", std::process::id())); + let mut h = harness(); + h.state_mut().save_override = Some(out.to_string_lossy().into_owned()); + h.state_mut().signature = Some(SavedSig::Typed("Ada Lovelace".into())); + h.state_mut().execute("sign.fill.signature"); + h.run_steps(2); + click(&mut h, 40.0, 300.0); + let signed = |h: &Harness<'static, PdfCraftApp>| { + h.state().session.get(h.state().views[0].id).unwrap().info.annotations.iter().filter(|a| a.fill_sign).count() + }; + assert_eq!(signed(&h), 1); + // Keep editable: saved, still a comment, and not asked again for this placement. + assert!(!h.state_mut().save_active(SaveTarget::InPlace), "asks first"); + h.run_steps(2); + h.get_by_label("Lock your signature into the page?"); + h.get_by_label("Keep editable").click(); + h.run_steps(3); + assert!(!h.state().session.get(h.state().views[0].id).unwrap().dirty, "saved"); + assert_eq!(signed(&h), 1, "still a removable comment"); + assert!(h.state_mut().save_active(SaveTarget::InPlace), "no new signature: no question"); + // A new signature asks again; Lock and save with Don't ask again flattens and remembers. + h.state_mut().execute("sign.fill.signature"); + h.run_steps(2); + click(&mut h, 40.0, 200.0); + assert!(!h.state_mut().save_active(SaveTarget::InPlace)); + h.run_steps(2); + h.get_by_label("Don't ask again").click(); + h.run_steps(1); + h.get_by_label("Lock and save").click(); + h.run_steps(3); + assert_eq!(signed(&h), 0, "locked into the page"); + assert!(!h.state().session.get(h.state().views[0].id).unwrap().dirty); + assert!(h.state().flatten_fill_sign_on_save, "remembered as the preference"); + // The Sign menu shows the same switch. + h.state_mut().flatten_fill_sign_on_save = false; + h.get_by_label("Fill & Sign").click(); + h.run_steps(2); + h.get_by_label("Fill & Sign").click(); + h.run_steps(2); + h.get_by_label("Lock into the page when saving").click(); + h.run_steps(2); + assert!(h.state().flatten_fill_sign_on_save); + let _ = std::fs::remove_file(&out); +} + +/// #2149: Cancel saves nothing, and Keep editable with Don't ask again turns the question off. +#[test] +fn cancelling_the_lock_question_saves_nothing() { + let out = std::env::temp_dir().join(format!("pdfcraft-lock-cancel-{}.pdf", std::process::id())); + let _ = std::fs::remove_file(&out); + let mut h = harness(); + h.state_mut().save_override = Some(out.to_string_lossy().into_owned()); + h.state_mut().signature = Some(SavedSig::Typed("Ada Lovelace".into())); + h.state_mut().execute("sign.fill.signature"); + h.run_steps(2); + click(&mut h, 40.0, 300.0); + assert!(!h.state_mut().save_active(SaveTarget::InPlace)); + h.run_steps(2); + h.get_by_label("Cancel").click(); + h.run_steps(3); + assert!(!out.exists() && h.state().session.get(h.state().views[0].id).unwrap().dirty, "nothing saved"); + assert!(!h.state_mut().save_active(SaveTarget::InPlace), "asked again"); + h.run_steps(2); + h.get_by_label("Don't ask again").click(); + h.run_steps(1); + h.get_by_label("Keep editable").click(); + h.run_steps(3); + assert!(out.exists() && !h.state().ask_to_lock_signatures); + let restored = { + let mut a = PdfCraftApp::new(); + a.restore(&h.state().persist()); + a.ask_to_lock_signatures + }; + assert!(!restored, "kept with the settings"); + let _ = std::fs::remove_file(&out); +} + /// Where a mode bar tab is, by its label. fn mode_tab(h: &Harness<'static, PdfCraftApp>, label: &str) -> egui::Rect { h.get_all_by_role_and_label(egui::accesskit::Role::Button, label).map(|n| n.rect()).find(|r| r.bottom() < 120.0).expect("a mode tab") diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index d03c27c95c..03381a30fa 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -136,7 +136,7 @@ workflows, exchange edge cases and everything outside the mainstream slice are e | Print | 8% | 55% | Good on macOS and Linux; Windows prints since #847 (#756), not yet re-scored | | Highlight, sticky notes, text comments | 12% | 85% | All markup types, replies, properties | | Fill in forms | 10% | 85% | Every AcroForm field type, Acrobat's formatting and calculations | -| Fill & Sign: typed, drawn or image signature | 10% | 85% | Fill & Sign tools; flatten on save | +| Fill & Sign: typed, drawn or image signature | 10% | 85% | Fill & Sign tools; flatten on save (opt-in, and asked on the first save after signing) | | Rotate, delete, reorder and extract pages | 8% | 85% | Organize grid, drag reorder, thumbnails | | Combine files | 6% | 85% | Combine tab with bookmarks per file | | Fix a typo in existing text | 5% | 40% | Latin paragraphs only; font may be substituted | diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index cabfc7823a..66f21615d8 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -5441,8 +5441,8 @@ milestone = "M5" status = "shipped" commands = ["comment.flatten"] tools = ["doc_save", "doc_flatten"] -evidence = ["crates/edit/src/tests.rs::fill_sign_flatten_bakes_marks_keeps_other_comments_and_does_not_reuse_pcfl0", "crates/engine/src/tests.rs::flattening_fill_and_sign_keeps_other_comments_fields_and_undoes", "crates/engine/src/tests.rs::flattening_fill_and_sign_is_refused_without_permission_to_change", "crates/automation/tests/it/automation.rs::saving_with_flatten_fill_sign_bakes_marks_and_leaves_other_comments", "crates/ui-egui/tests/it/fill_sign.rs::saving_flattens_fill_and_sign_only_when_the_preference_is_on"] -notes = "Preferences ▸ Fill & Sign, and doc_save flatten_fill_sign, bake text, marks and signatures into the page. The option defaults off, so a normal save leaves them editable. Other comments and form fields stay. Flatten comments still flattens every comment." +evidence = ["crates/edit/src/tests.rs::fill_sign_flatten_bakes_marks_keeps_other_comments_and_does_not_reuse_pcfl0", "crates/engine/src/tests.rs::flattening_fill_and_sign_keeps_other_comments_fields_and_undoes", "crates/engine/src/tests.rs::flattening_fill_and_sign_is_refused_without_permission_to_change", "crates/automation/tests/it/automation.rs::saving_with_flatten_fill_sign_bakes_marks_and_leaves_other_comments", "crates/ui-egui/tests/it/fill_sign.rs::saving_flattens_fill_and_sign_only_when_the_preference_is_on", "crates/ui-egui/tests/it/fill_sign.rs::the_first_save_after_placing_a_signature_asks_to_lock_it", "crates/ui-egui/tests/it/fill_sign.rs::cancelling_the_lock_question_saves_nothing"] +notes = "Preferences ▸ Fill & Sign, and doc_save flatten_fill_sign, bake text, marks and signatures into the page. The option defaults off, so a normal save leaves them editable; the first save after a signature or initials is placed asks whether to lock it into the page (Lock and save / Keep editable, with Don't ask again), and the Sign menu carries the same switch (#2149). Other comments and form fields stay. Flatten comments still flattens every comment." [[feature]] id = "form.autofill-profile"