mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-31 13:37:35 -06:00
fix(ui): text typed into a new text box counts as unsaved work (#4441)
* fix(ui): text typed into a new text box counts as unsaved work Closing a tab or quitting while the only unsaved thing was text in a new Add text box skipped the save prompt and lost the text. The box now counts like fill text does: only when it holds non-blank text. * fix(ui): saving on close keeps text typed into a new text box
This commit is contained in:
@@ -38,6 +38,11 @@ pub enum SaveTarget {
|
||||
As,
|
||||
}
|
||||
|
||||
/// Text typed into a new text box that isn't added to the page yet.
|
||||
fn new_text_typed(v: &crate::DocView) -> bool {
|
||||
v.content.draft.as_ref().is_some_and(|d| d.index.is_none() && !d.text.trim().is_empty())
|
||||
}
|
||||
|
||||
impl PdfCraftApp {
|
||||
/// Apply an edit to the active document. Returns `true` on success; failures are shown.
|
||||
pub fn apply_edit(&mut self, edit: Edit) -> bool {
|
||||
@@ -636,6 +641,7 @@ impl PdfCraftApp {
|
||||
|| v.content.blocked().is_some()
|
||||
|| v.forms.focus.as_ref().is_some_and(|f| crate::forms_ui::draft_edit(f, &doc.form).is_some())
|
||||
|| v.fill_text.as_ref().is_some_and(|t| !t.text.trim().is_empty())
|
||||
|| new_text_typed(v)
|
||||
|| v.line_editor.as_ref().map_or_else(|| false, |ed| ed.has_unsaved_text())
|
||||
}
|
||||
|
||||
@@ -1694,6 +1700,56 @@ mod revert_draft_tests {
|
||||
assert!(app.unsaved_flag.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
/// Text typed into a new text box is lost on close unless the save prompt appears; an empty
|
||||
/// box has nothing to lose.
|
||||
#[test]
|
||||
fn text_typed_into_a_new_text_box_counts_as_unsaved_work() {
|
||||
use crate::content_ui::{TextDraft, default_style};
|
||||
let mut app = app();
|
||||
let draft = |text: &str| TextDraft { page: 0, index: None, rect: [0.0; 4], text: text.into(), style: default_style(), focus: true };
|
||||
assert!(!app.has_unsaved_work(0));
|
||||
app.views[0].content.draft = Some(draft(" \n"));
|
||||
assert!(!app.has_unsaved_work(0));
|
||||
app.views[0].content.draft = Some(draft("Typed"));
|
||||
assert!(!app.session.get(app.views[0].id).unwrap().dirty);
|
||||
assert!(app.has_unsaved_work(0));
|
||||
}
|
||||
|
||||
/// Close ▸ Save, and Quit ▸ Save, write the text typed into a new text box before the tab
|
||||
/// closes.
|
||||
#[test]
|
||||
fn saving_on_close_keeps_text_typed_into_a_new_text_box() {
|
||||
use crate::content_ui::{TextDraft, default_style};
|
||||
use pdfcraft_engine::AddedContent;
|
||||
for quit in [false, true] {
|
||||
let dir = std::env::temp_dir().join(format!("pdfcraft-ui-new-text-{}-{quit}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join("source.pdf").to_string_lossy().into_owned();
|
||||
let bytes = include_bytes!("../tests/data/form.pdf").to_vec();
|
||||
std::fs::write(&path, &bytes).unwrap();
|
||||
let mut app = PdfCraftApp::new();
|
||||
app.open_bytes("source.pdf", Some(path.clone()), bytes).unwrap();
|
||||
let rect = [72.0, 72.0, 272.0, 92.0];
|
||||
app.views[0].content.draft = Some(TextDraft { page: 0, index: None, rect, text: "Typed".into(), style: default_style(), focus: true });
|
||||
let ctx = egui::Context::default();
|
||||
if quit {
|
||||
assert!(!app.request_quit(&ctx));
|
||||
} else {
|
||||
app.request_close_tab(0);
|
||||
}
|
||||
assert!(app.close_request.is_some());
|
||||
app.resolve_close(&ctx, Some(true));
|
||||
assert!(app.views.is_empty(), "the tab closes once saved");
|
||||
|
||||
let mut reopened = PdfCraftApp::new();
|
||||
reopened.open_bytes("source.pdf", Some(path.clone()), std::fs::read(&path).unwrap()).unwrap();
|
||||
let doc = reopened.session.get(reopened.views[0].id).unwrap();
|
||||
assert!(doc.added().iter().any(|a| matches!(&a.content, AddedContent::Text(t) if t.text == "Typed")), "quit: {quit}");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn successful_revert_clears_focused_or_queued_drafts_only_on_its_document() {
|
||||
for queued in [false, true] {
|
||||
|
||||
Reference in New Issue
Block a user