diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 2faa05a3f..622cf2481 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -3218,6 +3218,9 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) { } } if resp.drag_started() && press_here && !over_link { + // A drag replaces the selection without passing through none, so a + // re-drag over text whose bar Copy closed would keep the bar hidden. + view.actions_dismissed = None; view.selection_drag = true; let origin = ui.input(|inp| inp.pointer.press_origin()).unwrap_or(p); let (ox, oy) = xf.screen_to_view(origin); diff --git a/crates/ui-egui/tests/comments.rs b/crates/ui-egui/tests/comments.rs index aaea7990f..c127e2c99 100644 --- a/crates/ui-egui/tests/comments.rs +++ b/crates/ui-egui/tests/comments.rs @@ -379,6 +379,25 @@ fn selected_text_copy_action_closes_the_bar_and_keeps_the_selection() { h.get_by_label("Add comment"); } +#[test] +fn dragging_over_copied_text_again_brings_the_action_bar_back() { + let mut h = harness(|_| {}); + let (a, b) = { + let v = &h.state().views[0]; + (v.glyph_screen_pos(0, 4).expect("text layer"), v.glyph_screen_pos(0, 8).expect("glyph")) + }; + drag(&mut h, a, b); + let copied = h.state().views[0].selected_text(); + assert!(copied.is_some(), "the drag selects text"); + h.get_by_label("Copy").click(); + h.run_steps(3); + assert!(h.query_by_label("Add comment").is_none(), "the action bar closes after Copy"); + // The same drag again selects the same words, which is a new selection: the bar is back. + drag(&mut h, a, b); + assert_eq!(h.state().views[0].selected_text(), copied, "the drag selects the same words"); + assert!(h.query_by_label("Add comment").is_some(), "the action bar is back after a new drag"); +} + #[test] fn selected_text_replace_action_opens_replacement_composer() { let mut h = harness(|_| {});