feat: implement saved contact address list item component (#17400)
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
26ae434d07
commit
878a1cc285
|
@ -101,12 +101,29 @@
|
||||||
:stroke color-2
|
:stroke color-2
|
||||||
:stroke-width 1.1}]])
|
:stroke-width 1.1}]])
|
||||||
|
|
||||||
|
(defn- contact-12
|
||||||
|
[{:keys [color color-2]
|
||||||
|
:or {color colors/neutral-100
|
||||||
|
color-2 colors/white}
|
||||||
|
:as props}]
|
||||||
|
[container props
|
||||||
|
[svg/circle
|
||||||
|
{:cx 6
|
||||||
|
:cy 6
|
||||||
|
:r 6
|
||||||
|
:fill color}]
|
||||||
|
[svg/path
|
||||||
|
{:d
|
||||||
|
"M2.79504 9.01494C2.89473 8.85584 3.00297 8.70977 3.11963 8.5761C3.90594 7.67512 4.97212 7.45024 5.99992 7.45024C7.02772 7.45024 8.0939 7.67512 8.88021 8.5761C8.99688 8.70978 9.10512 8.85585 9.2048 9.01495C8.9501 9.28561 8.66149 9.52401 8.34577 9.72335C8.25403 9.55824 8.15512 9.41818 8.05145 9.29939C7.56503 8.74204 6.88121 8.55024 5.99992 8.55024C5.11862 8.55024 4.43481 8.74204 3.94839 9.29939C3.84472 9.41818 3.74582 9.55824 3.65408 9.72334C3.33835 9.524 3.04975 9.2856 2.79504 9.01494ZM5.99992 3.5502C5.47525 3.5502 5.04992 3.97552 5.04992 4.5002C5.04992 5.02487 5.47525 5.4502 5.99992 5.4502C6.52459 5.4502 6.94992 5.02487 6.94992 4.5002C6.94992 3.97552 6.52459 3.5502 5.99992 3.5502ZM3.94992 4.5002C3.94992 3.36801 4.86773 2.4502 5.99992 2.4502C7.1321 2.4502 8.04992 3.36801 8.04992 4.5002C8.04992 5.63238 7.1321 6.5502 5.99992 6.5502C4.86773 6.5502 3.94992 5.63238 3.94992 4.5002Z"
|
||||||
|
:fill color-2}]])
|
||||||
|
|
||||||
(def ^:private icons
|
(def ^:private icons
|
||||||
{:i/clear-20 clear-20
|
{:i/clear-20 clear-20
|
||||||
:i/dropdown-20 dropdown-20
|
:i/dropdown-20 dropdown-20
|
||||||
:i/pullup-20 pullup-20
|
:i/pullup-20 pullup-20
|
||||||
:i/dropdown-12 dropdown-12
|
:i/dropdown-12 dropdown-12
|
||||||
:i/pullup-12 pullup-12})
|
:i/pullup-12 pullup-12
|
||||||
|
:i/contact-12 contact-12})
|
||||||
|
|
||||||
(defn- append-to-keyword
|
(defn- append-to-keyword
|
||||||
[k & xs]
|
[k & xs]
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
(ns quo2.components.list-items.saved-contact-address.component-spec
|
||||||
|
(:require [test-helpers.component :as h]
|
||||||
|
[quo2.components.list-items.saved-contact-address.view :as saved-contact-address]
|
||||||
|
[quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def account
|
||||||
|
{:name "New House"
|
||||||
|
:address "0x21a...49e"
|
||||||
|
:emoji "🍔"
|
||||||
|
:customization-color :purple})
|
||||||
|
|
||||||
|
(h/describe "List items: saved contact address"
|
||||||
|
(h/test "default render"
|
||||||
|
(h/render [saved-contact-address/view])
|
||||||
|
(h/is-truthy (h/query-by-label-text :container)))
|
||||||
|
|
||||||
|
(h/test "renders account detail when passing one account"
|
||||||
|
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
|
||||||
|
(h/is-truthy (h/query-by-label-text :account-container)))
|
||||||
|
|
||||||
|
(h/test "renders account count when passing multiple accounts"
|
||||||
|
(h/render [saved-contact-address/view {:accounts (repeat 2 account)}])
|
||||||
|
(h/is-truthy (h/query-by-label-text :accounts-count)))
|
||||||
|
|
||||||
|
(h/test "on-press-in changes state to :pressed"
|
||||||
|
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
|
||||||
|
(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)})))
|
||||||
|
|
||||||
|
(h/test "on-press-out changes state to :active if active-state? is true (default value)"
|
||||||
|
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
|
||||||
|
(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)})))
|
||||||
|
|
||||||
|
(h/test "on-press-out changes state to :default if active-state? is false"
|
||||||
|
(h/render [saved-contact-address/view
|
||||||
|
{:accounts (repeat 1 account)
|
||||||
|
:active-state? false}])
|
||||||
|
(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 :transparent})))
|
||||||
|
|
||||||
|
(h/test "on-press calls on-press"
|
||||||
|
(let [on-press (h/mock-fn)]
|
||||||
|
(h/render [saved-contact-address/view
|
||||||
|
{:on-press on-press
|
||||||
|
:accounts (repeat 1 account)}])
|
||||||
|
(h/fire-event :on-press (h/get-by-label-text :container))
|
||||||
|
(h/was-called on-press))))
|
|
@ -0,0 +1,62 @@
|
||||||
|
(ns quo2.components.list-items.saved-contact-address.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(defn- background-color
|
||||||
|
[{:keys [state customization-color]}]
|
||||||
|
(cond (or (= state :pressed) (= state :selected))
|
||||||
|
(colors/custom-color customization-color 50 5)
|
||||||
|
(= state :active)
|
||||||
|
(colors/custom-color customization-color 50 10)
|
||||||
|
:else :transparent))
|
||||||
|
|
||||||
|
(defn container
|
||||||
|
[props]
|
||||||
|
{:height 56
|
||||||
|
:border-radius 12
|
||||||
|
:background-color (background-color props)
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center
|
||||||
|
:padding-horizontal 12
|
||||||
|
:padding-vertical 6
|
||||||
|
:justify-content :space-between})
|
||||||
|
|
||||||
|
(def left-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn dot-divider
|
||||||
|
[theme]
|
||||||
|
{:width 2
|
||||||
|
:height 2
|
||||||
|
:border-radius 2
|
||||||
|
:margin-horizontal 4
|
||||||
|
:background-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||||
|
|
||||||
|
(def saved-contact-container
|
||||||
|
{:margin-left 8})
|
||||||
|
|
||||||
|
(def account-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(def account-title-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:height 22
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn account-name
|
||||||
|
[theme]
|
||||||
|
{:margin-left 4
|
||||||
|
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||||
|
|
||||||
|
(defn accounts-count
|
||||||
|
[theme]
|
||||||
|
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||||
|
|
||||||
|
(defn account-address
|
||||||
|
[theme]
|
||||||
|
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||||
|
|
||||||
|
(def contact-icon-container
|
||||||
|
{:margin-left 4
|
||||||
|
:margin-top 1.5})
|
|
@ -0,0 +1,93 @@
|
||||||
|
(ns quo2.components.list-items.saved-contact-address.view
|
||||||
|
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||||
|
[quo2.components.avatars.account-avatar.view :as account-avatar]
|
||||||
|
[quo2.components.markdown.text :as text]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.theme :as quo.theme]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.components.list-items.saved-contact-address.style :as style]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[quo2.components.icon :as icon]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(defn- account
|
||||||
|
[{:keys [emoji name address customization-color theme]}]
|
||||||
|
[rn/view
|
||||||
|
{:accessibility-label :account-container
|
||||||
|
:style style/account-container}
|
||||||
|
[account-avatar/view
|
||||||
|
{:emoji emoji
|
||||||
|
:size 16
|
||||||
|
:customization-color customization-color}]
|
||||||
|
[text/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :monospace
|
||||||
|
:style (style/account-name theme)}
|
||||||
|
name]
|
||||||
|
[rn/view {:style (style/dot-divider theme)}]
|
||||||
|
[text/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :monospace
|
||||||
|
:style (style/account-address theme)}
|
||||||
|
address]])
|
||||||
|
|
||||||
|
(defn- internal-view
|
||||||
|
[]
|
||||||
|
(let [state (reagent/atom :default)
|
||||||
|
active? (atom false)
|
||||||
|
timer (atom nil)
|
||||||
|
on-press-in (fn []
|
||||||
|
(when-not (= @state :selected)
|
||||||
|
(reset! timer (js/setTimeout #(reset! state :pressed) 100))))]
|
||||||
|
(fn [{:keys [contact-props accounts active-state? customization-color on-press theme]
|
||||||
|
:or {customization-color :blue
|
||||||
|
accounts []
|
||||||
|
active-state? true}}]
|
||||||
|
(let [accounts-count (count accounts)
|
||||||
|
account-props (when (= accounts-count 1)
|
||||||
|
(first accounts))
|
||||||
|
on-press-out (fn []
|
||||||
|
(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)))]
|
||||||
|
[rn/pressable
|
||||||
|
{:style (style/container
|
||||||
|
{:state @state :customization-color customization-color})
|
||||||
|
:on-press-in on-press-in
|
||||||
|
:on-press-out on-press-out
|
||||||
|
:on-press #(when on-press
|
||||||
|
(on-press))
|
||||||
|
:accessibility-label :container}
|
||||||
|
[rn/view {:style style/left-container}
|
||||||
|
[user-avatar/user-avatar (assoc contact-props :size :small)]
|
||||||
|
[rn/view {:style style/saved-contact-container}
|
||||||
|
[rn/view
|
||||||
|
{:style style/account-title-container}
|
||||||
|
[text/text
|
||||||
|
{:weight :semi-bold
|
||||||
|
:size :paragraph-1}
|
||||||
|
(:full-name contact-props)]
|
||||||
|
[icon/icon :i/contact
|
||||||
|
{:container-style style/contact-icon-container
|
||||||
|
:accessibility-label :contact-icon
|
||||||
|
:size 12
|
||||||
|
:color (colors/theme-colors colors/primary-50 colors/primary-60 theme)
|
||||||
|
:color-2 colors/white}]]
|
||||||
|
(if account-props
|
||||||
|
[account (assoc account-props :theme theme)]
|
||||||
|
[text/text
|
||||||
|
{:accessibility-label :accounts-count
|
||||||
|
:size :paragraph-2
|
||||||
|
:style (style/accounts-count theme)}
|
||||||
|
(i18n/label :t/accounts-count {:count accounts-count})])]]
|
||||||
|
(when (> accounts-count 1)
|
||||||
|
[icon/icon :i/chevron-right
|
||||||
|
{:accessibility-label :check-icon
|
||||||
|
:size 20
|
||||||
|
:color (colors/theme-colors colors/neutral-50
|
||||||
|
colors/neutral-40
|
||||||
|
theme)}])]))))
|
||||||
|
|
||||||
|
(def view (quo.theme/with-theme internal-view))
|
|
@ -73,6 +73,7 @@
|
||||||
quo2.components.list-items.menu-item
|
quo2.components.list-items.menu-item
|
||||||
quo2.components.list-items.preview-list.view
|
quo2.components.list-items.preview-list.view
|
||||||
quo2.components.list-items.saved-address.view
|
quo2.components.list-items.saved-address.view
|
||||||
|
quo2.components.list-items.saved-contact-address.view
|
||||||
quo2.components.list-items.token-value.view
|
quo2.components.list-items.token-value.view
|
||||||
quo2.components.list-items.user-list
|
quo2.components.list-items.user-list
|
||||||
quo2.components.loaders.skeleton-list.view
|
quo2.components.loaders.skeleton-list.view
|
||||||
|
@ -269,6 +270,7 @@
|
||||||
(def user-list quo2.components.list-items.user-list/user-list)
|
(def user-list quo2.components.list-items.user-list/user-list)
|
||||||
(def community-list-item quo2.components.list-items.community.view/view)
|
(def community-list-item quo2.components.list-items.community.view/view)
|
||||||
(def saved-address quo2.components.list-items.saved-address.view/view)
|
(def saved-address quo2.components.list-items.saved-address.view/view)
|
||||||
|
(def saved-contact-address quo2.components.list-items.saved-contact-address.view/view)
|
||||||
(def token-value quo2.components.list-items.token-value.view/view)
|
(def token-value quo2.components.list-items.token-value.view/view)
|
||||||
|
|
||||||
;;;; Loaders
|
;;;; Loaders
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
[quo2.components.list-items.community.component-spec]
|
[quo2.components.list-items.community.component-spec]
|
||||||
[quo2.components.list-items.dapp.component-spec]
|
[quo2.components.list-items.dapp.component-spec]
|
||||||
[quo2.components.list-items.saved-address.component-spec]
|
[quo2.components.list-items.saved-address.component-spec]
|
||||||
|
[quo2.components.list-items.saved-contact-address.component-spec]
|
||||||
[quo2.components.list-items.token-value.component-spec]
|
[quo2.components.list-items.token-value.component-spec]
|
||||||
[quo2.components.loaders.skeleton-list.component-spec]
|
[quo2.components.loaders.skeleton-list.component-spec]
|
||||||
[quo2.components.markdown.text-component-spec]
|
[quo2.components.markdown.text-component-spec]
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
(ns status-im2.contexts.quo-preview.list-items.saved-contact-address
|
||||||
|
(:require [quo2.core :as quo]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im2.contexts.quo-preview.preview :as preview]
|
||||||
|
[status-im2.common.resources :as resources]))
|
||||||
|
|
||||||
|
(def descriptor
|
||||||
|
[{:key :accounts-number :type :number}
|
||||||
|
{:key :account-emoji :type :text}
|
||||||
|
{:key :account-name :type :text}
|
||||||
|
{:key :full-name :type :text}
|
||||||
|
{:key :show-alert-on-press? :type :boolean}
|
||||||
|
{:key :active-state? :type :boolean}
|
||||||
|
(preview/customization-color-option {:key :account-color})
|
||||||
|
(preview/customization-color-option)])
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
(let [state (reagent/atom {:customization-color :blue
|
||||||
|
:accounts-number 1
|
||||||
|
:account-name "New House"
|
||||||
|
:account-address "0x21a...49e"
|
||||||
|
:account-emoji "🍔"
|
||||||
|
:account-color :blue
|
||||||
|
:active-state? true
|
||||||
|
:full-name "Mark Villacampa"
|
||||||
|
:show-alert-on-press? false})]
|
||||||
|
(fn []
|
||||||
|
(let [account-props {:name (:account-name @state)
|
||||||
|
:address (:account-address @state)
|
||||||
|
:emoji (:account-emoji @state)
|
||||||
|
:customization-color (:account-color @state)}
|
||||||
|
contact-props {:full-name (:full-name @state)
|
||||||
|
:profile-picture (resources/get-mock-image
|
||||||
|
:user-picture-male4)
|
||||||
|
:customization-color :purple}]
|
||||||
|
[preview/preview-container
|
||||||
|
{:state state
|
||||||
|
:descriptor descriptor}
|
||||||
|
[quo/saved-contact-address
|
||||||
|
(merge @state
|
||||||
|
{:accounts (repeat (:accounts-number @state) account-props)
|
||||||
|
:contact-props contact-props}
|
||||||
|
(when (:show-alert-on-press? @state)
|
||||||
|
{:on-press #(js/alert "Pressed!")}))]]))))
|
|
@ -89,6 +89,7 @@
|
||||||
[status-im2.contexts.quo-preview.list-items.dapp :as dapp]
|
[status-im2.contexts.quo-preview.list-items.dapp :as dapp]
|
||||||
[status-im2.contexts.quo-preview.list-items.preview-lists :as preview-lists]
|
[status-im2.contexts.quo-preview.list-items.preview-lists :as preview-lists]
|
||||||
[status-im2.contexts.quo-preview.list-items.saved-address :as saved-address]
|
[status-im2.contexts.quo-preview.list-items.saved-address :as saved-address]
|
||||||
|
[status-im2.contexts.quo-preview.list-items.saved-contact-address :as saved-contact-address]
|
||||||
[status-im2.contexts.quo-preview.list-items.token-value :as token-value]
|
[status-im2.contexts.quo-preview.list-items.token-value :as token-value]
|
||||||
[status-im2.contexts.quo-preview.list-items.user-list :as user-list]
|
[status-im2.contexts.quo-preview.list-items.user-list :as user-list]
|
||||||
[status-im2.contexts.quo-preview.list-items.community-list :as
|
[status-im2.contexts.quo-preview.list-items.community-list :as
|
||||||
|
@ -316,6 +317,8 @@
|
||||||
:component preview-lists/view}
|
:component preview-lists/view}
|
||||||
{:name :saved-address
|
{:name :saved-address
|
||||||
:component saved-address/view}
|
:component saved-address/view}
|
||||||
|
{:name :saved-contact-address
|
||||||
|
:component saved-contact-address/view}
|
||||||
{:name :token-value
|
{:name :token-value
|
||||||
:component token-value/view}
|
:component token-value/view}
|
||||||
{:name :user-list
|
{:name :user-list
|
||||||
|
|
|
@ -2328,5 +2328,6 @@
|
||||||
"no-saved-addresses": "No saved addresses",
|
"no-saved-addresses": "No saved addresses",
|
||||||
"you-like-to-type-43-characters": "You like to type 43 characters?",
|
"you-like-to-type-43-characters": "You like to type 43 characters?",
|
||||||
"no-other-accounts": "No other accounts",
|
"no-other-accounts": "No other accounts",
|
||||||
"here-is-a-cat-in-a-box-instead": "Here’s a cat in a box instead"
|
"here-is-a-cat-in-a-box-instead": "Here’s a cat in a box instead",
|
||||||
|
"accounts-count": "{{count}} accounts"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue