Skip to content

Commit

Permalink
[#18459] - Add cursor-based input to token-input (#18594)
Browse files Browse the repository at this point in the history
  • Loading branch information
ulisesmac authored Feb 2, 2024
1 parent b6ddd8b commit c7bf9f0
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 48 deletions.
36 changes: 23 additions & 13 deletions src/quo/components/wallet/token_input/view.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns quo.components.wallet.token-input.view
(:require
[clojure.string :as string]
[oops.core :as oops]
[quo.components.buttons.button.view :as button]
[quo.components.dividers.divider-line.view :as divider-line]
[quo.components.markdown.text :as text]
Expand Down Expand Up @@ -72,18 +73,25 @@
[token-name-text theme text]])

(defn input-section
[{:keys [on-change-text value value-atom]}]
(let [input-ref (atom nil)
set-ref #(reset! input-ref %)
focus-input #(when-let [ref ^js @input-ref]
(.focus ref))
controlled-input? (some? value)
handle-on-change-text (fn [v]
(when-not controlled-input?
(reset! value-atom v))
(when on-change-text
(on-change-text v)))]
(fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?]
[{:keys [on-change-text value value-atom on-selection-change]}]
(let [input-ref (atom nil)
set-ref #(reset! input-ref %)
focus-input #(when-let [ref ^js @input-ref]
(.focus ref))
controlled-input? (some? value)
handle-on-change-text (fn [v]
(when-not controlled-input?
(reset! value-atom v))
(when on-change-text
(on-change-text v)))
handle-selection-change (fn [^js e]
(when on-selection-change
(-> e
(oops/oget "nativeEvent.selection")
(js->clj :keywordize-keys true)
(on-selection-change))))]
(fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?
selection]
:or {show-keyboard? true}}]
[rn/pressable
{:on-press focus-input
Expand All @@ -102,7 +110,9 @@
:max-length 12
:on-change-text handle-on-change-text
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?}
:show-soft-input-on-focus show-keyboard?
:on-selection-change handle-selection-change
:selection (clj->js selection)}
controlled-input? (assoc :value value)
(not controlled-input?) (assoc :default-value @value-atom))]]
[token-label
Expand Down
114 changes: 79 additions & 35 deletions src/status_im/contexts/wallet/send/input_amount/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,60 @@
non-numeric? (re-find not-digits-or-dot-pattern (str v))]
(not (or non-numeric? extra-dot? extra-leading-zero? length-overflow?))))

(defn- add-char-to-string
[s c idx]
(let [size (count s)]
(if (= size idx)
(str s c)
(str (subs s 0 idx)
c
(subs s idx size)))))

(defn- move-input-cursor
([input-selection-atom new-idx]
(move-input-cursor input-selection-atom new-idx new-idx))
([input-selection-atom new-start-idx new-end-idx]
(let [start-idx (if (< new-start-idx 0) 0 new-start-idx)
end-idx (if (< new-end-idx 0) 0 new-start-idx)]
(swap! input-selection-atom assoc :start start-idx :end end-idx))))

(defn- normalize-input
[current v]
(cond
(and (string/blank? current) (= v dot))
(str "0" v)
[current v input-selection-atom]
(let [{:keys [start end]} @input-selection-atom]
(if (= start end)
(cond
(and (string/blank? current) (= v dot))
(do
(move-input-cursor input-selection-atom 2)
(str "0" v))

(and (= current "0") (not= v dot))
(str v)
(and (= current "0") (not= v dot))
(do
(move-input-cursor input-selection-atom 1)
(str v))

:else
(str current v)))
:else
(do
(move-input-cursor input-selection-atom (inc start))
(add-char-to-string current v start)))
current)))

(defn- make-new-input
[current v]
[current v input-selection-atom]
(if (valid-input? current v)
(normalize-input current v)
(normalize-input current v input-selection-atom)
current))

