Skip to content

Commit

Permalink
feat: address (mocked) suggestions
Browse files Browse the repository at this point in the history
Signed-off-by: Brian Sztamfater <brian@status.im>
  • Loading branch information
briansztamfater committed Oct 24, 2023
1 parent 8296bda commit 2a0a3c7
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 109 deletions.
36 changes: 20 additions & 16 deletions src/quo/components/inputs/address_input/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,23 @@
ens-regex address-regex
valid-ens-or-address?]}]
(let [on-change (fn [text]
(let [ens? (when ens-regex
(boolean (re-matches ens-regex text)))
address? (when address-regex
(boolean (re-matches address-regex text)))]
(if (> (count text) 0)
(reset! status :typing)
(reset! status :active))
(reset! value text)
(when on-change-text
(on-change-text text))
(when (and ens? on-detect-ens)
(reset! status :loading)
(on-detect-ens text))
(when (and address? on-detect-address)
(reset! status :loading)
(on-detect-address text))))
(when (not= @value text)
(let [ens? (when ens-regex
(boolean (re-matches ens-regex text)))
address? (when address-regex
(boolean (re-matches address-regex text)))]
(if (> (count text) 0)
(reset! status :typing)
(reset! status :active))
(reset! value text)
(when on-change-text
(on-change-text text))
(when (and ens? on-detect-ens)
(reset! status :loading)
(on-detect-ens text))
(when (and address? on-detect-address)
(reset! status :loading)
(on-detect-address text)))))
on-paste (fn []
(clipboard/get-string
(fn [clipboard]
Expand All @@ -90,6 +91,8 @@
on-clear (fn []
(reset! value "")
(reset! status (if @focused? :active :default))
(when on-change-text
(on-change-text ""))
(when on-clear
(on-clear)))
on-scan #(when on-scan
Expand Down Expand Up @@ -119,6 +122,7 @@
:auto-complete (when platform/ios? :none)
:auto-capitalize :none
:auto-correct false
:spell-check false
:keyboard-appearance (quo.theme/theme-value :light :dark theme)
:on-focus on-focus
:on-blur on-blur
Expand Down
3 changes: 2 additions & 1 deletion src/quo/components/list_items/address/style.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@
:align-items :center})

(def account-container
{:margin-left 8})
{:margin-left 8
:padding-right 56})
12 changes: 7 additions & 5 deletions src/quo/components/list_items/address/view.cljs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
(ns quo.components.list-items.address.view
(:require
[clojure.string :as string]
[quo.components.avatars.wallet-user-avatar :as wallet-user-avatar]
[quo.components.list-items.address.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[utils.address :as address]))

(defn- left-container
[{:keys [theme address networks blur?]}]
Expand All @@ -25,15 +25,16 @@
[text/text
{:size :paragraph-1
:weight :semi-bold
:style {:color (colors/resolve-color network)}} (str (subs (name network) 0 3) ":")])
:style {:color (colors/resolve-color network theme)}}
(str (subs (name network) 0 3) ":")])
networks)
[text/text
{:size :paragraph-1
:weight :monospace
:style {:color (if blur?
colors/white
(colors/theme-colors colors/neutral-100 colors/white theme))}}
(string/replace address "x" "×")]]]])
(address/get-shortened-key address)]]]])

(defn- internal-view
[]
Expand All @@ -60,6 +61,7 @@
[left-container
{:theme theme
:networks networks
:address address}]]))))
:address address
:blur? blur?}]]))))

(def view (quo.theme/with-theme internal-view))
15 changes: 8 additions & 7 deletions src/quo/components/list_items/saved_address/component_spec.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
(h/render [saved-address/view])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 5)})))
{:backgroundColor (colors/resolve-color :blue :light 5)})))

(h/test "on-press-in changes state to :pressed with blur? enabled"
(h/render [saved-address/view {:blur? true}])
Expand All @@ -22,24 +22,25 @@
{:backgroundColor colors/white-opa-5})))

(h/test "on-press-out changes state to :active"
(h/render [saved-address/view])
(h/render [saved-address/view {:active-state? true}])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 10)})))
{:backgroundColor (colors/resolve-color :blue :light 10)})))

