Răsfoiți Sursa

wallet: UIObjects now have handle_commit_text() and handle_edit_text() for Android typing suggestions.

darkfi 1 an în urmă
părinte
comite
abf94e8eec

+ 1 - 0
bin/darkwallet/Cargo.lock

@@ -1170,6 +1170,7 @@ dependencies = [
  "futures-rustls",
  "halo2_gadgets",
  "halo2_proofs",
+ "httparse",
  "libc",
  "log",
  "num-bigint",

+ 17 - 1
bin/darkwallet/src/android.rs

@@ -21,13 +21,14 @@ use std::sync::{LazyLock, Mutex as SyncMutex};
 
 struct GlobalData {
     inp_conn: ndk_sys::jobject,
+    sender: Option<async_channel::Sender<AndroidSuggestEvent>>,
 }
 
 unsafe impl Send for GlobalData {}
 unsafe impl Sync for GlobalData {}
 
 static GLOBALS: LazyLock<SyncMutex<GlobalData>> =
-    LazyLock::new(|| SyncMutex::new(GlobalData { inp_conn: std::ptr::null_mut() }));
+    LazyLock::new(|| SyncMutex::new(GlobalData { inp_conn: std::ptr::null_mut(), sender: None }));
 
 #[no_mangle]
 pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_setup() {
@@ -40,6 +41,11 @@ pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_setup() {
     GLOBALS.lock().unwrap().inp_conn = inp_conn;
 }
 
+pub enum AndroidSuggestEvent {
+    CommitText(String),
+    EditText(String),
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onCommitText(
     env: *mut ndk_sys::JNIEnv,
@@ -48,6 +54,9 @@ pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onCommitText(
 ) {
     let text = ndk_utils::get_utf_str!(env, text);
     debug!(target: "android", "onCommitText: {text}");
+    if let Some(sender) = &GLOBALS.lock().unwrap().sender {
+        let _ = sender.try_send(AndroidSuggestEvent::CommitText(text.to_string()));
+    }
 }
 
 #[no_mangle]
@@ -58,4 +67,11 @@ pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onEndEdit(
 ) {
     let text = ndk_utils::get_utf_str!(env, text);
     debug!(target: "android", "onEditText: {text}");
+    if let Some(sender) = &GLOBALS.lock().unwrap().sender {
+        let _ = sender.try_send(AndroidSuggestEvent::EditText(text.to_string()));
+    }
+}
+
+pub fn set_sender(sender: async_channel::Sender<AndroidSuggestEvent>) {
+    GLOBALS.lock().unwrap().sender = Some(sender);
 }

+ 1 - 0
bin/darkwallet/src/gfx/mod.rs

@@ -678,6 +678,7 @@ impl EventHandler for Stage {
     }
 
     fn key_down_event(&mut self, keycode: KeyCode, mods: KeyMods, repeat: bool) {
+        debug!(target: "gfx", "key_down_event");
         self.event_pub.notify_key_down(keycode, mods, repeat);
     }
     fn key_up_event(&mut self, keycode: KeyCode, mods: KeyMods) {

+ 8 - 0
bin/darkwallet/src/ui/mod.rs

@@ -81,6 +81,14 @@ pub trait UIObject: Sync {
     async fn handle_touch(&self, phase: TouchPhase, id: u64, touch_pos: Point) -> bool {
         false
     }
+
+    // Android Autosuggest
+    async fn handle_edit_text(&self, text: &str) -> bool {
+        false
+    }
+    async fn handle_commit_text(&self, text: &str) -> bool {
+        false
+    }
 }
 
 pub struct DrawUpdate {

+ 39 - 0
bin/darkwallet/src/ui/win.rs

@@ -144,8 +144,32 @@ impl Window {
                 mouse_wheel_task,
                 touch_task,
             ];
+
             tasks.append(&mut on_modify.tasks);
 
+            #[cfg(target_os = "android")]
+            {
+                let (sender, recvr) = async_channel::unbounded();
+                crate::android::set_sender(sender);
+                let me2 = me.clone();
+                let autosuggest_task = ex.spawn(async move {
+                    loop {
+                        let Ok(ev) = recvr.recv().await else {
+                            debug!(target: "ui::win", "Event relayer closed");
+                            break
+                        };
+
+                        let Some(self_) = me2.upgrade() else {
+                            // Should not happen
+                            panic!("self destroyed before modify_task was stopped!");
+                        };
+
+                        self_.handle_autosuggest(ev).await;
+                    }
+                });
+                tasks.push(autosuggest_task);
+            }
+
             Self { node, tasks, screen_size, scale, render_api }
         });
 
@@ -372,6 +396,21 @@ impl Window {
         }
     }
 
+    #[cfg(target_os = "android")]
+    async fn handle_autosuggest(&self, ev: crate::android::AndroidSuggestEvent) {
+        use crate::android::AndroidSuggestEvent::*;
+        for child in self.get_children() {
+            let obj = get_ui_object3(&child);
+            let is_handled = match &ev {
+                EditText(text) => obj.handle_edit_text(&text).await,
+                CommitText(text) => obj.handle_commit_text(&text).await,
+            };
+            if is_handled {
+                return
+            }
+        }
+    }
+
     pub async fn draw(&self) {
         let local = self.screen_size.get() / self.scale.get();
         let rect = Rectangle::from([0., 0., local.w, local.h]);