Implement display of missing key pairs in wallet settings (#20094)
* fix: ensure the keypairs use blur for their theme * fix: allow for container-style to be passed to standard-title component * chore: add translations for for missing-keypair labels * tweak: add support for missing-keypair type for drawer-top component * tweak: add initial implementation of missing-keypair list-item component * tweak: add initial implementation of missing-keypairs list component * feature: add initial implementation of displaying missing key-pairs * tweak: update missing-keypair list-item to support blur, light, and dark mode * chore: add missing-keypair list-item preview * chore: add missing-keypairs preview * chore: decode :operable key in account to be keyword * tweak: remove unneeded keyword decoding * tweak: update drawer-top component to use keypair and stored field * tidy: revert change for checking for not default-keypair in actions menu
This commit is contained in:
parent
47b4ab923b
commit
60ef4fab4b
|
@ -80,10 +80,10 @@
|
|||
(h/is-truthy (h/get-by-text "0x62b...0a5"))
|
||||
(h/is-truthy (h/get-by-label-text :account-avatar)))
|
||||
|
||||
(h/test "component renders in keypair type when keycard? is false"
|
||||
(h/test "component renders keypair type with default label"
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? false
|
||||
:stored nil
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
|
@ -91,10 +91,21 @@
|
|||
(-> (h/expect (h/get-by-translation-text :t/on-device))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders in keypair type when keycard? is true"
|
||||
(h/test "component renders keypair type when stored on device"
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? true
|
||||
:stored :on-device
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(-> (h/expect (h/get-by-translation-text :t/on-device))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders keypair type when stored on keycard"
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:stored :on-keycard
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
|
@ -102,6 +113,17 @@
|
|||
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders keypair type when considered missing"
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:stored :missing
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(-> (h/expect (h/get-by-translation-text :t/import-to-use-derived-accounts))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders in default-keypair type"
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
|
|
|
@ -37,16 +37,18 @@
|
|||
nil))
|
||||
|
||||
(defn- keypair-subtitle
|
||||
[{:keys [theme blur? keycard?]}]
|
||||
[{:keys [theme blur? stored]}]
|
||||
[rn/view {:style style/row}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:style (style/description theme blur?)}
|
||||
(if keycard?
|
||||
(i18n/label :t/on-keycard)
|
||||
(case stored
|
||||
:on-device (i18n/label :t/on-device)
|
||||
:on-keycard (i18n/label :t/on-keycard)
|
||||
:missing (i18n/label :t/import-to-use-derived-accounts)
|
||||
(i18n/label :t/on-device))]
|
||||
(when keycard?
|
||||
(when (= stored :on-keycard)
|
||||
[icons/icon
|
||||
:i/keycard-card
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
|
@ -103,14 +105,14 @@
|
|||
description])
|
||||
|
||||
(defn- subtitle
|
||||
[{:keys [type theme blur? keycard? networks description community-name community-logo
|
||||
[{:keys [type theme blur? stored networks description community-name community-logo
|
||||
context-tag-type account-name emoji customization-color full-name profile-picture]}]
|
||||
(cond
|
||||
(= :keypair type)
|
||||
[keypair-subtitle
|
||||
{:theme theme
|
||||
:blur? blur?
|
||||
:keycard? keycard?}]
|
||||
{:theme theme
|
||||
:blur? blur?
|
||||
:stored stored}]
|
||||
|
||||
(= :account type)
|
||||
[account-subtitle
|
||||
|
@ -195,7 +197,7 @@
|
|||
(defn view
|
||||
[{:keys [title title-icon type description blur? community-name community-logo button-icon
|
||||
account-name emoji context-tag-type button-type container-style
|
||||
on-button-press on-button-long-press profile-picture keycard? networks label full-name
|
||||
on-button-press on-button-long-press profile-picture stored networks label full-name
|
||||
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style (merge style/container container-style)}
|
||||
|
@ -220,7 +222,7 @@
|
|||
{:type type
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:keycard? keycard?
|
||||
:stored stored
|
||||
:networks networks
|
||||
:description description
|
||||
:community-name community-name
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
(ns quo.components.list-items.missing-keypair.component-spec
|
||||
(:require
|
||||
[quo.components.list-items.missing-keypair.view :as missing-keypair]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def keypair-data
|
||||
{:accounts []
|
||||
:name "Key Pair Name"})
|
||||
|
||||
(def props
|
||||
{:keypair keypair-data
|
||||
:blur? true
|
||||
:on-options-press (fn [])})
|
||||
|
||||
(h/describe "List items: missing keypair item"
|
||||
(h/test "Test item container renders"
|
||||
(h/render-with-theme-provider [missing-keypair/view props])
|
||||
(h/is-truthy (h/get-by-label-text :missing-keypair-item)))
|
||||
(h/test "Test keypair icon renders"
|
||||
(h/render-with-theme-provider [missing-keypair/view props])
|
||||
(h/is-truthy (h/get-by-label-text :icon)))
|
||||
(h/test "Test name renders"
|
||||
(h/render-with-theme-provider [missing-keypair/view props])
|
||||
(h/is-truthy (h/get-by-label-text :name)))
|
||||
(h/test "Test preview-list renders"
|
||||
(h/render-with-theme-provider [missing-keypair/view props])
|
||||
(h/is-truthy (h/get-by-label-text :preview-list)))
|
||||
(h/test "Test options button renders"
|
||||
(h/render-with-theme-provider [missing-keypair/view props])
|
||||
(h/is-truthy (h/get-by-label-text :options-button))))
|
|
@ -0,0 +1,25 @@
|
|||
(ns quo.components.list-items.missing-keypair.schema)
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:keypair
|
||||
[:map
|
||||
[:key-uid :string]
|
||||
[:name :string]
|
||||
[:accounts
|
||||
[:sequential
|
||||
[:map {:closed true}
|
||||
[:type [:enum :default]]
|
||||
[:emoji :string]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]]]])
|
||||
|
||||
(def ^:private ?on-option-press
|
||||
[:map
|
||||
[:on-options-press {:optional true} [:maybe fn?]]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:cat
|
||||
[:merge ?base ?on-option-press]]
|
||||
:any])
|
|
@ -0,0 +1,46 @@
|
|||
(ns quo.components.list-items.missing-keypair.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[{:keys [blur? theme]}]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex 1
|
||||
:padding-right 12
|
||||
:padding-left 8
|
||||
:padding-vertical 8
|
||||
:border-radius 12
|
||||
:border-width (if blur? 0 1)
|
||||
:border-color (colors/theme-colors colors/neutral-10
|
||||
colors/neutral-80
|
||||
theme)
|
||||
:background-color (if blur?
|
||||
colors/white-opa-5
|
||||
(colors/theme-colors colors/neutral-2_5
|
||||
colors/neutral-80-opa-40
|
||||
theme))})
|
||||
|
||||
(defn icon-container
|
||||
[{:keys [blur? theme]}]
|
||||
{:border-radius 32
|
||||
:border-width 1
|
||||
:border-color (if blur?
|
||||
colors/white-opa-5
|
||||
(colors/theme-colors colors/neutral-20
|
||||
colors/neutral-80
|
||||
theme))})
|
||||
|
||||
(def name-container
|
||||
{:flex 1
|
||||
:padding-right 16
|
||||
:padding-left 8})
|
||||
|
||||
(def preview-list-container
|
||||
{:padding-right 16})
|
||||
|
||||
(defn options-icon-color
|
||||
[{:keys [theme blur?]}]
|
||||
(if blur?
|
||||
colors/white-opa-70
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
|
|
@ -0,0 +1,56 @@
|
|||
(ns quo.components.list-items.missing-keypair.view
|
||||
(:require
|
||||
[quo.components.avatars.icon-avatar :as icon-avatar]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.list-items.missing-keypair.schema :as component-schema]
|
||||
[quo.components.list-items.missing-keypair.style :as style]
|
||||
[quo.components.list-items.preview-list.view :as preview-list]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- internal-view
|
||||
[{{:keys [accounts name]} :keypair
|
||||
:keys [keypair blur? on-options-press]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
on-keypair-options-press (rn/use-callback
|
||||
(fn [event]
|
||||
(on-options-press event keypair))
|
||||
[keypair on-options-press])]
|
||||
[rn/view
|
||||
{:style (style/container {:theme theme
|
||||
:blur? blur?})
|
||||
:accessibility-label :missing-keypair-item}
|
||||
[rn/view
|
||||
{:style (style/icon-container {:theme theme
|
||||
:blur? blur?})
|
||||
:accessibility-label :icon}
|
||||
[icon-avatar/icon-avatar
|
||||
{:size :size-32
|
||||
:icon :i/seed
|
||||
:color :neutral
|
||||
:border? false}]]
|
||||
[rn/view
|
||||
{:style style/name-container
|
||||
:accessibility-label :name}
|
||||
[text/text
|
||||
{:weight :semi-bold}
|
||||
name]]
|
||||
[rn/view
|
||||
{:accessibility-label :preview-list}
|
||||
[preview-list/view
|
||||
{:blur? blur?
|
||||
:type :accounts
|
||||
:size :size-24
|
||||
:number (count accounts)
|
||||
:container-style style/preview-list-container}
|
||||
accounts]]
|
||||
[rn/pressable {:on-press on-keypair-options-press}
|
||||
[icon/icon :i/options
|
||||
{:color (style/options-icon-color
|
||||
{:theme theme
|
||||
:blur? blur?})
|
||||
:accessibility-label :options-button}]]]))
|
||||
|
||||
(def view (schema/instrument #'internal-view component-schema/?schema))
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:justify-content :space-between})
|
||||
|
||||
(def right-counter
|
||||
|
|
|
@ -55,8 +55,8 @@
|
|||
:icon-color (style/right-tag-icon-color blur? theme)}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [title right accessibility-label] :as props}]
|
||||
[rn/view {:style style/container}
|
||||
[{:keys [title right accessibility-label container-style] :as props}]
|
||||
[rn/view {:style (merge style/container container-style)}
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
(ns quo.components.wallet.missing-keypairs.component-spec
|
||||
(:require
|
||||
[quo.components.wallet.missing-keypairs.view :as missing-keypairs]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def ^:private theme :dark)
|
||||
|
||||
(def props
|
||||
{:blur? true
|
||||
:container-style {}
|
||||
:on-options-press (fn [])
|
||||
:keypairs [{:type :seed
|
||||
:name name
|
||||
:key-uid "123"
|
||||
:accounts [{:customization-color :turquoise
|
||||
:emoji "\uD83C\uDFB2"
|
||||
:type :default}]}]})
|
||||
|
||||
(h/describe "Wallet: Missing key pairs"
|
||||
(h/test "Missing key pair title renders"
|
||||
(h/render-with-theme-provider [missing-keypairs/view props]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :title))
|
||||
(h/is-truthy (h/get-by-label-text :t/import-to-use-derived-accounts))))
|
|
@ -0,0 +1,28 @@
|
|||
(ns quo.components.wallet.missing-keypairs.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:border-width 1
|
||||
:border-radius 16
|
||||
:padding 8
|
||||
:border-color colors/warning-50-opa-20
|
||||
:background-color colors/warning-50-opa-5})
|
||||
|
||||
(def title-icon-container
|
||||
{:top 1})
|
||||
|
||||
(def title-info-container
|
||||
{:padding-left 8})
|
||||
|
||||
(def title-container
|
||||
{:align-items :flex-start
|
||||
:flex-direction :row
|
||||
:padding-left 4
|
||||
:padding-bottom 12})
|
||||
|
||||
(defn subtitle
|
||||
[blur? theme]
|
||||
{:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
|
@ -0,0 +1,53 @@
|
|||
(ns quo.components.wallet.missing-keypairs.view
|
||||
(:require
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.list-items.missing-keypair.view :as missing-keypair]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.missing-keypairs.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn title-view
|
||||
[{:keys [keypairs blur?]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:accessibility-label :title
|
||||
:style style/title-container}
|
||||
[rn/view
|
||||
{:style style/title-icon-container}
|
||||
[icon/icon :i/info
|
||||
{:size 20
|
||||
:color colors/warning-60}]]
|
||||
[rn/view
|
||||
{:style style/title-info-container}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:style {:color colors/warning-60}}
|
||||
(i18n/label :t/amount-missing-keypairs
|
||||
{:amount (str (count keypairs))})]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/subtitle blur? theme)}
|
||||
(i18n/label :t/import-to-use-derived-accounts)]]]))
|
||||
|
||||
(defn- missing-keypair-item
|
||||
[keypair _index _separators
|
||||
{:keys [blur? on-options-press]}]
|
||||
[missing-keypair/view
|
||||
{:keypair keypair
|
||||
:blur? blur?
|
||||
:on-options-press on-options-press}])
|
||||
|
||||
(defn view
|
||||
[{:keys [blur? keypairs container-style on-options-press] :as props}]
|
||||
[rn/view
|
||||
{:style (merge style/container container-style)}
|
||||
[title-view props]
|
||||
[rn/flat-list
|
||||
{:data keypairs
|
||||
:render-fn missing-keypair-item
|
||||
:render-data {:blur? blur?
|
||||
:on-options-press on-options-press}
|
||||
:separator [rn/view {:style {:height 8}}]}]])
|
|
@ -85,6 +85,7 @@
|
|||
quo.components.list-items.community.view
|
||||
quo.components.list-items.dapp.view
|
||||
quo.components.list-items.menu-item
|
||||
quo.components.list-items.missing-keypair.view
|
||||
quo.components.list-items.network-list.view
|
||||
quo.components.list-items.preview-list.view
|
||||
quo.components.list-items.quiz-item.view
|
||||
|
@ -169,6 +170,7 @@
|
|||
quo.components.wallet.approval-label.view
|
||||
quo.components.wallet.confirmation-progress.view
|
||||
quo.components.wallet.keypair.view
|
||||
quo.components.wallet.missing-keypairs.view
|
||||
quo.components.wallet.network-amount.view
|
||||
quo.components.wallet.network-bridge.view
|
||||
quo.components.wallet.network-link.view
|
||||
|
@ -320,6 +322,7 @@
|
|||
(def community-list quo.components.list-items.community.view/view)
|
||||
(def dapp quo.components.list-items.dapp.view/view)
|
||||
(def menu-item quo.components.list-items.menu-item/menu-item)
|
||||
(def missing-keypair quo.components.list-items.missing-keypair.view/view)
|
||||
(def network-list quo.components.list-items.network-list.view/view)
|
||||
(def preview-list quo.components.list-items.preview-list.view/view)
|
||||
(def quiz-item quo.components.list-items.quiz-item.view/view)
|
||||
|
@ -440,6 +443,7 @@
|
|||
(def approval-label quo.components.wallet.approval-label.view/view)
|
||||
(def confirmation-progress quo.components.wallet.confirmation-progress.view/view)
|
||||
(def keypair quo.components.wallet.keypair.view/view)
|
||||
(def missing-keypairs quo.components.wallet.missing-keypairs.view/view)
|
||||
(def network-amount quo.components.wallet.network-amount.view/view)
|
||||
(def network-bridge quo.components.wallet.network-bridge.view/view)
|
||||
(def network-routing quo.components.wallet.network-routing.view/view)
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
:value "null"}]}
|
||||
{:key :blur?
|
||||
:type :boolean}
|
||||
{:key :keycard?
|
||||
:type :boolean}
|
||||
{:key :stored
|
||||
:type :select
|
||||
:options [{:key :on-device}
|
||||
{:key :on-keycard}
|
||||
{:key :missing}]}
|
||||
{:key :title
|
||||
:type :text}
|
||||
{:key :description
|
||||
|
@ -44,7 +47,7 @@
|
|||
:title "Title"
|
||||
:type :default
|
||||
:label "Drawer label"
|
||||
:keycard? true
|
||||
:stored :on-device
|
||||
:networks [{:network-name :ethereum :short-name "eth"}]
|
||||
:description "0x62b...0a5"
|
||||
:button-icon :i/placeholder
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
(ns status-im.contexts.preview.quo.list-items.missing-keypair
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :blur?
|
||||
:type :boolean}])
|
||||
|
||||
(def component-props
|
||||
{:blur? false
|
||||
:keypair {:type :seed
|
||||
:key-uid "0x01"
|
||||
:name "Trip to Vegas"
|
||||
:accounts [{:type :default
|
||||
:emoji "🍑"
|
||||
:customization-color :purple}]}})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom component-props)]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true
|
||||
:blur-dark-only? true}
|
||||
[rn/view {:style {:align-items :flex-start}}
|
||||
[quo/missing-keypair @state]]])))
|
|
@ -103,6 +103,7 @@
|
|||
[status-im.contexts.preview.quo.list-items.address :as address]
|
||||
[status-im.contexts.preview.quo.list-items.channel :as channel]
|
||||
[status-im.contexts.preview.quo.list-items.dapp :as dapp]
|
||||
[status-im.contexts.preview.quo.list-items.missing-keypair :as missing-keypair]
|
||||
[status-im.contexts.preview.quo.list-items.network-list :as network-list]
|
||||
[status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists]
|
||||
[status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item]
|
||||
|
@ -196,6 +197,7 @@
|
|||
[status-im.contexts.preview.quo.wallet.confirmation-progress :as
|
||||
confirmation-progress]
|
||||
[status-im.contexts.preview.quo.wallet.keypair :as keypair]
|
||||
[status-im.contexts.preview.quo.wallet.missing-keypairs :as missing-keypairs]
|
||||
[status-im.contexts.preview.quo.wallet.network-amount :as network-amount]
|
||||
[status-im.contexts.preview.quo.wallet.network-bridge :as network-bridge]
|
||||
[status-im.contexts.preview.quo.wallet.network-link :as network-link]
|
||||
|
@ -380,6 +382,8 @@
|
|||
:component community-list-item/view}
|
||||
{:name :dapp
|
||||
:component dapp/preview}
|
||||
{:name :missing-keypair
|
||||
:component missing-keypair/view}
|
||||
{:name :network-list
|
||||
:component network-list/view}
|
||||
{:name :preview-lists
|
||||
|
@ -535,6 +539,8 @@
|
|||
{:name :confirmation-progress
|
||||
:component confirmation-progress/view}
|
||||
{:name :keypair :component keypair/view}
|
||||
{:name :missing-keypairs
|
||||
:component missing-keypairs/view}
|
||||
{:name :network-amount :component network-amount/view}
|
||||
{:name :network-bridge :component network-bridge/view}
|
||||
{:name :network-link :component network-link/view}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
(ns status-im.contexts.preview.quo.wallet.missing-keypairs
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def keypair
|
||||
{:key-uid "0x01"
|
||||
:type "seed"
|
||||
:name "My Key Pair"
|
||||
:blur? false})
|
||||
|
||||
(def accounts
|
||||
[{:customization-color :turquoise
|
||||
:emoji "\uD83C\uDFB2"
|
||||
:type :default}
|
||||
{:customization-color :purple
|
||||
:emoji "\uD83C\uDF7F"
|
||||
:type :default}
|
||||
{:customization-color :army
|
||||
:emoji "\uD83D\uDCC8"
|
||||
:type :default}
|
||||
{:customization-color :orange
|
||||
:emoji "\uD83C\uDFF0"
|
||||
:type :default}
|
||||
{:customization-color :yellow
|
||||
:emoji "\uD83C\uDFDD️"
|
||||
:type :default}])
|
||||
|
||||
(def descriptor
|
||||
[{:key :blur? :type :boolean}])
|
||||
|
||||
(def component-props
|
||||
{:blur? false
|
||||
:keypairs [{:name (:name keypair)
|
||||
:key-uid (:key-uid keypair)
|
||||
:type (keyword (:type keypair))
|
||||
:accounts accounts}]})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:blur? false})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true
|
||||
:blur-dark-only? true
|
||||
:blur-height 400
|
||||
:component-container-style {:padding-vertical 30
|
||||
:flex-direction :row
|
||||
:justify-content :center}}
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/missing-keypairs
|
||||
(merge component-props @state)]]])))
|
|
@ -16,3 +16,10 @@
|
|||
(def keypair-container-style
|
||||
{:margin-horizontal 20
|
||||
:margin-vertical 8})
|
||||
|
||||
(def missing-keypairs-container-style
|
||||
{:margin-horizontal 20
|
||||
:margin-vertical 8})
|
||||
|
||||
(def settings-keypairs-container
|
||||
{:flex 1})
|
||||
|
|
|
@ -20,6 +20,21 @@
|
|||
{:content (fn [] [actions/view props keypair])
|
||||
:theme theme}]))
|
||||
|
||||
(defn options-drawer-props
|
||||
[{{:keys [name]} :keypair
|
||||
:keys [type stored theme shortened-key customization-color profile-picture]}]
|
||||
(cond-> {:theme theme
|
||||
:type type
|
||||
:blur? true
|
||||
:title name
|
||||
:stored stored}
|
||||
(= type :default-keypair)
|
||||
(assoc :description shortened-key
|
||||
:customization-color customization-color
|
||||
:profile-picture profile-picture)
|
||||
(= type :keypair)
|
||||
(assoc :icon-avatar :i/seed)))
|
||||
|
||||
(defn- keypair
|
||||
[{keypair-type :type
|
||||
:keys [accounts name]
|
||||
|
@ -33,22 +48,19 @@
|
|||
on-press (rn/use-callback
|
||||
(fn []
|
||||
(on-options-press
|
||||
(cond-> {:theme theme
|
||||
:blur? true
|
||||
:title name}
|
||||
default-keypair?
|
||||
(assoc :type :default-keypair
|
||||
:description shortened-key
|
||||
:customization-color customization-color
|
||||
:profile-picture profile-picture)
|
||||
(not default-keypair?)
|
||||
(assoc :type :keypair
|
||||
:icon-avatar :i/seed))
|
||||
(options-drawer-props
|
||||
{:theme theme
|
||||
:keypair item
|
||||
:type (if default-keypair? :default-keypair :keypair)
|
||||
:stored :on-device
|
||||
:shortened-key shortened-key
|
||||
:customization-color customization-color
|
||||
:profile-picture profile-picture})
|
||||
item))
|
||||
[customization-color default-keypair? name
|
||||
[customization-color default-keypair? item
|
||||
profile-picture shortened-key theme])]
|
||||
[quo/keypair
|
||||
{:blur? false
|
||||
{:blur? true
|
||||
:status-indicator false
|
||||
:stored :on-device
|
||||
:action :options
|
||||
|
@ -61,13 +73,27 @@
|
|||
:details {:full-name name
|
||||
:address shortened-key}}]))
|
||||
|
||||
(defn on-missing-keypair-options-press
|
||||
[_event keypair-data]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:content (fn [] [actions/view
|
||||
(options-drawer-props
|
||||
{:theme :dark
|
||||
:type :keypair
|
||||
:stored :missing
|
||||
:blur? true
|
||||
:keypair keypair-data})
|
||||
keypair-data])}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [insets (safe-area/get-insets)
|
||||
compressed-key (rf/sub [:profile/compressed-key])
|
||||
profile-picture (rf/sub [:profile/image])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
quo-keypairs-accounts (rf/sub [:wallet/settings-keypairs-accounts])]
|
||||
(let [insets (safe-area/get-insets)
|
||||
compressed-key (rf/sub [:profile/compressed-key])
|
||||
profile-picture (rf/sub [:profile/image])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
{missing-keypairs :missing
|
||||
operable-keypairs :operable} (rf/sub [:wallet/settings-keypairs-accounts])]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:container-style (style/page-wrapper (:top insets))}
|
||||
|
@ -81,9 +107,15 @@
|
|||
{:title (i18n/label :t/keypairs-and-accounts)
|
||||
:accessibility-label :keypairs-and-accounts-header
|
||||
:customization-color customization-color}]]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/view {:style style/settings-keypairs-container}
|
||||
(when (seq missing-keypairs)
|
||||
[quo/missing-keypairs
|
||||
{:blur? true
|
||||
:keypairs missing-keypairs
|
||||
:container-style style/missing-keypairs-container-style
|
||||
:on-options-press on-missing-keypair-options-press}])
|
||||
[rn/flat-list
|
||||
{:data quo-keypairs-accounts
|
||||
{:data operable-keypairs
|
||||
:render-fn keypair
|
||||
:render-data {:profile-picture profile-picture
|
||||
:compressed-key compressed-key
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
(update :prod-preferred-chain-ids chain-ids-string->set)
|
||||
(update :test-preferred-chain-ids chain-ids-string->set)
|
||||
(update :type keyword)
|
||||
(update :operable keyword)
|
||||
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))
|
||||
(update :emoji sanitize-emoji)
|
||||
(assoc :default-account? (:wallet account))
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
:position 1
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false}
|
||||
|
|
|
@ -71,4 +71,5 @@
|
|||
{:source (resources/get-image :transaction-progress)
|
||||
:style {:margin-bottom 12}}]
|
||||
[quo/standard-title
|
||||
{:title (titles (combined-status-overview transaction-details))}]]]))))
|
||||
{:container-style {:flex 1}
|
||||
:title (titles (combined-status-overview transaction-details))}]]]))))
|
||||
|
|
|
@ -520,9 +520,7 @@
|
|||
:component saved-addresses-settings/view}
|
||||
|
||||
{:name :screen/settings.keypairs-and-accounts
|
||||
:options (merge
|
||||
options/transparent-modal-screen-options
|
||||
options/dark-screen)
|
||||
:options options/transparent-modal-screen-options
|
||||
:component keypairs-and-accounts/view}
|
||||
|
||||
{:name :screen/settings.network-settings
|
||||
|
|
|
@ -195,17 +195,40 @@
|
|||
:state :default
|
||||
:action :none})))))
|
||||
|
||||
(defn- format-settings-missing-keypair-accounts
|
||||
[accounts]
|
||||
(->> accounts
|
||||
(map (fn [{:keys [customization-color emoji]}]
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:type :default}))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/settings-keypairs-accounts
|
||||
:<- [:wallet/keypairs]
|
||||
(fn [keypairs [_ format-options]]
|
||||
(->> keypairs
|
||||
(map (fn [{:keys [accounts name type key-uid]}]
|
||||
{:type (keyword type)
|
||||
:name name
|
||||
:key-uid key-uid
|
||||
:accounts (format-settings-keypair-accounts accounts format-options)})))))
|
||||
|
||||
:<- [:wallet/accounts]
|
||||
(fn [[keypairs accounts] [_ format-options]]
|
||||
(let [grouped-accounts (->> accounts
|
||||
(map #(select-keys % [:operable :key-uid]))
|
||||
(group-by :operable))
|
||||
operable-key-pair-ids (->> (map :key-uid (:fully grouped-accounts))
|
||||
(into #{}))
|
||||
missing-key-pair-ids (->> (map :key-uid (:no grouped-accounts))
|
||||
(into #{}))]
|
||||
{:operable (->> keypairs
|
||||
(filter #(contains? operable-key-pair-ids (:key-uid %)))
|
||||
(map (fn [{:keys [accounts name type key-uid]}]
|
||||
{:type (keyword type)
|
||||
:name name
|
||||
:key-uid key-uid
|
||||
:accounts (format-settings-keypair-accounts accounts format-options)})))
|
||||
:missing (->> keypairs
|
||||
(filter #(contains? missing-key-pair-ids (:key-uid %)))
|
||||
(map (fn [{:keys [accounts name type key-uid]}]
|
||||
{:type (keyword type)
|
||||
:name name
|
||||
:key-uid key-uid
|
||||
:accounts (format-settings-missing-keypair-accounts accounts)})))})))
|
||||
(rf/reg-sub
|
||||
:wallet/derivation-path-state
|
||||
:<- [:wallet/create-account]
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
:position 0
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -125,7 +125,7 @@
|
|||
:position 1
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -146,7 +146,7 @@
|
|||
:position 2
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x"
|
||||
:removed false
|
||||
|
@ -221,7 +221,7 @@
|
|||
:position 0
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -243,7 +243,7 @@
|
|||
:position 1
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -265,7 +265,7 @@
|
|||
:position 2
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x"
|
||||
:removed false
|
||||
|
@ -308,7 +308,7 @@
|
|||
:position 0
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -369,7 +369,7 @@
|
|||
:position 0
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -391,7 +391,7 @@
|
|||
:position 2
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x"
|
||||
:removed false
|
||||
|
@ -426,7 +426,7 @@
|
|||
:position 0
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -449,7 +449,7 @@
|
|||
:position 1
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:operable :fully
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false
|
||||
|
@ -568,7 +568,7 @@
|
|||
:hidden false
|
||||
:removed false})
|
||||
|
||||
(def wallet-account
|
||||
(def operable-wallet-account
|
||||
{:path "m/44'/60'/0'/0/0"
|
||||
:emoji "🤡"
|
||||
:key-uid "abc"
|
||||
|
@ -579,83 +579,147 @@
|
|||
:chat false
|
||||
:customization-color :primary
|
||||
:hidden false
|
||||
:operable :fully
|
||||
:removed false})
|
||||
|
||||
(def keypairs-accounts
|
||||
(def inoperable-wallet-account
|
||||
{:path "m/44'/60'/0'/0/0"
|
||||
:emoji "🧠"
|
||||
:key-uid "def"
|
||||
:address "address-3"
|
||||
:wallet true
|
||||
:name "My Other Account"
|
||||
:type "generated"
|
||||
:chat false
|
||||
:customization-color :primary
|
||||
:hidden false
|
||||
:operable :no
|
||||
:removed false})
|
||||
|
||||
(def default-keypair-accounts
|
||||
{:key-uid "abc"
|
||||
:name "My Profile"
|
||||
:type "profile"
|
||||
:accounts []})
|
||||
|
||||
(def seed-phrase-keypair-accounts
|
||||
{:key-uid "def"
|
||||
:name "My Key Pair"
|
||||
:type "seed"
|
||||
:accounts []})
|
||||
|
||||
(h/deftest-sub :wallet/settings-keypairs-accounts
|
||||
[sub-name]
|
||||
(testing "returns formatted key-pairs and accounts"
|
||||
(swap! rf-db/app-db
|
||||
assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc keypairs-accounts
|
||||
:accounts
|
||||
[wallet-account])])
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc default-keypair-accounts
|
||||
:accounts
|
||||
[operable-wallet-account])
|
||||
(assoc seed-phrase-keypair-accounts
|
||||
:accounts
|
||||
[inoperable-wallet-account])])
|
||||
(assoc-in
|
||||
[:wallet :accounts]
|
||||
{(:address operable-wallet-account) operable-wallet-account
|
||||
(:address inoperable-wallet-account) inoperable-wallet-account}))))
|
||||
|
||||
(let [{:keys [customization-color name address emoji]} wallet-account]
|
||||
(is
|
||||
(match? [{:name (:name keypairs-accounts)
|
||||
:type (keyword (:type keypairs-accounts))
|
||||
:accounts [{:account-props {:customization-color customization-color
|
||||
:size 32
|
||||
:emoji emoji
|
||||
:type :default
|
||||
:name name
|
||||
:address address}
|
||||
:networks []
|
||||
:state :default
|
||||
:action :none}]}]
|
||||
(rf/sub [sub-name])))))
|
||||
(is
|
||||
(match?
|
||||
{:missing [{:name (:name seed-phrase-keypair-accounts)
|
||||
:key-uid (:key-uid seed-phrase-keypair-accounts)
|
||||
:type (keyword (:type seed-phrase-keypair-accounts))
|
||||
:accounts [{:customization-color (:customization-color inoperable-wallet-account)
|
||||
:emoji (:emoji inoperable-wallet-account)
|
||||
:type :default}]}]
|
||||
:operable [{:name (:name default-keypair-accounts)
|
||||
:key-uid (:key-uid default-keypair-accounts)
|
||||
:type (keyword (:type default-keypair-accounts))
|
||||
:accounts [{:account-props {:customization-color (:customization-color
|
||||
operable-wallet-account)
|
||||
:size 32
|
||||
:emoji (:emoji operable-wallet-account)
|
||||
:type :default
|
||||
:name (:name operable-wallet-account)
|
||||
:address (:address operable-wallet-account)}
|
||||
:networks []
|
||||
:state :default
|
||||
:action :none}]}]}
|
||||
(rf/sub [sub-name]))))
|
||||
|
||||
(testing "allows for passing account format options"
|
||||
(swap! rf-db/app-db
|
||||
assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc keypairs-accounts
|
||||
:accounts
|
||||
[wallet-account])])
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc default-keypair-accounts
|
||||
:accounts
|
||||
[operable-wallet-account])])
|
||||
(assoc-in
|
||||
[:wallet :accounts]
|
||||
{(:address operable-wallet-account) operable-wallet-account}))))
|
||||
|
||||
(let [{:keys [customization-color
|
||||
name
|
||||
address
|
||||
emoji]} wallet-account
|
||||
emoji]} operable-wallet-account
|
||||
network-options [{:network-name :ethereum :short-name "eth"}
|
||||
{:network-name :optimism :short-name "oeth"}
|
||||
{:network-name :arbitrum :short-name "arb1"}]
|
||||
size-option 20]
|
||||
(is
|
||||
(match? [{:name (:name keypairs-accounts)
|
||||
:type (keyword (:type keypairs-accounts))
|
||||
:accounts [{:account-props {:customization-color customization-color
|
||||
:size size-option
|
||||
:emoji emoji
|
||||
:type :default
|
||||
:name name
|
||||
:address address}
|
||||
:networks network-options
|
||||
:state :default
|
||||
:action :none}]}]
|
||||
(match? {:missing []
|
||||
:operable [{:name (:name default-keypair-accounts)
|
||||
:key-uid (:key-uid default-keypair-accounts)
|
||||
:type (keyword (:type default-keypair-accounts))
|
||||
:accounts [{:account-props {:customization-color customization-color
|
||||
:size size-option
|
||||
:emoji emoji
|
||||
:type :default
|
||||
:name name
|
||||
:address address}
|
||||
:networks network-options
|
||||
:state :default
|
||||
:action :none}]}]}
|
||||
(rf/sub [sub-name
|
||||
{:networks network-options
|
||||
:size size-option}])))))
|
||||
|
||||
(testing "filters non-wallet accounts"
|
||||
(swap! rf-db/app-db
|
||||
assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc keypairs-accounts
|
||||
:accounts
|
||||
[chat-account])])
|
||||
(fn [db]
|
||||
(-> db
|
||||
(assoc-in
|
||||
[:wallet :keypairs]
|
||||
[(assoc default-keypair-accounts
|
||||
:accounts
|
||||
[operable-wallet-account
|
||||
chat-account])])
|
||||
(assoc-in
|
||||
[:wallet :accounts]
|
||||
{(:address operable-wallet-account) operable-wallet-account
|
||||
(:address chat-account) chat-account}))))
|
||||
(is
|
||||
(match? [{:name (:name keypairs-accounts)
|
||||
:type (keyword (:type keypairs-accounts))
|
||||
:accounts []}]
|
||||
(rf/sub [sub-name])))))
|
||||
(match?
|
||||
{:missing []
|
||||
:operable [{:name (:name default-keypair-accounts)
|
||||
:key-uid (:key-uid default-keypair-accounts)
|
||||
:type (keyword (:type default-keypair-accounts))
|
||||
:accounts [{:account-props {:customization-color (:customization-color
|
||||
operable-wallet-account)
|
||||
:size 32
|
||||
:emoji (:emoji operable-wallet-account)
|
||||
:type :default
|
||||
:name (:name operable-wallet-account)
|
||||
:address (:address operable-wallet-account)}
|
||||
:networks []
|
||||
:state :default
|
||||
:action :none}]}]}
|
||||
(rf/sub [sub-name])))))
|
||||
|
||||
(def local-suggestions ["a" "b"])
|
||||
|
||||
|
|
|
@ -2625,6 +2625,8 @@
|
|||
"invite-friend-to-status": "Invite friends to Status",
|
||||
"enter-private-key": "Enter the private key of an address",
|
||||
"enter-private-key-placeholder": "Enter your private key",
|
||||
"import-to-use-derived-accounts": "Import to use derived accounts",
|
||||
"amount-missing-keypairs": "{{amount} missing key pairs",
|
||||
"import-private-key-info": "New addresses cannot be derived from an account imported from a private key. Import using a seed phrase if you wish to derive addresses.",
|
||||
"invalid-private-key": "It’s not a valid private key",
|
||||
"private-key-public-address": "Public address of private key",
|
||||
|
|
Loading…
Reference in New Issue