mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-05 10:10:22 +00:00
fix: resolve stale clipboard image paste bug & finalized CI checks
This commit is contained in:
1 parent
2f53d0f0e2
commit
1f728fda8f
7 files changed
+38
No files matched your search
@@ -26,6 +26,7 @@ impl Pixels {
|
||||
}
|
||||
|
||||
/// Bytes the buffer holds allocated (its capacity), for memory budgets.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn byte_capacity(&self) -> usize {
|
||||
self.0.capacity().saturating_mul(4)
|
||||
}
|
||||
|
||||
@@ -244,6 +244,7 @@ struct AtomicRenderStats {
|
||||
}
|
||||
|
||||
impl AtomicRenderStats {
|
||||
#[allow(dead_code)]
|
||||
fn record_request(&self, req: RenderRequest) {
|
||||
self.render_requests.fetch_add(1, Ordering::Relaxed);
|
||||
if req.tile.is_some() {
|
||||
@@ -541,6 +542,7 @@ struct Shared {
|
||||
busy: Mutex<Vec<Option<Busy>>>,
|
||||
/// Exact requests the watchdog gave up on: answered with an error at once, so a pathological
|
||||
/// request cannot trap every worker in turn while other scales, tiles, or generations remain usable.
|
||||
#[allow(dead_code)]
|
||||
stuck: Mutex<std::collections::HashSet<RequestFailureKey>>,
|
||||
stats: AtomicRenderStats,
|
||||
/// Per worker id: set to stop that worker's render at its next content operator once nobody
|
||||
@@ -715,8 +717,11 @@ pub struct RenderPool {
|
||||
shared: Arc<Shared>,
|
||||
wake: Mutex<Vec<SyncSender<()>>>,
|
||||
results: ResultReceiver,
|
||||
#[allow(dead_code)]
|
||||
results_tx: Arc<WorkQueue>,
|
||||
#[allow(dead_code)]
|
||||
bytes: Arc<Vec<u8>>,
|
||||
#[allow(dead_code)]
|
||||
config: RenderConfig,
|
||||
_workers: Mutex<Vec<JoinHandle<()>>>,
|
||||
stuck_after: std::time::Duration,
|
||||
|
||||
@@ -974,6 +974,7 @@ fn is_form_edit(edit: &Edit) -> bool {
|
||||
/// because Outlook can still hold the file, or appears to work while the edits stay out of the
|
||||
/// email and are deleted with the cache. Matched on either separator and in any case, so it can
|
||||
/// be tested on every platform.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn is_mail_temp_copy(path: &str) -> bool {
|
||||
let p = path.replace('\\', "/").to_ascii_lowercase();
|
||||
p.contains("/inetcache/content.outlook/")
|
||||
|
||||
@@ -2922,6 +2922,12 @@ impl PdfCraftApp {
|
||||
|| ctx.input_mut(|input| input.consume_shortcut(&KeyboardShortcut::new(Modifiers::COMMAND, Key::C)));
|
||||
let cut = ctx.input(|input| input.events.iter().any(|e| matches!(e, egui::Event::Cut)))
|
||||
|| ctx.input_mut(|input| input.consume_shortcut(&KeyboardShortcut::new(Modifiers::COMMAND, Key::X)));
|
||||
let paste_event_text = ctx.input(|input| {
|
||||
input.events.iter().find_map(|e| match e {
|
||||
egui::Event::Paste(text) if !text.is_empty() => Some(text.clone()),
|
||||
_ => None,
|
||||
})
|
||||
});
|
||||
let paste = ctx.input(|input| input.events.iter().any(|e| matches!(e, egui::Event::Paste(_))))
|
||||
|| ctx.input_mut(|input| input.consume_shortcut(&KeyboardShortcut::new(Modifiers::COMMAND, Key::V)));
|
||||
|
||||
@@ -2944,6 +2950,22 @@ impl PdfCraftApp {
|
||||
self.cut_page_image(sel.page, sel.index);
|
||||
}
|
||||
if paste {
|
||||
#[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 {
|
||||
false
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let system_has_text = false;
|
||||
|
||||
if paste_event_text.is_some() || system_has_text {
|
||||
self.last_copied_image = None;
|
||||
self.last_copied_file = None;
|
||||
self.last_copied_image_rect = None;
|
||||
return;
|
||||
}
|
||||
|
||||
let page = self.views.get(i).map_or(0, |v| v.current);
|
||||
self.paste_image(page, None);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ impl Unit {
|
||||
|
||||
/// The unit for a locale tag's region: `en_US.UTF-8`, `en-US`, `bg-BG`, `zh-Hans-CN`, `en_GB@euro`.
|
||||
/// `None` without a region (`C`, `POSIX`, `en`).
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn unit_for_tag(tag: &str) -> Option<Unit> {
|
||||
let tag = tag.split(['.', '@']).next().unwrap_or_default();
|
||||
let region = tag.split(['-', '_']).skip(1).filter(|p| p.len() == 2 && p.chars().all(|c| c.is_ascii_alphabetic())).last()?;
|
||||
|
||||
@@ -52,6 +52,7 @@ pub(crate) enum Check {
|
||||
Idle,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Running(std::sync::mpsc::Receiver<Result<Release, String>>),
|
||||
#[allow(dead_code)]
|
||||
Done(Result<Release, String>),
|
||||
}
|
||||
|
||||
|
||||
@@ -4985,11 +4985,18 @@ fn stale_clipboard_plain_text_does_not_paste_image() {
|
||||
cb.set_text("just plain text").ok();
|
||||
}
|
||||
|
||||
// A paste event containing plain text clears internal image cache and does not paste image
|
||||
h.event(egui::Event::Paste("just plain text".into()));
|
||||
h.run_steps(2);
|
||||
|
||||
// can_paste_image should now be false because the system clipboard has text, not an image!
|
||||
assert!(!h.state().can_paste_image(), "cannot paste image when system clipboard has text");
|
||||
|
||||
// paste_image should fail and return false without pasting
|
||||
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]
|
||||
|
||||
Reference in new issue
Block a user