(defn- reset-input-error
[new-value prev-value input-error]
(reset! input-error
(> new-value prev-value)))

(defn delete-from-string
[s idx]
(let [size (count s)]
(str (subs s 0 (dec idx)) (subs s idx size))))

(defn- f-view-internal
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
;; for component tests only
Expand All @@ -72,24 +103,28 @@
input-value (reagent/atom "")
input-error (reagent/atom false)
crypto-currency? (reagent/atom initial-crypto-currency?)
input-selection (reagent/atom {:start 0 :end 0})
handle-swap (fn [{:keys [crypto? limit-fiat limit-crypto]}]
(let [num-value (parse-double @input-value)
current-limit (if crypto? limit-crypto limit-fiat)]
(reset! crypto-currency? crypto?)
(reset-input-error num-value current-limit input-error)))
handle-keyboard-press (fn [v loading-routes? current-limit-amount]
(let [current-value @input-value
new-value (make-new-input current-value v)
num-value (or (parse-double new-value) 0)]
(when (not loading-routes?)
(when-not loading-routes?
(let [current-value @input-value
new-value (make-new-input current-value v input-selection)
num-value (or (parse-double new-value) 0)]
(reset! input-value new-value)
(reset-input-error num-value current-limit-amount input-error)
(reagent/flush))))
handle-delete (fn [loading-routes? current-limit-amount]
(when-not loading-routes?
(swap! input-value #(subs % 0 (dec (count %))))
(reset-input-error @input-value current-limit-amount input-error)
(reagent/flush)))
(let [{:keys [start end]} @input-selection]
(reset-input-error @input-value current-limit-amount input-error)
(when (= start end)
(swap! input-value delete-from-string start)
(move-input-cursor input-selection (dec start)))
(reagent/flush))))
handle-on-change (fn [v current-limit-amount]
(when (valid-input? @input-value v)
(let [num-value (or (parse-double v) 0)]
Expand All @@ -110,7 +145,14 @@
handle-on-confirm (fn []
(rf/dispatch [:wallet/send-select-amount
{:amount @input-value
:stack-id :wallet-send-input-amount}]))]
:stack-id :wallet-send-input-amount}]))
selection-change (fn [selection]
;; `reagent/flush` is needed to properly propagate the
;; input cursor state. Since this is a controlled
;; component the cursor will become static if
;; `reagent/flush` is removed.
(reset! input-selection selection)
(reagent/flush))]
(fn []
(let [{fiat-currency :currency} (rf/sub [:profile/profile])
{:keys [color]} (rf/sub [:wallet/current-viewing-account])
Expand Down Expand Up @@ -154,23 +196,25 @@
:on-press on-navigate-back
:switcher-type :select-account}]
[quo/token-input
{:container-style style/input-container
:token token-symbol
:currency current-currency
:crypto-decimals crypto-decimals
:error? @input-error
:networks token-networks
:title (i18n/label :t/send-limit {:limit limit-label})
:conversion conversion-rate
:show-keyboard? false
:value @input-value
:on-change-text #(handle-on-change % current-limit)
:on-swap #(handle-swap
{:crypto? %
:currency current-currency
:token-symbol token-symbol
:limit-fiat fiat-limit
:limit-crypto crypto-limit})}]
{:container-style style/input-container
:token token-symbol
:currency current-currency
:crypto-decimals crypto-decimals
:error? @input-error
:networks token-networks
:title (i18n/label :t/send-limit {:limit limit-label})
:conversion conversion-rate
:show-keyboard? false
:value @input-value
:selection @input-selection
:on-change-text #(handle-on-change % current-limit)
:on-selection-change selection-change
:on-swap #(handle-swap
{:crypto? %
:currency current-currency
:token-symbol token-symbol
:limit-fiat fiat-limit
:limit-crypto crypto-limit})}]
[routes/view
{:amount amount-text
:routes suggested-routes
Expand Down

0 comments on commit c7bf9f0

Please sign in to comment.