(h/test "on-press-out changes state to :active with blur? enabled"
(h/render [saved-address/view {:blur? true}])
(h/render [saved-address/view
{:blur? true
:active-state? true}])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor colors/white-opa-10})))

(h/test "on-press-out calls on-press"
(h/test "on-press container calls on-press"
(let [on-press (h/mock-fn)]
(h/render [saved-address/view {:on-press on-press}])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/fire-event :on-press (h/get-by-label-text :container))
(h/was-called on-press)))

(h/test "renders options button if type :action"
Expand Down
43 changes: 22 additions & 21 deletions src/quo/components/list_items/saved_address/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[utils.address :as address]))

(defn- left-container
[{:keys [blur? theme name address customization-color]}]
[{:keys [blur? theme name ens address customization-color]}]
(let [names (remove string/blank? (string/split name " "))
first-name (if (> (count names) 0) (first names) "")
last-name (if (> (count names) 1) (last names) "")]
[rn/view {:style style/left-container}
[wallet-user-avatar/wallet-user-avatar
{:size :medium
:f-name first-name
:l-name last-name
:color customization-color}]
{:size :medium
:f-name first-name
:l-name last-name
:customization-color customization-color}]
[rn/view {:style style/account-container}
[text/text
{:weight :semi-bold
Expand All @@ -32,7 +33,7 @@
{:size :paragraph-2
:weight :monospace
:style (style/account-address blur? theme)}
address]]]]))
(or ens (address/get-shortened-key address))]]]]))

(defn- internal-view
[]
Expand All @@ -42,39 +43,39 @@
on-press-in (fn []
(when-not (= @state :selected)
(reset! timer (js/setTimeout #(reset! state :pressed) 100))))]
(fn [{:keys [blur? user-props customization-color
(fn [{:keys [blur? user-props active-state? customization-color
on-press
on-options-press
theme]
:or {customization-color :blue
blur? false}}]
(let [on-press-out (fn []
(let [new-state (if @active? :default :active)]
(let [new-state (if (or (not active-state?) @active?) :default :active)]
(when @timer (js/clearTimeout @timer))
(reset! timer nil)
(reset! active? (= new-state :active))
(reset! state new-state)
(when on-press
(on-press))))]
(reset! state new-state)))]
[rn/pressable
{:style (style/container
{:state @state :blur? blur? :customization-color customization-color})
:on-press-in on-press-in
:on-press-out on-press-out
:on-press on-press
:accessibility-label :container}
[left-container
{:blur? blur?
:theme theme
:name (:name user-props)
:ens (:ens user-props)
:address (:address user-props)
:customization-color (:customization-color user-props)}]
[rn/pressable
{:accessibility-label :options-button
:on-press #(when on-options-press
(on-options-press))}
[icon/icon :i/options
{:color (if blur?
colors/white-opa-70
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]]]))))
:customization-color (or (:customization-color user-props) :blue)}]
(when on-options-press
[rn/pressable
{:accessibility-label :options-button
:on-press on-options-press}
[icon/icon :i/options
{:color (if blur?
colors/white-opa-70
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])]))))

(def view (quo.theme/with-theme internal-view))
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[utils.address :as address]
[utils.i18n :as i18n]))

(defn- account
Expand All @@ -30,7 +31,7 @@
{:size :paragraph-2
:weight :monospace
:style (style/account-address theme)}
address]])
(address/get-shortened-key address)]])

