From a2da122b5d83cd4b03b94954ca0fa5364c4da590 Mon Sep 17 00:00:00 2001 From: darkfi Date: Thu, 9 Jan 2025 19:21:27 +0100 Subject: [PATCH] wallet: use arboard for clipboard on wayland --- bin/darkwallet/Cargo.toml | 3 ++ bin/darkwallet/Makefile | 2 +- bin/darkwallet/src/app/schema/chat.rs | 50 +++++++++++++++++++++++---- bin/darkwallet/src/ui/chatedit.rs | 14 +++++--- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/bin/darkwallet/Cargo.toml b/bin/darkwallet/Cargo.toml index 8820dd7a8e2d..c054633299e5 100644 --- a/bin/darkwallet/Cargo.toml +++ b/bin/darkwallet/Cargo.toml @@ -69,6 +69,9 @@ halo2_gadgets = {git="https://github.com/parazyd/halo2", branch="v4"} # This patch didn't work for me #dirs-sys = {git="https://github.com/sbechet/dirs-sys-rs.git"} +[target.'cfg(not(target_os = "android"))'.dependencies] +arboard = {version = "3.4.1", features=["wayland-data-control"]} + [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.13.3" # Required by Arti: tor-dirmgr diff --git a/bin/darkwallet/Makefile b/bin/darkwallet/Makefile index 05e2a83af3f0..13d162d01593 100644 --- a/bin/darkwallet/Makefile +++ b/bin/darkwallet/Makefile @@ -36,7 +36,7 @@ android: $(SRC) fonts adb install $(APK) reset adb logcat -c - adb logcat -v color -s darkfi -s SAPP + adb logcat -v color -s darkfi -s SAPP -s libc -s DEBUG -s ActivityManager -s ActivityTaskManager -s WindowManager # Useful for dev cli: diff --git a/bin/darkwallet/src/app/schema/chat.rs b/bin/darkwallet/src/app/schema/chat.rs index 0852e80221cf..841caba6eeb6 100644 --- a/bin/darkwallet/src/app/schema/chat.rs +++ b/bin/darkwallet/src/app/schema/chat.rs @@ -179,6 +179,36 @@ mod ui_consts { use super::EMOJI_PICKER_ICON_SIZE; use ui_consts::*; +struct Clipboard { + #[cfg(not(target_os = "android"))] + clip: arboard::Clipboard +} + +impl Clipboard { + fn new() -> Self { + Self { + #[cfg(not(target_os = "android"))] + clip: arboard::Clipboard::new().unwrap() + } + } + + fn get(&mut self) -> Option { + #[cfg(target_os = "android")] + return window::clipboard_get(); + + #[cfg(not(target_os = "android"))] + return self.clip.get_text().ok(); + } + + fn set(&mut self, data: &str) { + #[cfg(target_os = "android")] + return window::clipboard_set(data); + + #[cfg(not(target_os = "android"))] + return self.clip.set_text(data).unwrap(); + } +} + pub async fn make( app: &App, window: SceneNodePtr, @@ -751,7 +781,7 @@ pub async fn make( //node.set_property_bool(Role::App, "debug", true).unwrap(); let editz_text = PropertyStr::wrap(&node, Role::App, "text", 0).unwrap(); - let editz_select_text_prop = node.get_property("select_text").unwrap(); + let editz_select_text = node.get_property("select_text").unwrap(); //let editbox_focus = PropertyBool::wrap(node, Role::App, "is_focused", 0).unwrap(); //let darkirc_backend = app.darkirc_backend.clone(); @@ -1237,10 +1267,14 @@ pub async fn make( let (slot, recvr) = Slot::new("copy_clicked"); node.register("click", slot).unwrap(); let actions_is_visible2 = actions_is_visible.clone(); + let editz_select_text2 = editz_select_text.clone(); let listen_click = app.ex.spawn(async move { + let mut clip = Clipboard::new(); while let Ok(_) = recvr.recv().await { info!(target: "app::chat", "clicked copy"); actions_is_visible2.set(false); + let select_text = editz_select_text2.get_str(0).unwrap(); + clip.set(&select_text); } }); app.tasks.lock().unwrap().push(listen_click); @@ -1261,8 +1295,13 @@ pub async fn make( node.register("click", slot).unwrap(); let actions_is_visible2 = actions_is_visible.clone(); let listen_click = app.ex.spawn(async move { + let mut clip = Clipboard::new(); while let Ok(_) = recvr.recv().await { - info!(target: "app::chat", "clicked paste"); + if let Some(text) = clip.get() { + info!(target: "app::chat", "clicked paste: {text}"); + } else { + info!(target: "app::chat", "clicked paste but clip is empty"); + } actions_is_visible2.set(false); } }); @@ -1286,7 +1325,6 @@ pub async fn make( let listen_click = app.ex.spawn(async move { while let Ok(_) = recvr.recv().await { info!(target: "app::chat", "clicked select_all"); - actions_is_visible2.set(false); } }); app.tasks.lock().unwrap().push(listen_click); @@ -1294,14 +1332,14 @@ pub async fn make( let node = node.setup(|me| Button::new(me, app.ex.clone())).await; layer_node.clone().link(node); - let editz_select_sub = editz_select_text_prop.subscribe_modify(); + let editz_select_sub = editz_select_text.subscribe_modify(); let editz_select_task = app.ex.spawn(async move { while let Ok(_) = editz_select_sub.receive().await { - if editz_select_text_prop.is_null(0).unwrap() { + if editz_select_text.is_null(0).unwrap() { info!(target: "app::chat", "selection changed: null"); actions_is_visible.set(false); } else { - let select_text = editz_select_text_prop.get_str(0).unwrap(); + let select_text = editz_select_text.get_str(0).unwrap(); info!(target: "app::chat", "selection changed: {select_text}"); actions_is_visible.set(true); } diff --git a/bin/darkwallet/src/ui/chatedit.rs b/bin/darkwallet/src/ui/chatedit.rs index 21b2532c43d6..fac0ccdea5a0 100644 --- a/bin/darkwallet/src/ui/chatedit.rs +++ b/bin/darkwallet/src/ui/chatedit.rs @@ -643,10 +643,10 @@ impl ChatEdit { // .lock() // .editable // .set_text("".to_string(), "king!๐Ÿ˜๐Ÿ†jelly ๐Ÿ†1234".to_string()); - //self_.text_wrap.lock().editable.set_text( - // "".to_string(), - // "A berry is a small, pulpy, and often edible fruit. Typically, berries are juicy, rounded, brightly colored, sweet, sour or tart, and do not have a stone or pit, although many pips or seeds may be present. Common examples of berries in the culinary sense are strawberries, raspberries, blueberries, blackberries, white currants, blackcurrants, and redcurrants. In Britain, soft fruit is a horticultural term for such fruits. The common usage of the term berry is different from the scientific or botanical definition of a berry, which refers to a fruit produced from the ovary of a single flower where the outer layer of the ovary wall develops into an edible fleshy portion (pericarp). The botanical definition includes many fruits that are not commonly known or referred to as berries, such as grapes, tomatoes, cucumbers, eggplants, bananas, and chili peppers.".to_string() - //); + self_.text_wrap.lock().editable.set_text( + "".to_string(), + "A berry is a small, pulpy, and often edible fruit. Typically, berries are juicy, rounded, brightly colored, sweet, sour or tart, and do not have a stone or pit, although many pips or seeds may be present. Common examples of berries in the culinary sense are strawberries, raspberries, blueberries, blackberries, white currants, blackcurrants, and redcurrants. In Britain, soft fruit is a horticultural term for such fruits. The common usage of the term berry is different from the scientific or botanical definition of a berry, which refers to a fruit produced from the ovary of a single flower where the outer layer of the ovary wall develops into an edible fleshy portion (pericarp). The botanical definition includes many fruits that are not commonly known or referred to as berries, such as grapes, tomatoes, cucumbers, eggplants, bananas, and chili peppers.".to_string() + ); //self_ // .text_wrap // .lock() @@ -1288,8 +1288,12 @@ impl ChatEdit { } return }; + + let start = std::cmp::min(select.start, select.end); + let end = std::cmp::max(select.start, select.end); + let rendered = text_wrap.get_render(); - let glyphs = &rendered.glyphs[select.start..select.end]; + let glyphs = &rendered.glyphs[start..end]; let text = text::glyph_str(glyphs); self.select_text.set_str(Role::Internal, 0, text).unwrap(); }