From 4a1e5863f49db6eedda4e88192d67ec0647db52b Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Mon, 28 Sep 2020 13:37:03 +0300 Subject: [PATCH] [#11216] Fix moving cursor after pressing mention suggestion on samsung device --- .../status/ethereum/module/StatusModule.java | 27 +++++++++++++++++++ src/quo/react_native.cljs | 2 ++ src/status_im/chat/models/input.cljs | 8 +++--- src/status_im/chat/models/mentions.cljs | 17 +++++++++++- src/status_im/events.cljs | 4 +-- src/status_im/native_module/core.cljs | 4 +++ .../ui/screens/chat/components/input.cljs | 8 +++--- src/status_im/ui/screens/chat/views.cljs | 2 +- 8 files changed, 61 insertions(+), 11 deletions(-) diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index 03819714b90c..5efcfd518ae7 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -19,6 +19,11 @@ import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebStorage; +import android.content.Context; +import android.view.View; +import android.widget.TextView; +import android.widget.EditText; +import android.view.inputmethod.InputMethodManager; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; @@ -30,6 +35,9 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIBlock; +import com.facebook.react.uimanager.NativeViewHierarchyManager; import statusgo.SignalHandler; import statusgo.Statusgo; @@ -1386,5 +1394,24 @@ public void run() { }); } } + + @ReactMethod + public void resetKeyboardInputCursor(final int reactTagToReset, final int selection) { + UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class); + uiManager.addUIBlock(new UIBlock() { + @Override + public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) { + InputMethodManager imm = (InputMethodManager) getReactApplicationContext().getBaseContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + View viewToReset = nativeViewHierarchyManager.resolveView(reactTagToReset); + imm.restartInput(viewToReset); + try { + EditText textView = (EditText) viewToReset; + textView.setSelection(selection); + } catch (Exception e) {} + } + } + }); + } } diff --git a/src/quo/react_native.cljs b/src/quo/react_native.cljs index a8949c4d328f..585c3880a7f7 100644 --- a/src/quo/react_native.cljs +++ b/src/quo/react_native.cljs @@ -9,6 +9,8 @@ (def platform (.-Platform ^js rn)) +(def find-node-handle (.-findNodeHandle ^js rn)) + (def view (reagent/adapt-react-class (.-View ^js rn))) (def image (reagent/adapt-react-class (.-Image rn))) (def text (reagent/adapt-react-class (.-Text ^js rn))) diff --git a/src/status_im/chat/models/input.cljs b/src/status_im/chat/models/input.cljs index 5a6fc77de931..06e56fc5f375 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im/chat/models/input.cljs @@ -30,16 +30,18 @@ {:db (assoc-in db [:chat/inputs current-chat-id :input-text] (text->emoji new-input))}) (fx/defn select-mention - [{:keys [db] :as cofx} {:keys [alias name searched-text match] :as user}] + [{:keys [db] :as cofx} text-input-ref {:keys [alias name searched-text match] :as user}] (let [chat-id (:current-chat-id db) new-text (mentions/new-input-text-with-mention cofx user) - at-sign-idx (get-in db [:chats chat-id :mentions :at-sign-idx])] + at-sign-idx (get-in db [:chats chat-id :mentions :at-sign-idx]) + cursor (+ at-sign-idx (count name) 2)] (fx/merge cofx {:db (-> db - (assoc-in [:chats/cursor chat-id] (+ at-sign-idx (count name) 2)) + (assoc-in [:chats/cursor chat-id] cursor) (assoc-in [:chats/mention-suggestions chat-id] nil))} (set-chat-input-text new-text) + (mentions/reset-text-input-cursor text-input-ref cursor) ;; NOTE(roman): on-text-input event is not dispatched when we change input ;; programmatically, so we have to call `on-text-input` manually (mentions/on-text-input diff --git a/src/status_im/chat/models/mentions.cljs b/src/status_im/chat/models/mentions.cljs index 89f8af7c2e50..d59df27dd313 100644 --- a/src/status_im/chat/models/mentions.cljs +++ b/src/status_im/chat/models/mentions.cljs @@ -1,10 +1,14 @@ (ns status-im.chat.models.mentions (:require [clojure.string :as string] + [re-frame.core :as re-frame] [status-im.utils.fx :as fx] [status-im.contact.db :as contact.db] [status-im.utils.platform :as platform] [taoensso.timbre :as log] - [status-im.utils.utils :as utils])) + [status-im.utils.utils :as utils] + [status-im.native-module.core :as status] + [quo.react-native :as rn] + [quo.react :as react])) (def at-sign "@") @@ -450,3 +454,14 @@ (calculate-suggestions mentionable-users)) (clear-suggestions cofx))))) +(re-frame/reg-fx + ::reset-text-input-cursor + (fn [[ref cursor]] + (when ref + (status/reset-keyboard-input + (rn/find-node-handle (react/current-ref ref)) + cursor)))) + +(fx/defn reset-text-input-cursor + [_ ref cursor] + {::reset-text-input-cursor [ref cursor]}) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index efbc7db4b59c..281f243584ac 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -506,8 +506,8 @@ (handlers/register-handler-fx :chat.ui/select-mention - (fn [cofx [_ mention]] - (chat.input/select-mention cofx mention))) + (fn [cofx [_ text-input-ref mention]] + (chat.input/select-mention cofx text-input-ref mention))) (handlers/register-handler-fx :chat.ui/set-chat-input-text diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index 501d3d9999a3..7583c01f7da4 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -380,3 +380,7 @@ (defn deactivate-keep-awake [] (log/debug "[native-module] deactivateKeepAwake") (.deactivateKeepAwake ^js (status))) + +(defn reset-keyboard-input [input selection] + (log/debug "[native-module] resetKeyboardInput") + (.resetKeyboardInputCursor ^js (status) input selection)) diff --git a/src/status_im/ui/screens/chat/components/input.cljs b/src/status_im/ui/screens/chat/components/input.cljs index 21d781d350b0..856f97d1156b 100644 --- a/src/status_im/ui/screens/chat/components/input.cljs +++ b/src/status_im/ui/screens/chat/components/input.cljs @@ -197,7 +197,7 @@ input-with-mentions)]])) (defn mention-item - [[_ {:keys [identicon alias name nickname] :as user}]] + [text-input-ref [_ {:keys [identicon alias name nickname] :as user}]] (let [ens-name? (not= alias name)] [list-item/list-item (cond-> {:icon @@ -233,14 +233,14 @@ :title-text-weight :medium :on-press (fn [] - (re-frame/dispatch [:chat.ui/select-mention user]))} + (re-frame/dispatch [:chat.ui/select-mention text-input-ref user]))} ens-name? (assoc :subtitle alias))])) (def chat-input-height (reagent/atom nil)) -(defn autocomplete-mentions [] +(defn autocomplete-mentions [text-input-ref] (let [suggestions @(re-frame/subscribe [:chat/mention-suggestions])] (when (and (seq suggestions) @chat-input-height) (let [height (+ 16 (* 52 (min 4.5 (count suggestions))))] @@ -254,7 +254,7 @@ :header [rn/view {:style {:height 8}}] :data suggestions :key-fn first - :render-fn #(mention-item %)}]]])))) + :render-fn #(mention-item text-input-ref %)}]]])))) (defn chat-input [{:keys [set-active-panel active-panel on-send-press reply diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index 9eee5a2f8798..695e32d0bc21 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -301,7 +301,7 @@ ;; :always doesn't work and keyboard is hidden on pressing suggestion. ;; Scrolling of suggestions doesn't work neither in this case. (when platform/android? - [components/autocomplete-mentions]) + [components/autocomplete-mentions text-input-ref]) (when show-input? [accessory/view {:y position-y :pan-state pan-state