(defn- internal-view
[]
Expand Down
1 change: 1 addition & 0 deletions src/status_im2/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
(def regx-address #"^0x[a-fA-F0-9]{40}$")
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
(def regx-address-fragment #"^0x[a-fA-F0-9]{1,40}$")

(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
Expand Down
119 changes: 118 additions & 1 deletion src/status_im2/contexts/wallet/events.cljs
Original file line number Diff line number Diff line change
@@ -1,5 +1,51 @@
(ns status-im2.contexts.wallet.events
(:require [utils.re-frame :as rf]))
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[react-native.background-timer :as background-timer]
[status-im2.common.resources :as resources]
[status-im2.contexts.wallet.item-types :as types]
[utils.re-frame :as rf]))

(def ens-local-suggestion-saved-address-mock
{:type types/saved-address
:name "Pedro"
:ens "pedro.eth"
:address "0x4732894732894738294783294723894723984"
:networks [:ethereum :optimism]})

(def ens-local-suggestion-mock
{:type types/address
:ens "pedro.eth"
:address "0x4732894732894738294783294723894723984"
:networks [:ethereum :optimism]})

(def address-local-suggestion-saved-contact-address-mock
{:type types/saved-contact-address
:customization-color :blue
:accounts [{:name "New House"
:address "0x62cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:emoji "🍔"
:customization-color :blue}]
:contact-props {:full-name "Mark Libot"
:profile-picture (resources/get-mock-image :user-picture-male4)
:customization-color :purple}})

(def address-local-suggestion-saved-address-mock
{:type types/saved-address
:name "Peter Lamborginski"
:address "0x12FaBc34De56Ef78A9B0Cd12Ef3456AbC7D8E9F0"
:customization-color :magenta
:networks [:ethereum :optimism]})

(def address-local-suggestion-mock
{:type types/address
:address "0x1233cD34De56Ef78A9B0Cd12Ef3456AbC7123dee"
:networks [:ethereum :optimism]})

(defn find-matching-addresses
[substring]
(let [all-addresses [address-local-suggestion-saved-address-mock address-local-suggestion-mock]]
(vec (filter #(string/starts-with? (:address %) substring) all-addresses))))

(rf/defn scan-address-success
{:events [:wallet/scan-address-success]}
Expand All @@ -10,3 +56,74 @@
{:events [:wallet/clean-scanned-address]}
[{:keys [db]}]
{:db (dissoc db :wallet/scanned-address)})

(defn fetch-address-suggestions
[{:keys [db]} [address]]
{:db (assoc db
:wallet/local-suggestions
(cond
(= address
(get-in
address-local-suggestion-saved-contact-address-mock
[:accounts 0 :address]))
[address-local-suggestion-saved-contact-address-mock]
(= address
(get address-local-suggestion-saved-address-mock
:address))
[address-local-suggestion-saved-address-mock]
:else (find-matching-addresses address))
:wallet/valid-ens-or-address?
false)})

(re-frame/reg-event-fx :wallet/fetch-address-suggestions fetch-address-suggestions)

(defn fetch-ens-suggestions
[{:keys [db]} [ens]]
{:db (assoc db
:wallet/local-suggestions (if (= ens
(:ens ens-local-suggestion-saved-address-mock))
[ens-local-suggestion-saved-address-mock]
[ens-local-suggestion-mock])
:wallet/valid-ens-or-address? true)})

(re-frame/reg-event-fx :wallet/ens-validation-success fetch-ens-suggestions)

(defn address-validation-success
[{:keys [db]} [_]]
{:db (assoc db :wallet/valid-ens-or-address? true)})

(re-frame/reg-event-fx :wallet/address-validation-success address-validation-success)

(defn validate-address
[{:keys [db]} [address]]
(let [current-timeout (get db :wallet/search-timeout)
timeout (background-timer/set-timeout
#(rf/dispatch [:wallet/address-validation-success address])
2000)]
(background-timer/clear-timeout current-timeout)
{:db (assoc db
:wallet/valid-ens-or-address? false
:wallet/search-timeout timeout)}))

(re-frame/reg-event-fx :wallet/validate-address validate-address)

(defn validate-ens
[{:keys [db]} [ens]]
(let [current-timeout (get db :wallet/search-timeout)
timeout (background-timer/set-timeout
#(rf/dispatch [:wallet/ens-validation-success ens])
2000)]
(background-timer/clear-timeout current-timeout)
{:db (assoc db
:wallet/valid-ens-or-address? false
:wallet/search-timeout timeout)}))

(re-frame/reg-event-fx :wallet/validate-ens validate-ens)

(defn clean-local-suggestions
[{:keys [db]}]
(let [current-timeout (get db :wallet/search-timeout)]
(background-timer/clear-timeout current-timeout)
{:db (assoc db :wallet/local-suggestions [] :wallet/valid-ens-or-address? false)}))

(re-frame/reg-event-fx :wallet/clean-local-suggestions clean-local-suggestions)
Loading

0 comments on commit 2a0a3c7

Please sign in to comment.