From 0345fa70f2d5c7b8582ac9a6b8c0376a3018fb06 Mon Sep 17 00:00:00 2001 From: xfy Date: Tue, 9 Jun 2026 11:33:26 +0800 Subject: [PATCH] fix: add click handler for code block copy button --- Cargo.toml | 2 +- src/components/post/post_content.rs | 38 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 522c6a9..df7e8e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ moka = { version = "0.12", features = ["future"], optional = true } governor = { version = "0.8", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -web-sys = { version = "0.3", features = ["Document", "Window", "Storage", "Element", "DomTokenList", "MediaQueryList", "HtmlImageElement", "MouseEvent", "KeyboardEvent", "Node", "EventTarget"] } +web-sys = { version = "0.3", features = ["Document", "Window", "Storage", "Element", "DomTokenList", "MediaQueryList", "HtmlImageElement", "MouseEvent", "KeyboardEvent", "Node", "EventTarget", "Navigator"] } wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" js-sys = "0.3" diff --git a/src/components/post/post_content.rs b/src/components/post/post_content.rs index 7a57cdb..3703fd0 100644 --- a/src/components/post/post_content.rs +++ b/src/components/post/post_content.rs @@ -24,6 +24,44 @@ pub fn PostContent(content_html: String) -> Element { copybutton.set_text_content(Some("copy")); copybutton.set_attribute("aria-label", "Copy code").unwrap(); + let code_text = codeblock.text_content().unwrap_or_default(); + let btn = copybutton.clone(); + let copy_closure = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| { + let has_clipboard = web_sys::window() + .map(|w| { + let clip = js_sys::Reflect::get(&w.navigator(), &js_sys::JsString::from("clipboard")).unwrap_or(wasm_bindgen::JsValue::UNDEFINED); + !clip.is_undefined() + }) + .unwrap_or(false); + + if has_clipboard { + let _ = js_sys::eval(&format!( + "navigator.clipboard.writeText({})", + serde_json::to_string(&code_text).unwrap_or_default() + )); + } else { + let _ = js_sys::eval(&format!( + "((t)=>{{const e=document.createElement('textarea');e.value=t;e.style.position='fixed';e.style.opacity='0';document.body.appendChild(e);e.select();document.execCommand('copy');document.body.removeChild(e)}})({})", + serde_json::to_string(&code_text).unwrap_or_default() + )); + } + + btn.set_text_content(Some("copied!")); + let btn_clone = btn.clone(); + let reset_closure = Closure::wrap(Box::new(move || { + btn_clone.set_text_content(Some("copy")); + }) as Box); + let _ = web_sys::window() + .unwrap() + .set_timeout_with_callback_and_timeout_and_arguments_0( + reset_closure.as_ref().unchecked_ref(), + 2000, + ); + reset_closure.forget(); + }) as Box); + copybutton.add_event_listener_with_callback("click", copy_closure.as_ref().unchecked_ref()).unwrap(); + copy_closure.forget(); + let _ = parent.append_child(©button); } }