feat: implement saved contact address list item component (#17400)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2023-10-03 15:51:11 -03:00 committed by GitHub
parent 26ae434d07
commit 878a1cc285
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 279 additions and 2 deletions

View File

@ -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]

View File

@ -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))))

View File

@ -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})

View File

@ -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))

View File

@ -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

View File

@ -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]

View File

@ -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!")}))]]))))

View File

@ -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

View File

@ -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": "Heres a cat in a box instead" "here-is-a-cat-in-a-box-instead": "Heres a cat in a box instead",
"accounts-count": "{{count}} accounts"
} }