mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-28 12:46:48 -06:00
Merge pull request #36 from harrisonoconnorhover/fix/rich-table-clipboard
Fix copying selected cells as rich HTML tables
This commit is contained in:
@@ -93,6 +93,7 @@ impl eframe::App for WebShell {
|
||||
fn services(inbox: Inbox, ctx: egui::Context) -> Services {
|
||||
let open_inbox = inbox.clone();
|
||||
Services {
|
||||
copy_html: Some(Box::new(copy_html)),
|
||||
open_async: Some(Box::new(move || {
|
||||
let inbox = open_inbox.clone();
|
||||
let ctx = ctx.clone();
|
||||
@@ -124,6 +125,39 @@ fn services(inbox: Inbox, ctx: egui::Context) -> Services {
|
||||
}
|
||||
}
|
||||
|
||||
/// Start inside the copy gesture; deferring `write` can lose browser user activation.
|
||||
fn copy_html(html: &str, text: &str) -> Result<(), String> {
|
||||
let js = |e: wasm_bindgen::JsValue| format!("{e:?}");
|
||||
let window = web_sys::window().ok_or("no window")?;
|
||||
let clipboard = window.navigator().clipboard();
|
||||
if clipboard.is_undefined() || clipboard.is_null() {
|
||||
return Err("browser clipboard is unavailable (a secure context is required)".into());
|
||||
}
|
||||
if !js_sys::Reflect::get(&clipboard, &"write".into()).map_err(js)?.is_function() {
|
||||
return Err("browser does not support rich clipboard writes".into());
|
||||
}
|
||||
let data = js_sys::Object::new();
|
||||
for (mime, value) in [("text/html", html), ("text/plain", text)] {
|
||||
let opts = web_sys::BlobPropertyBag::new();
|
||||
opts.set_type(mime);
|
||||
let parts = js_sys::Array::of1(&wasm_bindgen::JsValue::from_str(value));
|
||||
let blob = web_sys::Blob::new_with_str_sequence_and_options(&parts, &opts).map_err(js)?;
|
||||
js_sys::Reflect::set(&data, &mime.into(), &blob).map_err(js)?;
|
||||
}
|
||||
let item = web_sys::ClipboardItem::new_with_record_from_str_to_blob_promise(&data).map_err(js)?;
|
||||
let promise = clipboard.write(&js_sys::Array::of1(&item));
|
||||
let text = text.to_owned();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
if let Err(e) = wasm_bindgen_futures::JsFuture::from(promise).await {
|
||||
log::warn!("Rich clipboard write failed; trying plain text: {e:?}");
|
||||
if let Err(e) = wasm_bindgen_futures::JsFuture::from(clipboard.write_text(&text)).await {
|
||||
log::error!("Plain-text clipboard fallback also failed: {e:?}");
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Triggers a browser download of `bytes`.
|
||||
fn download(name: &str, bytes: &[u8]) -> Result<(), String> {
|
||||
let js = |e: wasm_bindgen::JsValue| format!("{e:?}");
|
||||
|
||||
Reference in New Issue
Block a user