Эх сурвалжийг харах

app: add focus/unfocus text area when moving between different chats :)

darkfi 1 жил өмнө
parent
commit
d3238da4c3

+ 20 - 2
bin/app/java/MainActivity.java

@@ -40,6 +40,9 @@ public void createComposer(final int id) {
     });
 }
 
+private InputMethodManager getIMM() {
+    return (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+}
 public boolean focus(final int id) {
     final InvisibleInputView iv = editors.get(id);
     if (iv == null) {
@@ -55,8 +58,23 @@ public boolean focus(final int id) {
                 Log.w("darkfi", "error requesting focus for id=" + id + ": " + iv);
             }
 
-            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
-            imm.showSoftInput(iv, InputMethodManager.SHOW_IMPLICIT);
+            getIMM().showSoftInput(iv, InputMethodManager.SHOW_IMPLICIT);
+        }
+    });
+
+    return true;
+}
+public boolean unfocus(final int id) {
+    final InvisibleInputView iv = editors.get(id);
+    if (iv == null) {
+        return false;
+    }
+
+    runOnUiThread(new Runnable() {
+        @Override
+        public void run() {
+            iv.clearFocus();
+            getIMM().hideSoftInputFromWindow(iv.getWindowToken(), 0);
         }
     });
 

+ 5 - 4
bin/app/java/autosuggest/InvisibleInputView.java

@@ -76,10 +76,11 @@ public class InvisibleInputView extends View {
     @Override
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
         Log.d("darkfi", "Create InputConnection for view=" + this.toString());
-        if (inputConnection != null) {
-            Log.d("darkfi", "  ->  return existing InputConnection");
-            return inputConnection;
-        }
+        // Losing focus requires the inputConnection to be destroyed
+        //if (inputConnection != null) {
+        //    Log.d("darkfi", "  ->  return existing InputConnection");
+        //    return inputConnection;
+        //}
 
         outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
             | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;

+ 12 - 0
bin/app/src/android.rs

@@ -184,6 +184,18 @@ pub fn focus(id: usize) -> Option<()> {
         Some(())
     }
 }
+pub fn unfocus(id: usize) -> Option<()> {
+    let is_success = unsafe {
+        let env = android::attach_jni_env();
+
+        ndk_utils::call_bool_method!(env, android::ACTIVITY, "unfocus", "(I)Z", id as i32)
+    };
+    if is_success == 0u8 {
+        None
+    } else {
+        Some(())
+    }
+}
 
 pub fn set_text(id: usize, text: &str) -> Option<()> {
     let ctext = std::ffi::CString::new(text).unwrap();

+ 1 - 0
bin/app/src/app/node.rs

@@ -453,6 +453,7 @@ pub fn create_chatedit(name: &str) -> SceneNode {
     // Used by emoji_picker
     node.add_method("insert_text", vec![("text", "Text", CallArgType::Str)], None).unwrap();
     node.add_method("focus", vec![], None).unwrap();
+    node.add_method("unfocus", vec![], None).unwrap();
 
     node
 }

+ 8 - 3
bin/app/src/app/schema/chat.rs

@@ -291,12 +291,18 @@ pub async fn make(
     prop.clone().set_f32(atom, Role::App, 2, EMOJI_BG_W).unwrap();
     prop.clone().set_f32(atom, Role::App, 3, CHATEDIT_HEIGHT).unwrap();
 
+    // Menu doesn't exist yet ;)
+    // So look it up in the callback.
     let sg_root = app.sg_root.clone();
+    let layer_node2 = layer_node.clone();
     let chatview_is_visible = PropertyBool::wrap(&layer_node, Role::App, "is_visible", 0).unwrap();
-    let goback = move || {
+    let goback = async move || {
         info!(target: "app::chat", "clicked back");
         let atom = &mut PropertyAtomicGuard::new();
 
+        let editz_node = layer_node2.clone().lookup_node("/content/editz").unwrap();
+        editz_node.call_method("unfocus", vec![]).await.unwrap();
+
         let menu_node = sg_root.clone().lookup_node("/window/menu_layer").unwrap();
         menu_node.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
 
@@ -306,10 +312,9 @@ pub async fn make(
     let (slot, recvr) = Slot::new("back_clicked");
     node.register("click", slot).unwrap();
     let goback2 = goback.clone();
-    // Menu doesn't exist yet ;)
     let listen_click = app.ex.spawn(async move {
         while let Ok(_) = recvr.recv().await {
-            goback2();
+            goback2().await;
         }
     });
     app.tasks.lock().unwrap().push(listen_click);

+ 3 - 0
bin/app/src/text2/editor/android.rs

@@ -128,6 +128,9 @@ impl Editor {
         }
         android::focus(self.composer_id).unwrap();
     }
+    pub fn unfocus(&self) {
+        android::unfocus(self.composer_id).unwrap();
+    }
 
     pub async fn refresh(&mut self, atom: &mut PropertyAtomicGuard) {
         let font_size = self.font_size.get();

+ 25 - 1
bin/app/src/ui/chatedit.rs

@@ -1305,6 +1305,25 @@ impl ChatEdit {
         editor.focus();
         true
     }
+    async fn process_unfocus_method(me: &Weak<Self>, sub: &MethodCallSub) -> bool {
+        let Ok(method_call) = sub.receive().await else {
+            debug!(target: "ui::chatedit", "Event relayer closed");
+            return false
+        };
+
+        t!("method called: focus({method_call:?})");
+        assert!(method_call.send_res.is_none());
+        assert!(method_call.data.is_empty());
+
+        let Some(self_) = me.upgrade() else {
+            // Should not happen
+            panic!("self destroyed before insert_text_method_task was stopped!");
+        };
+
+        let mut editor = self_.editor.lock().await;
+        editor.unfocus();
+        true
+    }
 
     async fn handle_android_event(&self, ev: AndroidSuggestEvent) {
         t!("handle_android_event({ev:?})");
@@ -1370,6 +1389,11 @@ impl UIObject for ChatEdit {
         let focus_task =
             ex.spawn(async move { while Self::process_focus_method(&me2, &method_sub).await {} });
 
+        let method_sub = node_ref.subscribe_method_call("unfocus").unwrap();
+        let me2 = me.clone();
+        let unfocus_task =
+            ex.spawn(async move { while Self::process_unfocus_method(&me2, &method_sub).await {} });
+
         let mut on_modify = OnModify::new(ex.clone(), self.node.clone(), me.clone());
         on_modify.when_change(self.is_focused.prop(), Self::change_focus);
 
@@ -1454,7 +1478,7 @@ impl UIObject for ChatEdit {
             }
         });
 
-        let mut tasks = vec![insert_text_task, focus_task, blinking_cursor_task];
+        let mut tasks = vec![insert_text_task, focus_task, unfocus_task, blinking_cursor_task];
         tasks.append(&mut on_modify.tasks);
 
         #[cfg(target_os = "android")]