Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c573d82507 | ||
|
|
712e67a62e | ||
|
|
d223151b93 | ||
|
|
9c7cb0fe93 | ||
|
|
a3e713bbf0 | ||
|
|
cedd4900d5 | ||
|
|
d43e8881ef | ||
|
|
75c8437cc5 | ||
|
|
f1310c7e6c | ||
|
|
d7530dfbee | ||
|
|
0d6bd9c15d | ||
|
|
2da6d9dffb | ||
|
|
879a4067e5 | ||
|
|
e1317f503f | ||
|
|
ec00ddf10e | ||
|
|
c0e10b7c6f | ||
|
|
da449bcd17 | ||
|
|
ab93088d93 | ||
|
|
b4a0e74a4a | ||
|
|
379ba87c16 | ||
|
|
901dddc603 | ||
|
|
9300377c6c | ||
|
|
9445363467 |
@@ -527,9 +527,11 @@
|
||||
|
||||
(defn validate-mnemonic
|
||||
"Validate that a mnemonic conforms to BIP39 dictionary/checksum standards"
|
||||
[mnemonic callback]
|
||||
(log/debug "[native-module] validate-mnemonic")
|
||||
(.validateMnemonic ^js (utils) mnemonic callback))
|
||||
([mnemonic]
|
||||
(native-utils/promisify-native-module-call validate-mnemonic mnemonic))
|
||||
([mnemonic callback]
|
||||
(log/debug "[native-module] validate-mnemonic")
|
||||
(.validateMnemonic ^js (utils) mnemonic callback)))
|
||||
|
||||
(defn delete-multiaccount
|
||||
"Delete multiaccount from database, deletes multiaccount's database and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns quo.components.animated-header-flatlist.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn container-view
|
||||
@@ -28,16 +29,18 @@
|
||||
:right right}))
|
||||
|
||||
(defn blur-view
|
||||
[animation]
|
||||
[animation theme]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity animation}
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:height 100
|
||||
:z-index 2
|
||||
:overflow :hidden}))
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:height 100
|
||||
:z-index 2
|
||||
:overflow :hidden
|
||||
:background-color (when platform/android?
|
||||
(colors/theme-colors colors/white colors/neutral-80 theme))}))
|
||||
|
||||
(defn entity-picture
|
||||
[animation theme]
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
{:blurAmount 32
|
||||
:blurType :light
|
||||
:overlayColor (if platform/ios? colors/white-opa-70 :transparent)
|
||||
:style (style/blur-view opacity-animation)}
|
||||
:style (style/blur-view opacity-animation theme)}
|
||||
[reanimated/view {:style (style/header-comp translate-animation title-opacity-animation)}
|
||||
[header-comp]]]
|
||||
[reanimated/flat-list
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
(ns quo.components.banners.alert-banner.component-spec
|
||||
(:require
|
||||
[quo.components.banners.alert-banner.view :as alert-banner]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Alert Banner"
|
||||
(h/test "Render without props is not throwing any error"
|
||||
(h/render [alert-banner/view {}])
|
||||
(h/is-truthy (h/query-by-label-text :alert-banner)))
|
||||
|
||||
(h/test "Button is not displayed when :action? prop is false"
|
||||
(h/render [alert-banner/view {}])
|
||||
(h/is-falsy (h/query-by-label-text :button)))
|
||||
|
||||
(h/test "Button is displayed when :action? prop is true"
|
||||
(h/render [alert-banner/view {:action? true}])
|
||||
(h/is-truthy (h/query-by-label-text :button)))
|
||||
|
||||
(h/test "Button text is displayed when :action? prop is true and :button-text prop is set"
|
||||
(h/render [alert-banner/view
|
||||
{:action? true
|
||||
:button-text "button"}])
|
||||
(h/is-truthy (h/get-by-text "button")))
|
||||
|
||||
(h/test "Button is called when it's pressed and :action? prop is true"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [alert-banner/view
|
||||
{:action? true
|
||||
:on-button-press event}])
|
||||
(h/fire-event :press (h/query-by-label-text :button))
|
||||
(h/was-called event)))
|
||||
|
||||
(h/test "Text message is displayed :text prop is passed"
|
||||
(h/render [alert-banner/view {:text "message"}])
|
||||
(h/is-truthy (h/get-by-text "message"))))
|
||||
@@ -0,0 +1,12 @@
|
||||
(ns quo.components.banners.alert-banner.schema)
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:action? {:optional true} [:maybe boolean?]]
|
||||
[:text {:optional true} [:maybe string?]]
|
||||
[:button-text {:optional true} [:maybe string?]]
|
||||
[:on-button-press {:optional true} [:maybe fn?]]]]]
|
||||
:any])
|
||||
@@ -0,0 +1,18 @@
|
||||
(ns quo.components.banners.alert-banner.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height 50
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 12})
|
||||
|
||||
(defn label
|
||||
[theme]
|
||||
{:flex 1
|
||||
:color (colors/resolve-color :danger theme)
|
||||
:margin-horizontal 4})
|
||||
|
||||
(def button-text
|
||||
{:color colors/white})
|
||||
@@ -0,0 +1,48 @@
|
||||
(ns quo.components.banners.alert-banner.view
|
||||
(:require [quo.components.banners.alert-banner.schema :as component-schema]
|
||||
[quo.components.banners.alert-banner.style :as style]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [action? text button-text on-button-press]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:accessibility-label :alert-banner}
|
||||
[linear-gradient/linear-gradient
|
||||
{:style style/container
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0 :y 1}
|
||||
:colors [(colors/theme-colors
|
||||
colors/danger-50-opa-5
|
||||
colors/danger-50-opa-10
|
||||
theme)
|
||||
colors/danger-50-opa-0]}
|
||||
[icon/icon
|
||||
:i/alert
|
||||
{:color (colors/resolve-color :danger theme)
|
||||
:size 16}]
|
||||
[text/text
|
||||
{:style (style/label theme)
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
text]
|
||||
(when action?
|
||||
[button/button
|
||||
{:accessibility-label :button
|
||||
:type :danger
|
||||
:size 24
|
||||
:on-press on-button-press}
|
||||
[text/text
|
||||
{:style style/button-text
|
||||
:size :paragraph-2
|
||||
:weight :medium}
|
||||
button-text]])]]))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns quo.components.blur.view
|
||||
(:require [quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn- view-android
|
||||
([props] (view-android props nil))
|
||||
([{:keys [style]} child]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:style (assoc style
|
||||
:pointer-events :box-none
|
||||
:background-color
|
||||
(or (:background-color style)
|
||||
(colors/theme-colors colors/white colors/neutral-80 theme)))}
|
||||
child])))
|
||||
|
||||
(def view (if platform/ios? blur/view view-android))
|
||||
@@ -1,12 +1,12 @@
|
||||
(ns quo.components.buttons.button.view
|
||||
(:require
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.buttons.button.properties :as button-properties]
|
||||
[quo.components.buttons.button.style :as style]
|
||||
[quo.components.icon :as quo.icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.customization-colors :as customization-colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn button
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(ns quo.components.drawers.drawer-buttons.view
|
||||
(:require
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.drawers.drawer-buttons.style :as style]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
(ns quo.components.drawers.permission-context.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(def ^:private radius 20)
|
||||
|
||||
(def blur-container
|
||||
{:background-color :transparent
|
||||
{:background-color (when platform/ios? :transparent)
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns quo.components.drawers.permission-context.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.drawers.permission-context.schema :as component-schema]
|
||||
[quo.components.drawers.permission-context.style :as style]
|
||||
@@ -10,7 +11,6 @@
|
||||
[quo.components.tags.token-tag.view :as token-tag]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.shadow :as shadow]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
(ns quo.components.dropdowns.dropdown.view
|
||||
(:require
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.dropdowns.dropdown.properties :as properties]
|
||||
[quo.components.dropdowns.dropdown.style :as style]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.customization-colors :as customization-colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
|
||||
@@ -28,6 +28,19 @@
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
:close-button colors/white}
|
||||
:shell {:default {:bg colors/white-opa-5
|
||||
:border colors/white-opa-10
|
||||
:icon colors/white-opa-70
|
||||
:text colors/white}
|
||||
:informative {:bg colors/primary-50-opa-5
|
||||
:border colors/primary-50-opa-10
|
||||
:icon colors/primary-50
|
||||
:text colors/white}
|
||||
:error {:bg colors/danger-50-opa-5
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
:close-button colors/white}})
|
||||
|
||||
(defn get-color
|
||||
|
||||
@@ -53,11 +53,11 @@
|
||||
:button-label string
|
||||
:on-button-press function
|
||||
:on-close function"
|
||||
[{:keys [type closed? icon style button-label
|
||||
[{:keys [type closed? blur? icon style button-label
|
||||
on-button-press on-close no-icon-color? icon-size]}
|
||||
message]
|
||||
(when-not closed?
|
||||
(let [theme (quo.theme/use-theme)
|
||||
(let [theme (if blur? :shell (quo.theme/use-theme))
|
||||
include-button? (not (string/blank? button-label))]
|
||||
[rn/view
|
||||
{:accessibility-label :information-box
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
(defn recovery-phrase-input
|
||||
[{:keys [customization-color blur? on-focus on-blur mark-errors?
|
||||
error-pred-current-word error-pred-written-words word-limit
|
||||
container-style placeholder-text-color]
|
||||
container-style placeholder-text-color on-input-ref]
|
||||
:or {customization-color :blue
|
||||
word-limit ##Inf
|
||||
error-pred-current-word (constantly false)
|
||||
@@ -60,7 +60,8 @@
|
||||
extra-props (apply dissoc props custom-props)]
|
||||
[rn/view {:style (style/container container-style)}
|
||||
[rn/text-input
|
||||
(merge {:accessibility-label :recovery-phrase-input
|
||||
(merge {:ref on-input-ref
|
||||
:accessibility-label :recovery-phrase-input
|
||||
:style (style/input theme)
|
||||
:placeholder-text-color (or placeholder-text-color
|
||||
(style/placeholder-color state theme blur?))
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns quo.components.notifications.notification.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.shadows :as shadows]))
|
||||
[quo.foundations.shadows :as shadows]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def box-container
|
||||
{:margin-horizontal 8
|
||||
@@ -15,7 +16,7 @@
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:background-color :transparent})
|
||||
:background-color (when platform/ios? :transparent)})
|
||||
|
||||
(defn content-container
|
||||
[theme]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(ns quo.components.notifications.notification.view
|
||||
(:require
|
||||
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.notifications.notification.style :as style]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn header-container
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns quo.components.notifications.toast.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.shadows :as shadows]))
|
||||
[quo.foundations.shadows :as shadows]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn box-container
|
||||
[theme]
|
||||
@@ -17,7 +18,7 @@
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:background-color :transparent})
|
||||
:background-color (when platform/ios? :transparent)})
|
||||
|
||||
(defn content-container
|
||||
[theme]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
(ns quo.components.notifications.toast.view
|
||||
(:require
|
||||
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.notifications.count-down-circle :as count-down-circle]
|
||||
[quo.components.notifications.toast.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
(defn overlay-background
|
||||
[type]
|
||||
(let [background-color (case type
|
||||
:shell colors/neutral-80-opa-80-blur
|
||||
:shell colors/overlay-background-blur
|
||||
:drawer colors/neutral-100-opa-70-blur
|
||||
nil)]
|
||||
{:position :absolute
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns quo.components.overlay.view
|
||||
(:require
|
||||
[quo.components.blur.view :as blur]
|
||||
[quo.components.overlay.style :as style]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
|
||||
@@ -7,13 +7,12 @@
|
||||
{:left 0
|
||||
:right 0
|
||||
:padding-horizontal 20
|
||||
:padding-top (when label 12)
|
||||
:padding-top (if label 12 8)
|
||||
:padding-bottom 8})
|
||||
|
||||
(defn settings-items
|
||||
[{:keys [label blur?]} theme]
|
||||
{:margin-top (if label 12 4)
|
||||
:border-radius 16
|
||||
[{:keys [blur?]} theme]
|
||||
{:border-radius 16
|
||||
:background-color (if blur?
|
||||
colors/white-opa-5
|
||||
(colors/theme-colors colors/white colors/neutral-95 theme))
|
||||
@@ -24,9 +23,10 @@
|
||||
|
||||
(defn label
|
||||
[{:keys [blur?]} theme]
|
||||
{:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
{:margin-bottom 12
|
||||
:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(def reorder-items
|
||||
{:margin-top 12})
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(def right-counter
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
|
||||
(defn alert-icon-color
|
||||
[theme]
|
||||
(colors/theme-colors colors/neutral-50 colors/white theme))
|
||||
(colors/theme-colors colors/neutral-80-opa-60 colors/white-70-blur theme))
|
||||
|
||||
@@ -12,29 +12,38 @@
|
||||
|
||||
(defn card
|
||||
[{:keys [customization-color type theme pressed? metrics?]}]
|
||||
{:width 161
|
||||
:height (if metrics? 88 68)
|
||||
:background-color (when (not= :watch-only type)
|
||||
(colors/theme-colors
|
||||
(colors/resolve-color customization-color
|
||||
theme
|
||||
(when (= :missing-keypair type) (if pressed? 20 10)))
|
||||
(colors/resolve-color customization-color
|
||||
theme
|
||||
(when (= :missing-keypair type) (if pressed? 30 20)))
|
||||
theme))
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
:border-color (if (or (= :missing-keypair type)
|
||||
(= :watch-only type))
|
||||
(colors/theme-colors
|
||||
(if pressed? colors/neutral-80-opa-10 colors/neutral-80-opa-5)
|
||||
(if pressed? colors/white-opa-10 colors/white-opa-5)
|
||||
theme)
|
||||
colors/neutral-80-opa-10)
|
||||
:padding-horizontal 12
|
||||
:padding-top 6
|
||||
:padding-bottom 9})
|
||||
(let [missing-keypair? (= :missing-keypair type)
|
||||
watch-only? (= :watch-only type)]
|
||||
{:width 161
|
||||
:height (if metrics? 88 68)
|
||||
:background-color (when (and (not missing-keypair?) (not watch-only?))
|
||||
(colors/theme-colors
|
||||
(colors/resolve-color customization-color
|
||||
theme
|
||||
(when missing-keypair? (if pressed? 20 10)))
|
||||
(colors/resolve-color customization-color
|
||||
theme
|
||||
(when missing-keypair? (if pressed? 30 20)))
|
||||
theme))
|
||||
:border-radius 16
|
||||
:border-style (if missing-keypair? :dashed :solid)
|
||||
:border-width 1
|
||||
:border-color (cond
|
||||
watch-only?
|
||||
(colors/theme-colors
|
||||
(if pressed? colors/neutral-80-opa-10 colors/neutral-80-opa-5)
|
||||
(if pressed? colors/white-opa-10 colors/white-opa-5)
|
||||
theme)
|
||||
missing-keypair?
|
||||
(colors/theme-colors
|
||||
(if pressed? colors/neutral-40 colors/neutral-30)
|
||||
(if pressed? colors/neutral-70 colors/neutral-80)
|
||||
theme)
|
||||
:else
|
||||
colors/neutral-80-opa-10)
|
||||
:padding-horizontal 12
|
||||
:padding-top 6
|
||||
:padding-bottom 9}))
|
||||
|
||||
(def profile-container
|
||||
{:margin-bottom 8
|
||||
@@ -100,10 +109,12 @@
|
||||
:line-height 20})
|
||||
|
||||
(defn loader-view
|
||||
[{:keys [width height watch-only? theme]}]
|
||||
[{:keys [width height watch-only? theme missing-keypair?]}]
|
||||
{:width width
|
||||
:height height
|
||||
:background-color (if (and watch-only? (= :light theme)) colors/neutral-80-opa-5 colors/white-opa-10)
|
||||
:background-color (if (and (or missing-keypair? watch-only?) (= :light theme))
|
||||
colors/neutral-80-opa-5
|
||||
colors/white-opa-10)
|
||||
:border-radius 6})
|
||||
|
||||
(def loader-container
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
(defn- loading-view
|
||||
[{:keys [customization-color type theme metrics?]}]
|
||||
(let [watch-only? (= :watch-only type)
|
||||
empty-type? (= :empty type)]
|
||||
(let [missing-keypair? (= :missing-keypair type)
|
||||
watch-only? (= :watch-only type)
|
||||
empty-type? (= :empty type)]
|
||||
[rn/view
|
||||
{:accessibility-label :loading
|
||||
:style (style/card {:customization-color customization-color
|
||||
@@ -26,33 +27,37 @@
|
||||
:metrics? metrics?})}
|
||||
[rn/view {:style style/loader-container}
|
||||
[rn/view
|
||||
{:style (assoc (style/loader-view {:width 16
|
||||
:height 16
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
{:style (assoc (style/loader-view {:width 16
|
||||
:height 16
|
||||
:missing-keypair? missing-keypair?
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
:margin-right 8
|
||||
:margin-top 2)}]
|
||||
[rn/view {:style style/watch-only-container}
|
||||
[rn/view
|
||||
{:style (style/loader-view {:width 57
|
||||
:height 8
|
||||
:watch-only? watch-only?
|
||||
:theme theme})}]
|
||||
{:style (style/loader-view {:width 57
|
||||
:height 8
|
||||
:missing-keypair? missing-keypair?
|
||||
:watch-only? watch-only?
|
||||
:theme theme})}]
|
||||
(when watch-only? [icon/icon :i/reveal {:color colors/neutral-50 :size 12}])]]
|
||||
[rn/view
|
||||
{:style (assoc (style/loader-view {:width (if empty-type? 56 80)
|
||||
:height 16
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
{:style (assoc (style/loader-view {:width (if empty-type? 56 80)
|
||||
:height 16
|
||||
:missing-keypair? missing-keypair?
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
:margin-top
|
||||
13)}]
|
||||
(when metrics?
|
||||
[rn/view
|
||||
{:accessibility-label :metrics
|
||||
:style (assoc (style/loader-view {:width (if empty-type? 37 96)
|
||||
:height 8
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
:style (assoc (style/loader-view {:width (if empty-type? 37 96)
|
||||
:height 8
|
||||
:missing-keypair? missing-keypair?
|
||||
:watch-only? watch-only?
|
||||
:theme theme})
|
||||
:margin-top
|
||||
10)}])]))
|
||||
|
||||
@@ -154,7 +159,7 @@
|
||||
[gradient-overview theme customization-color])])))
|
||||
|
||||
(defn- add-account-view
|
||||
[{:keys [on-press customization-color metrics?]}]
|
||||
[{:keys [on-press metrics?]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
[pressed? set-pressed] (rn/use-state false)
|
||||
on-press-in (rn/use-callback #(set-pressed true))
|
||||
@@ -168,13 +173,12 @@
|
||||
:pressed? pressed?})}
|
||||
[button/button
|
||||
{:on-press on-press
|
||||
:type :primary
|
||||
:size 24
|
||||
:type :ghost
|
||||
:size 32
|
||||
:icon true
|
||||
:accessibility-label :add-account
|
||||
:pressed? pressed?
|
||||
:icon-only? true
|
||||
:customization-color customization-color}
|
||||
:icon-only? true}
|
||||
:i/add]]))
|
||||
|
||||
(defn- view-internal
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
quo.components.avatars.token-avatar.view
|
||||
quo.components.avatars.user-avatar.view
|
||||
quo.components.avatars.wallet-user-avatar.view
|
||||
quo.components.banners.alert-banner.view
|
||||
quo.components.banners.banner.view
|
||||
quo.components.blur.view
|
||||
quo.components.browser.browser-input.view
|
||||
quo.components.buttons.button.view
|
||||
quo.components.buttons.composer-button.view
|
||||
@@ -202,6 +204,7 @@
|
||||
(def wallet-user-avatar quo.components.avatars.wallet-user-avatar.view/wallet-user-avatar)
|
||||
|
||||
;;;; Banner
|
||||
(def alert-banner quo.components.banners.alert-banner.view/view)
|
||||
(def banner quo.components.banners.banner.view/view)
|
||||
|
||||
;;;; Buttons
|
||||
@@ -218,6 +221,9 @@
|
||||
;;;; Browser
|
||||
(def browser-input quo.components.browser.browser-input.view/view)
|
||||
|
||||
;;;; Blur
|
||||
(def blur quo.components.blur.view/view)
|
||||
|
||||
;;;; Calendar
|
||||
(def calendar quo.components.calendar.calendar.view/view)
|
||||
(def calendar-day quo.components.calendar.calendar-day.view/view)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
quo.components.avatars.dapp-avatar.component-spec
|
||||
quo.components.avatars.token-avatar.component-spec
|
||||
quo.components.avatars.user-avatar.component-spec
|
||||
quo.components.banners.alert-banner.component-spec
|
||||
quo.components.banners.banner.component-spec
|
||||
quo.components.browser.browser-input.component-spec
|
||||
quo.components.buttons.button.component-spec
|
||||
|
||||
@@ -141,6 +141,9 @@
|
||||
(def neutral-95-opa-70-blur neutral-95-opa-70)
|
||||
(def neutral-100-opa-70-blur (if platform/android? neutral-100-opa-70 "#0D1014B3"))
|
||||
|
||||
(def overlay-background-blur (if platform/android? (alpha "#192438" 0.8) "#242830cc"))
|
||||
(def bottom-sheet-background-blur (if platform/ios? "#ED9D1D0D" neutral-100-opa-90))
|
||||
|
||||
;;;;Black
|
||||
|
||||
;;Solid
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
(:require
|
||||
["@react-native-community/blur" :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def view (reagent/adapt-react-class (.-BlurView blur)))
|
||||
|
||||
;; blur view is currently not working correctly on Android.
|
||||
(def ios-view (if platform/ios? view rn/view))
|
||||
(def view
|
||||
(if blur
|
||||
(reagent/adapt-react-class (.-BlurView blur))
|
||||
rn/view))
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
[]
|
||||
(.-CachesDirectoryPath ^js react-native-fs))
|
||||
|
||||
(defn download-dir
|
||||
[]
|
||||
(.-DownloadDirectoryPath ^js react-native-fs))
|
||||
|
||||
(defn copy-assets
|
||||
[src dest]
|
||||
(.copyFileAssets ^js react-native-fs src dest))
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
runOnJS)]
|
||||
["react-native-redash" :refer (withPause)]
|
||||
[react-native.flat-list :as rn-flat-list]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.utils :as rn.utils]
|
||||
[reagent.core :as reagent]
|
||||
[utils.transforms :as transforms]
|
||||
@@ -60,7 +61,7 @@
|
||||
(def touchable-opacity (create-animated-component (.-TouchableOpacity ^js rn)))
|
||||
(def linear-gradient (create-animated-component LinearGradient))
|
||||
(def fast-image (create-animated-component FastImage))
|
||||
(def blur-view (create-animated-component (.-BlurView blur)))
|
||||
(def blur-view (if platform/ios? (create-animated-component (.-BlurView blur)) view))
|
||||
|
||||
;; Hooks
|
||||
(def use-shared-value useSharedValue)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns react-native.wallet-connect
|
||||
(:require
|
||||
["@walletconnect/core" :refer [Core]]
|
||||
["@walletconnect/utils" :refer [buildApprovedNamespaces getSdkError]]
|
||||
["@walletconnect/utils" :refer
|
||||
[buildApprovedNamespaces getSdkError parseUri]]
|
||||
["@walletconnect/web3wallet" :refer [Web3Wallet]]))
|
||||
|
||||
(defn- wallet-connect-core
|
||||
@@ -24,3 +25,9 @@
|
||||
(defn get-sdk-error
|
||||
[error-key]
|
||||
(getSdkError error-key))
|
||||
|
||||
(defn parse-uri
|
||||
[uri]
|
||||
(-> uri
|
||||
parseUri
|
||||
(js->clj :keywordize-keys true)))
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
:z-index 1
|
||||
:max-height max-height
|
||||
:border-top-left-radius sheet-border-radius
|
||||
:border-top-right-radius sheet-border-radius
|
||||
:overflow :hidden})
|
||||
:border-top-right-radius sheet-border-radius})
|
||||
|
||||
(def gradient-bg
|
||||
{:position :absolute
|
||||
@@ -23,13 +22,22 @@
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def shell-bg
|
||||
{:position :absolute
|
||||
:background-color (if platform/ios? colors/white-opa-5 colors/neutral-100-opa-90)
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0})
|
||||
(defn shell-bg
|
||||
[blur-background]
|
||||
{:background-color (if blur-background
|
||||
blur-background
|
||||
(if platform/ios? colors/white-opa-5 colors/neutral-100-opa-90))
|
||||
:flex 1})
|
||||
|
||||
(def shell-bg-container
|
||||
{:border-top-left-radius sheet-border-radius
|
||||
:border-top-right-radius sheet-border-radius
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:position :absolute
|
||||
:overflow :hidden})
|
||||
|
||||
(defn sheet-content
|
||||
[{:keys [theme padding-bottom shell?]}]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.hooks :as hooks]
|
||||
@@ -64,7 +63,7 @@
|
||||
(defn view
|
||||
[{:keys [hide? insets]}
|
||||
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
|
||||
gradient-cover? customization-color hide-handle? blur-radius]
|
||||
gradient-cover? customization-color hide-handle? blur-radius blur-background]
|
||||
:or {border-radius 12}}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
{window-height :height} (rn/get-window)
|
||||
@@ -133,12 +132,13 @@
|
||||
{:transform [{:translateY translate-y}]}
|
||||
(style/sheet {:max-height sheet-max-height}))}
|
||||
(when shell?
|
||||
[blur/ios-view
|
||||
{:style style/shell-bg
|
||||
:blur-radius (or blur-radius 20)
|
||||
:blur-amount 32
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent}])
|
||||
[rn/view {:style style/shell-bg-container}
|
||||
[quo/blur
|
||||
{:style (style/shell-bg blur-background)
|
||||
:blur-radius (or blur-radius 20)
|
||||
:blur-amount 32
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent}]])
|
||||
(when selected-item
|
||||
[rn/view
|
||||
{:on-layout handle-item-height
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
(def init-state
|
||||
{:value ""
|
||||
:error? false
|
||||
:upper-limit nil})
|
||||
:upper-limit nil
|
||||
:lower-limit nil})
|
||||
|
||||
(defn input-value
|
||||
[state]
|
||||
@@ -23,19 +24,31 @@
|
||||
[state error?]
|
||||
(assoc state :error? error?))
|
||||
|
||||
(defn- upper-limit
|
||||
(defn upper-limit
|
||||
[state]
|
||||
(:upper-limit state))
|
||||
|
||||
(defn lower-limit
|
||||
[state]
|
||||
(:lower-limit state))
|
||||
|
||||
(defn upper-limit-exceeded?
|
||||
[state]
|
||||
(and
|
||||
(upper-limit state)
|
||||
(> (numeric-value state) (upper-limit state))))
|
||||
|
||||
(defn lower-limit-exceeded?
|
||||
[state]
|
||||
(and
|
||||
(lower-limit state)
|
||||
(< (numeric-value state) (lower-limit state))))
|
||||
|
||||
(defn- recheck-errorness
|
||||
[state]
|
||||
(set-input-error state (upper-limit-exceeded? state)))
|
||||
(set-input-error state
|
||||
(or (upper-limit-exceeded? state)
|
||||
(lower-limit-exceeded? state))))
|
||||
|
||||
(defn set-input-value
|
||||
[state value]
|
||||
@@ -43,12 +56,33 @@
|
||||
(assoc :value value)
|
||||
recheck-errorness))
|
||||
|
||||
(defn set-numeric-value
|
||||
[state value]
|
||||
(set-input-value state (str value)))
|
||||
|
||||
(defn set-upper-limit
|
||||
[state limit]
|
||||
(when limit
|
||||
(-> state
|
||||
(assoc :upper-limit limit)
|
||||
recheck-errorness)))
|
||||
|
||||
(defn set-lower-limit
|
||||
[state limit]
|
||||
(-> state
|
||||
(assoc :upper-limit limit)
|
||||
(assoc :lower-limit limit)
|
||||
recheck-errorness))
|
||||
|
||||
(defn increase
|
||||
[state]
|
||||
(let [new-val (inc (numeric-value state))]
|
||||
(set-input-value state (str new-val))))
|
||||
|
||||
(defn decrease
|
||||
[state]
|
||||
(let [new-val (dec (numeric-value state))]
|
||||
(set-input-value state (str new-val))))
|
||||
|
||||
(def ^:private not-digits-or-dot-pattern
|
||||
#"[^0-9+\.]")
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.platform :as platform]
|
||||
@@ -131,7 +130,7 @@
|
||||
:scroll-ref scroll-ref}))]
|
||||
(fn []
|
||||
[rn/view {:style style/category-container}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/category-blur-container
|
||||
:blur-radius (if platform/android? 20 10)
|
||||
:blur-amount (if platform/ios? 20 10)
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
(comp not word-in-dictionary?))
|
||||
|
||||
(defn- header
|
||||
[seed-phrase-count]
|
||||
[text seed-phrase-count]
|
||||
[rn/view {:style style/header-container}
|
||||
[quo/text {:weight :semi-bold :size :heading-1}
|
||||
(i18n/label :t/use-recovery-phrase)]
|
||||
text]
|
||||
[rn/view {:style style/word-count-container}
|
||||
[quo/text
|
||||
{:style {:color colors/white-opa-40}
|
||||
@@ -51,34 +51,42 @@
|
||||
(string/replace #"\s+" " ")
|
||||
(string/trim)))
|
||||
|
||||
(defn- recovery-form
|
||||
[{:keys [seed-phrase word-count error-state? all-words-valid? on-change-seed-phrase
|
||||
keyboard-shown? on-submit]}]
|
||||
(let [button-disabled? (or error-state?
|
||||
(not (constants/seed-phrase-valid-length word-count))
|
||||
(not all-words-valid?))]
|
||||
[rn/view {:style style/form-container}
|
||||
[header word-count]
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/recovery-phrase-input
|
||||
{:accessibility-label :passphrase-input
|
||||
:placeholder (i18n/label :t/seed-phrase-placeholder)
|
||||
:placeholder-text-color colors/white-opa-30
|
||||
:auto-capitalize :none
|
||||
:auto-correct false
|
||||
:auto-focus true
|
||||
:mark-errors? true
|
||||
:word-limit max-seed-phrase-length
|
||||
:error-pred-current-word partial-word-not-in-dictionary?
|
||||
:error-pred-written-words word-not-in-dictionary?
|
||||
:on-change-text on-change-seed-phrase}
|
||||
seed-phrase]]
|
||||
[quo/button
|
||||
{:container-style (style/continue-button keyboard-shown?)
|
||||
:type :primary
|
||||
:disabled? button-disabled?
|
||||
:on-press on-submit}
|
||||
(i18n/label :t/continue)]]))
|
||||
(defn- secure-clean-seed-phrase
|
||||
[seed-phrase]
|
||||
(-> seed-phrase
|
||||
security/safe-unmask-data
|
||||
clean-seed-phrase
|
||||
security/mask-data))
|
||||
|
||||
(defn- recovery-phrase-form
|
||||
[{:keys [keypair title seed-phrase word-count on-change-seed-phrase ref]} & children]
|
||||
(->> children
|
||||
(into
|
||||
[rn/view {:style style/form-container}
|
||||
[header title word-count]
|
||||
(when keypair
|
||||
[quo/context-tag
|
||||
{:type :icon
|
||||
:container-style {:padding-top 8}
|
||||
:icon :i/seed-phrase
|
||||
:size 24
|
||||
:blur? true
|
||||
:context (:name keypair)}])
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/recovery-phrase-input
|
||||
{:accessibility-label :passphrase-input
|
||||
:ref ref
|
||||
:placeholder (i18n/label :t/seed-phrase-placeholder)
|
||||
:placeholder-text-color colors/white-opa-30
|
||||
:auto-capitalize :none
|
||||
:auto-correct false
|
||||
:auto-focus true
|
||||
:mark-errors? true
|
||||
:word-limit max-seed-phrase-length
|
||||
:error-pred-current-word partial-word-not-in-dictionary?
|
||||
:error-pred-written-words word-not-in-dictionary?
|
||||
:on-change-text on-change-seed-phrase}
|
||||
seed-phrase]]])))
|
||||
|
||||
(defn keyboard-suggestions
|
||||
[current-word]
|
||||
@@ -86,8 +94,8 @@
|
||||
(filter #(string/starts-with? % current-word))
|
||||
(take 7)))
|
||||
|
||||
(defn screen
|
||||
[recovering-keypair?]
|
||||
(defn recovery-phrase-screen
|
||||
[{:keys [keypair title recovering-keypair? render-controls]}]
|
||||
(reagent/with-let [keyboard-shown? (reagent/atom false)
|
||||
keyboard-show-listener (.addListener rn/keyboard
|
||||
"keyboardDidShow"
|
||||
@@ -96,6 +104,11 @@
|
||||
"keyboardDidHide"
|
||||
#(reset! keyboard-shown? false))
|
||||
invalid-seed-phrase? (reagent/atom false)
|
||||
input-ref (reagent/atom nil)
|
||||
focus-input (fn []
|
||||
(let [ref @input-ref]
|
||||
(when ref
|
||||
(.focus ref))))
|
||||
set-invalid-seed-phrase #(reset! invalid-seed-phrase? true)
|
||||
seed-phrase (reagent/atom "")
|
||||
on-change-seed-phrase (fn [new-phrase]
|
||||
@@ -139,16 +152,33 @@
|
||||
words-exceeded? (i18n/label :t/seed-phrase-words-exceeded)
|
||||
error-in-words? (i18n/label :t/seed-phrase-error)
|
||||
@invalid-seed-phrase? (i18n/label :t/seed-phrase-invalid)
|
||||
:else (i18n/label :t/seed-phrase-info))]
|
||||
:else (i18n/label :t/seed-phrase-info))
|
||||
error-state? (= suggestions-state :error)
|
||||
button-disabled? (or error-state?
|
||||
(not (constants/seed-phrase-valid-length word-count))
|
||||
(not all-words-valid?))]
|
||||
[:<>
|
||||
[recovery-form
|
||||
{:seed-phrase @seed-phrase
|
||||
:error-state? (= suggestions-state :error)
|
||||
:all-words-valid? all-words-valid?
|
||||
[recovery-phrase-form
|
||||
{:title title
|
||||
:keypair keypair
|
||||
:seed-phrase @seed-phrase
|
||||
:on-change-seed-phrase on-change-seed-phrase
|
||||
:word-count word-count
|
||||
:on-submit on-submit
|
||||
:keyboard-shown? @keyboard-shown?}]
|
||||
:ref #(reset! input-ref %)}
|
||||
(if (fn? render-controls)
|
||||
(render-controls {:submit-disabled? button-disabled?
|
||||
:keyboard-shown? @keyboard-shown?
|
||||
:container-style (style/continue-button @keyboard-shown?)
|
||||
:prepare-seed-phrase secure-clean-seed-phrase
|
||||
:focus-input focus-input
|
||||
:seed-phrase (security/mask-data @seed-phrase)
|
||||
:set-invalid-seed-phrase set-invalid-seed-phrase})
|
||||
[quo/button
|
||||
{:container-style (style/continue-button @keyboard-shown?)
|
||||
:type :primary
|
||||
:disabled? button-disabled?
|
||||
:on-press on-submit}
|
||||
(i18n/label :t/continue)])]
|
||||
(when @keyboard-shown?
|
||||
[rn/view {:style style/keyboard-container}
|
||||
[quo/predictive-keyboard
|
||||
@@ -161,16 +191,29 @@
|
||||
(.remove keyboard-show-listener)
|
||||
(.remove keyboard-hide-listener))))
|
||||
|
||||
(defn screen
|
||||
[{:keys [initial-insets title keypair navigation-icon recovering-keypair? render-controls]}]
|
||||
(let [{navigation-bar-top :top} initial-insets]
|
||||
[rn/view {:style style/full-layout}
|
||||
[rn/keyboard-avoiding-view {:style style/page-container}
|
||||
[quo/page-nav
|
||||
{:margin-top navigation-bar-top
|
||||
:background :blur
|
||||
:icon-name (or navigation-icon
|
||||
(if recovering-keypair? :i/close :i/arrow-left))
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[recovery-phrase-screen
|
||||
{:title title
|
||||
:keypair keypair
|
||||
:render-controls render-controls
|
||||
:recovering-keypair? recovering-keypair?}]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{navigation-bar-top :top} (safe-area/get-insets)]
|
||||
(let [insets (safe-area/get-insets)]
|
||||
(fn []
|
||||
(let [{:keys [recovering-keypair?]} (rf/sub [:get-screen-params])]
|
||||
[rn/view {:style style/full-layout}
|
||||
[rn/keyboard-avoiding-view {:style style/page-container}
|
||||
[quo/page-nav
|
||||
{:margin-top navigation-bar-top
|
||||
:background :blur
|
||||
:icon-name (if recovering-keypair? :i/close :i/arrow-left)
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[screen recovering-keypair?]]]))))
|
||||
[screen
|
||||
{:title (i18n/label :t/use-recovery-phrase)
|
||||
:initial-insets insets
|
||||
:recovering-keypair? recovering-keypair?}]))))
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
(ns status-im.common.floating-button-page.floating-container.view
|
||||
(:require [quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.floating-button-page.floating-container.style :as style]))
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.floating-button-page.floating-container.style :as style]))
|
||||
|
||||
(defn- blur-container
|
||||
[child]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:blur-amount 12
|
||||
:blur-radius 12
|
||||
:blur-type theme}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
@@ -34,7 +33,7 @@
|
||||
(let [open-sheet? (-> (rf/sub [:bottom-sheet]) :sheets seq)
|
||||
theme (quo.theme/use-theme)]
|
||||
[reanimated/view {:style (style/banner-card-blur-layer scroll-shared-value theme)}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/fill-space
|
||||
:blur-amount (if platform/ios? 20 10)
|
||||
:blur-type (if (= theme :light) (if platform/ios? :light :xlight) :dark)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.camera-kit :as camera-kit]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
@@ -177,7 +176,7 @@
|
||||
[hole-view/hole-view
|
||||
{:style style/hole
|
||||
:holes [(assoc qr-view-finder :borderRadius 16)]}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/absolute-fill
|
||||
:blur-amount 10
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -23,10 +23,7 @@
|
||||
:right 0
|
||||
:left 0
|
||||
:background-color (if platform/android?
|
||||
(colors/theme-colors
|
||||
colors/white-opa-70
|
||||
colors/neutral-95-opa-70
|
||||
theme)
|
||||
(colors/theme-colors colors/white colors/neutral-80 theme)
|
||||
:transparent)}))
|
||||
|
||||
(defn sticky-header-title
|
||||
|
||||
@@ -105,6 +105,12 @@
|
||||
"waku.backedup.settings"
|
||||
{:fx [[:dispatch [:profile/update-setting-from-backup (transforms/js->clj event-js)]]]}
|
||||
|
||||
"waku.backedup.keypair"
|
||||
{:fx [[:dispatch [:wallet/process-keypair-from-backup (transforms/js->clj event-js)]]]}
|
||||
|
||||
"waku.backedup.watch-only-account"
|
||||
{:fx [[:dispatch [:wallet/process-watch-only-account-from-backup (transforms/js->clj event-js)]]]}
|
||||
|
||||
"mediaserver.started"
|
||||
{:db (assoc db :mediaserver/port (oops/oget event-js :port))}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
|
||||
|
||||
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
|
||||
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
|
||||
@@ -202,7 +202,8 @@
|
||||
{:events [:chat/navigate-to-chat]}
|
||||
[{db :db :as cofx} chat-id animation]
|
||||
(rf/merge cofx
|
||||
{:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]}
|
||||
(when-not (:current-chat-id db)
|
||||
{:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]})
|
||||
(close-chat chat-id)
|
||||
(force-close-chat chat-id)
|
||||
(fn [{:keys [db]}]
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
[oops.core :as oops]
|
||||
[quo.theme :as quo.theme]
|
||||
[re-frame.core :as re-frame]
|
||||
[re-frame.db :as rf-db]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fs :as fs]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.common.contact-list-item.view :as contact-list-item]
|
||||
[status-im.common.contact-list.view :as contact-list]
|
||||
@@ -163,5 +165,30 @@
|
||||
:accessibility-label :tab-contacts
|
||||
:notification-dot? (pos? (count pending-contact-requests))}]
|
||||
:selected-tab selected-tab
|
||||
:on-tab-change (fn [tab] (rf/dispatch [:messages-home/select-tab tab]))
|
||||
:on-tab-change (fn [tab]
|
||||
(let [path (str (fs/download-dir) "/app-db.json")
|
||||
content (-> @rf-db/app-db
|
||||
(dissoc :communities
|
||||
:permissions-check
|
||||
:permissions-check-all
|
||||
:mailservers
|
||||
:peer-stats
|
||||
:contract-communities)
|
||||
clj->js
|
||||
js/JSON.stringify)
|
||||
content-size (.-length content)]
|
||||
(fs/write-file
|
||||
path
|
||||
content
|
||||
"utf8"
|
||||
(fn []
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :positive
|
||||
:text (str "app-db " content-size
|
||||
" bytes written to " path)}]))
|
||||
(fn [error]
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :negative
|
||||
:text (str "Error: " (oops/oget error :message))}]))))
|
||||
(rf/dispatch [:messages-home/select-tab tab]))
|
||||
:scroll-shared-value scroll-shared-value}]]))
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
(ns status-im.contexts.chat.messenger.composer.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.hooks :as hooks]
|
||||
@@ -168,7 +168,7 @@
|
||||
[rn/view (when platform/ios? {:style {:z-index 1}})
|
||||
[reanimated/view {:style (style/background opacity background-y window-height)}]
|
||||
[reanimated/view {:style (style/blur-container composer-default-height shared-values)}
|
||||
[blur/view (style/blur-view theme)]]
|
||||
[quo/blur (style/blur-view theme)]]
|
||||
[:f> sheet-component extra-params props state shared-values]]))
|
||||
|
||||
(defn composer
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[re-frame.db]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
@@ -115,7 +114,7 @@
|
||||
messages.constants/pinned-banner-animation-start-position)))]
|
||||
[:<>
|
||||
[reanimated/view {:style (style/animated-background-view background-opacity navigation-view-height)}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style {:flex 1}
|
||||
:blur-amount 20
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.messages.pin.banner.style :as style]
|
||||
@@ -12,7 +11,7 @@
|
||||
[{:keys [chat-id banner-opacity top-offset]} latest-pin-text pins-count]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[reanimated/view {:style (style/container-animated-style top-offset banner-opacity)}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/container
|
||||
:blur-radius (if platform/ios? 20 10)
|
||||
:blur-type theme
|
||||
|
||||
@@ -22,17 +22,17 @@
|
||||
[{:keys [db]} [community-js]]
|
||||
(when community-js
|
||||
(let [{:keys [clock
|
||||
token-permissions-check joined id last-opened-at]
|
||||
token-permissions-check id last-opened-at]
|
||||
:as community} (data-store.communities/<-rpc community-js)
|
||||
previous-last-opened-at (get-in db [:communities id :last-opened-at])]
|
||||
(when (> clock (get-in db [:communities id :clock]))
|
||||
{:db (assoc-in db
|
||||
[:communities id]
|
||||
(assoc community :last-opened-at (max last-opened-at previous-last-opened-at)))
|
||||
;; NOTE(cammellos): these two looks suspicious, we should not check for permissions at
|
||||
;; every event signalled
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community-with-all-addresses id]]
|
||||
(when (not joined)
|
||||
[:dispatch [:chat.ui/spectate-community id]])
|
||||
(when (nil? token-permissions-check)
|
||||
[:dispatch [:communities/check-permissions-to-join-community id]])]}))))
|
||||
|
||||
@@ -293,33 +293,23 @@
|
||||
[{:keys [db]} [{:keys [communities]}]]
|
||||
(when-let [community (first communities)]
|
||||
{:db (-> db
|
||||
(assoc-in [:communities (:id community) :spectated] true)
|
||||
(assoc-in [:communities (:id community) :spectating] false))
|
||||
(assoc-in [:communities (:id community) :spectated] true))
|
||||
:fx [[:dispatch [:communities/handle-community community]]
|
||||
[:dispatch [::mailserver/request-messages]]]}))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
|
||||
|
||||
(defn spectate-community-failed
|
||||
[{:keys [db]} [community-id]]
|
||||
{:db (assoc-in db [:communities community-id :spectating] false)})
|
||||
|
||||
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
|
||||
|
||||
(defn spectate-community
|
||||
[{:keys [db]} [community-id]]
|
||||
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
|
||||
(when (and (not joined) (not spectated) (not spectating))
|
||||
{:db (assoc-in db [:communities community-id :spectating] true)
|
||||
:json-rpc/call [{:method "wakuext_spectateCommunity"
|
||||
(let [{:keys [spectated joined]} (get-in db [:communities community-id])]
|
||||
(when (and (not joined) (not spectated))
|
||||
{:json-rpc/call [{:method "wakuext_spectateCommunity"
|
||||
:params [community-id]
|
||||
:on-success [:chat.ui/spectate-community-success]
|
||||
:on-error (fn [err]
|
||||
(log/error {:message
|
||||
"Failed to spectate community"
|
||||
:error err})
|
||||
(rf/dispatch [:chat.ui/spectate-community-failed
|
||||
community-id]))}]})))
|
||||
:error err}))}]})))
|
||||
|
||||
(schema/=> spectate-community
|
||||
[:=>
|
||||
@@ -329,7 +319,6 @@
|
||||
[:schema [:catn [:community-id [:? :string]]]]]]
|
||||
[:maybe
|
||||
[:map
|
||||
[:db map?]
|
||||
[:json-rpc/call :schema.common/rpc-call]]]])
|
||||
|
||||
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
|
||||
@@ -350,7 +339,8 @@
|
||||
(navigate-to-serialized-community community-id)
|
||||
(rf/merge
|
||||
cofx
|
||||
{:fx [[:dispatch
|
||||
{:fx [[:dispatch [:chat.ui/spectate-community community-id]]
|
||||
[:dispatch
|
||||
[:communities/fetch-community
|
||||
{:community-id community-id
|
||||
:update-last-opened-at? true}]]
|
||||
|
||||
@@ -95,35 +95,16 @@
|
||||
nil
|
||||
(events/spectate-community {:db {:communities {community-id {:spectated true}}}}
|
||||
[community-id])))))
|
||||
(testing "given a spectating community"
|
||||
(testing "do nothing"
|
||||
(is (match?
|
||||
nil
|
||||
(events/spectate-community {:db {:communities {community-id {:spectating true}}}}
|
||||
[community-id])))))
|
||||
|
||||
(testing "given a community"
|
||||
(testing "mark community spectating"
|
||||
(is (match?
|
||||
{:db {:communities {community-id {:spectating true}}}}
|
||||
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))
|
||||
(testing "call spectate community rpc with correct community id"
|
||||
(is (match?
|
||||
{:json-rpc/call [{:method "wakuext_spectateCommunity"
|
||||
:params [community-id]}]}
|
||||
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))))
|
||||
|
||||
(deftest spectate-community-failed-test
|
||||
(testing "mark community spectating false"
|
||||
(is (match?
|
||||
{:db {:communities {community-id {:spectating false}}}}
|
||||
(events/spectate-community-failed {} [community-id])))))
|
||||
|
||||
(deftest spectate-community-success-test
|
||||
(testing "given communities"
|
||||
(testing "mark first community spectating false"
|
||||
(is (match?
|
||||
{:db {:communities {community-id {:spectating false}}}}
|
||||
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
|
||||
(testing "mark first community spectated true"
|
||||
(is (match?
|
||||
{:db {:communities {community-id {:spectated true}}}}
|
||||
@@ -178,7 +159,6 @@
|
||||
(is (match?
|
||||
[[:dispatch
|
||||
[:communities/check-permissions-to-join-community-with-all-addresses community-id]]
|
||||
[:dispatch [:chat.ui/spectate-community community-id]]
|
||||
[:dispatch [:communities/check-permissions-to-join-community community-id]]]
|
||||
(filter some? (:fx effects))))))
|
||||
|
||||
@@ -196,8 +176,7 @@
|
||||
effects (events/handle-community {} [community])]
|
||||
(is (match?
|
||||
[[:dispatch
|
||||
[:communities/check-permissions-to-join-community-with-all-addresses community-id]]
|
||||
[:dispatch [:chat.ui/spectate-community community-id]]]
|
||||
[:communities/check-permissions-to-join-community-with-all-addresses community-id]]]
|
||||
(filter some? (:fx effects))))))
|
||||
(testing "given a community with lower clock"
|
||||
(let [effects (events/handle-community {:db {:communities {community-id {:clock 3}}}} [community])]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
@@ -271,7 +270,7 @@
|
||||
[_]
|
||||
(fn [{:keys [enabled label]}]
|
||||
(when enabled
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/blur-channel-header
|
||||
:blur-amount 20
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.contexts.onboarding.common.background.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def background-container
|
||||
{:background-color colors/neutral-95
|
||||
@@ -18,4 +19,4 @@
|
||||
:top 0
|
||||
:bottom 0
|
||||
:right 0
|
||||
:background-color colors/neutral-80-opa-80-blur})
|
||||
:background-color (when platform/ios? colors/neutral-80-opa-80-blur)})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns status-im.contexts.onboarding.common.background.view
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[quo.core :as quo]
|
||||
[react-native.async-storage :as async-storage]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
@@ -89,7 +89,7 @@
|
||||
:gesture :swipeable
|
||||
:background [background-image (* 4 window-width)]}]
|
||||
(when dark-overlay?
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/background-blur-overlay
|
||||
:blur-amount (if platform/android? 30 20)
|
||||
:blur-radius (if platform/android? 25 10)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.contexts.onboarding.common.overlay.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn blur-container
|
||||
@@ -15,4 +16,4 @@
|
||||
|
||||
(def blur-style
|
||||
{:flex 1
|
||||
:background-color colors/neutral-80-opa-80-blur})
|
||||
:background-color (when platform/ios? colors/neutral-80-opa-80-blur)})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns status-im.contexts.onboarding.common.overlay.view
|
||||
(:require
|
||||
[react-native.blur :as blur]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
@@ -65,7 +65,7 @@
|
||||
[reanimated/view
|
||||
{:pointer-events :none
|
||||
:style (style/blur-container opacity)}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:blur-amount @blur-amount
|
||||
:blur-radius (if platform/android? 25 10)
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[react-native.platform :as platform]
|
||||
@@ -43,7 +42,7 @@
|
||||
[rn/view {:style {:margin-top :auto}}
|
||||
(cond
|
||||
(and (> @height 0) show-background?)
|
||||
[blur/ios-view
|
||||
[quo/blur
|
||||
(when keyboard-shown
|
||||
{:blur-amount 34
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.contexts.onboarding.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
status-im.common.biometric.events
|
||||
[status-im.constants :as constants]
|
||||
@@ -9,19 +8,7 @@
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:multiaccount/validate-mnemonic
|
||||
(fn [[mnemonic on-success on-error]]
|
||||
(native-module/validate-mnemonic
|
||||
(security/safe-unmask-data mnemonic)
|
||||
(fn [result]
|
||||
(let [{:keys [error keyUID]} (transforms/json->clj result)]
|
||||
(if (seq error)
|
||||
(when on-error (on-error error))
|
||||
(on-success mnemonic keyUID)))))))
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(rf/defn profile-data-set
|
||||
{:events [:onboarding/profile-data-set]}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns status-im.contexts.preview.quo.banners.alert-banner
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :text
|
||||
:type :text}
|
||||
{:key :button-text
|
||||
:type :text}
|
||||
{:key :action?
|
||||
:type :boolean}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:action? true
|
||||
:text "Alert text"
|
||||
:button-text "Button"
|
||||
:on-button-press #(js/alert "pressed")})]
|
||||
(fn []
|
||||
[preview/preview-container {:state state :descriptor descriptor}
|
||||
[quo/alert-banner @state]])))
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.preview.quo.gradient.gradient-cover
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.resources :as resources]
|
||||
@@ -63,7 +62,7 @@
|
||||
[rn/image
|
||||
{:style {:height 332}
|
||||
:source (resources/get-mock-image :dark-blur-bg)}])
|
||||
[(if @blur? blur/view rn/view)
|
||||
[(if @blur? quo/blur rn/view)
|
||||
{:style {:height 332
|
||||
:padding-vertical 40}
|
||||
:blur-type :dark}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
[status-im.contexts.preview.quo.avatars.user-avatar :as user-avatar]
|
||||
[status-im.contexts.preview.quo.avatars.wallet-user-avatar :as
|
||||
wallet-user-avatar]
|
||||
[status-im.contexts.preview.quo.banners.alert-banner :as alert-banner]
|
||||
[status-im.contexts.preview.quo.banners.banner :as banner]
|
||||
[status-im.contexts.preview.quo.browser.browser-input :as browser-input]
|
||||
[status-im.contexts.preview.quo.buttons.button :as button]
|
||||
@@ -243,7 +244,9 @@
|
||||
:component collection-avatar/view}
|
||||
{:name :account-avatar
|
||||
:component account-avatar/view}]
|
||||
:banner [{:name :banner
|
||||
:banner [{:name :alert-banners
|
||||
:component alert-banner/view}
|
||||
{:name :banner
|
||||
:component banner/view}]
|
||||
:buttons [{:name :button
|
||||
:component button/view}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
@@ -351,7 +350,7 @@
|
||||
[rn/image
|
||||
{:source (or image (resources/get-mock-image :dark-blur-bg))
|
||||
:style {:height "100%" :width "100%"}}]
|
||||
[blur/view
|
||||
[quo/blur
|
||||
(merge {:style {:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.profile.settings.list-items
|
||||
(:require [status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.config :as config]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -35,13 +34,12 @@
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow}
|
||||
{:title (i18n/label :t/wallet)
|
||||
:on-press #(rf/dispatch [:navigate-to-within-stack [:screen/settings.wallet :screen/settings]])
|
||||
:image-props :i/wallet
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow
|
||||
:feature-flag ::ff/settings.wallet-settings}
|
||||
{:title (i18n/label :t/wallet)
|
||||
:on-press #(rf/dispatch [:navigate-to-within-stack [:screen/settings.wallet :settings]])
|
||||
:image-props :i/wallet
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow}
|
||||
(when config/show-not-implemented-features?
|
||||
{:title (i18n/label :t/dapps)
|
||||
:on-press not-implemented/alert
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
(ns status-im.contexts.settings.wallet.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[status-im.contexts.settings.wallet.data-store :as data-store]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/rename-keypair-success
|
||||
@@ -117,3 +119,54 @@
|
||||
:sha3-pwd password}]))}]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/success-keypair-qr-scan success-keypair-qr-scan)
|
||||
|
||||
(defn wallet-validate-seed-phrase
|
||||
[_ [seed-phrase on-success on-error]]
|
||||
{:fx [[:multiaccount/validate-mnemonic [seed-phrase on-success on-error]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/validate-seed-phrase wallet-validate-seed-phrase)
|
||||
|
||||
(defn make-seed-phrase-keypair-fully-operable
|
||||
[_ [mnemonic password on-success on-error]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "accounts_makeSeedPhraseKeypairFullyOperable"
|
||||
:params [(security/safe-unmask-data mnemonic)
|
||||
(-> password security/safe-unmask-data native-module/sha3)]
|
||||
:on-success on-success
|
||||
:on-error on-error}]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/make-seed-phrase-keypair-fully-operable make-seed-phrase-keypair-fully-operable)
|
||||
|
||||
(defn import-keypair-by-seed-phrase
|
||||
[_ [{:keys [keypair-key-uid seed-phrase password on-success on-error]}]]
|
||||
{:fx [[:import-keypair-by-seed-phrase
|
||||
{:keypair-key-uid keypair-key-uid
|
||||
:seed-phrase seed-phrase
|
||||
:password password
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable
|
||||
#{keypair-key-uid}])
|
||||
(cond
|
||||
(vector? on-success) (rf/dispatch (conj on-success))
|
||||
(fn? on-success) (on-success)))
|
||||
:on-error (fn [error]
|
||||
(rf/dispatch [:wallet/import-keypair-by-seed-phrase-failed error])
|
||||
(cond
|
||||
(vector? on-error) (rf/dispatch (conj on-error error))
|
||||
(fn? on-error) (on-error error)))}]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/import-keypair-by-seed-phrase import-keypair-by-seed-phrase)
|
||||
|
||||
(defn import-keypair-by-seed-phrase-failed
|
||||
[_ [error]]
|
||||
(let [error-type (-> error ex-message keyword)
|
||||
error-data (ex-data error)]
|
||||
(when-not (and (= error-type :import-keypair-by-seed-phrase/import-error)
|
||||
(= (:hint error-data) :incorrect-seed-phrase-for-keypair))
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (:error error-data)}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/import-keypair-by-seed-phrase-failed import-keypair-by-seed-phrase-failed)
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.settings.wallet.events :as sut]))
|
||||
[native-module.core :as native-module]
|
||||
[status-im.contexts.settings.wallet.events :as sut]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(def mock-key-uid "key-1")
|
||||
(defn mock-db
|
||||
@@ -95,3 +97,33 @@
|
||||
(let [effects (sut/success-keypair-qr-scan nil [connection-string keypairs-key-uids])
|
||||
fx (:fx effects)]
|
||||
(is (some? fx))))))
|
||||
|
||||
(deftest wallet-validate-seed-phrase-test
|
||||
(let [cofx {:db {}}
|
||||
seed-phrase-masked (security/mask-data "seed phrase")
|
||||
on-success #(prn "success")
|
||||
on-error #(prn "error")
|
||||
expected {:fx [[:multiaccount/validate-mnemonic
|
||||
[seed-phrase-masked on-success on-error]]]}]
|
||||
(is (= expected
|
||||
(sut/wallet-validate-seed-phrase
|
||||
cofx
|
||||
[seed-phrase-masked on-success on-error])))))
|
||||
|
||||
(deftest make-seed-phrase-keypair-fully-operable-test
|
||||
(let [cofx {:db {}}
|
||||
mnemonic "seed phrase"
|
||||
password "password"
|
||||
mnemonic-masked (security/mask-data mnemonic)
|
||||
password-masked (security/mask-data password)
|
||||
on-success #(prn "success")
|
||||
on-error #(prn "error")
|
||||
expected {:fx [[:json-rpc/call
|
||||
[{:method "accounts_makeSeedPhraseKeypairFullyOperable"
|
||||
:params [mnemonic (native-module/sha3 password)]
|
||||
:on-success fn?
|
||||
:on-error fn?}]]]}]
|
||||
(is (match? expected
|
||||
(sut/make-seed-phrase-keypair-fully-operable
|
||||
cofx
|
||||
[mnemonic-masked password-masked on-success on-error])))))
|
||||
|
||||
@@ -6,27 +6,31 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[props keypair]
|
||||
(let [has-paired-device (rf/sub [:pairing/has-paired-devices])
|
||||
missing-keypair? (= (:stored props) :missing)
|
||||
on-scan-qr (rn/use-callback #(rf/dispatch [:open-modal :screen/settings.scan-keypair-qr
|
||||
[(:key-uid keypair)]])
|
||||
[keypair])
|
||||
on-show-qr (rn/use-callback #(rf/dispatch [:open-modal
|
||||
:screen/settings.encrypted-key-pair-qr
|
||||
keypair])
|
||||
[keypair])
|
||||
on-remove-keypair (rn/use-callback #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:content (fn []
|
||||
[remove-key-pair/view keypair])}])
|
||||
[keypair])
|
||||
on-rename-keypair (rn/use-callback #(rf/dispatch [:open-modal :screen/settings.rename-keypair
|
||||
keypair])
|
||||
[keypair])]
|
||||
[{:keys [drawer-props keypair]}]
|
||||
(let [has-paired-device (rf/sub [:pairing/has-paired-devices])
|
||||
missing-keypair? (= (:stored drawer-props) :missing)
|
||||
on-scan-qr (rn/use-callback #(rf/dispatch [:open-modal
|
||||
:screen/settings.scan-keypair-qr
|
||||
[(:key-uid keypair)]])
|
||||
[keypair])
|
||||
on-show-qr (rn/use-callback #(rf/dispatch [:open-modal
|
||||
:screen/settings.encrypted-key-pair-qr
|
||||
keypair])
|
||||
[keypair])
|
||||
on-remove-keypair (rn/use-callback #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:content (fn []
|
||||
[remove-key-pair/view keypair])}])
|
||||
[keypair])
|
||||
on-rename-keypair (rn/use-callback #(rf/dispatch [:open-modal :screen/settings.rename-keypair
|
||||
keypair])
|
||||
[keypair])
|
||||
on-import-seed-phrase (rn/use-callback
|
||||
#(rf/dispatch [:open-modal :screen/settings.import-seed-phrase keypair])
|
||||
[keypair])]
|
||||
[:<>
|
||||
[quo/drawer-top props]
|
||||
[quo/drawer-top drawer-props]
|
||||
[quo/action-drawer
|
||||
[(when has-paired-device
|
||||
(if-not missing-keypair?
|
||||
@@ -38,8 +42,15 @@
|
||||
:accessibility-label :import-by-scan-qr
|
||||
:label (i18n/label :t/import-by-scanning-encrypted-qr)
|
||||
:on-press on-scan-qr}]))
|
||||
(when (= (:type props) :keypair)
|
||||
[{:icon :i/edit
|
||||
(when (= (:type drawer-props) :keypair)
|
||||
[(when missing-keypair?
|
||||
(case (:type keypair)
|
||||
:seed {:icon :i/seed
|
||||
:accessibility-label :import-seed-phrase
|
||||
:label (i18n/label :t/import-by-entering-recovery-phrase)
|
||||
:on-press #(on-import-seed-phrase keypair)}
|
||||
nil))
|
||||
{:icon :i/edit
|
||||
:accessibility-label :rename-key-pair
|
||||
:label (i18n/label :t/rename-key-pair)
|
||||
:on-press on-rename-keypair}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.import-seed-phrase.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.enter-seed-phrase.view :as enter-seed-phrase]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn import-seed-phrase-controls
|
||||
[{:keys [submit-disabled?
|
||||
container-style
|
||||
prepare-seed-phrase
|
||||
seed-phrase
|
||||
set-invalid-seed-phrase
|
||||
focus-input]}]
|
||||
(let [keypair (rf/sub [:get-screen-params])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
show-errors (rn/use-callback
|
||||
#(js/setTimeout
|
||||
(fn []
|
||||
(focus-input)
|
||||
(reagent/next-tick set-invalid-seed-phrase))
|
||||
600))
|
||||
on-import-error (rn/use-callback
|
||||
(fn [_error]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(show-errors)))
|
||||
on-import-success (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:navigate-back])))
|
||||
on-auth-success (rn/use-callback
|
||||
(fn [password]
|
||||
(rf/dispatch [:wallet/import-keypair-by-seed-phrase
|
||||
{:keypair-key-uid (:key-uid keypair)
|
||||
:seed-phrase (prepare-seed-phrase seed-phrase)
|
||||
:password password
|
||||
:on-success on-import-success
|
||||
:on-error on-import-error}]))
|
||||
[keypair seed-phrase on-import-success on-import-error])]
|
||||
[standard-auth/slide-button
|
||||
{:blur? true
|
||||
:size :size-48
|
||||
:customization-color customization-color
|
||||
:track-text (i18n/label :t/slide-to-import)
|
||||
:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/import-key-pair)
|
||||
:auth-button-icon-left :i/seed
|
||||
:container-style container-style
|
||||
:disabled? submit-disabled?
|
||||
:dependencies [on-auth-success]}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [keypair (rf/sub [:get-screen-params])]
|
||||
[quo/overlay {:type :shell}
|
||||
[enter-seed-phrase/screen
|
||||
{:keypair keypair
|
||||
:navigation-icon :i/close
|
||||
:render-controls import-seed-phrase-controls
|
||||
:title (i18n/label :t/enter-recovery-phrase)
|
||||
:initial-insets (safe-area/get-insets)}]]))
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.style)
|
||||
|
||||
(def title-container
|
||||
{:padding-horizontal 20
|
||||
{:flex 0
|
||||
:padding-horizontal 20
|
||||
:margin-vertical 12})
|
||||
|
||||
(defn page-wrapper
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn on-options-press
|
||||
[{:keys [theme]
|
||||
:as props} keypair]
|
||||
[{:keys [drawer-props keypair]}]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [actions/view props keypair])
|
||||
:theme theme}]))
|
||||
{:content (fn [] [actions/view
|
||||
{:drawer-props drawer-props
|
||||
:keypair keypair}])
|
||||
:theme (:theme drawer-props)}]))
|
||||
|
||||
(defn options-drawer-props
|
||||
[{{:keys [name]} :keypair
|
||||
@@ -48,15 +49,17 @@
|
||||
on-press (rn/use-callback
|
||||
(fn []
|
||||
(on-options-press
|
||||
(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))
|
||||
{:keypair item
|
||||
:drawer-props (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})}))
|
||||
[customization-color default-keypair? item
|
||||
profile-picture shortened-key theme])]
|
||||
[quo/keypair
|
||||
@@ -78,13 +81,13 @@
|
||||
(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])}]))
|
||||
{:keypair keypair-data
|
||||
:drawer-props (options-drawer-props
|
||||
{:theme :dark
|
||||
:type :keypair
|
||||
:stored :missing
|
||||
:blur? true
|
||||
:keypair keypair-data})}])}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
@@ -106,22 +109,22 @@
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigate-back}]
|
||||
[rn/view {:style style/title-container}
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/keypairs-and-accounts)
|
||||
:accessibility-label :keypairs-and-accounts-header
|
||||
:customization-color customization-color}]]
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/keypairs-and-accounts)
|
||||
:container-style style/title-container
|
||||
:accessibility-label :keypairs-and-accounts-header
|
||||
:customization-color customization-color}]
|
||||
[rn/view {:style style/settings-keypairs-container}
|
||||
(when (seq missing-keypairs)
|
||||
[quo/missing-keypairs
|
||||
{:blur? true
|
||||
:keypairs missing-keypairs
|
||||
:on-import-press on-import-press
|
||||
:container-style style/missing-keypairs-container-style
|
||||
:on-options-press on-missing-keypair-options-press}])
|
||||
[rn/flat-list
|
||||
{:data operable-keypairs
|
||||
:render-fn keypair
|
||||
:header (when (seq missing-keypairs)
|
||||
[quo/missing-keypairs
|
||||
{:blur? true
|
||||
:keypairs missing-keypairs
|
||||
:on-import-press on-import-press
|
||||
:container-style style/missing-keypairs-container-style
|
||||
:on-options-press on-missing-keypair-options-press}])
|
||||
:render-data {:profile-picture profile-picture
|
||||
:compressed-key compressed-key
|
||||
:customization-color customization-color}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def title-container
|
||||
{:padding-horizontal 20
|
||||
:margin-vertical 12})
|
||||
{:flex 0
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 12})
|
||||
|
||||
(defn page-wrapper
|
||||
[inset-top]
|
||||
|
||||
@@ -19,21 +19,24 @@
|
||||
(rf/dispatch [:profile.settings/profile-update :test-networks-enabled? enable? {:on-success logout}]))
|
||||
|
||||
(defn testnet-mode-confirm-change-sheet
|
||||
[{:keys [title description on-confirm on-cancel]}]
|
||||
[{:keys [title blur? description on-confirm on-cancel]}]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title title
|
||||
:blur? blur?
|
||||
:container-style style/drawer-top}]
|
||||
[quo/text {:style style/description} description]
|
||||
[rn/view {:style style/info-box-container}
|
||||
[quo/information-box
|
||||
{:type :default
|
||||
:icon :i/info}
|
||||
{:type :default
|
||||
:blur? blur?
|
||||
:icon :i/info}
|
||||
(i18n/label :t/change-testnet-mode-logout-info)]]
|
||||
[quo/bottom-actions
|
||||
{:container-style {:style style/bottom-actions-container}
|
||||
:actions :two-actions
|
||||
:blur? blur?
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
:button-one-props {:accessibility-label :confirm-testnet-mode-change
|
||||
:on-press on-confirm
|
||||
@@ -41,22 +44,24 @@
|
||||
:customization-color customization-color}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:accessibility-label :cancel-testnet-mode-change
|
||||
:type :dark-grey
|
||||
:type :grey
|
||||
:on-press on-cancel}}]]))
|
||||
|
||||
(defn view
|
||||
[{:keys [enable?]}]
|
||||
[{:keys [enable? blur?]}]
|
||||
(let [on-confirm (rn/use-callback
|
||||
#(on-confirm-change enable?)
|
||||
[enable?])]
|
||||
(if enable?
|
||||
[testnet-mode-confirm-change-sheet
|
||||
{:title (i18n/label :t/turn-on-testnet-mode)
|
||||
{:blur? blur?
|
||||
:title (i18n/label :t/turn-on-testnet-mode)
|
||||
:description (i18n/label :t/testnet-mode-enable-description)
|
||||
:on-confirm on-confirm
|
||||
:on-cancel hide-bottom-sheet}]
|
||||
[testnet-mode-confirm-change-sheet
|
||||
{:title (i18n/label :t/turn-off-testnet-mode)
|
||||
{:blur? blur?
|
||||
:title (i18n/label :t/turn-off-testnet-mode)
|
||||
:description (i18n/label :t/testnet-mode-disable-description)
|
||||
:on-confirm on-confirm
|
||||
:on-cancel hide-bottom-sheet}])))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.settings.wallet.network-settings.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
@@ -44,9 +45,7 @@
|
||||
:data (map make-network-settings-item
|
||||
[{:details (:optimism networks)
|
||||
:testnet-mode? testnet-mode?
|
||||
:testnet-label [quo/text
|
||||
{:style style/testnet-not-available}
|
||||
(i18n/label :t/testnet-not-available)]}
|
||||
:testnet-label (i18n/label :t/sepolia-active)}
|
||||
{:details (:arbitrum networks)
|
||||
:testnet-mode? testnet-mode?
|
||||
:testnet-label (i18n/label :t/sepolia-active)}])
|
||||
@@ -56,9 +55,9 @@
|
||||
(defn testnet-mode-setting
|
||||
[{:keys [testnet-mode? on-enable on-disable]}]
|
||||
(let [on-change-testnet (rn/use-callback
|
||||
(fn [active?]
|
||||
(if active? (on-enable) (on-disable)))
|
||||
[on-enable on-disable])]
|
||||
(fn []
|
||||
(if-not testnet-mode? (on-enable) (on-disable)))
|
||||
[testnet-mode? on-enable on-disable])]
|
||||
{:blur? true
|
||||
:title (i18n/label :t/testnet-mode)
|
||||
:action :selector
|
||||
@@ -79,25 +78,32 @@
|
||||
:list-type :settings}])
|
||||
|
||||
(defn on-change-testnet
|
||||
[{:keys [enable? theme]}]
|
||||
[{:keys [enable? blur? theme]}]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [testnet/view {:enable? enable?}])
|
||||
:theme theme}]))
|
||||
{:content (fn [] [testnet/view
|
||||
{:enable? enable?
|
||||
:blur? blur?}])
|
||||
:theme theme
|
||||
:shell? blur?
|
||||
:blur-background colors/bottom-sheet-background-blur}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [insets (safe-area/get-insets)
|
||||
(let [blur? true
|
||||
insets (safe-area/get-insets)
|
||||
theme (quo.theme/use-theme)
|
||||
networks-by-name (rf/sub [:wallet/network-details-by-network-name])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
enable-testnet (rn/use-callback
|
||||
(fn []
|
||||
(on-change-testnet {:theme theme
|
||||
:blur? blur?
|
||||
:enable? true}))
|
||||
[theme])
|
||||
disable-testnet (rn/use-callback
|
||||
(fn []
|
||||
(on-change-testnet {:theme theme
|
||||
:blur? blur?
|
||||
:enable? false}))
|
||||
[theme])]
|
||||
[quo/overlay
|
||||
@@ -108,10 +114,10 @@
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigate-back}]
|
||||
[rn/view {:style style/title-container}
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/network-settings)
|
||||
:accessibility-label :network-settings-header}]]
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/network-settings)
|
||||
:container-style style/title-container
|
||||
:accessibility-label :network-settings-header}]
|
||||
[rn/view {:style (style/settings-container (:bottom insets))}
|
||||
(when networks-by-name
|
||||
[rn/view {:style style/networks-container}
|
||||
|
||||
+63
-40
@@ -6,9 +6,9 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
|
||||
[status-im.contexts.wallet.common.validation :as validation]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
(defn- validate-input
|
||||
[account-addresses saved-addresses user-input]
|
||||
(cond
|
||||
(or (nil? user-input) (= user-input ""))
|
||||
(string/blank? user-input)
|
||||
nil
|
||||
|
||||
(contains? saved-addresses user-input)
|
||||
@@ -35,7 +35,9 @@
|
||||
|
||||
(defn- address-input
|
||||
[{:keys [input-value on-change-text paste-into-input clear-input]}]
|
||||
(let [empty-input? (string/blank? input-value)]
|
||||
(let [empty-input? (string/blank? input-value)
|
||||
on-scan-address (rn/use-callback #(rf/dispatch [:open-modal :screen/wallet.scan-address
|
||||
{:on-result on-change-text}]))]
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/input
|
||||
{:accessibility-label :add-address-to-save
|
||||
@@ -55,7 +57,7 @@
|
||||
:value input-value}]
|
||||
[quo/button
|
||||
{:type :outline
|
||||
:on-press not-implemented/alert
|
||||
:on-press on-scan-address
|
||||
:container-style style/scan-button
|
||||
:background :blur
|
||||
:size 40
|
||||
@@ -88,7 +90,7 @@
|
||||
|
||||
(defn- existing-saved-address
|
||||
[{:keys [address]}]
|
||||
(let [{:keys [name customization-color chain-short-names ens has-ens?]}
|
||||
(let [{:keys [name customization-color chain-short-names ens ens?]}
|
||||
(rf/sub [:wallet/saved-address-by-address
|
||||
address])]
|
||||
[rn/view {:style style/existing-saved-address-container}
|
||||
@@ -102,43 +104,65 @@
|
||||
:active-state? true
|
||||
:user-props {:name name
|
||||
:address (str chain-short-names address)
|
||||
:ens (when has-ens? ens)
|
||||
:ens (when ens? ens)
|
||||
:customization-color customization-color
|
||||
:blur? true}
|
||||
:container-style style/saved-address-item}]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [profile-color (rf/sub [:profile/customization-color])
|
||||
accounts-addresses (rf/sub [:wallet/addresses])
|
||||
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
|
||||
[input-value set-input-value] (rn/use-state nil)
|
||||
[error set-error] (rn/use-state nil)
|
||||
error? (some? error)
|
||||
validate #(validate-input accounts-addresses
|
||||
saved-addresses-addresses
|
||||
%)
|
||||
clear-input (rn/use-callback
|
||||
(fn []
|
||||
(set-input-value nil)
|
||||
(set-error nil)))
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-value]
|
||||
(let [lowercase-value (string/lower-case new-value)]
|
||||
(set-error (validate lowercase-value))
|
||||
(set-input-value lowercase-value))))
|
||||
paste-into-input (rn/use-callback #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
(on-change-text clipboard-text))))
|
||||
on-press-continue (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:wallet/set-address-to-save
|
||||
{:address input-value}])
|
||||
(rf/dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/settings.save-address
|
||||
:screen/settings.add-address-to-save]]))
|
||||
[input-value])]
|
||||
(let [profile-color (rf/sub [:profile/customization-color])
|
||||
accounts-addresses (rf/sub [:wallet/addresses])
|
||||
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
|
||||
[address-or-ens set-address-or-ens] (rn/use-state "")
|
||||
[ens-address set-ens-address] (rn/use-state "")
|
||||
[error set-error] (rn/use-state nil)
|
||||
error? (some? error)
|
||||
ens-name? (validation/ens-name? address-or-ens)
|
||||
address (if ens-name? ens-address address-or-ens)
|
||||
button-disabled? (or (string/blank? address-or-ens)
|
||||
(and ens-name? (string/blank? ens-address))
|
||||
error?)
|
||||
validate #(validate-input accounts-addresses
|
||||
saved-addresses-addresses
|
||||
%)
|
||||
clear-input (rn/use-callback
|
||||
(fn []
|
||||
(set-address-or-ens "")
|
||||
(set-ens-address "")
|
||||
(set-error nil)))
|
||||
on-ens-resolve (rn/use-callback
|
||||
(fn [resolved-address]
|
||||
(set-error (validate resolved-address))
|
||||
(set-ens-address resolved-address)))
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-value]
|
||||
(let [trimmed-value (string/trim new-value)]
|
||||
(set-error (validate (string/lower-case trimmed-value)))
|
||||
(set-address-or-ens trimmed-value)
|
||||
(set-ens-address "")
|
||||
(when (validation/ens-name? trimmed-value)
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet/resolve-ens
|
||||
{:ens new-value
|
||||
:on-success on-ens-resolve
|
||||
:on-error #(set-error :ens-not-registered)}]
|
||||
300)))))
|
||||
paste-into-input (rn/use-callback #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
(on-change-text clipboard-text))))
|
||||
on-press-continue (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
[:wallet/set-address-to-save
|
||||
{:address address
|
||||
:ens address-or-ens
|
||||
:ens? ens-name?}])
|
||||
(rf/dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/settings.save-address
|
||||
:screen/settings.add-address-to-save]]))
|
||||
[address ens-name? address-or-ens])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-address-to-save]))
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
@@ -152,8 +176,7 @@
|
||||
:accessibility-label :add-address-to-save-page-nav}]
|
||||
:footer [quo/button
|
||||
{:customization-color profile-color
|
||||
:disabled? (or (string/blank? input-value)
|
||||
error?)
|
||||
:disabled? button-disabled?
|
||||
:on-press on-press-continue}
|
||||
(i18n/label :t/continue)]}
|
||||
[quo/page-top
|
||||
@@ -163,7 +186,7 @@
|
||||
:description :text
|
||||
:description-text (i18n/label :t/add-address-to-save-description)}]
|
||||
[address-input
|
||||
{:input-value input-value
|
||||
{:input-value address-or-ens
|
||||
:on-change-text on-change-text
|
||||
:paste-into-input paste-into-input
|
||||
:clear-input clear-input}]
|
||||
@@ -171,4 +194,4 @@
|
||||
[:<>
|
||||
[error-view {:error error}]
|
||||
(when (= error :existing-saved-address)
|
||||
[existing-saved-address {:address input-value}])])]]))
|
||||
[existing-saved-address {:address address}])])]]))
|
||||
|
||||
@@ -55,10 +55,8 @@
|
||||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:has-ens? false
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
:ens? false
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:name "Bob"
|
||||
:created-at 1716826714
|
||||
:ens ""
|
||||
@@ -76,10 +74,8 @@
|
||||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
:has-ens? false
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:ens? false
|
||||
:name "Bob"
|
||||
:created-at 1716826714
|
||||
:ens ""
|
||||
@@ -89,10 +85,8 @@
|
||||
:address "0x1"
|
||||
:mixedcase-address "0x1"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
:has-ens? false
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:ens? false
|
||||
:name "Amy"
|
||||
:created-at 1716826806
|
||||
:ens ""
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.save-address.style :as style]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[status-im.contexts.wallet.sheets.network-preferences.view :as network-preferences]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -17,29 +18,86 @@
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn- extract-address
|
||||
[address]
|
||||
(re-find constants/regx-address-contains address))
|
||||
(defn- network-preferences-sheet
|
||||
[{:keys [address color selected-networks set-selected-networks]}]
|
||||
(fn []
|
||||
[network-preferences/view
|
||||
{:title (i18n/label :t/add-network-preferences)
|
||||
:description (i18n/label :t/saved-address-network-preference-selection-description)
|
||||
:button-label (i18n/label :t/add-preferences)
|
||||
:blur? true
|
||||
:selected-networks (set selected-networks)
|
||||
:account {:address address
|
||||
:color color}
|
||||
:on-save (fn [chain-ids]
|
||||
(set-selected-networks (map network-utils/id->network chain-ids))
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [address]} (rf/sub [:wallet/saved-address])
|
||||
(let [{:keys [address ens ens?]} (rf/sub [:wallet/saved-address])
|
||||
[network-prefixes address-without-prefix] (utils/split-prefix-and-address address)
|
||||
[address-label set-address-label] (rn/use-state "")
|
||||
[address-color set-address-color] (rn/use-state (rand-nth colors/account-colors))
|
||||
placeholder (i18n/label :t/address-name)
|
||||
on-press-save (rn/use-callback
|
||||
(fn []
|
||||
(let [address-without-prefix (extract-address address)]
|
||||
(rf/dispatch [:wallet/save-address
|
||||
{:on-success
|
||||
[:wallet/add-saved-address-success
|
||||
(i18n/label :t/address-saved)]
|
||||
:on-error
|
||||
[:wallet/add-saved-address-failed]
|
||||
:name address-label
|
||||
:address address-without-prefix
|
||||
:customization-color address-color}])))
|
||||
[address address-label address-color])]
|
||||
[selected-networks set-selected-networks]
|
||||
(rn/use-state (network-utils/network-preference-prefix->network-names network-prefixes))
|
||||
chain-short-names (rn/use-memo
|
||||
#(network-utils/network-names->network-preference-prefix
|
||||
selected-networks)
|
||||
[selected-networks])
|
||||
placeholder (i18n/label :t/address-name)
|
||||
address-text (rn/use-callback
|
||||
(fn []
|
||||
[quo/address-text
|
||||
{:full-address? true
|
||||
:address (str chain-short-names address-without-prefix)
|
||||
:format :long}])
|
||||
[address-without-prefix chain-short-names])
|
||||
open-network-preferences (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content (network-preferences-sheet
|
||||
{:address address-without-prefix
|
||||
:color address-color
|
||||
:selected-networks selected-networks
|
||||
:set-selected-networks
|
||||
set-selected-networks})}]))
|
||||
[address selected-networks address-color])
|
||||
on-press-save (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:wallet/save-address
|
||||
{:on-success
|
||||
[:wallet/add-saved-address-success
|
||||
(i18n/label :t/address-saved)]
|
||||
:on-error
|
||||
[:wallet/add-saved-address-failed]
|
||||
:name address-label
|
||||
:ens ens
|
||||
:address address-without-prefix
|
||||
:customization-color address-color
|
||||
:chain-short-names chain-short-names}]))
|
||||
[address-without-prefix chain-short-names address-label
|
||||
address-color])
|
||||
data-item-props (rn/use-memo
|
||||
#(cond-> {:status :default
|
||||
:size :default
|
||||
:subtitle-type :default
|
||||
:label :none
|
||||
:blur? true
|
||||
:icon-right? true
|
||||
:right-icon :i/advanced
|
||||
:card? true
|
||||
:title (i18n/label :t/address)
|
||||
:subtitle ens
|
||||
:custom-subtitle address-text
|
||||
:on-press open-network-preferences
|
||||
:container-style style/data-item}
|
||||
ens?
|
||||
(dissoc :custom-subtitle))
|
||||
[ens ens? open-network-preferences address-text])]
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
@@ -92,22 +150,4 @@
|
||||
[quo/divider-line
|
||||
{:blur? true
|
||||
:container-style style/color-picker-bottom-divider}]
|
||||
[quo/data-item
|
||||
{:status :default
|
||||
:size :default
|
||||
:subtitle-type :default
|
||||
:label :none
|
||||
:blur? true
|
||||
:icon-right? true
|
||||
:right-icon :i/advanced
|
||||
:card? true
|
||||
:title (i18n/label :t/address)
|
||||
:custom-subtitle (rn/use-callback
|
||||
(fn []
|
||||
[quo/address-text
|
||||
{:full-address? true
|
||||
:address address
|
||||
:format :long}])
|
||||
[address])
|
||||
:on-press not-implemented/alert
|
||||
:container-style style/data-item}]]]))
|
||||
[quo/data-item data-item-props]]]))
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
(ns status-im.contexts.settings.wallet.saved-addresses.share-address.style)
|
||||
|
||||
(def screen-container
|
||||
{:flex 1})
|
||||
|
||||
(def top-container
|
||||
{:margin-bottom 8})
|
||||
|
||||
(def qr-wrapper
|
||||
{:padding-horizontal 20})
|
||||
@@ -0,0 +1,107 @@
|
||||
(ns status-im.contexts.settings.wallet.saved-addresses.share-address.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.share-address.style :as style]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[status-im.contexts.wallet.sheets.network-preferences.view :as network-preferences]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.image-server :as image-server]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def qr-size 500)
|
||||
|
||||
(defn- navigate-back
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn- share-action
|
||||
[address share-title]
|
||||
(rf/dispatch [:open-share
|
||||
{:options (if platform/ios?
|
||||
{:activityItemSources [{:placeholderItem {:type :text
|
||||
:content address}
|
||||
:item {:default {:type :text
|
||||
:content
|
||||
address}}
|
||||
:linkMetadata {:title share-title}}]}
|
||||
{:title share-title
|
||||
:subject share-title
|
||||
:message address
|
||||
:isNewTask true})}]))
|
||||
|
||||
(defn- open-preferences
|
||||
[{:keys [address color selected-networks set-selected-networks]}]
|
||||
(let [on-save (fn [chain-ids]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(set-selected-networks (map network-utils/id->network chain-ids)))
|
||||
sheet-content (fn []
|
||||
[network-preferences/view
|
||||
{:description (i18n/label
|
||||
:t/saved-address-network-preference-selection-description)
|
||||
:button-label (i18n/label :t/display)
|
||||
:blur? true
|
||||
:selected-networks (set selected-networks)
|
||||
:account {:address address
|
||||
:color color}
|
||||
:on-save on-save}])]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content sheet-content}])))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [name address customization-color
|
||||
network-preferences-names]} (rf/sub [:get-screen-params])
|
||||
[wallet-type set-wallet-type] (rn/use-state :legacy)
|
||||
[selected-networks set-selected-networks] (rn/use-state network-preferences-names)
|
||||
on-settings-press (rn/use-callback
|
||||
#(open-preferences
|
||||
{:selected-networks selected-networks
|
||||
:set-selected-networks set-selected-networks
|
||||
:address address
|
||||
:color customization-color})
|
||||
[address customization-color selected-networks])
|
||||
on-legacy-press (rn/use-callback #(set-wallet-type :legacy))
|
||||
on-multichain-press (rn/use-callback #(set-wallet-type :multichain))
|
||||
share-title (str name " " (i18n/label :t/address))
|
||||
qr-url (rn/use-memo #(utils/get-wallet-qr
|
||||
{:wallet-type wallet-type
|
||||
:selected-networks selected-networks
|
||||
:address address})
|
||||
[wallet-type selected-networks address])
|
||||
qr-media-server-uri (rn/use-memo
|
||||
#(image-server/get-qr-image-uri-for-any-url
|
||||
{:url qr-url
|
||||
:port (rf/sub [:mediaserver/port])
|
||||
:qr-size qr-size
|
||||
:error-level :highest})
|
||||
[qr-url])]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:top-inset? true}
|
||||
[rn/view {:style style/screen-container}
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:on-press navigate-back
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/share-address)
|
||||
:container-style style/top-container}]
|
||||
[rn/view {:style style/qr-wrapper}
|
||||
[quo/share-qr-code
|
||||
{:type :saved-address
|
||||
:address wallet-type
|
||||
:qr-image-uri qr-media-server-uri
|
||||
:qr-data qr-url
|
||||
:networks selected-networks
|
||||
:on-share-press #(share-action qr-url share-title)
|
||||
:full-name name
|
||||
:customization-color customization-color
|
||||
:on-legacy-press on-legacy-press
|
||||
:on-multichain-press on-multichain-press
|
||||
:on-settings-press on-settings-press}]]]]))
|
||||
+11
-5
@@ -2,6 +2,7 @@
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
@@ -52,10 +53,15 @@
|
||||
open-remove-confirmation-sheet (rn/use-callback
|
||||
#(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content (fn []
|
||||
[remove-address/view opts])}])
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:blur-background colors/bottom-sheet-background-blur
|
||||
:content (fn []
|
||||
[remove-address/view opts])}])
|
||||
[opts])
|
||||
open-show-address-qr (rn/use-callback
|
||||
#(rf/dispatch [:open-modal
|
||||
:screen/settings.share-saved-address opts])
|
||||
[opts])]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/arrow-up
|
||||
@@ -91,7 +97,7 @@
|
||||
{:icon :i/qr-code
|
||||
:label (i18n/label :t/show-address-qr)
|
||||
:blur? true
|
||||
:on-press not-implemented/alert
|
||||
:on-press open-show-address-qr
|
||||
:accessibility-label :show-address-qr-code}
|
||||
{:icon :i/edit
|
||||
:label (i18n/label :t/edit-account)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns status-im.contexts.settings.wallet.saved-addresses.style)
|
||||
|
||||
(def title-container
|
||||
{:padding-horizontal 20
|
||||
{:flex 0
|
||||
:padding-horizontal 20
|
||||
:margin-top 12
|
||||
:margin-bottom 16})
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.contexts.settings.wallet.saved-addresses.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
@@ -20,26 +21,29 @@
|
||||
:container-style style/empty-container-style}]))
|
||||
|
||||
(defn- saved-address
|
||||
[{:keys [name address chain-short-names customization-color has-ens? ens]}]
|
||||
[{:keys [name address chain-short-names customization-color ens? ens network-preferences-names]}]
|
||||
(let [full-address (str chain-short-names address)
|
||||
on-press-saved-address (rn/use-callback
|
||||
#(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content (fn []
|
||||
[address-options/view
|
||||
{:address address
|
||||
:chain-short-names chain-short-names
|
||||
:full-address full-address
|
||||
:name name
|
||||
:customization-color customization-color}])}])
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:blur-background colors/bottom-sheet-background-blur
|
||||
:content (fn []
|
||||
[address-options/view
|
||||
{:address address
|
||||
:chain-short-names chain-short-names
|
||||
:full-address full-address
|
||||
:name name
|
||||
:network-preferences-names
|
||||
network-preferences-names
|
||||
:customization-color customization-color}])}])
|
||||
[address chain-short-names full-address name customization-color])]
|
||||
[quo/saved-address
|
||||
{:blur? true
|
||||
:user-props {:name name
|
||||
:address full-address
|
||||
:ens (when has-ens? ens)
|
||||
:ens (when ens? ens)
|
||||
:customization-color customization-color
|
||||
:blur? true}
|
||||
:container-style {:margin-horizontal 8}
|
||||
@@ -78,21 +82,22 @@
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigate-back}]
|
||||
[rn/view {:style style/title-container}
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/saved-addresses)
|
||||
:accessibility-label :saved-addresses-header
|
||||
:right :action
|
||||
:on-press add-address-to-save
|
||||
:customization-color customization-color
|
||||
:icon :i/add}]]
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/saved-addresses)
|
||||
:accessibility-label :saved-addresses-header
|
||||
:right :action
|
||||
:on-press add-address-to-save
|
||||
:customization-color customization-color
|
||||
:icon :i/add
|
||||
:container-style style/title-container}]
|
||||
[rn/section-list
|
||||
{:key-fn :title
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn header
|
||||
:render-section-footer-fn footer
|
||||
:sections saved-addresses
|
||||
:render-fn saved-address
|
||||
:separator [rn/view {:style {:height 4}}]
|
||||
:content-container-style {:flex-grow 1}
|
||||
:empty-component [empty-state]}]]))
|
||||
{:key-fn :title
|
||||
:shows-vertical-scroll-indicator false
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn header
|
||||
:render-section-footer-fn footer
|
||||
:sections saved-addresses
|
||||
:render-fn saved-address
|
||||
:separator [rn/view {:style {:height 4}}]
|
||||
:content-container-style {:flex-grow 1}
|
||||
:empty-component [empty-state]}]]))
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
(defn open-saved-addresses-settings-modal
|
||||
[]
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.saved-addresses :screen/settings]]))
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.saved-addresses :settings]]))
|
||||
|
||||
(defn open-keypairs-and-accounts-settings-modal
|
||||
[]
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.keypairs-and-accounts :screen/settings]]))
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.keypairs-and-accounts :settings]]))
|
||||
|
||||
(defn basic-settings-options
|
||||
[]
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
(defn open-network-settings-modal
|
||||
[]
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.network-settings :screen/settings]]))
|
||||
(rf/dispatch [:navigate-to-within-stack [:screen/settings.network-settings :settings]]))
|
||||
|
||||
(defn advanced-settings-options
|
||||
[]
|
||||
@@ -49,13 +49,12 @@
|
||||
|
||||
(defn advanced-settings
|
||||
[]
|
||||
(when (ff/enabled? ::ff/settings.network-settings)
|
||||
[quo/category
|
||||
{:key :advanced-wallet-settings
|
||||
:label (i18n/label :t/advanced)
|
||||
:data (advanced-settings-options)
|
||||
:blur? true
|
||||
:list-type :settings}]))
|
||||
[quo/category
|
||||
{:key :advanced-wallet-settings
|
||||
:label (i18n/label :t/advanced)
|
||||
:data (advanced-settings-options)
|
||||
:blur? true
|
||||
:list-type :settings}])
|
||||
|
||||
(defn navigate-back
|
||||
[]
|
||||
@@ -75,5 +74,7 @@
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/wallet)
|
||||
:title-accessibility-label :wallet-settings-header}]
|
||||
[basic-settings]
|
||||
(when (or (ff/enabled? ::ff/settings.keypairs-and-accounts)
|
||||
(ff/enabled? ::ff/settings.saved-addresses))
|
||||
[basic-settings])
|
||||
[advanced-settings]]))
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
(defn bottom-tabs-container
|
||||
[pass-through? height]
|
||||
[{:height height}
|
||||
{:background-color (if pass-through? :transparent colors/neutral-100)
|
||||
{:background-color (if (and platform/ios? pass-through?)
|
||||
:transparent
|
||||
colors/neutral-100)
|
||||
:flex 1
|
||||
:align-items :center
|
||||
:height (utils/bottom-tabs-container-height)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.contexts.shell.jump-to.components.jump-to-screen.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.contexts.shell.jump-to.utils :as utils]))
|
||||
|
||||
;;;; Placeholder
|
||||
@@ -63,4 +64,4 @@
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:background-color colors/neutral-100-opa-70-blur})
|
||||
:background-color (when platform/ios? colors/neutral-100-opa-70-blur)})
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.safe-area :as safe-area]
|
||||
@@ -84,7 +83,7 @@
|
||||
(let [pass-through? (rf/sub [:shell/shell-pass-through?])]
|
||||
[rn/view {:style (style/top-nav-blur-overlay-container (+ 56 top) pass-through?)}
|
||||
(when pass-through?
|
||||
[blur/view (bottom-tabs/blur-overlay-params style/top-nav-blur-overlay)])]))
|
||||
[quo/blur (bottom-tabs/blur-overlay-params style/top-nav-blur-overlay)])]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
(ns status-im.contexts.shell.qr-reader.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im.common.router :as router]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.common.validation.general :as validators]
|
||||
[status-im.contexts.communities.events]
|
||||
[status-im.contexts.wallet.common.validation :as wallet-validation]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.url :as url]))
|
||||
(:require [clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im.common.router :as router]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.common.validation.general :as validators]
|
||||
[status-im.contexts.communities.events]
|
||||
[status-im.contexts.wallet.common.validation :as wallet-validation]
|
||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.url :as url]))
|
||||
|
||||
(def invalid-qr-toast
|
||||
{:type :negative
|
||||
@@ -42,10 +43,6 @@
|
||||
[_]
|
||||
false)
|
||||
|
||||
(defn wallet-connect-code?
|
||||
[scanned-text]
|
||||
(string/starts-with? scanned-text "wc:"))
|
||||
|
||||
(defn url?
|
||||
[scanned-text]
|
||||
(url/url? scanned-text))
|
||||
@@ -68,6 +65,12 @@
|
||||
[:toasts/upsert invalid-qr-toast]
|
||||
300))
|
||||
|
||||
(defn- handle-wallet-connect
|
||||
[scanned-text]
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet-connect/on-scan-connection scanned-text]
|
||||
300))
|
||||
|
||||
(defn on-qr-code-scanned
|
||||
[scanned-text]
|
||||
(cond
|
||||
@@ -100,9 +103,10 @@
|
||||
;; TODO: https://github.com/status-im/status-mobile/issues/18744
|
||||
nil
|
||||
|
||||
(wallet-connect-code? scanned-text)
|
||||
;; WalletConnect is not working yet, this flow should be updated once WalletConnect is ready
|
||||
nil
|
||||
(and
|
||||
(wc-utils/valid-uri? scanned-text)
|
||||
(ff/enabled? ::ff/wallet.wallet-connect))
|
||||
(handle-wallet-connect scanned-text)
|
||||
|
||||
(url? scanned-text)
|
||||
(debounce/debounce-and-dispatch [:browser.ui/open-url scanned-text] 300)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.camera-kit :as camera-kit]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
@@ -254,7 +253,7 @@
|
||||
[hole-view/hole-view
|
||||
{:style style/hole
|
||||
:holes [(assoc qr-view-finder :borderRadius 16)]}
|
||||
[blur/view
|
||||
[quo/blur
|
||||
{:style style/absolute-fill
|
||||
:blur-amount 10
|
||||
:blur-type :transparent
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
(defn view
|
||||
[]
|
||||
(let [padding-top (:top (safe-area/get-insets))
|
||||
wallet-type (reagent/atom :legacy)
|
||||
wallet-type (reagent/atom :multichain)
|
||||
selected-networks (reagent/atom constants/default-network-names)
|
||||
on-settings-press #(open-preferences selected-networks)
|
||||
on-legacy-press #(reset! wallet-type :legacy)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [tokens-loading? (rf/sub [:wallet/tokens-loading?])
|
||||
(let [tokens-loading? (rf/sub [:wallet/current-viewing-account-tokens-loading?])
|
||||
tokens (rf/sub [:wallet/current-viewing-account-token-values])
|
||||
{:keys [watch-only?]} (rf/sub [:wallet/current-viewing-account])]
|
||||
(if tokens-loading?
|
||||
|
||||
+1
-4
@@ -46,8 +46,6 @@
|
||||
:public-key ""}])}}
|
||||
[quo/data-item
|
||||
{:card? true
|
||||
:right-icon :i/advanced
|
||||
:icon-right? true
|
||||
:emoji @account-emoji
|
||||
:title (i18n/label :t/watched-address)
|
||||
:subtitle address
|
||||
@@ -60,5 +58,4 @@
|
||||
;; https://github.com/status-im/status-mobile/issues/17009
|
||||
:weight :monospace}
|
||||
address])
|
||||
:container-style style/data-item
|
||||
:on-press #(js/alert "To be implemented")}]]])))
|
||||
:container-style style/data-item}]]])))
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
(defn get-keypairs-success
|
||||
[{:keys [db]} [keypairs]]
|
||||
(let [parsed-keypairs (data-store/parse-keypairs keypairs)
|
||||
default-key-uid (:key-uid (first parsed-keypairs))]
|
||||
(let [parsed-keypairs (data-store/rpc->keypairs keypairs)
|
||||
default-key-uid (:key-uid (some #(when (= (:type %) :profile) %) parsed-keypairs))]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :keypairs] parsed-keypairs)
|
||||
(assoc-in [:wallet :ui :create-account :selected-keypair-uid] default-key-uid))}))
|
||||
|
||||
+1
-2
@@ -4,7 +4,6 @@
|
||||
[native-module.core :as native-module]
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.style :as
|
||||
@@ -86,7 +85,7 @@
|
||||
:first-half? false}]])
|
||||
(when-not @revealed?
|
||||
[rn/view {:style style/blur-container}
|
||||
[blur/view (style/blur theme)]])]
|
||||
[quo/blur (style/blur theme)]])]
|
||||
(when-not @revealed?
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 20
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
(->> given-accounts
|
||||
(filter (fn [{:keys [path]}]
|
||||
(not (string/starts-with? path constants/path-eip1581))))
|
||||
(map (fn [{:keys [customization-color emoji name address]}]
|
||||
{:account-props {:customization-color customization-color
|
||||
(map (fn [{:keys [color emoji name address]}]
|
||||
{:account-props {:customization-color color
|
||||
:size 32
|
||||
:emoji emoji
|
||||
:type :default
|
||||
@@ -48,20 +48,21 @@
|
||||
:action :none}))))
|
||||
|
||||
(defn- keypair
|
||||
[item index _
|
||||
[item _ _
|
||||
{:keys [profile-picture compressed-key selected-key-uid set-selected-key-uid customization-color]}]
|
||||
(let [accounts (parse-accounts (:accounts item))]
|
||||
(let [profile-keypair? (= (:type item) :profile)
|
||||
accounts (parse-accounts (:accounts item))]
|
||||
[quo/keypair
|
||||
{:customization-color customization-color
|
||||
:profile-picture (when (zero? index) profile-picture)
|
||||
:profile-picture (when profile-keypair? profile-picture)
|
||||
:status-indicator false
|
||||
:type (if (zero? index) :default-keypair :other)
|
||||
:type (if profile-keypair? :default-keypair :other)
|
||||
:stored :on-device
|
||||
:on-options-press #(js/alert "Options pressed")
|
||||
:action :selector
|
||||
:blur? false
|
||||
:details {:full-name (:name item)
|
||||
:address (when (zero? index)
|
||||
:address (when profile-keypair?
|
||||
(utils/get-shortened-compressed-key compressed-key))}
|
||||
:on-press #(set-selected-key-uid (:key-uid item))
|
||||
:accounts accounts
|
||||
|
||||
@@ -110,6 +110,20 @@
|
||||
new-request? (update-in [:wallet :accounts] update-vals #(dissoc % :collectibles)))
|
||||
:fx collectible-requests})))
|
||||
|
||||
(defn request-new-collectibles-for-account-from-signal
|
||||
[{:keys [db]} [address]]
|
||||
(let [pending-requests (get-in db [:wallet :ui :collectibles :pending-requests] 0)
|
||||
[request-id] (get-unique-collectible-request-id 1)]
|
||||
{:db (assoc-in db [:wallet :ui :collectibles :pending-requests] (inc pending-requests))
|
||||
:fx [[:dispatch
|
||||
[:wallet/request-new-collectibles-for-account
|
||||
{:request-id request-id
|
||||
:account address
|
||||
:amount collectibles-request-batch-size}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/request-new-collectibles-for-account-from-signal
|
||||
request-new-collectibles-for-account-from-signal)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/request-collectibles-for-current-viewing-account
|
||||
(fn [{:keys [db]} _]
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
(ns status-im.contexts.wallet.collectible.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.wallet.collectible.events :as events]))
|
||||
|
||||
(deftest store-collectibles-test
|
||||
(testing "flush-collectibles"
|
||||
(let [collectible-1 {:collectible-data {:image-url "https://..." :animation-url "https://..."}
|
||||
:ownership [{:address "0x1"
|
||||
:balance "1"}]}
|
||||
collectible-2 {:collectible-data {:image-url "" :animation-url "https://..."}
|
||||
:ownership [{:address "0x1"
|
||||
:balance "1"}]}
|
||||
collectible-3 {:collectible-data {:image-url "" :animation-url nil}
|
||||
:ownership [{:address "0x2"
|
||||
:balance "1"}]}
|
||||
db {:wallet {:ui {:collectibles {:pending-requests 0
|
||||
:fetched {"0x1" [collectible-1
|
||||
collectible-2]
|
||||
"0x2" [collectible-3]}}}
|
||||
:accounts {"0x1" {}
|
||||
"0x3" {}}}}
|
||||
expected-db {:wallet {:ui {:collectibles {}}
|
||||
:accounts {"0x1" {:collectibles (list collectible-1 collectible-2)}
|
||||
"0x2" {:collectibles (list collectible-3)}
|
||||
"0x3" {}}}}
|
||||
result-db (:db (events/flush-collectibles {:db db}))]
|
||||
|
||||
(is (match? result-db expected-db)))))
|
||||
|
||||
(deftest clear-stored-collectibles-test
|
||||
(let [db {:wallet {:accounts {"0x1" {:collectibles [{:id 1} {:id 2}]}
|
||||
"0x2" {"some other stuff" "with any value"
|
||||
:collectibles [{:id 3}]}
|
||||
"0x3" {}}}}]
|
||||
(testing "clear-stored-collectibles"
|
||||
(let [expected-db {:wallet {:accounts {"0x1" {}
|
||||
"0x2" {"some other stuff" "with any value"}
|
||||
"0x3" {}}}}
|
||||
effects (events/clear-stored-collectibles {:db db})
|
||||
result-db (:db effects)]
|
||||
|
||||
(is (match? result-db expected-db))))))
|
||||
|
||||
(deftest store-last-collectible-details-test
|
||||
(testing "store-last-collectible-details"
|
||||
(let [db {:wallet {}}
|
||||
last-collectible {:description "Pandaria"
|
||||
:image-url "https://..."}
|
||||
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
|
||||
:image-url "https://..."}}}
|
||||
effects (events/store-last-collectible-details {:db db}
|
||||
[last-collectible])
|
||||
result-db (:db effects)]
|
||||
(is (match? result-db expected-db)))))
|
||||
|
||||
(deftest request-new-collectibles-for-account-from-signal-test
|
||||
(testing "request new collectibles for account from signal"
|
||||
(let [db {:wallet {}}
|
||||
address "0x1"
|
||||
expected {:db {:wallet {:ui {:collectibles {:pending-requests 1}}}}
|
||||
:fx [[:dispatch
|
||||
[:wallet/request-new-collectibles-for-account
|
||||
{:request-id 0
|
||||
:account address
|
||||
:amount events/collectibles-request-batch-size}]]]}
|
||||
effects (events/request-new-collectibles-for-account-from-signal {:db db}
|
||||
[address])]
|
||||
(is (match? expected effects)))))
|
||||
@@ -17,7 +17,8 @@
|
||||
"image/gif"
|
||||
"image/bmp"
|
||||
"image/png"
|
||||
"image/webp"})
|
||||
"image/webp"
|
||||
"image/avif"})
|
||||
|
||||
(defn supported-file?
|
||||
[collectible-type]
|
||||
|
||||
@@ -83,7 +83,9 @@
|
||||
(colors/theme-colors colors/white-opa-50 colors/neutral-95-opa-70-blur theme))]
|
||||
[rn/view {:style style/animated-header}
|
||||
[reanimated/blur-view
|
||||
{:style {:flex 1}
|
||||
{:style {:flex 1
|
||||
:background-color (when platform/android?
|
||||
(colors/theme-colors colors/white colors/neutral-80 theme))}
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent
|
||||
:blur-amount blur-amount
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(ns status-im.contexts.wallet.common.scan-account.view
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.constants :as constants]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.constants :as constants]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def ^:private supported-networks #{:eth :arb1 :oeth})
|
||||
|
||||
|
||||
@@ -114,7 +114,17 @@
|
||||
[prefix]
|
||||
(as-> prefix $
|
||||
(string/split $ ":")
|
||||
(map short-name->network $)))
|
||||
(map short-name->network $)
|
||||
(remove nil? $)))
|
||||
|
||||
(defn network-names->network-preference-prefix
|
||||
[network-names]
|
||||
(if (empty? network-names)
|
||||
""
|
||||
(->> network-names
|
||||
(map network->short-name)
|
||||
(remove nil?)
|
||||
short-names->network-preference-prefix)))
|
||||
|
||||
(defn network-ids->formatted-text
|
||||
[network-ids]
|
||||
|
||||
@@ -33,7 +33,18 @@
|
||||
(= expected (utils/network-preference-prefix->network-names short-names))
|
||||
(seq [:mainnet]) "eth"
|
||||
(seq [:mainnet :optimism]) "eth:oeth"
|
||||
(seq [:mainnet :optimism :arbitrum]) "eth:oeth:arb1"))
|
||||
(seq [:mainnet :optimism :arbitrum]) "eth:oeth:arb1"
|
||||
(seq [:mainnet :arbitrum]) "eth:sol:arb1"))
|
||||
|
||||
(deftest network-names->network-preference-prefix-test
|
||||
(are [expected network-names]
|
||||
(= expected (utils/network-names->network-preference-prefix network-names))
|
||||
"eth:" [:mainnet]
|
||||
"eth:oeth:" [:mainnet :optimism]
|
||||
"eth:oeth:arb1:" [:mainnet :optimism :arbitrum]
|
||||
"eth:arb1:" [:mainnet :polygon :arbitrum]
|
||||
"" []
|
||||
"" nil))
|
||||
|
||||
(deftest network-ids->formatted-text-test
|
||||
(testing "Empty network-ids should return an empty string"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user