From dcbb080217646a62f6d4749d516415cbf55c3e37 Mon Sep 17 00:00:00 2001 From: Ulises Manuel <90291778+ulisesmac@users.noreply.github.com> Date: Mon, 22 Jan 2024 20:01:00 -0600 Subject: [PATCH] [#18458] Token input fixes (#18520) * Add custom keyboard to token-input preview * Fix token input flickering --- .../components/wallet/token_input/style.cljs | 61 +++++-- .../components/wallet/token_input/view.cljs | 165 +++++++++++------- .../contexts/preview/quo/preview.cljs | 9 +- .../preview/quo/wallet/token_input.cljs | 33 ++-- 4 files changed, 174 insertions(+), 94 deletions(-) diff --git a/src/quo/components/wallet/token_input/style.cljs b/src/quo/components/wallet/token_input/style.cljs index ab8773fbc9..bef187a3a9 100644 --- a/src/quo/components/wallet/token_input/style.cljs +++ b/src/quo/components/wallet/token_input/style.cljs @@ -1,8 +1,7 @@ (ns quo.components.wallet.token-input.style (:require [quo.foundations.colors :as colors] - [quo.foundations.typography :as typography] - [react-native.platform :as platform])) + [quo.foundations.typography :as typography])) (defn main-container [width] @@ -16,23 +15,51 @@ :flex-direction :row :justify-content :space-between}) +(defn token-name + [theme] + {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme) + :margin-right 8 + :padding-bottom 2}) + +(def token-label-container + {:position :absolute + :left 40 ; token image size + margin + :right 0 + :bottom 0 + :top 0 + :flex-direction :row + :align-items :flex-end}) + +(def text-input-container + {:position :absolute + :top 0 + :bottom 0 + :left 40 ; token image size + margin + :right 0}) + +(def text-input-dimensions + (-> typography/heading-1 + (dissoc :letter-spacing) + (assoc :font-weight "600" + :margin-right 5 + :padding-left 0 + :padding-right 0 + :padding-top 0 + :padding-bottom 0 + :height "100%"))) + (defn text-input [theme] - (merge typography/heading-1 - {:font-weight "600" - :margin-left 8 - :margin-right (if platform/ios? 6 4) - :color (colors/theme-colors colors/neutral-100 colors/white theme) - :padding 0 - :text-align :center - :height "100%"})) + (assoc text-input-dimensions :color (colors/theme-colors colors/neutral-100 colors/white theme))) + +(defn placeholder-text + [theme] + (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)) (defn divider - [width theme] - {:height 1 - :width width - :background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme) - :margin-vertical 8}) + [theme] + {:margin-vertical 8 + :background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)}) (def data-container {:padding-top 4 @@ -40,3 +67,7 @@ :flex-direction :row :justify-content :space-between :align-items :center}) + +(defn fiat-amount + [theme] + {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}) diff --git a/src/quo/components/wallet/token_input/view.cljs b/src/quo/components/wallet/token_input/view.cljs index 753de36ccf..e992d1cb42 100644 --- a/src/quo/components/wallet/token_input/view.cljs +++ b/src/quo/components/wallet/token_input/view.cljs @@ -7,7 +7,6 @@ [quo.components.tags.network-tags.view :as network-tag] [quo.components.utilities.token.view :as token] [quo.components.wallet.token-input.style :as style] - [quo.foundations.colors :as colors] [quo.foundations.common :as common] [quo.theme :as quo.theme] [react-native.core :as rn] @@ -25,83 +24,117 @@ (defn calc-value [{:keys [crypto? currency token value conversion crypto-decimals]}] - (let [num-value (if (string? value) (parse-double (or value "0")) value)] + (let [num-value (if (string? value) + (or (parse-double value) 0) + value)] (if crypto? (fiat-format currency num-value conversion) (crypto-format num-value conversion crypto-decimals token)))) +(defn- data-info + [{:keys [theme token crypto-decimals conversion networks title crypto? currency amount]}] + [rn/view {:style style/data-container} + [network-tag/view {:networks networks :title title}] + [text/text + {:size :paragraph-2 + :weight :medium + :style (style/fiat-amount theme)} + (calc-value {:crypto? crypto? + :currency currency + :token token + :value amount + :conversion conversion + :crypto-decimals crypto-decimals})]]) + +(defn- token-name-text + [theme text] + [text/text + {:style (style/token-name theme) + :size :paragraph-2 + :weight :semi-bold} + (string/upper-case (or (clj->js text) ""))]) + +(defn- token-label + [{:keys [theme value text]}] + [rn/view + {:style style/token-label-container + :pointer-events :none} + [rn/text-input + {:max-length 12 + :style style/text-input-dimensions + :editable false + :placeholder "0" + :opacity 0 + :value value}] + [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] + :or {show-keyboard? true}}] + [rn/pressable + {:on-press focus-input + :style {:flex 1}} + [token/view + {:token token + :size :size-32}] + [rn/view {:style style/text-input-container} + [rn/text-input + (cond-> {:style (style/text-input theme) + :placeholder-text-color (style/placeholder-text theme) + :auto-focus true + :ref set-ref + :placeholder "0" + :keyboard-type :numeric + :max-length 12 + :on-change-text handle-on-change-text + :selection-color customization-color + :show-soft-input-on-focus show-keyboard?} + controlled-input? (assoc :value value) + (not controlled-input?) (assoc :default-value @value-atom))]] + [token-label + {:theme theme + :text (if crypto? token currency) + :value (if controlled-input? value @value-atom)}]]))) + (defn- view-internal - [{external-value :value}] - (let [width (:width (rn/get-window)) - value (reagent/atom nil) - crypto? (reagent/atom true) - input-ref (atom nil) - controlled-input? (some? external-value)] - (fn [{:keys [theme token currency crypto-decimals conversion networks title - customization-color - on-change-text on-swap container-style show-keyboard?] - :or {show-keyboard? true} - external-value :value}] - [rn/view - {:style (merge - (style/main-container width) - container-style)} + [{:keys [on-swap]}] + (let [width (:width (rn/get-window)) + value-atom (reagent/atom nil) + crypto? (reagent/atom true) + handle-on-swap (fn [] + (swap! crypto? not) + (when on-swap + (on-swap @crypto?)))] + (fn [{:keys [theme container-style value] :as props}] + [rn/view {:style (merge (style/main-container width) container-style)} [rn/view {:style style/amount-container} - [rn/pressable - {:on-press #(when @input-ref (.focus ^js @input-ref)) - :style {:flex-direction :row - :flex-grow 1 - :align-items :flex-end}} - [token/view {:token token :size :size-32}] - [rn/text-input - (cond-> {:auto-focus true - :ref #(reset! input-ref %) - :placeholder "0" - :placeholder-text-color (colors/theme-colors colors/neutral-40 - colors/neutral-50 - theme) - :keyboard-type :numeric - :max-length 12 - :on-change-text (fn [v] - (when-not controlled-input? - (reset! value v)) - (when on-change-text - (on-change-text v))) - :style (style/text-input theme) - :selection-color customization-color - :show-soft-input-on-focus show-keyboard?} - controlled-input? (assoc :value external-value) - (not controlled-input?) (assoc :default-value @value))] - [text/text - {:size :paragraph-2 - :weight :semi-bold - :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme) - :margin-right 8 - :padding-bottom 2}} - (string/upper-case (or (clj->js (if @crypto? token currency)) ""))]] + [input-section + (assoc props + :value-atom value-atom + :crypto? @crypto?)] [button/button {:icon true :icon-only? true :size 32 - :on-press (fn [] - (swap! crypto? not) - (when on-swap - (on-swap @crypto?))) + :on-press handle-on-swap :type :outline :accessibility-label :reorder} :i/reorder]] - [divider-line/view {:container-style {:margin-vertical 8}}] - [rn/view {:style style/data-container} - [network-tag/view {:networks networks :title title}] - [text/text - {:size :paragraph-2 - :weight :medium - :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}} - (calc-value {:crypto? @crypto? - :currency currency - :token token - :value (or external-value @value) - :conversion conversion - :crypto-decimals crypto-decimals})]]]))) + [divider-line/view {:container-style (style/divider theme)}] + [data-info + (assoc props + :crypto? @crypto? + :amount (or value @value-atom))]]))) (def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im/contexts/preview/quo/preview.cljs b/src/status_im/contexts/preview/quo/preview.cljs index dafaaa2571..f522b1d1f7 100644 --- a/src/status_im/contexts/preview/quo/preview.cljs +++ b/src/status_im/contexts/preview/quo/preview.cljs @@ -320,7 +320,7 @@ (defn- f-preview-container [{:keys [title state descriptor blur? blur-dark-only? component-container-style - blur-container-style blur-view-props blur-height show-blur-background?] + blur-container-style blur-view-props blur-height show-blur-background? full-screen?] :or {blur-height 200}} & children] (let [theme (quo.theme/use-theme-value) @@ -337,8 +337,11 @@ [common/navigation-bar {:title title}] [rn/scroll-view {:style (style/panel-basic) - :shows-vertical-scroll-indicator false} - [rn/pressable {:on-press rn/dismiss-keyboard!} + :shows-vertical-scroll-indicator false + :content-container-style (when full-screen? {:flex 1})} + [rn/pressable + {:style (when full-screen? {:flex 1}) + :on-press rn/dismiss-keyboard!} (when descriptor [rn/view {:style style/customizer-container} [customizer state descriptor]]) diff --git a/src/status_im/contexts/preview/quo/wallet/token_input.cljs b/src/status_im/contexts/preview/quo/wallet/token_input.cljs index 36b92af0c8..cfdb3c1728 100644 --- a/src/status_im/contexts/preview/quo/wallet/token_input.cljs +++ b/src/status_im/contexts/preview/quo/wallet/token_input.cljs @@ -2,6 +2,7 @@ (:require [quo.core :as quo] [quo.foundations.resources :as resources] + [react-native.safe-area :as safe-area] [reagent.core :as reagent] [status-im.contexts.preview.quo.preview :as preview])) @@ -24,17 +25,29 @@ (defn view [] - (let [state (reagent/atom {:token :eth - :currency :usd - :conversion 0.02 - :networks networks - :title title - :customization-color :blue})] + (let [state (reagent/atom {:token :eth + :currency :usd + :conversion 0.02 + :networks networks + :title title + :customization-color :blue + :show-keyboard? false}) + value (reagent/atom "") + set-value (fn [v] + (swap! value str v)) + delete (fn [_] + (swap! value #(subs % 0 (dec (count %)))))] (fn [] [preview/preview-container {:state state :descriptor descriptor - :component-container-style {:padding-horizontal 20 - :margin-top 50 - :align-items :center}} - [quo/token-input @state]]))) + :full-screen? true + :component-container-style {:flex 1 + :justify-content :space-between}} + [quo/token-input (assoc @state :value @value)] + [quo/numbered-keyboard + {:container-style {:padding-bottom (safe-area/get-top)} + :left-action :dot + :delete-key? true + :on-press set-value + :on-delete delete}]])))