Restored some code

This commit is contained in:
Combiler01 committed 2026-10-17 22:52:53 +05:30
1 parent a02b7198ee
commit ca76c52511
10 files changed
+38 -190

No files matched your search

+2 -2
View File
@@ -85,11 +85,11 @@ jobs:
- name: Test
if: runner.os != 'Linux'
run: cargo test --workspace
run: cargo test --workspace -- --test-threads=1
- name: Test (with craft-fonts)
if: runner.os == 'Linux'
run: cargo test --workspace
run: cargo test --workspace -- --test-threads=1
- name: Layering
if: runner.os == 'Linux'
-2
View File
@@ -368,8 +368,6 @@ fn app_creator<'a>(
Box::new(move |cc| {
started.set(true);
let mut app = PdfCraftApp::new();
app.system_clipboard = true;
app.clipboard_override = None;
// First start (or settings from before Units existed): the region's unit.
app.units = pdfcraft_ui_egui::units::Unit::system();
#[cfg(target_os = "linux")]
-38
View File
@@ -1,38 +0,0 @@
//! Deterministic in-memory clipboard for headless UI tests and automation.
//!
//! Prevents headless tests running in parallel from competing for the native
//! operating system clipboard, eliminating concurrency races and OS heap corruption.
use std::path::PathBuf;
/// A deterministic, in-memory mock clipboard for tests.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct MockClipboard {
pub text: Option<String>,
pub image: Option<(usize, usize, Vec<u8>)>,
pub files: Option<Vec<PathBuf>>,
}
impl MockClipboard {
/// Creates an empty mock clipboard.
pub fn new() -> Self {
Self::default()
}
/// Creates a mock clipboard containing plain text.
pub fn with_text(text: impl Into<String>) -> Self {
Self { text: Some(text.into()), image: None, files: None }
}
/// Creates a mock clipboard containing an image (width, height, RGBA bytes).
pub fn with_image(width: usize, height: usize, rgba: Vec<u8>) -> Self {
Self { text: None, image: Some((width, height, rgba)), files: None }
}
/// Clears all clipboard contents.
pub fn clear(&mut self) {
self.text = None;
self.image = None;
self.files = None;
}
}
+18 -51
View File
@@ -821,19 +821,14 @@ impl crate::PdfCraftApp {
return false;
};
let copied = pixels.and_then(|(w, h, rgba)| {
if let Some(mock) = &mut self.clipboard_override {
mock.image = Some((w as usize, h as usize, rgba.clone()));
mock.text = None;
} else {
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
let img = arboard::ImageData { width: w as usize, height: h as usize, bytes: std::borrow::Cow::Borrowed(&rgba) };
arboard::Clipboard::new().and_then(|mut c| c.set_image(img)).map_err(|e| e.to_string())?;
}
#[cfg(target_arch = "wasm32")]
if self.system_clipboard {
return Err("the web version can't put images on the clipboard yet; use Save Image As".to_string());
}
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
let img = arboard::ImageData { width: w as usize, height: h as usize, bytes: std::borrow::Cow::Borrowed(&rgba) };
arboard::Clipboard::new().and_then(|mut c| c.set_image(img)).map_err(|e| e.to_string())?;
}
#[cfg(target_arch = "wasm32")]
if self.system_clipboard {
return Err("the web version can't put images on the clipboard yet; use Save Image As".to_string());
}
self.last_copied_image = Some((w, h, rgba));
Ok((w, h))
@@ -900,25 +895,11 @@ impl crate::PdfCraftApp {
/// Whether there is an image in the in-memory clipboard or system clipboard ready to paste.
pub fn can_paste_image(&self) -> bool {
if let Some(mock) = &self.clipboard_override {
if mock.text.as_ref().is_some_and(|t| !t.is_empty()) {
return false;
}
if mock.image.is_some() {
return true;
}
return self.last_copied_image.is_some() || self.last_copied_file.is_some();
}
#[cfg(not(target_arch = "wasm32"))]
{
if self.system_clipboard
&& let Ok(mut cb) = arboard::Clipboard::new()
{
if let Ok(text) = cb.get_text()
&& !text.is_empty()
{
return false;
}
return cb.get_image().is_ok();
}
}
@@ -937,33 +918,19 @@ impl crate::PdfCraftApp {
return false;
}
let (has_system_cb, os_image, system_has_text) = if let Some(mock) = &self.clipboard_override {
let has_text = mock.text.as_ref().is_some_and(|t| !t.is_empty());
let img = mock.image.clone();
(true, img, has_text)
} else {
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
if let Ok(mut cb) = arboard::Clipboard::new() {
let has_text = cb.get_text().map(|t| !t.is_empty()).unwrap_or(false);
let img_opt = cb.get_image().ok().map(|img| (img.width, img.height, img.bytes.to_vec()));
(true, img_opt, has_text)
} else {
(false, None, false)
}
#[cfg(not(target_arch = "wasm32"))]
let (has_system_cb, os_image) = if self.system_clipboard {
if let Ok(mut cb) = arboard::Clipboard::new() {
let img_opt = cb.get_image().ok().map(|img| (img.width, img.height, img.bytes.to_vec()));
(true, img_opt)
} else {
(false, None, false)
(false, None)
}
#[cfg(target_arch = "wasm32")]
(false, None, false)
} else {
(false, None)
};
if system_has_text {
self.last_copied_image = None;
self.last_copied_file = None;
self.last_copied_image_rect = None;
return false;
}
#[cfg(target_arch = "wasm32")]
let (has_system_cb, os_image): (bool, Option<(usize, usize, Vec<u8>)>) = (false, None);
let image_data: Option<(String, Vec<u8>)> = if has_system_cb {
match os_image {
+4 -18
View File
@@ -111,24 +111,10 @@ impl PdfCraftApp {
/// Create ▸ Clipboard: a new document from the image (one page, its size) or the text on
/// the clipboard, as Acrobat does.
pub(crate) fn create_from_clipboard(&mut self) {
let clip = if let Some(mock) = &self.clipboard_override {
if let Some((w, h, rgba)) = &mock.image {
Some(Clip::Image { width: *w, height: *h, rgba: rgba.clone() })
} else {
mock.text.as_ref().map(|t| Clip::Text(t.clone()))
}
} else if self.system_clipboard {
#[cfg(not(target_arch = "wasm32"))]
{
read_clipboard()
}
#[cfg(target_arch = "wasm32")]
{
None
}
} else {
None
};
#[cfg(not(target_arch = "wasm32"))]
let clip = read_clipboard();
#[cfg(target_arch = "wasm32")]
let clip: Option<Clip> = None;
match clip {
Some(c) => {
if let Err(e) = self.create_from_clip(c) {
+1 -1
View File
@@ -203,7 +203,7 @@ impl PdfCraftApp {
/// previous copy, and puts that file on the system clipboard.
#[cfg(not(target_arch = "wasm32"))]
fn put_file_on_clipboard(&self, name: &str, bytes: &[u8]) -> Result<(), String> {
if self.clipboard_override.is_some() || !self.system_clipboard {
if !self.system_clipboard {
return Ok(());
}
let dir = clipboard_dir().ok_or("there is no folder for the copied file")?;
+6 -41
View File
@@ -44,8 +44,6 @@ mod combine_ui;
pub mod docking;
pub use combine_ui::{Columns as CombineColumns, CombineView, Lock as CombineLock, SortKey};
mod camera_ui;
pub mod clipboard;
pub use clipboard::MockClipboard;
mod commands;
mod comment_props;
pub mod comments;
@@ -734,9 +732,6 @@ pub struct PdfCraftApp {
pub last_copied_file: Option<(String, Vec<u8>)>,
pub last_copied_image_rect: Option<[f64; 4]>,
pub system_clipboard: bool,
/// Deterministic in-memory clipboard for headless UI tests and automation.
/// When `Some`, clipboard operations use this mock instead of the OS clipboard.
pub clipboard_override: Option<MockClipboard>,
/// Attach file: the file to attach instead of asking (tests, automation).
pub attach_override: Option<(String, Vec<u8>)>,
/// Duplicate Field: which field and onto which pages.
@@ -1037,8 +1032,7 @@ impl PdfCraftApp {
last_copied_image: None,
last_copied_file: None,
last_copied_image_rect: None,
system_clipboard: false,
clipboard_override: Some(MockClipboard::default()),
system_clipboard: true,
attach_override: None,
duplicate_draft: None,
form_preview: false,
@@ -2514,31 +2508,6 @@ impl PdfCraftApp {
}
}
/// Injects a deterministic mock clipboard for headless tests.
pub fn set_mock_clipboard(&mut self, mock: MockClipboard) {
self.clipboard_override = Some(mock);
}
/// Sets plain text on the mock clipboard (creating one if absent).
pub fn set_mock_clipboard_text(&mut self, text: impl Into<String>) {
if let Some(mock) = &mut self.clipboard_override {
mock.text = Some(text.into());
mock.image = None;
} else {
self.clipboard_override = Some(MockClipboard::with_text(text));
}
}
/// Sets an image on the mock clipboard (creating one if absent).
pub fn set_mock_clipboard_image(&mut self, width: usize, height: usize, rgba: Vec<u8>) {
if let Some(mock) = &mut self.clipboard_override {
mock.image = Some((width, height, rgba));
mock.text = None;
} else {
self.clipboard_override = Some(MockClipboard::with_image(width, height, rgba));
}
}
/// `true` while any open document still waits for page renders (used by headless capture).
pub fn render_pending(&self) -> bool {
self.views.iter().any(|v| v.render_pending())
@@ -2981,18 +2950,14 @@ impl PdfCraftApp {
self.cut_page_image(sel.page, sel.index);
}
if paste {
let system_has_text = if let Some(mock) = &self.clipboard_override {
mock.text.as_ref().is_some_and(|t| !t.is_empty())
#[cfg(not(target_arch = "wasm32"))]
let system_has_text = if self.system_clipboard {
arboard::Clipboard::new().and_then(|mut cb| cb.get_text()).map(|t| !t.is_empty()).unwrap_or(false)
} else {
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
arboard::Clipboard::new().and_then(|mut cb| cb.get_text()).map(|t| !t.is_empty()).unwrap_or(false)
} else {
false
}
#[cfg(target_arch = "wasm32")]
false
};
#[cfg(target_arch = "wasm32")]
let system_has_text = false;
if paste_event_text.is_some() || system_has_text {
self.last_copied_image = None;
+4 -9
View File
@@ -138,15 +138,10 @@ impl PdfCraftApp {
return Err(e);
}
let (w, h) = (out.width, out.height);
if let Some(mock) = &mut self.clipboard_override {
mock.image = Some((w as usize, h as usize, out.rgba.to_vec()));
mock.text = None;
} else {
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
let img = arboard::ImageData { width: w as usize, height: h as usize, bytes: std::borrow::Cow::Borrowed(&out.rgba) };
arboard::Clipboard::new().and_then(|mut c| c.set_image(img)).map_err(|e| e.to_string())?;
}
#[cfg(not(target_arch = "wasm32"))]
if self.system_clipboard {
let img = arboard::ImageData { width: w as usize, height: h as usize, bytes: std::borrow::Cow::Borrowed(&out.rgba) };
arboard::Clipboard::new().and_then(|mut c| c.set_image(img)).map_err(|e| e.to_string())?;
}
self.last_snapshot = Some((w, h, out.rgba));
Ok((w, h))
+3 -23
View File
@@ -44,7 +44,6 @@ fn harness(pages: usize, setup: impl FnOnce(&mut PdfCraftApp) + 'static) -> Harn
let mut h = builder.build_eframe(move |_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.clipboard_override = Some(pdfcraft_ui_egui::MockClipboard::default());
app.open_bytes("doc.pdf", None, fixture(pages)).expect("fixture opens");
setup(&mut app);
app
@@ -4979,13 +4978,11 @@ fn stale_clipboard_plain_text_does_not_paste_image() {
h.state_mut().last_copied_image = Some((10, 10, vec![0; 400]));
h.state_mut().last_copied_file = Some(("cached.png".to_string(), vec![1, 2, 3]));
h.state_mut().system_clipboard = true;
h.state_mut().clipboard_override = None;
// Set actual system clipboard to plain text, asserting success explicitly
// Set actual system clipboard to plain text
#[cfg(not(target_arch = "wasm32"))]
{
let mut cb = arboard::Clipboard::new().expect("acquire OS clipboard");
cb.set_text("just plain text").expect("set OS clipboard text");
if let Ok(mut cb) = arboard::Clipboard::new() {
cb.set_text("just plain text").ok();
}
// A paste event containing plain text clears internal image cache and does not paste image
@@ -5002,23 +4999,6 @@ fn stale_clipboard_plain_text_does_not_paste_image() {
assert_eq!(doc.page_images(0).len(), 0, "no image pasted on the page");
}
#[test]
fn deterministic_mock_clipboard_plain_text_does_not_paste_image() {
let mut h = harness(1, |_| {});
h.run_steps(4);
h.state_mut().last_copied_image = Some((10, 10, vec![0; 400]));
h.state_mut().last_copied_file = Some(("cached.png".to_string(), vec![1, 2, 3]));
// Inject plain text into the mock clipboard
h.state_mut().set_mock_clipboard_text("just plain text");
assert!(!h.state().can_paste_image(), "cannot paste image when mock clipboard has text");
assert!(!h.state_mut().paste_image(0, None), "must not paste stale cached image");
let doc = h.state().session.get(h.state().views[0].id).unwrap();
assert_eq!(doc.page_images(0).len(), 0, "no image pasted on the page");
}
#[test]
fn rotated_image_selection_and_crop() {
let mut png = Vec::new();
-5
View File
@@ -48,11 +48,6 @@ ignore = [
# winprint's fmt-derive (craft-print's Windows spooler), so it runs at compile time on Windows
# and is not in the binary.
{ id = "RUSTSEC-2024-0370", reason = "compile-time proc macro of winprint's fmt-derive (craft-print Windows printing, #1107)" },
# zbus_names, zvariant, and zvariant_derive are unmaintained (no vulnerability). Reached via
# eframe -> accesskit_unix until upstream migrates to zbus v6.
{ id = "RUSTSEC-2026-0370", reason = "unmaintained zbus_names dependency via eframe -> accesskit_unix until upstream migrates to zbus v6" },
{ id = "RUSTSEC-2026-0371", reason = "unmaintained zvariant dependency via eframe -> accesskit_unix until upstream migrates to zbus v6" },
{ id = "RUSTSEC-2026-0372", reason = "unmaintained zvariant_derive dependency via eframe -> accesskit_unix until upstream migrates to zbus v6" },
]
# egui's default UI fonts (Ubuntu-Light, Hack, emoji-icon-font): font licences on the AGENTS.md