Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
747d6bb128 | ||
|
|
a29264a1a1 | ||
|
|
1386bd4777 | ||
|
|
e86faa0767 | ||
|
|
abe0342be0 | ||
|
|
6669c33e33 | ||
|
|
1351a54fd1 | ||
|
|
da192dcdb3 | ||
|
|
6e22e63158 | ||
|
|
d1f22cd2b8 | ||
|
|
9dacc9e8af | ||
|
|
9acf67dd5b | ||
|
|
ab73c7e56a | ||
|
|
f1db73d149 | ||
|
|
d78d7719cd | ||
|
|
e381998b19 | ||
|
|
025c38ae88 | ||
|
|
523a5809d0 | ||
|
|
505f2fe624 | ||
|
|
ac32de89f9 | ||
|
|
52a82fffab | ||
|
|
d1c8f6411d | ||
|
|
7b639f2ffe | ||
|
|
ae7ee33f00 | ||
|
|
c70646bd5c | ||
|
|
484ab919b1 | ||
|
|
052d88b531 | ||
|
|
0aba789b5c | ||
|
|
73450d736a | ||
|
|
cc63c8fff5 | ||
|
|
ef6027575f |
@@ -16,18 +16,19 @@
|
||||
:clj-kondo-config {:level :error}
|
||||
:cond-else {:level :error}
|
||||
:consistent-alias {:level :error
|
||||
:aliases {clojure.set set
|
||||
clojure.string string
|
||||
clojure.walk walk
|
||||
malli.core malli
|
||||
malli.dev.pretty malli.pretty
|
||||
malli.dev.virhe malli.virhe
|
||||
malli.error malli.error
|
||||
malli.generator malli.generator
|
||||
malli.transform malli.transform
|
||||
malli.util malli.util
|
||||
schema.core schema
|
||||
taoensso.timbre log}}
|
||||
:aliases {clojure.set set
|
||||
clojure.string string
|
||||
clojure.walk walk
|
||||
malli.core malli
|
||||
malli.dev.pretty malli.pretty
|
||||
malli.dev.virhe malli.virhe
|
||||
malli.error malli.error
|
||||
malli.generator malli.generator
|
||||
malli.transform malli.transform
|
||||
malli.util malli.util
|
||||
schema.core schema
|
||||
status-im.feature-flags ff
|
||||
taoensso.timbre log}}
|
||||
:deprecated-namespace {:level :warning}
|
||||
:docstring-blank {:level :error}
|
||||
:equals-true {:level :error}
|
||||
|
||||
@@ -373,15 +373,20 @@ test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connection
|
||||
"until [ -f $$SHADOW_OUTPUT_TO ] ; do sleep 1 ; done ; node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO --repl"
|
||||
|
||||
test-unit: export SHADOW_OUTPUT_TO := target/unit_test/test.js
|
||||
test-unit: export SHADOW_NS_REGEXP := ^(?!status-im\.integration-test).*-test$$
|
||||
test-unit: export SHADOW_NS_REGEXP := ^(?!tests\.integration-test)(?!tests-im\.contract-test).*-test$$
|
||||
test-unit: ##@test Run unit tests
|
||||
test-unit: _test-clojure
|
||||
|
||||
test-integration: export SHADOW_OUTPUT_TO := target/integration_test/test.js
|
||||
test-integration: export SHADOW_NS_REGEXP := ^status-im\.integration-test.*$$
|
||||
test-integration: export SHADOW_NS_REGEXP := ^tests\.integration-test.*$$
|
||||
test-integration: ##@test Run integration tests
|
||||
test-integration: _test-clojure
|
||||
|
||||
test-contract: export SHADOW_OUTPUT_TO := target/contract_test/test.js
|
||||
test-contract: export SHADOW_NS_REGEXP := ^tests\.contract-test.*$$
|
||||
test-contract: ##@test Run contract tests
|
||||
test-contract: _test-clojure
|
||||
|
||||
android-test: jsbundle
|
||||
android-test: export TARGET := android
|
||||
android-test:
|
||||
@@ -457,3 +462,18 @@ repl-clojure: ##@repl Start Clojure repl for mobile App
|
||||
yarn shadow-cljs cljs-repl mobile
|
||||
|
||||
repl-nix: nix-repl ##@repl Start an interactive Nix REPL
|
||||
|
||||
#--------------
|
||||
# Dev Automation Flows
|
||||
#--------------
|
||||
|
||||
auto-login: export TARGET := default
|
||||
auto-login: ##@auto runs flow for login or onboarding app on simulator/emulator
|
||||
maestro test "maestro/create-account-or-login.yaml"
|
||||
|
||||
auto-custom: export TARGET := default
|
||||
auto-custom: ##@auto runs any custom maestro automation flow on simulator/emulator
|
||||
ifndef FLOW
|
||||
$(error Usage: make automate FLOW=your-maestro-flow-file.yaml)
|
||||
endif
|
||||
maestro test "$(FLOW)"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
appId: im.status.ethereum.debug
|
||||
---
|
||||
- runFlow: # to run onboarding flow only when device is in onboarding state
|
||||
when:
|
||||
visible: "I’m new to Status"
|
||||
file: onboarding.yaml
|
||||
|
||||
- runFlow: # to run login flow only when device is on login screen
|
||||
when:
|
||||
visible: "Profile password"
|
||||
file: login.yaml
|
||||
@@ -0,0 +1,5 @@
|
||||
appId: im.status.ethereum.debug
|
||||
---
|
||||
- tapOn: "password-input"
|
||||
- inputText: "password123" # update your account password here
|
||||
- tapOn: login-button
|
||||
@@ -0,0 +1,15 @@
|
||||
appId: im.status.ethereum.debug
|
||||
---
|
||||
- tapOn: "I’m new to Status"
|
||||
- tapOn: "small-option-card"
|
||||
- tapOn: "Your name"
|
||||
- inputText: "DeviceA"
|
||||
- tapOn: "submit-create-profile-button"
|
||||
- inputText: "password123"
|
||||
- tapOn: "Repeat password"
|
||||
- inputText: "password123"
|
||||
- tapOn: "disclaimer-touchable-opacity"
|
||||
- tapOn: "Confirm password"
|
||||
- tapOn: "skip-identifiers"
|
||||
- tapOn: "enable-notifications-later-button"
|
||||
- tapOn: "welcome-button"
|
||||
@@ -97,4 +97,5 @@ in {
|
||||
patchMavenSources = callPackage ./pkgs/patch-maven-srcs { };
|
||||
goMavenResolver = callPackage ./pkgs/go-maven-resolver { };
|
||||
xcbeautify = callPackage ./pkgs/xcbeautify { };
|
||||
idb-companion = callPackage ./pkgs/idb-companion { };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{ stdenv, fetchurl, lib }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "idb-companion";
|
||||
version = "1.1.8";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/facebook/idb/releases/download/v${version}/idb-companion.universal.tar.gz";
|
||||
sha256 = "sha256-O3LMappbGiKhiCBahAkNOilDR6hGGA79dVzxo8hI4+c=";
|
||||
};
|
||||
|
||||
buildInputs = [ ];
|
||||
|
||||
unpackPhase = ''
|
||||
tar -xzf $src
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp -r ./* $out/bin/
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "A powerful command line tool for automating iOS simulators and devices";
|
||||
homepage = "https://github.com/facebook/idb";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.darwin;
|
||||
};
|
||||
}
|
||||
@@ -23,9 +23,9 @@ in mkShell {
|
||||
# build specific utilities
|
||||
clojure maven watchman
|
||||
# other nice to have stuff
|
||||
yarn nodejs python310
|
||||
yarn nodejs python310 maestro
|
||||
] # and some special cases
|
||||
++ lib.optionals stdenv.isDarwin ([ cocoapods clang tcl ] ++ appleSDKFrameworks)
|
||||
++ lib.optionals stdenv.isDarwin ([ cocoapods clang tcl idb-companion ] ++ appleSDKFrameworks)
|
||||
++ lib.optionals (!stdenv.isDarwin) [ gcc8 ]
|
||||
);
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 695 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 217 B |
@@ -45,6 +45,9 @@
|
||||
;; To match the folder created by Nix build of JSBundle.
|
||||
:output-dir "result"
|
||||
:init-fn status-im.core/init
|
||||
:build-hooks [(status-im.setup.build-hooks.worklets/transform-output)
|
||||
(status-im.setup.build-hooks.worklets/optimize-start)
|
||||
(status-im.setup.build-hooks.worklets/optimize-output)]
|
||||
;; When false, the Shadow-CLJS watcher won't automatically refresh
|
||||
;; the target files (a.k.a hot reload). When false, you can manually
|
||||
;; reload by calling `shadow.cljs.devtools.api/watch-compile-all!`.
|
||||
@@ -176,7 +179,6 @@
|
||||
;; option setupFilesAfterEnv.
|
||||
test-helpers.component-tests-preload
|
||||
status-im.setup.schema-preload
|
||||
|
||||
quo.core-spec
|
||||
status-im.core-spec]
|
||||
:ns-regexp "component-spec$"
|
||||
|
||||
@@ -4,14 +4,19 @@
|
||||
|
||||
(def backgrounds #{:photo :blur})
|
||||
|
||||
(defn custom-color-type
|
||||
;; Note: We hardcode the :light theme for the background-color and apply an overlay when necessary, such
|
||||
;; as for dark themes and pressed states. This approach is taken because, for communities, we only have
|
||||
;; one color available, which is the light theme version.
|
||||
;; For more information, see the related issue: https://github.com/status-im/status-mobile/issues/16396
|
||||
(defn- custom-color-type
|
||||
[customization-color icon-only?]
|
||||
{:icon-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color (colors/custom-color customization-color 50)
|
||||
:border-radius (when icon-only? 24)})
|
||||
{:icon-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color (colors/resolve-color customization-color :light)
|
||||
:border-radius (when icon-only? 24)
|
||||
:overlay-customization-color customization-color})
|
||||
|
||||
(defn grey-photo
|
||||
(defn- grey-photo
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-70 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -24,7 +29,7 @@
|
||||
theme))
|
||||
:blur-type (if (= theme :light) :light :dark)})
|
||||
|
||||
(defn grey-blur
|
||||
(defn- grey-blur
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-70 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -32,7 +37,7 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme))})
|
||||
|
||||
(defn outline-blur
|
||||
(defn- outline-blur
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -40,7 +45,7 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
|
||||
(colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme))})
|
||||
|
||||
(defn grey
|
||||
(defn- grey
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -50,7 +55,7 @@
|
||||
colors/neutral-90
|
||||
theme))})
|
||||
|
||||
(defn dark-grey
|
||||
(defn- dark-grey
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -58,7 +63,7 @@
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme)
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-90 theme))})
|
||||
|
||||
(defn outline
|
||||
(defn- outline
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
@@ -66,29 +71,32 @@
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-70 theme))})
|
||||
|
||||
(defn ghost
|
||||
(defn- ghost
|
||||
[theme pressed?]
|
||||
{:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:background-color (when pressed?
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
|
||||
|
||||
(defn black
|
||||
(defn- black
|
||||
[pressed?]
|
||||
{:label-color colors/white
|
||||
:background-color (if pressed? colors/neutral-80 colors/neutral-95)})
|
||||
|
||||
(defn get-values
|
||||
[{:keys [customization-color theme type background pressed? icon-only?]}]
|
||||
(cond
|
||||
(= type :primary) (custom-color-type customization-color icon-only?)
|
||||
(= type :positive) (custom-color-type customization-color icon-only?)
|
||||
(= type :danger) (custom-color-type customization-color icon-only?)
|
||||
(and (= :photo background) (= type :grey)) (grey-photo theme pressed?)
|
||||
(and (= :blur background) (= type :grey)) (grey-blur theme pressed?)
|
||||
(and (= :blur background) (= type :outline)) (outline-blur theme pressed?)
|
||||
(= type :grey) (grey theme pressed?)
|
||||
(= type :dark-grey) (dark-grey theme pressed?)
|
||||
(= type :outline) (outline theme pressed?)
|
||||
(= type :ghost) (ghost theme pressed?)
|
||||
(= type :black) (black pressed?)))
|
||||
(let [customization-color (get {:primary customization-color
|
||||
:positive :success
|
||||
:danger :danger}
|
||||
type)]
|
||||
(cond
|
||||
(contains? #{:primary :positive :danger} type) (custom-color-type customization-color
|
||||
icon-only?)
|
||||
(and (= :photo background) (= type :grey)) (grey-photo theme pressed?)
|
||||
(and (= :blur background) (= type :grey)) (grey-blur theme pressed?)
|
||||
(and (= :blur background) (= type :outline)) (outline-blur theme pressed?)
|
||||
(= type :grey) (grey theme pressed?)
|
||||
(= type :dark-grey) (dark-grey theme pressed?)
|
||||
(= type :outline) (outline theme pressed?)
|
||||
(= type :ghost) (ghost theme pressed?)
|
||||
(= type :black) (black pressed?))))
|
||||
|
||||
@@ -37,13 +37,10 @@
|
||||
pressed? on-press-in on-press-out allow-multiple-presses?]
|
||||
:or {type :primary
|
||||
size 40
|
||||
customization-color (cond (= type :primary) :blue
|
||||
(= type :positive) :success
|
||||
(= type :danger) :danger
|
||||
:else nil)}}
|
||||
customization-color (if (= type :primary) :blue nil)}}
|
||||
children]
|
||||
(let [{:keys [icon-color background-color label-color border-color blur-type
|
||||
blur-overlay-color border-radius]}
|
||||
blur-overlay-color border-radius overlay-customization-color]}
|
||||
(button-properties/get-values {:customization-color customization-color
|
||||
:background background
|
||||
:type type
|
||||
@@ -79,9 +76,9 @@
|
||||
:icon-left icon-left
|
||||
:icon-right icon-right})
|
||||
inner-style)}
|
||||
(when customization-color
|
||||
(when overlay-customization-color
|
||||
[customization-colors/overlay
|
||||
{:customization-color customization-color
|
||||
{:customization-color overlay-customization-color
|
||||
:theme theme
|
||||
:pressed? (if pressed? pressed? @pressed-state?)}])
|
||||
(when (= background :photo)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
(when (and @ref (>= index 0))
|
||||
(some-> ^js @ref
|
||||
(.scrollToIndex #js
|
||||
{:animated true
|
||||
{:animated false
|
||||
:index index
|
||||
:viewPosition 0.5})))))
|
||||
50)))
|
||||
|
||||
@@ -3,34 +3,60 @@
|
||||
[quo.components.drawers.bottom-actions.view :as bottom-actions]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- render
|
||||
[component]
|
||||
(h/render-with-theme-provider component :light))
|
||||
|
||||
(h/describe "bottom actions tests"
|
||||
(h/test "default render with no description and single action button"
|
||||
(h/render [bottom-actions/view {:button-one-label "Request to join"}])
|
||||
(render [bottom-actions/view {:actions :one-action :button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "Request to join")))
|
||||
|
||||
(h/test "render with description"
|
||||
(h/render [bottom-actions/view {:description "Sample description"}])
|
||||
(h/is-truthy (h/get-by-text "Sample description")))
|
||||
(h/test "render with description & 1 action"
|
||||
(render [bottom-actions/view
|
||||
{:description :bottom
|
||||
:description-text "Sample description"
|
||||
:actions :one-action
|
||||
:button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "Sample description"))
|
||||
(h/is-truthy (h/get-by-text "Request to join")))
|
||||
|
||||
(h/test "render with 2 actions"
|
||||
(let [button-one "Button One"
|
||||
button-two "Button Two"]
|
||||
(h/render [bottom-actions/view
|
||||
{:actions :2-actions
|
||||
:button-one-label button-one
|
||||
:button-one-props {:icon-left :i/arrow-left}
|
||||
:button-two-label button-two}])
|
||||
(render [bottom-actions/view
|
||||
{:actions :two-actions
|
||||
:button-one-label button-one
|
||||
:button-one-props {:icon-left :i/arrow-left}
|
||||
:button-two-label button-two}])
|
||||
(h/is-truthy (h/get-by-text button-one))
|
||||
(h/is-truthy (h/get-by-label-text :icon))
|
||||
(h/is-truthy (h/get-by-text button-two))))
|
||||
|
||||
(h/test "render disabled button"
|
||||
(h/render [bottom-actions/view
|
||||
{:description "Sample description"
|
||||
:button-one-props {:disabled? true}
|
||||
:button-one-label "button"}])
|
||||
(render [bottom-actions/view
|
||||
{:description :bottom
|
||||
:actions :one-action
|
||||
:description-text "Sample description"
|
||||
:button-one-props {:disabled? true}
|
||||
:button-one-label "button"}])
|
||||
(h/is-disabled (h/get-by-label-text :button-one)))
|
||||
|
||||
(h/test "sane defaults"
|
||||
(h/render [bottom-actions/view {}])
|
||||
(h/is-truthy (h/get-by-label-text :button-one))))
|
||||
(h/test "render with error & 1 action"
|
||||
(render [bottom-actions/view
|
||||
{:description :top-error
|
||||
:error-message "Sample error"
|
||||
:actions :one-action
|
||||
:button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "Sample error"))
|
||||
(h/is-truthy (h/get-by-text "Request to join")))
|
||||
|
||||
(h/test "render with top description & 1 action"
|
||||
(render [bottom-actions/view
|
||||
{:description :top
|
||||
:role :admin
|
||||
:actions :one-action
|
||||
:button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "Eligible to join as"))
|
||||
(h/is-truthy (h/get-by-text "Admin"))
|
||||
(h/is-truthy (h/get-by-text "Request to join"))))
|
||||
|
||||
@@ -2,34 +2,58 @@
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn- text-color
|
||||
[scroll? blur? theme]
|
||||
(cond
|
||||
scroll? (if blur?
|
||||
colors/white-70-blur
|
||||
(colors/theme-colors colors/neutral-80-opa-70
|
||||
colors/white-opa-70
|
||||
theme))
|
||||
blur? colors/white-opa-40
|
||||
:else (colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)))
|
||||
|
||||
(defn container
|
||||
[scroll? blur? theme]
|
||||
{:background-color (when-not (or scroll? blur?)
|
||||
(colors/theme-colors colors/white colors/neutral-95 theme))})
|
||||
|
||||
(def buttons-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-around
|
||||
:padding-vertical 12
|
||||
:gap 12
|
||||
:padding-horizontal 20})
|
||||
|
||||
(def button-container
|
||||
{:flex 1})
|
||||
|
||||
(def button-container-2-actions
|
||||
(assoc button-container :margin-right 12))
|
||||
(def description-top
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:gap 5
|
||||
:padding-top 12
|
||||
:padding-bottom 4
|
||||
:justify-content :center})
|
||||
|
||||
(defn description
|
||||
[theme scroll?]
|
||||
{:color (colors/theme-colors
|
||||
(if scroll?
|
||||
(colors/custom-color colors/neutral-80 70)
|
||||
colors/neutral-50)
|
||||
(if scroll?
|
||||
colors/white-opa-70
|
||||
colors/neutral-40)
|
||||
theme)
|
||||
(defn description-top-text
|
||||
[scroll? blur? theme]
|
||||
{:color (text-color scroll? blur? theme)})
|
||||
|
||||
(defn description-bottom
|
||||
[scroll? blur? theme]
|
||||
{:color (text-color scroll? blur? theme)
|
||||
:text-align :center
|
||||
:padding-bottom 12
|
||||
:padding-horizontal 40})
|
||||
|
||||
(def scroll
|
||||
{:margin-top 21
|
||||
:margin-horizontal 120
|
||||
:margin-bottom 8
|
||||
:width 134
|
||||
:height 5})
|
||||
(def error-message
|
||||
{:flex-direction :row
|
||||
:gap 4
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-top 15
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 7})
|
||||
|
||||
@@ -2,55 +2,96 @@
|
||||
(:require
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.drawers.bottom-actions.style :as style]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.context-tag.view :as context-tag]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def default-props
|
||||
{:button-one-type :primary
|
||||
:button-two-type :grey
|
||||
:customization-color :blue})
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:actions [:maybe [:enum :one-action :two-actions]]]
|
||||
[:description {:optional true} [:maybe [:enum :top :bottom :top-error]]]
|
||||
[:description-text {:optional true} [:maybe :string]]
|
||||
[:error-message {:optional true} [:maybe :string]]
|
||||
[:role {:optional true} [:maybe [:enum :admin :member :token-master :owner]]]
|
||||
[:button-one-label {:optional true} [:maybe :string]]
|
||||
[:button-two-label {:optional true} [:maybe :string]]
|
||||
[:button-one-props {:optional true} [:maybe :map]]
|
||||
[:button-two-props {:optional true} [:maybe :map]]
|
||||
[:theme :schema.common/theme]
|
||||
[:scroll? {:optional true} [:maybe :boolean]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:container-style {:optional true} [:maybe :map]]]]]
|
||||
:any])
|
||||
|
||||
(def ^:private role-icon
|
||||
{:admin :i/gavel
|
||||
:member :i/members
|
||||
:token-master :i/token-master
|
||||
:owner :i/crown})
|
||||
|
||||
(defn- view-internal
|
||||
"Options:
|
||||
[{:keys [actions description description-text error-message role button-one-label button-two-label
|
||||
blur? button-one-props button-two-props theme scroll? container-style]}]
|
||||
[rn/view
|
||||
{:style (merge (style/container scroll? blur? theme) container-style)}
|
||||
(when (= description :top-error)
|
||||
[rn/view {:style style/error-message}
|
||||
[icon/icon
|
||||
:i/alert
|
||||
{:color (colors/theme-colors colors/danger-50 colors/danger-60 theme)
|
||||
:size 16}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (colors/theme-colors colors/danger-50 colors/danger-60 theme)}}
|
||||
error-message]])
|
||||
|
||||
:actions - keyword (default nil) - :1-action/:2-actions
|
||||
:description - string (default nil) - Description to display below the title
|
||||
:button-one-label - string (default nil) - Label for the first button
|
||||
:button-two-label - string (default nil) - Label for the second button
|
||||
:button-one-props - map with props for button one
|
||||
:button-two-props - map with props for button two
|
||||
:theme - :light/:dark
|
||||
:scroll? - bool (default false) - Whether the iOS Home Indicator should be rendered"
|
||||
[props]
|
||||
(let [{:keys [actions description button-one-label button-two-label
|
||||
button-one-props button-two-props theme scroll? customization-color container-style]}
|
||||
(merge default-props props)]
|
||||
[rn/view {:style container-style}
|
||||
[rn/view {:style style/buttons-container}
|
||||
(when (= actions :2-actions)
|
||||
[button/button
|
||||
(merge
|
||||
{:size 40
|
||||
:background (when scroll? :blur)
|
||||
:container-style style/button-container-2-actions
|
||||
:theme theme
|
||||
:accessibility-label :button-two}
|
||||
button-two-props)
|
||||
button-two-label])
|
||||
(when (= description :top)
|
||||
[rn/view
|
||||
{:style style/description-top}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description-top-text scroll? blur? theme)}
|
||||
(i18n/label :t/eligible-to-join-as)]
|
||||
[context-tag/view
|
||||
{:type :icon
|
||||
:size 24
|
||||
:icon (role role-icon)
|
||||
:blur? blur?
|
||||
:context (i18n/label (keyword "t" role))}]])
|
||||
|
||||
[rn/view {:style style/buttons-container}
|
||||
(when (= actions :two-actions)
|
||||
[button/button
|
||||
(merge
|
||||
{:size 40
|
||||
:background (when (or blur? scroll?) :blur)
|
||||
:container-style style/button-container
|
||||
:background (when scroll? :blur)
|
||||
:theme theme
|
||||
:accessibility-label :button-one
|
||||
:customization-color customization-color}
|
||||
button-one-props)
|
||||
button-one-label]]
|
||||
(when description
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description theme scroll?)} description])]))
|
||||
:accessibility-label :button-two}
|
||||
button-two-props)
|
||||
button-two-label])
|
||||
[button/button
|
||||
(merge
|
||||
{:size 40
|
||||
:container-style style/button-container
|
||||
:background (when (or blur? scroll?) :blur)
|
||||
:theme theme
|
||||
:accessibility-label :button-one}
|
||||
button-one-props)
|
||||
button-one-label]]
|
||||
(when (= description :bottom)
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description-bottom scroll? blur? theme)} description-text])])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -3,97 +3,110 @@
|
||||
[quo.core :as quo]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def ^:private theme :light)
|
||||
|
||||
(h/describe "drawer top tests"
|
||||
(h/test "component renders in default type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :default}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :default}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "component renders in default + description type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :default
|
||||
:description "Description"}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :default
|
||||
:description "Description"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-text "Description")))
|
||||
|
||||
(h/test "component renders in info type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :info}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :info}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-label-text :info-icon)))
|
||||
|
||||
(h/test "component renders in info + description type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:description "Description"
|
||||
:type :info}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:description "Description"
|
||||
:type :info}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-text "Description"))
|
||||
(h/is-truthy (h/get-by-label-text :info-icon)))
|
||||
|
||||
(h/test "component renders in context-tag type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :context-tag
|
||||
:community-name "Coinbase"}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :context-tag
|
||||
:community-name "Coinbase"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-label-text :context-tag-wrapper)))
|
||||
|
||||
(h/test "component renders in context-tag + button type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :context-tag
|
||||
:button-icon :i/placeholder
|
||||
:community-name "Coinbase"}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :context-tag
|
||||
:button-icon :i/placeholder
|
||||
:community-name "Coinbase"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-label-text :button-icon))
|
||||
(h/is-truthy (h/get-by-label-text :context-tag-wrapper)))
|
||||
|
||||
(h/test "component renders in account type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :account
|
||||
:account-avatar-emoji "🍿"
|
||||
:networks [{:name :ethereum :short-name "eth"}]
|
||||
:description "0x62b...0a5"
|
||||
:customization-color :purple}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:type :account
|
||||
:account-avatar-emoji "🍿"
|
||||
:networks [{:name :ethereum :short-name "eth"}]
|
||||
:description "0x62b...0a5"
|
||||
:customization-color :purple}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-text "0x62b...0a5"))
|
||||
(h/is-truthy (h/get-by-label-text :account-avatar)))
|
||||
|
||||
(h/test "component renders in keypair type when keycard? is false"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? false
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? false
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(-> (h/expect (h/get-by-translation-text :t/on-device))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders in keypair type when keycard? is true"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? true
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:keycard? true
|
||||
:icon-avatar :i/placeholder
|
||||
:type :keypair}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "component renders in default-keypair type"
|
||||
(h/render [quo/drawer-top
|
||||
{:title "Title"
|
||||
:description "0x62b...0a5"
|
||||
:type :default-keypair}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:title "Title"
|
||||
:description "0x62b...0a5"
|
||||
:type :default-keypair}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-label-text :default-keypair-text)))
|
||||
|
||||
(h/test "component renders in label type"
|
||||
(h/render [quo/drawer-top
|
||||
{:label "label"
|
||||
:type :label}])
|
||||
(h/render-with-theme-provider [quo/drawer-top
|
||||
{:label "label"
|
||||
:type :label}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-text "label"))))
|
||||
|
||||
@@ -61,24 +61,30 @@
|
||||
value (reagent/atom "")
|
||||
focused? (atom false)]
|
||||
(fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan
|
||||
on-detect-ens on-detect-address address-regex valid-ens-or-address?
|
||||
container-style]}]
|
||||
on-detect-ens on-detect-address on-detect-unclassified address-regex ens-regex
|
||||
valid-ens-or-address? container-style]}]
|
||||
(let [on-change (fn [text]
|
||||
(when (not= @value text)
|
||||
(let [address? (when address-regex
|
||||
(boolean (re-matches address-regex text)))]
|
||||
(boolean (re-matches address-regex text)))
|
||||
ens? (when ens-regex
|
||||
(boolean (re-matches ens-regex text)))]
|
||||
(if (> (count text) 0)
|
||||
(reset! status :typing)
|
||||
(reset! status :active))
|
||||
(reset! value text)
|
||||
(when on-change-text
|
||||
(on-change-text text))
|
||||
(when (and on-detect-ens (> (count text) 0))
|
||||
(when (and on-detect-ens ens?)
|
||||
(reset! status :loading)
|
||||
(on-detect-ens text #(reset! status :typing)))
|
||||
(when (and address? on-detect-address)
|
||||
(reset! status :loading)
|
||||
(on-detect-address text)))))
|
||||
(on-detect-address text))
|
||||
(when (and (not address?)
|
||||
(not ens?)
|
||||
on-detect-unclassified)
|
||||
(on-detect-unclassified text)))))
|
||||
on-paste (fn []
|
||||
(clipboard/get-string
|
||||
(fn [clipboard]
|
||||
|
||||
@@ -4,79 +4,83 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def ^:private theme :light)
|
||||
|
||||
(h/describe "List items: account"
|
||||
(h/test "default render'"
|
||||
(h/render [account/view])
|
||||
(h/render-with-theme-provider [account/view] theme)
|
||||
(h/is-truthy (h/query-by-label-text :container)))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed"
|
||||
(h/render [account/view])
|
||||
(h/render-with-theme-provider [account/view] theme)
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/resolve-color :blue :light 5)})))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed with blur? enabled"
|
||||
(h/render [account/view {:blur? true}])
|
||||
(h/render-with-theme-provider [account/view {:blur? true}] theme)
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-5})))
|
||||
|
||||
(h/test "render with state :active"
|
||||
(h/render [account/view {:state :active}])
|
||||
(h/render-with-theme-provider [account/view {:state :active}] theme)
|
||||
(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/resolve-color :blue :light 10)}))
|
||||
|
||||
(h/test "render with state :active and blur? enabled"
|
||||
(h/render [account/view
|
||||
{:blur? true
|
||||
:state :active}])
|
||||
(h/render-with-theme-provider [account/view
|
||||
{:blur? true
|
||||
:state :active}]
|
||||
theme)
|
||||
(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-10}))
|
||||
|
||||
(h/test "render with state :selected"
|
||||
(h/render [account/view {:state :selected}])
|
||||
(h/render-with-theme-provider [account/view {:state :selected}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :check-icon)))
|
||||
|
||||
(h/test "calls on-press"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [account/view {:on-press on-press}])
|
||||
(h/render-with-theme-provider [account/view {:on-press on-press}] theme)
|
||||
(h/fire-event :on-press (h/get-by-label-text :container))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "renders token props if type :tag"
|
||||
(h/render [account/view {:type :tag}])
|
||||
(h/render-with-theme-provider [account/view {:type :tag}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :tag-container)))
|
||||
|
||||
(h/test "renders keycard icon if title-icon is present"
|
||||
(h/render [account/view {:title-icon :i/placeholder}])
|
||||
(h/render-with-theme-provider [account/view {:title-icon :i/placeholder}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :title-icon)))
|
||||
|
||||
(h/test "doesn't render keycard icon if title-icon is missing"
|
||||
(h/render [account/view])
|
||||
(h/render-with-theme-provider [account/view] theme)
|
||||
(h/is-falsy (h/query-by-label-text :title-icon)))
|
||||
|
||||
(h/test "renders balance container but not arrow icon if type :balance-neutral"
|
||||
(h/render [account/view {:type :balance-neutral}])
|
||||
(h/render-with-theme-provider [account/view {:type :balance-neutral}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-falsy (h/query-by-label-text :arrow-icon)))
|
||||
|
||||
(h/test "renders balance container and negative arrow icon if type :balance-negative"
|
||||
(h/render [account/view {:type :balance-negative}])
|
||||
(h/render-with-theme-provider [account/view {:type :balance-negative}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-truthy (h/query-by-label-text :icon-negative))
|
||||
(h/is-falsy (h/query-by-label-text :icon-positive)))
|
||||
|
||||
(h/test "renders balance container and positive arrow icon if type :balance-positive"
|
||||
(h/render [account/view {:type :balance-positive}])
|
||||
(h/render-with-theme-provider [account/view {:type :balance-positive}] theme)
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-falsy (h/query-by-label-text :icon-negative))
|
||||
(h/is-truthy (h/query-by-label-text :icon-positive)))
|
||||
|
||||
(h/test "renders options button if type :action"
|
||||
(let [on-options-press (h/mock-fn)]
|
||||
(h/render [account/view
|
||||
{:type :action
|
||||
:on-options-press on-options-press}])
|
||||
(h/render-with-theme-provider [account/view
|
||||
{:type :action
|
||||
:on-options-press on-options-press}]
|
||||
theme)
|
||||
(h/is-truthy (h/query-by-label-text :options-button))
|
||||
(h/fire-event :on-press (h/get-by-label-text :options-button))
|
||||
(h/was-called on-options-press))))
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [state theme number word] :as props}]
|
||||
[rn/view {:style (style/container props)}
|
||||
[{:keys [state theme number word on-press] :as props}]
|
||||
[rn/pressable
|
||||
{:style (style/container props)
|
||||
:on-press on-press}
|
||||
(if (or (= state :empty) (= state :disabled))
|
||||
[rn/view
|
||||
{:style (style/num-container props)
|
||||
|
||||
@@ -24,9 +24,7 @@
|
||||
{:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:padding 8
|
||||
:border-radius 12})
|
||||
|
||||
(defn title
|
||||
@@ -47,8 +45,13 @@
|
||||
theme))
|
||||
:container-style {:width 20 :height 20}})
|
||||
|
||||
(def left-side-container {:padding 2})
|
||||
(def right-side-container {:padding 4 :flex 1})
|
||||
(def left-side-container
|
||||
{:padding 2
|
||||
:padding-top 3})
|
||||
|
||||
(def right-side-container
|
||||
{:padding 4
|
||||
:flex 1})
|
||||
|
||||
(defn action-container
|
||||
[theme]
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
:blur-radius 10
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent}]
|
||||
|
||||
[rn/view {:style (style/content-container theme)}
|
||||
[rn/view {:style style/left-side-container}
|
||||
left]
|
||||
@@ -77,16 +76,19 @@
|
||||
:or {type :neutral icon :i/placeholder}}]
|
||||
(let [context-theme (or theme (quo.theme/get-theme))
|
||||
icon-name (case type
|
||||
:positive :i/correct
|
||||
:negative :i/incorrect
|
||||
:positive (if (= theme :light)
|
||||
:i/correct
|
||||
:i/correct-dark)
|
||||
:negative (if (= theme :light)
|
||||
:i/incorrect
|
||||
:i/incorrect-dark)
|
||||
:neutral icon)]
|
||||
[quo.theme/provider {:theme context-theme}
|
||||
[toast-container
|
||||
{:left (cond user
|
||||
[user-avatar/user-avatar user]
|
||||
icon-name
|
||||
[icon/icon icon-name (style/icon type context-theme)]
|
||||
)
|
||||
[icon/icon icon-name (style/icon type context-theme)])
|
||||
:title title
|
||||
:text text
|
||||
:right (if undo-duration
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
(fn [{:keys [disabled? theme blur? on-press type]} label]
|
||||
(fn [{:keys [disabled? theme blur? on-press on-long-press type]} label]
|
||||
(let [label-color (style/get-label-color disabled? theme blur?)
|
||||
background-color (style/toggle-background-color @pressed? blur? theme)]
|
||||
[rn/pressable
|
||||
@@ -24,6 +24,9 @@
|
||||
:on-press (fn []
|
||||
(when on-press
|
||||
(on-press label)))
|
||||
:on-long-press (fn []
|
||||
(when (fn? on-long-press)
|
||||
(on-long-press label)))
|
||||
:allow-multiple-presses? true
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)
|
||||
|
||||
@@ -6,18 +6,19 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn keyboard-item
|
||||
[{:keys [item type disabled? on-press blur? theme]}]
|
||||
[{:keys [item type disabled? on-press on-long-press blur? theme]}]
|
||||
[keyboard-key/view
|
||||
{:disabled? disabled?
|
||||
:on-press on-press
|
||||
:blur? blur?
|
||||
:theme theme
|
||||
:type type}
|
||||
{:disabled? disabled?
|
||||
:on-press on-press
|
||||
:on-long-press on-long-press
|
||||
:blur? blur?
|
||||
:theme theme
|
||||
:type type}
|
||||
item])
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete
|
||||
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete on-long-press-delete
|
||||
container-style]
|
||||
:or {left-action :none}}]
|
||||
[rn/view
|
||||
@@ -62,12 +63,13 @@
|
||||
:theme theme}]
|
||||
(if delete-key?
|
||||
[keyboard-item
|
||||
{:item :i/backspace
|
||||
:type :key
|
||||
:disabled? disabled?
|
||||
:on-press on-delete
|
||||
:blur? blur?
|
||||
:theme theme}]
|
||||
{:item :i/backspace
|
||||
:type :key
|
||||
:disabled? disabled?
|
||||
:on-press on-delete
|
||||
:on-long-press on-long-press-delete
|
||||
:blur? blur?
|
||||
:theme theme}]
|
||||
[keyboard-item])]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
{:accessibility-label :data-item
|
||||
:disabled (not icon-right?)
|
||||
:on-press on-press
|
||||
:style (merge container-style (style/container size card? blur? theme))}
|
||||
:style (merge (style/container size card? blur? theme) container-style)}
|
||||
[left-side props]
|
||||
(when (and (= :default status) (not= :small size))
|
||||
[right-side
|
||||
|
||||
@@ -2,9 +2,64 @@
|
||||
(:require [quo.components.share.share-qr-code.view :as share-qr-code]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def qr-label "Text shown below QR")
|
||||
|
||||
(def default-props
|
||||
{:qr-data qr-label
|
||||
:qr-image-uri "test-uri"
|
||||
:full-name "Default name"})
|
||||
|
||||
(def profile-props
|
||||
{:type :profile
|
||||
:profile-picture 123})
|
||||
|
||||
(def wallet-props {:networks '(:ethereum)})
|
||||
|
||||
(def text-press-event
|
||||
{:test-name "Text pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :press
|
||||
:callback-prop-key :on-text-press})
|
||||
|
||||
(def text-long-press-event
|
||||
{:test-name "Text long pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :long-press
|
||||
:callback-prop-key :on-text-long-press})
|
||||
|
||||
(def share-press-event
|
||||
{:test-name "Share button"
|
||||
:accessibility-label :link-to-profile
|
||||
:event-name :press
|
||||
:callback-prop-key :on-share-press})
|
||||
|
||||
(def multichain-press-event
|
||||
{:test-name "Multichain tab pressed"
|
||||
:accessibility-label :share-qr-code-multichain-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-multichain-press})
|
||||
|
||||
(def legacy-press-event
|
||||
{:test-name "Legacy tab pressed"
|
||||
:accessibility-label :share-qr-code-legacy-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-legacy-press})
|
||||
|
||||
(def settings-press-event
|
||||
{:test-name "Settings pressed"
|
||||
:accessibility-label :share-qr-code-settings
|
||||
:event-name :press
|
||||
:callback-prop-key :on-settings-press})
|
||||
|
||||
(defn render-share-qr-code
|
||||
[{share-qr-type :type :as props}]
|
||||
(let [component-rendered (h/render [share-qr-code/view {:type share-qr-type}])
|
||||
[props]
|
||||
;; NOTE: rendering the profile type first, so that the re-render is triggered.
|
||||
;; Passing a :key breaks it for some reason.
|
||||
(let [component-rendered (h/render [share-qr-code/view
|
||||
(merge
|
||||
default-props
|
||||
profile-props
|
||||
{:qr-data "initial-render"})])
|
||||
rerender-fn (h/get-rerender-fn component-rendered)
|
||||
share-qr-code (h/get-by-label-text :share-qr-code)]
|
||||
;; Fires on-layout since it's needed to render the content
|
||||
@@ -13,23 +68,52 @@
|
||||
|
||||
(h/describe "Share QR Code component"
|
||||
(h/describe "Renders share-qr-code component in all types"
|
||||
(let [qr-label "Text shown below QR"]
|
||||
(h/test "Profile"
|
||||
(render-share-qr-code {:type :profile
|
||||
:qr-data qr-label})
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
(h/test "Profile"
|
||||
(render-share-qr-code (merge default-props
|
||||
profile-props))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Wallet Legacy"
|
||||
(render-share-qr-code {:type :wallet-legacy
|
||||
:qr-data qr-label
|
||||
:emoji "👻"})
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
(h/test "Wallet Legacy"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :wallet
|
||||
:address :legacy}))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Wallet Multichain"
|
||||
(render-share-qr-code {:type :wallet-multichain
|
||||
:qr-data qr-label
|
||||
:emoji "👻"})
|
||||
(h/is-truthy (h/get-by-text qr-label)))))
|
||||
(h/test "Wallet multichain"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :wallet
|
||||
:address :multichain}))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Saved address legacy"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :saved-address
|
||||
:address :legacy}))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Saved address multichain"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :saved-address
|
||||
:address :multichain}))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Watched address legacy"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :watched-address
|
||||
:address :legacy}))
|
||||
(h/is-truthy (h/get-by-text qr-label)))
|
||||
|
||||
(h/test "Watched address multichain"
|
||||
(render-share-qr-code (merge default-props
|
||||
wallet-props
|
||||
{:type :watched-address
|
||||
:address :multichain}))
|
||||
(h/is-truthy (h/get-by-text qr-label))))
|
||||
|
||||
(h/describe "Fires all events for all types"
|
||||
(letfn [(test-fire-events [props test-seq]
|
||||
@@ -44,68 +128,86 @@
|
||||
|
||||
(h/describe "Profile"
|
||||
(test-fire-events
|
||||
{:type :profile}
|
||||
[{:test-name "Text pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :press
|
||||
:callback-prop-key :on-text-press}
|
||||
{:test-name "Text long pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :long-press
|
||||
:callback-prop-key :on-text-long-press}
|
||||
{:test-name "Share button"
|
||||
:accessibility-label :link-to-profile
|
||||
:event-name :press
|
||||
:callback-prop-key :on-share-press}]))
|
||||
(merge default-props
|
||||
profile-props)
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event]))
|
||||
|
||||
(h/describe "Wallet Legacy"
|
||||
(test-fire-events
|
||||
{:type :wallet-legacy :emoji "👽"}
|
||||
[{:test-name "Text pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :press
|
||||
:callback-prop-key :on-text-press}
|
||||
{:test-name "Text long pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :long-press
|
||||
:callback-prop-key :on-text-long-press}
|
||||
{:test-name "Share button pressed"
|
||||
:accessibility-label :link-to-profile
|
||||
:event-name :press
|
||||
:callback-prop-key :on-share-press}
|
||||
{:test-name "Legacy tab pressed"
|
||||
:accessibility-label :share-qr-code-legacy-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-legacy-press}
|
||||
{:test-name "Multichain tab pressed"
|
||||
:accessibility-label :share-qr-code-multichain-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-multichain-press}]))
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :wallet
|
||||
:address :legacy
|
||||
:emoji "👻"})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
multichain-press-event
|
||||
legacy-press-event]))
|
||||
|
||||
(h/describe "Wallet Multichain"
|
||||
(test-fire-events
|
||||
{:type :wallet-multichain :emoji "👽"}
|
||||
[{:test-name "Text pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :press
|
||||
:callback-prop-key :on-text-press}
|
||||
{:test-name "Text long pressed"
|
||||
:accessibility-label :share-qr-code-info-text
|
||||
:event-name :long-press
|
||||
:callback-prop-key :on-text-long-press}
|
||||
{:test-name "Share button pressed"
|
||||
:accessibility-label :link-to-profile
|
||||
:event-name :press
|
||||
:callback-prop-key :on-share-press}
|
||||
{:test-name "Legacy tab pressed"
|
||||
:accessibility-label :share-qr-code-legacy-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-legacy-press}
|
||||
{:test-name "Multichain tab pressed"
|
||||
:accessibility-label :share-qr-code-multichain-tab
|
||||
:event-name :press
|
||||
:callback-prop-key :on-multichain-press}
|
||||
{:test-name "Settings pressed"
|
||||
:accessibility-label :share-qr-code-settings
|
||||
:event-name :press
|
||||
:callback-prop-key :on-settings-press}])))))
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :wallet
|
||||
:address :multichain
|
||||
:emoji "👻"})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
legacy-press-event
|
||||
multichain-press-event
|
||||
settings-press-event]))
|
||||
|
||||
(h/describe "Saved Address Legacy"
|
||||
(test-fire-events
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :saved-address
|
||||
:address :legacy})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
legacy-press-event
|
||||
multichain-press-event]))
|
||||
|
||||
(h/describe "Saved Address Multichain"
|
||||
(test-fire-events
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :saved-address :address :multichain})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
legacy-press-event
|
||||
multichain-press-event
|
||||
settings-press-event]))
|
||||
|
||||
(h/describe "Watched Address Legacy"
|
||||
(test-fire-events
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :watched-address
|
||||
:address :legacy
|
||||
:emoji "👽"})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
legacy-press-event
|
||||
multichain-press-event]))
|
||||
|
||||
(h/describe "Watched Address Multichain"
|
||||
(test-fire-events
|
||||
(merge default-props
|
||||
wallet-props
|
||||
{:type :watched-address
|
||||
:address :multichain
|
||||
:emoji "👽"})
|
||||
[text-press-event
|
||||
text-long-press-event
|
||||
share-press-event
|
||||
legacy-press-event
|
||||
multichain-press-event
|
||||
settings-press-event])))))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
(ns quo.components.share.share-qr-code.schema
|
||||
(:require
|
||||
[quo.foundations.resources :as resources]))
|
||||
|
||||
(defn- valid-network?
|
||||
[network]
|
||||
(-> network resources/get-network boolean))
|
||||
|
||||
(def ?base
|
||||
[:map
|
||||
[:type [:enum :profile :wallet :saved-address :watched-address]]
|
||||
[:full-name :string]
|
||||
[:qr-image-uri :string]
|
||||
[:qr-data :string]
|
||||
[:on-text-press {:optional true} [:maybe fn?]]
|
||||
[:on-text-long-press {:optional true} [:maybe fn?]]
|
||||
[:on-share-press {:optional true} [:maybe fn?]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:unblur-on-android? {:optional true} [:maybe :boolean]]])
|
||||
|
||||
(def ?emoji :string)
|
||||
|
||||
(def ?profile
|
||||
[:map
|
||||
[:type [:= :profile]]
|
||||
[:profile-picture :schema.common/image-source]])
|
||||
|
||||
(def ?wallet
|
||||
[:map
|
||||
[:type [:= :wallet]]
|
||||
[:emoji {:optional true} [:maybe ?emoji]]])
|
||||
|
||||
(def ?address-multichain
|
||||
[:map
|
||||
[:address [:= :multichain]]
|
||||
[:on-settings-press {:optional true} fn?]])
|
||||
|
||||
(def ?address-base
|
||||
[:merge
|
||||
[:map
|
||||
[:networks [:sequential [:fn valid-network?]]]
|
||||
[:on-legacy-press {:optional true} [:maybe fn?]]
|
||||
[:on-multichain-press {:optional true} [:maybe fn?]]
|
||||
[:address [:enum :legacy :multichain]]]
|
||||
[:multi {:dispatch :address}
|
||||
[:multichain ?address-multichain]]])
|
||||
|
||||
(def ?saved-address
|
||||
[:map
|
||||
[:type [:= :saved-address]]
|
||||
[:on-settings-press {:optional true} fn?]])
|
||||
|
||||
(def ?watched-address
|
||||
[:map
|
||||
[:type [:= :watched-address]]
|
||||
[:emoji {:optional true} [:maybe ?emoji]]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:multi {:dispatch :type}
|
||||
[:profile [:merge ?base ?profile]]
|
||||
[:wallet [:merge ?base ?address-base ?wallet]]
|
||||
[:saved-address [:merge ?base ?address-base ?saved-address]]
|
||||
[:watched-address [:merge ?base ?address-base ?watched-address]]]]]
|
||||
:any])
|
||||
|
||||
@@ -106,3 +106,6 @@
|
||||
{:color (-> network-short-name
|
||||
(get-network-full-name :unknown)
|
||||
(colors/resolve-color nil))})
|
||||
|
||||
(def watched-account-icon
|
||||
{:margin-left 4})
|
||||
|
||||
@@ -3,19 +3,25 @@
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[quo.components.avatars.account-avatar.view :as account-avatar]
|
||||
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.gradient.gradient-cover.view :as gradient-cover]
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.share.qr-code.view :as qr-code]
|
||||
[quo.components.share.share-qr-code.schema :as component-schema]
|
||||
[quo.components.share.share-qr-code.style :as style]
|
||||
[quo.components.tabs.tab.view :as tab]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- header
|
||||
[{:keys [share-qr-type on-legacy-press on-multichain-press]}]
|
||||
[{:keys [on-legacy-press on-multichain-press address]}]
|
||||
[rn/view {:style style/header-container}
|
||||
[tab/view
|
||||
{:accessibility-label :share-qr-code-legacy-tab
|
||||
@@ -23,7 +29,7 @@
|
||||
:active-item-container-style style/header-tab-active
|
||||
:item-container-style style/header-tab-inactive
|
||||
:size 24
|
||||
:active (= :wallet-legacy share-qr-type)
|
||||
:active (= :legacy address)
|
||||
:on-press on-legacy-press}
|
||||
(i18n/label :t/legacy)]
|
||||
[rn/view {:style style/space-between-tabs}]
|
||||
@@ -33,7 +39,7 @@
|
||||
:active-item-container-style style/header-tab-active
|
||||
:item-container-style style/header-tab-inactive
|
||||
:size 24
|
||||
:active (= :wallet-multichain share-qr-type)
|
||||
:active (= :multichain address)
|
||||
:on-press on-multichain-press}
|
||||
(i18n/label :t/multichain)]])
|
||||
|
||||
@@ -121,77 +127,69 @@
|
||||
:on-press on-settings-press}
|
||||
:i/advanced]])
|
||||
|
||||
(defn- header-icon
|
||||
[{:keys [share-qr-type customization-color emoji profile-picture full-name]}]
|
||||
(case share-qr-type
|
||||
:profile [user-avatar/user-avatar
|
||||
{:size :small
|
||||
:status-indicator? false
|
||||
:profile-picture profile-picture
|
||||
:customization-color customization-color}]
|
||||
(:wallet :watched-address) [account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size 32}]
|
||||
:saved-address [wallet-user-avatar/wallet-user-avatar
|
||||
{:size :size-32
|
||||
:customization-color customization-color
|
||||
:full-name full-name}]
|
||||
nil))
|
||||
|
||||
(defn- share-qr-code
|
||||
[{:keys [share-qr-type qr-image-uri component-width customization-color full-name
|
||||
profile-picture emoji on-share-press]
|
||||
profile-picture emoji on-share-press address]
|
||||
:as props}]
|
||||
[:<>
|
||||
[rn/view {:style style/gradient-bg}
|
||||
[gradient-cover/view {:customization-color customization-color :height 463}]]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view
|
||||
{:style style/share-qr-container}
|
||||
[rn/view
|
||||
{:style style/share-qr-inner-container}
|
||||
[account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size 32}]
|
||||
[rn/view {:style style/share-qr-container}
|
||||
[rn/view {:style style/share-qr-inner-container}
|
||||
[header-icon props]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style {:margin-left 8}} full-name]]
|
||||
:style {:margin-left 8}} full-name]
|
||||
(when (= share-qr-type :watched-address)
|
||||
[icons/icon
|
||||
:i/reveal
|
||||
{:color colors/white-opa-40
|
||||
:container-style style/watched-account-icon}])]
|
||||
[share-button {:on-press on-share-press}]]
|
||||
(when (#{:wallet-legacy :wallet-multichain} share-qr-type)
|
||||
(when (not= share-qr-type :profile)
|
||||
[header props])
|
||||
[quo.theme/provider {:theme :light}
|
||||
[qr-code/view
|
||||
{:qr-image-uri qr-image-uri
|
||||
:size (style/qr-code-size component-width)
|
||||
:avatar (if (= share-qr-type :profile)
|
||||
:profile
|
||||
:wallet-account)
|
||||
:avatar (case share-qr-type
|
||||
:profile :profile
|
||||
(:watched-address :wallet) :wallet-account
|
||||
:saved-address :saved-address
|
||||
nil)
|
||||
:customization-color customization-color
|
||||
:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:emoji emoji}]]
|
||||
[rn/view {:style style/bottom-container}
|
||||
(case share-qr-type
|
||||
:profile [profile-bottom props]
|
||||
:wallet-legacy [wallet-legacy-bottom props]
|
||||
:wallet-multichain [wallet-multichain-bottom props]
|
||||
nil)]]])
|
||||
(if (= share-qr-type :profile)
|
||||
[profile-bottom props]
|
||||
(case address
|
||||
:legacy [wallet-legacy-bottom props]
|
||||
:multichain [wallet-multichain-bottom props]
|
||||
nil))]]])
|
||||
|
||||
(defn- view-internal
|
||||
"Receives the following properties:
|
||||
- type: :profile | :wallet-legacy | :wallet-multichain
|
||||
- qr-image-uri: Image source value.
|
||||
- qr-data: Text to show below the QR code.
|
||||
- on-text-press: Callback for the `qr-data` text.
|
||||
- on-text-long-press: Callback for the `qr-data` text.
|
||||
- on-share-press: Callback for the share button.
|
||||
- customization-color: Custom color for the QR code component.
|
||||
- unblur-on-android?: [Android only] disables blur for this component.
|
||||
|
||||
Depending on the `type`, different properties are accepted:
|
||||
`:profile`
|
||||
- full-name: User full name.
|
||||
- profile-picture: map ({:source image-source}) or any image source.
|
||||
`:wallet-legacy`
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- on-multichain-press: Callback for the multichain tab.
|
||||
`:wallet-multichain`
|
||||
- networks: A vector of network names as keywords (`[:ethereum, :my-net, ...]`).
|
||||
- on-settings-press: Callback for the settings button.
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- on-multichain-press: Callback for the multichain tab.
|
||||
|
||||
WARNING on Android:
|
||||
Sometimes while using a blur layer on top of another on Android, this component looks
|
||||
bad because of the `blur/view`, so we can set `unblur-on-android? true` to fix it.
|
||||
"
|
||||
[props]
|
||||
(reagent/with-let [component-width (reagent/atom nil)
|
||||
container-component [rn/view {:background-color style/overlay-color}]]
|
||||
@@ -207,5 +205,6 @@
|
||||
(assoc :component-width @component-width)
|
||||
(clojure.set/rename-keys {:type :share-qr-type}))]))]]))
|
||||
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
(ns quo.components.tags.collectible-tag.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[size options blur? theme]
|
||||
(let [hold? (= options :hold)]
|
||||
(merge {:background-color (if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme))
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-left 2
|
||||
:border-width (if hold? 1 0)
|
||||
:border-radius 0
|
||||
:border-color (colors/resolve-color :success theme)}
|
||||
(condp = size
|
||||
:size-24 {:height (if hold? 26 24)
|
||||
:padding-right 10
|
||||
:border-radius 8}
|
||||
:size-32 {:height (if hold? 34 32)
|
||||
:padding-right 12
|
||||
:border-radius 10}))))
|
||||
|
||||
(defn options-icon
|
||||
[size]
|
||||
(assoc
|
||||
(condp = size
|
||||
:size-24 {:right -8
|
||||
:top -8}
|
||||
:size-32 {:right -6
|
||||
:top -6})
|
||||
:position
|
||||
:absolute))
|
||||
|
||||
(defn collectible-img
|
||||
[size]
|
||||
(condp = size
|
||||
:size-24 {:width 20
|
||||
:height 20
|
||||
:margin-right 6
|
||||
:border-radius 6}
|
||||
:size-32 {:width 28
|
||||
:height 28
|
||||
:margin-right 8
|
||||
:border-radius 8}))
|
||||
|
||||
(defn label
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||
@@ -0,0 +1,70 @@
|
||||
(ns quo.components.tags.collectible-tag.view
|
||||
(:require
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.collectible-tag.style :as style]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:options {:optional true} [:maybe [:enum false :add :hold]]]
|
||||
[:size {:optional true} [:enum :size-24 :size-32]]
|
||||
[:blur? {:optional true} :boolean]
|
||||
[:theme :schema.common/theme]
|
||||
[:collectible-img-src [:or :int :string]]
|
||||
[:collectible-name :string]
|
||||
[:collectible-id :string]
|
||||
[:container-width :number]
|
||||
[:on-layout {:optional true} [:maybe fn?]]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(fn [{:keys [options size blur? theme collectible-img-src collectible-name collectible-id
|
||||
container-width on-layout]
|
||||
:or {size :size-24}}]
|
||||
[rn/view
|
||||
{:on-layout on-layout}
|
||||
[hole-view/hole-view
|
||||
{:holes (if options
|
||||
[{:x (- container-width
|
||||
(case size
|
||||
:size-24 10
|
||||
:size-32 12
|
||||
nil))
|
||||
:y (case size
|
||||
:size-24 -6
|
||||
:size-32 -4
|
||||
nil)
|
||||
:width 16
|
||||
:height 16
|
||||
:borderRadius 8}]
|
||||
[])}
|
||||
[rn/view {:style (style/container size options blur? theme)}
|
||||
[rn/image {:style (style/collectible-img size) :source collectible-img-src}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/label theme)}
|
||||
collectible-name]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:margin-left 5
|
||||
:style (style/label theme)}
|
||||
collectible-id]]]
|
||||
(when options
|
||||
[rn/view {:style (style/options-icon size)}
|
||||
[icons/icon (if (= options :hold) :i/hold :i/add-token)
|
||||
{:size 20
|
||||
:no-color true}]])]))
|
||||
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
(def username "Alisher account")
|
||||
(def empty-username "Account 1")
|
||||
(def ^:private theme :light)
|
||||
|
||||
(defn get-test-data
|
||||
[{:keys [type watch-only? empty-type? loading? no-metrics?]}]
|
||||
@@ -21,54 +22,54 @@
|
||||
(h/describe "Account_card tests"
|
||||
(h/test "Renders Default"
|
||||
(let [data (get-test-data {:type :default})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-text username))))
|
||||
|
||||
(h/test "Renders Watch-Only"
|
||||
(let [data (get-test-data {:type :watch-only
|
||||
:watch-only? true})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-text username))))
|
||||
|
||||
(h/test "Renders Add-Account"
|
||||
(let [data {:type :add-account}]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-label-text :add-account))))
|
||||
|
||||
(h/test "Renders Empty"
|
||||
(let [data (get-test-data {:type :empty
|
||||
:empty-type? true})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-text empty-username))))
|
||||
|
||||
(h/test "Renders Missing Keypair"
|
||||
(let [data (get-test-data {:type :missing-keypair})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-text username))))
|
||||
|
||||
(h/test "Add account on press fires correctly"
|
||||
(let [on-press (h/mock-fn)
|
||||
data {:type :add-account
|
||||
:on-press on-press}]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/fire-event :on-press (h/get-by-label-text :add-account))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "Renders component without metrics"
|
||||
(let [data (get-test-data {:type :default
|
||||
:no-metrics? true})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-falsy (h/query-by-label-text :metrics))))
|
||||
|
||||
(h/test "Renders loading state"
|
||||
(let [data (get-test-data {:type :default
|
||||
:loading? true})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-truthy (h/get-by-label-text :loading))))
|
||||
|
||||
(h/test "Renders loading state without metrics"
|
||||
(let [data (get-test-data {:type :default
|
||||
:no-metrics? true
|
||||
:loading? true})]
|
||||
(h/render [account-card/view data])
|
||||
(h/render-with-theme-provider [account-card/view data] theme)
|
||||
(h/is-falsy (h/query-by-label-text :metrics)))))
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
(ns quo.components.wallet.account-card.schema)
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:type {:optional true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:theme :schema.common/theme]
|
||||
[:metrics? {:optional true} [:maybe :boolean]]
|
||||
[:on-press {:optional true} [:maybe fn?]]])
|
||||
|
||||
(def ^:private ?amount
|
||||
[:map
|
||||
[:amount {:optional true} [:maybe :string]]])
|
||||
|
||||
(def ^:private ?card
|
||||
[:map
|
||||
[:balance {:optional true} [:maybe :string]]
|
||||
[:loading? {:optional true} [:maybe :boolean]]
|
||||
[:name {:optional true} [:maybe :string]]
|
||||
[:percentage-value {:optional true} [:maybe :string]]
|
||||
[:emoji {:optional true} [:maybe :string]]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:multi {:dispatch :type}
|
||||
[:default [:merge ?base ?amount ?card]]
|
||||
[:watch-only [:merge ?base ?amount ?card]]
|
||||
[:missing-keypair [:merge ?base ?amount ?card]]
|
||||
[:empty [:merge ?base ?card]]
|
||||
[:add-account ?base]]]]
|
||||
:any])
|
||||
@@ -4,13 +4,15 @@
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.account-card.properties :as properties]
|
||||
[quo.components.wallet.account-card.schema :as component-schema]
|
||||
[quo.components.wallet.account-card.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.customization-colors :as customization-colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[reagent.core :as reagent]))
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- loading-view
|
||||
[{:keys [customization-color type theme metrics?]}]
|
||||
@@ -183,4 +185,6 @@
|
||||
:add-account [add-account-view props]
|
||||
nil))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -3,92 +3,104 @@
|
||||
[quo.core :as quo]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def ^:private theme :light)
|
||||
|
||||
(h/describe "account origin tests"
|
||||
(h/test "component renders"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(-> (h/expect (h/get-by-translation-text :t/origin))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "recovery phrase icon is visible when :type is :recovery-phrase"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :recovery-phrase-icon)))
|
||||
|
||||
(h/test "recovery phrase icon is visible when :type is :recovery-phrase"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :recovery-phrase-icon)))
|
||||
|
||||
(h/test "private-key-icon is visible when :type is :private-key"
|
||||
(h/render [quo/account-origin
|
||||
{:type :private-key
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :private-key
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :private-key-icon)))
|
||||
|
||||
(h/test "derivation-path-icon is visible when :type is :default-keypair"
|
||||
(h/render [quo/account-origin
|
||||
{:type :default-keypair
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :default-keypair
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :derivation-path-icon)))
|
||||
|
||||
(h/test "derivation-path-icon is visible when :type is :recovery-phrase"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :derivation-path-icon)))
|
||||
|
||||
(h/test "on-device text is visible when :stored is :on-device"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-device
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-device
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(-> (h/expect (h/get-by-translation-text :t/on-device))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "on-keycard text is visible when :stored is :on-keycard"
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"}]
|
||||
theme)
|
||||
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "on-press is called when :type is :recovery-phrase"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"
|
||||
:on-press on-press}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :recovery-phrase
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"
|
||||
:on-press on-press}]
|
||||
theme)
|
||||
(h/fire-event :press (h/query-by-label-text :derivation-path-button))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "on-press is called when :type is :default-keypair"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [quo/account-origin
|
||||
{:type :default-keypair
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"
|
||||
:on-press on-press}])
|
||||
(h/render-with-theme-provider [quo/account-origin
|
||||
{:type :default-keypair
|
||||
:stored :on-keycard
|
||||
:derivation-path "m / 44’ / 60’ / 0’ / 0’ / 2"
|
||||
:user-name "Test Name"
|
||||
:on-press on-press}]
|
||||
theme)
|
||||
(h/fire-event :press (h/query-by-label-text :derivation-path-button))
|
||||
(h/was-called on-press))))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(ns quo.components.wallet.account-origin.schema)
|
||||
|
||||
(def ^:private ?base
|
||||
[:map
|
||||
[:type {:optional true} [:enum :default-keypair :recovery-phrase :private-key]]
|
||||
[:stored {:optional true} [:enum :on-device :on-keycard]]
|
||||
[:theme :schema.common/theme]])
|
||||
|
||||
(def ^:private ?default-keypair
|
||||
[:map
|
||||
[:user-name {:optional true} [:maybe :string]]
|
||||
[:profile-picture {:optional true} [:maybe [:or :schema.common/image-source :string]]]
|
||||
[:derivation-path {:optional true} [:maybe :string]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]])
|
||||
|
||||
(def ^:private ?recovery-phrase
|
||||
[:map
|
||||
[:derivation-path {:optional true} [:maybe :string]]
|
||||
[:on-press {:optional true} [:maybe fn?]]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:multi {:dispatch :type}
|
||||
[:default-keypair [:merge ?base ?default-keypair]]
|
||||
[:recovery-phrase [:merge ?base ?recovery-phrase]]
|
||||
[:private-key ?base]]]]
|
||||
:any])
|
||||
@@ -3,10 +3,12 @@
|
||||
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.account-origin.schema :as component-schema]
|
||||
[quo.components.wallet.account-origin.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- row-title
|
||||
@@ -107,14 +109,5 @@
|
||||
[card-view theme derivation-path secondary-color on-press])]))
|
||||
|
||||
(def view
|
||||
"Create an account-origin UI component.
|
||||
| key | values |
|
||||
| ----------------------|------------------------------------------------|
|
||||
| :type | :default-keypair :recovery-phrase :private-key
|
||||
| :stored | :on-device :on-keycard
|
||||
| :profile-picture | image source
|
||||
| :customization-color | profile color
|
||||
| :derivation-path | string
|
||||
| :user-name | string
|
||||
| :on-press | function"
|
||||
(quo.theme/with-theme view-internal))
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns quo.components.wallet.account-overview.schema)
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:account-name {:optional true} [:maybe :string]]
|
||||
[:currency-change {:optional true} [:maybe :string]]
|
||||
[:current-value {:optional true} [:maybe :string]]
|
||||
[:percentage-change {:optional true} [:maybe :string]]
|
||||
[:time-frame-string {:optional true} [:maybe :string]]
|
||||
[:time-frame-to-string {:optional true} [:maybe :string]]
|
||||
[:state {:optional true} [:enum :default :loading]]
|
||||
[:metrics {:optional true} [:enum :negative :positive]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:account {:optional true} [:enum :default :watched-address]]
|
||||
[:time-frame {:optional true}
|
||||
[:enum :one-week :one-month :three-months :one-year :all-time :custom]]]]]
|
||||
:any])
|
||||
@@ -2,10 +2,12 @@
|
||||
(:require
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.account-overview.schema :as component-schema]
|
||||
[quo.components.wallet.account-overview.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- loading-state
|
||||
@@ -129,16 +131,5 @@
|
||||
[numeric-changes percentage-change currency-change customization-color theme up?])]])]))
|
||||
|
||||
(def view
|
||||
"Create a account-overview UI component.
|
||||
| key | description |
|
||||
| -------------|-------------|
|
||||
| `:account-name` | A value representing the account name (default `nil`)
|
||||
| `:account` | A value that represents if the account is a `:watched-address` or a `:default` account. (default `nil`)
|
||||
| `:time-frame` | A value that represents the type of the timeframe, Can be from a preset of time frames. `[:1-week :1-month :3-months :1-year :custom]` (default `nil`) if custom is set, We expect a start time and if there's a space between two times that are in `time-frame-string` we'll split them with an arrow to the right icon
|
||||
| `:loading?` | A value that indicates that component is loading data. (default `nil`)
|
||||
| `:metrics` | A value that indicates if the account value have increased can be `:positive` or `:negative` (default `nil`)
|
||||
| `:time-frame-string` | A value representing time frame string. (default `nil`)
|
||||
| `:current-value` | A value representing the current value of the selected account. (default `nil`)
|
||||
| `:currency-change` | A value representing the change of the value of the selected account in the selected currency. (default `nil`)
|
||||
| `:percentage-change` | A value representing the change of the value of the selected account in percentage relative to it's previous value. (default `nil`)"
|
||||
(quo.theme/with-theme view-internal))
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -42,18 +42,22 @@
|
||||
(render [account-permissions/view
|
||||
{:account account
|
||||
:token-details [{:token "SNT"
|
||||
:amount "100"}]}])
|
||||
:amount "100"
|
||||
:type :token}]}])
|
||||
(h/is-truthy (h/get-by-text "100 SNT")))
|
||||
|
||||
(h/test "render with multiple token details"
|
||||
(render [account-permissions/view
|
||||
{:account account
|
||||
:token-details [{:token "SNT"
|
||||
:amount "100"}
|
||||
:amount "100"
|
||||
:type :token}
|
||||
{:token "ETH"
|
||||
:amount "18"}
|
||||
:amount "18"
|
||||
:type :token}
|
||||
{:token "BTM"
|
||||
:amount "1000"}]}])
|
||||
:amount "1000"
|
||||
:type :token}]}])
|
||||
(h/is-truthy (h/get-by-text "100 SNT"))
|
||||
(h/is-truthy (h/get-by-text "18 ETH"))
|
||||
(h/is-truthy (h/get-by-text "1000 BTM")))
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
(ns quo.components.wallet.account-permissions.schema
|
||||
(:require [quo.components.wallet.required-tokens.view :as required-tokens]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:account
|
||||
[:map
|
||||
[:name [:maybe :string]]
|
||||
[:address [:maybe :string]]
|
||||
[:emoji [:maybe :string]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]
|
||||
[:token-details {:optional true} [:maybe [:sequential required-tokens/?schema]]]
|
||||
[:keycard? {:optional true} [:maybe :boolean]]
|
||||
[:checked? {:optional true} [:maybe :boolean]]
|
||||
[:disabled? {:optional true} [:maybe :boolean]]
|
||||
[:on-change {:optional true} [:maybe fn?]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
@@ -4,6 +4,7 @@
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.selectors.selectors.view :as selectors]
|
||||
[quo.components.wallet.account-permissions.schema :as component-schema]
|
||||
[quo.components.wallet.account-permissions.style :as style]
|
||||
[quo.components.wallet.address-text.view :as address-text]
|
||||
[quo.components.wallet.required-tokens.view :as required-tokens]
|
||||
@@ -13,26 +14,6 @@
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:account
|
||||
[:map {:closed true}
|
||||
[:name [:maybe :string]]
|
||||
[:address [:maybe :string]]
|
||||
[:emoji [:maybe :string]]
|
||||
[:customization-color [:maybe [:or :string :keyword]]]]]
|
||||
[:token-details {:optional true} [:maybe [:vector required-tokens/?schema]]]
|
||||
[:keycard? {:optional true} [:maybe :boolean]]
|
||||
[:checked? {:optional true} [:maybe :boolean]]
|
||||
[:disabled? {:optional true} [:maybe :boolean]]
|
||||
[:on-change {:optional true} [:maybe fn?]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
(defn- token-details-section
|
||||
[tokens]
|
||||
(when tokens
|
||||
@@ -47,14 +28,16 @@
|
||||
(i18n/label :t/no-relevant-tokens)]
|
||||
|
||||
(let [token-length (dec (count tokens))]
|
||||
(map-indexed (fn [idx {:keys [token amount]}]
|
||||
(map-indexed (fn [idx {:keys [type token amount collectible-name collectible-img-src]}]
|
||||
^{:key idx}
|
||||
[required-tokens/view
|
||||
{:container-style style/token-and-text
|
||||
:type :token
|
||||
:amount amount
|
||||
:token token
|
||||
:divider? (not= token-length idx)}])
|
||||
{:container-style style/token-and-text
|
||||
:type type
|
||||
:amount amount
|
||||
:token token
|
||||
:collectible-img-src collectible-img-src
|
||||
:collectible-name collectible-name
|
||||
:divider? (not= token-length idx)}])
|
||||
tokens)))]]))
|
||||
|
||||
(defn- view-internal
|
||||
@@ -93,4 +76,4 @@
|
||||
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
(ns quo.components.wallet.address-text.schema)
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:address {:optional true} [:maybe :string]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:format {:optional true} [:enum :short :long]]
|
||||
[:theme :schema.common/theme]
|
||||
[:networks {:optional true}
|
||||
[:maybe [:sequential [:map [:name :keyword] [:short-name :string]]]]]]]]
|
||||
:any])
|
||||
@@ -1,8 +1,10 @@
|
||||
(ns quo.components.wallet.address-text.view
|
||||
(:require [quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.address-text.schema :as component-schema]
|
||||
[quo.components.wallet.address-text.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[schema.core :as schema]
|
||||
[utils.address :as utils]))
|
||||
|
||||
(defn- colored-network-text
|
||||
@@ -28,4 +30,6 @@
|
||||
(into [text/text] network-text-xf $)
|
||||
(conj $ address-text))))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
(ns quo.components.wallet.amount-input.component-spec
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[quo.components.wallet.amount-input.view :as amount-input]
|
||||
[quo.foundations.colors :as colors]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- render
|
||||
[component]
|
||||
(h/render-with-theme-provider component :light))
|
||||
|
||||
(h/describe "Amount input component"
|
||||
(h/test "Renders with default value"
|
||||
(let [text-expected 0]
|
||||
(render [amount-input/view {:init-value text-expected}])
|
||||
(h/is-truthy (h/query-by-label-text :amount-input))
|
||||
(h/is-equal (oops/oget (h/get-by-label-text :amount-input) "props" "value")
|
||||
(str text-expected))))
|
||||
|
||||
(h/test "When the value = minimum dec button is disabled"
|
||||
(render [amount-input/view
|
||||
{:init-value 0
|
||||
:min-value 0}])
|
||||
(h/is-truthy
|
||||
(oops/oget (h/get-by-label-text :amount-input-dec-button) "props" "accessibilityState" "disabled")))
|
||||
|
||||
(h/test "When the value = maximum inc button is disabled"
|
||||
(render [amount-input/view
|
||||
{:init-value 100
|
||||
:max-value 100}])
|
||||
(h/is-truthy
|
||||
(oops/oget (h/get-by-label-text :amount-input-inc-button) "props" "accessibilityState" "disabled")))
|
||||
|
||||
(h/test "Renders the error state"
|
||||
(render [amount-input/view {:status :error}])
|
||||
(h/is-equal (colors/resolve-color :danger :light)
|
||||
(oops/oget (h/get-by-label-text :amount-input) "props" "style" "color")))
|
||||
|
||||
(h/test "on-change-text function is fired"
|
||||
(let [on-change-text (h/mock-fn)]
|
||||
(render [amount-input/view {:on-change-text on-change-text}])
|
||||
(h/fire-event :change-text (h/get-by-label-text :amount-input) "100")
|
||||
(h/was-called on-change-text))))
|
||||
@@ -0,0 +1,21 @@
|
||||
(ns quo.components.wallet.amount-input.schema)
|
||||
|
||||
(def return-key-types
|
||||
[:enum :done :go :next :search :send :none :previous :default
|
||||
:emergency-call :google :join :route :yahoo])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:status {:optional true} [:maybe [:enum :default :error]]]
|
||||
[:theme :schema.common/theme]
|
||||
[:on-change-text {:optional true} [:maybe fn?]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:auto-focus? {:optional true} [:maybe :boolean]]
|
||||
[:min-value {:optional true} [:maybe :int]]
|
||||
[:max-value {:optional true} [:maybe :int]]
|
||||
[:return-key-type {:optional true} [:maybe return-key-types]]
|
||||
[:init-value {:optional true} [:maybe :int]]]]]
|
||||
:any])
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns quo.components.wallet.amount-input.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(def input-container {:flex 1})
|
||||
|
||||
(defn input-text
|
||||
[theme type]
|
||||
{:padding 0
|
||||
:color (if (= type :error)
|
||||
(colors/resolve-color :danger theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme))})
|
||||
@@ -0,0 +1,81 @@
|
||||
(ns quo.components.wallet.amount-input.view
|
||||
(:require
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.amount-input.schema :as amount-input.schema]
|
||||
[quo.components.wallet.amount-input.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- amount-button
|
||||
[{:keys [theme accessibility-label disabled? icon on-press]}]
|
||||
[button/button
|
||||
{:icon-only? true
|
||||
:theme theme
|
||||
:disabled? disabled?
|
||||
:type :outline
|
||||
:accessibility-label accessibility-label
|
||||
:size 32
|
||||
:on-press on-press}
|
||||
icon])
|
||||
|
||||
(defn- process-amount
|
||||
[input-value min-value max-value]
|
||||
(let [parsed-input-value (parse-double input-value)]
|
||||
(cond
|
||||
(nil? parsed-input-value) min-value
|
||||
(>= input-value max-value) max-value
|
||||
(<= input-value min-value) min-value
|
||||
:else parsed-input-value)))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [init-value]}]
|
||||
(let [init-value (or init-value 0)
|
||||
value (reagent/atom init-value)
|
||||
on-dec-press #(swap! value dec)
|
||||
on-inc-press #(swap! value inc)]
|
||||
(fn [{:keys [theme status min-value max-value auto-focus?
|
||||
return-key-type container-style on-change-text]}]
|
||||
(let [min-value (or min-value 0)
|
||||
max-value (or max-value 999999999)]
|
||||
[rn/view
|
||||
{:style (merge style/container container-style)}
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:accessibility-label :amount-input-dec-button
|
||||
:icon :i/remove
|
||||
:on-press on-dec-press
|
||||
:disabled? (>= min-value @value)}]
|
||||
[rn/view {:style style/input-container}
|
||||
[rn/text-input
|
||||
{:style
|
||||
(text/text-style
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:align :center
|
||||
:style (style/input-text theme (or status :default))})
|
||||
:accessibility-label :amount-input
|
||||
:editable true
|
||||
:auto-focus (or auto-focus? false)
|
||||
:value (str @value)
|
||||
:keyboard-appearance (quo.theme/theme-value :light :dark theme)
|
||||
:return-key-type (or return-key-type :done)
|
||||
:input-mode :numeric
|
||||
:on-change-text (fn [input-value]
|
||||
(let [processed-amount (process-amount input-value min-value max-value)]
|
||||
(reset! value processed-amount)
|
||||
(when on-change-text
|
||||
(on-change-text processed-amount))
|
||||
(reagent/flush)))}]] ; Fixes the input flickering issue when typing.
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:icon :i/add
|
||||
:accessibility-label :amount-input-inc-button
|
||||
:on-press on-inc-press
|
||||
:disabled? (>= @value max-value)}]]))))
|
||||
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal amount-input.schema/?schema)))
|
||||
@@ -1,99 +1,115 @@
|
||||
(ns quo.components.wallet.confirmation-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
|
||||
(defn- get-test-data
|
||||
[{:keys [state network]
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:counter (reagent/atom 0)
|
||||
{:counter 0
|
||||
:total-box 85
|
||||
:progress-value "10"
|
||||
:progress-value 10
|
||||
:network network
|
||||
:state state
|
||||
:customization-color :blue})
|
||||
|
||||
(h/describe "Confirmation Progress"
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/render-with-theme-provider [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box))))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box))))
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render-with-theme-provider
|
||||
[quo/confirmation-propgress
|
||||
(get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
(ns quo.components.wallet.confirmation-progress.schema)
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:total-box {:optional true} [:maybe :int]]
|
||||
[:counter {:optional true} [:maybe :int]]
|
||||
[:progress-value {:optional true} [:maybe :int]]
|
||||
[:network {:optional true} [:enum :mainnet :optimism :arbitrum]]
|
||||
[:state {:optional true} [:enum :pending :sending :confirmed :finalising :finalized :error]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
@@ -1,8 +1,10 @@
|
||||
(ns quo.components.wallet.confirmation-progress.view
|
||||
(:require [quo.components.wallet.confirmation-progress.style :as style]
|
||||
(:require [quo.components.wallet.confirmation-progress.schema :as component-schema]
|
||||
[quo.components.wallet.confirmation-progress.style :as style]
|
||||
[quo.components.wallet.progress-bar.view :as progress-box]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(def ^:private max-progress 100)
|
||||
(def ^:private min-progress 0)
|
||||
@@ -66,4 +68,6 @@
|
||||
(:arbitrum :optimism) [progress-boxes-sidenet props]
|
||||
nil))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
[quo.components.wallet.keypair.view :as keypair]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def ^:private theme :light)
|
||||
|
||||
(def accounts
|
||||
[{:account-props {:customization-color :turquoise
|
||||
:size 32
|
||||
@@ -23,41 +25,45 @@
|
||||
|
||||
(h/describe "Wallet: Keypair"
|
||||
(h/test "Default keypair title renders"
|
||||
(h/render [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :default-keypair
|
||||
:stored :on-device
|
||||
:action :selector
|
||||
:details default-details}])
|
||||
(h/render-with-theme-provider [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :default-keypair
|
||||
:stored :on-device
|
||||
:action :selector
|
||||
:details default-details}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :title)))
|
||||
|
||||
(h/test "On device renders"
|
||||
(h/render [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-device
|
||||
:action :selector
|
||||
:details other-details}])
|
||||
(h/render-with-theme-provider [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-device
|
||||
:action :selector
|
||||
:details other-details}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :details)))
|
||||
|
||||
(h/test "Selector action renders"
|
||||
(h/render [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-keycard
|
||||
:action :selector
|
||||
:details other-details}])
|
||||
(h/render-with-theme-provider [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-keycard
|
||||
:action :selector
|
||||
:details other-details}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :radio-on)))
|
||||
|
||||
(h/test "Options action renders"
|
||||
(h/render [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-keycard
|
||||
:action :options
|
||||
:details other-details}])
|
||||
(h/render-with-theme-provider [keypair/view
|
||||
{:accounts accounts
|
||||
:customization-color :blue
|
||||
:type :other
|
||||
:stored :on-keycard
|
||||
:action :options
|
||||
:details other-details}]
|
||||
theme)
|
||||
(h/is-truthy (h/get-by-label-text :options-button))))
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
(h/describe "Wallet: Network Amount"
|
||||
(h/test "Amount renders"
|
||||
(h/render [network-amount/view
|
||||
{:amount "5.123"
|
||||
:token :eth}])
|
||||
(h/render-with-theme-provider
|
||||
[network-amount/view
|
||||
{:amount "5.123"
|
||||
:token :eth}])
|
||||
(h/is-truthy (h/get-by-text "5.123 ETH"))))
|
||||
|
||||
@@ -5,7 +5,18 @@
|
||||
[quo.components.utilities.token.view :as token]
|
||||
[quo.components.wallet.network-amount.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:amount {:optional true} [:maybe :string]]
|
||||
[:token {:optional true} [:or :keyword :string]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [amount token theme]}]
|
||||
@@ -19,4 +30,4 @@
|
||||
[rn/view
|
||||
{:style (style/divider theme)}]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view (quo.theme/with-theme (schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -4,37 +4,37 @@
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Wallet: Network Bridge"
|
||||
(h/test "Amount renders"
|
||||
(h/render [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :ethereum
|
||||
:status :default}])
|
||||
(h/test "Amount render-with-theme-providers"
|
||||
(h/render-with-theme-provider [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :ethereum
|
||||
:status :default}])
|
||||
(h/is-truthy (h/get-by-text "50 SNT")))
|
||||
|
||||
(h/test "Network label renders"
|
||||
(h/render [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :default}])
|
||||
(h/test "Network label render"
|
||||
(h/render-with-theme-provider [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :default}])
|
||||
(h/is-truthy (h/get-by-text "Optimism")))
|
||||
|
||||
(h/test "Locked state"
|
||||
(h/render [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :locked}])
|
||||
(h/render-with-theme-provider [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :locked}])
|
||||
(h/is-truthy (h/get-by-label-text :lock)))
|
||||
|
||||
(h/test "Loading state"
|
||||
(h/render [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :loading}])
|
||||
(h/render-with-theme-provider [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :loading}])
|
||||
(h/is-truthy (h/get-by-label-text :loading)))
|
||||
|
||||
(h/test "Disabled state"
|
||||
(h/render [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :disabled}])
|
||||
(h/render-with-theme-provider [network-bridge/view
|
||||
{:amount "50 SNT"
|
||||
:network :optimism
|
||||
:status :disabled}])
|
||||
(h/has-style (h/get-by-label-text :container) {:opacity 0.3})))
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn network-bridge-add
|
||||
[{:keys [network state theme container-style on-press]}]
|
||||
@@ -24,6 +25,22 @@
|
||||
(= network :ethereum) "Mainnet"
|
||||
:else (string/capitalize (name network))))
|
||||
|
||||
(def ^:private ?network-bridge-status
|
||||
[:enum :add :loading :locked :disabled :default])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:theme :schema.common/theme]
|
||||
[:network {:optional true} [:maybe :keyword]]
|
||||
[:status {:optional true} [:maybe ?network-bridge-status]]
|
||||
[:amount {:optional true} [:maybe :string]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:on-press {:optional true} [:maybe fn?]]]]]
|
||||
:any])
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [theme network status amount container-style on-press] :as args}]
|
||||
(if (= status :add)
|
||||
@@ -62,4 +79,6 @@
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
(network->text network)]]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns quo.components.wallet.network-routing.component-spec
|
||||
(:require [oops.core :as oops]
|
||||
[quo.components.wallet.network-routing.view :as network-routing]
|
||||
quo.theme
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
@@ -11,17 +12,18 @@
|
||||
:requesting-data? false
|
||||
:on-amount-selected (fn [_new-amount _network-idx] nil)}]
|
||||
(h/test "Renders Default"
|
||||
(h/render [network-routing/view default-props])
|
||||
(h/render-with-theme-provider [network-routing/view default-props])
|
||||
(h/is-truthy (h/get-by-label-text :network-routing)))
|
||||
|
||||
(h/test "Renders bars inside"
|
||||
(let [component (h/render [network-routing/view default-props])
|
||||
(let [component (h/render-with-theme-provider [network-routing/view default-props])
|
||||
rerender-fn #((oops/oget component "rerender") (reagent/as-element %))
|
||||
component (h/get-by-label-text :network-routing)]
|
||||
;; Fires on-layout callback since the total width is required
|
||||
(h/fire-event :layout component #js {:nativeEvent #js {:layout #js {:width 1000}}})
|
||||
;; Update props to trigger rerender, otherwise it won't be updated
|
||||
(rerender-fn [network-routing/view (assoc default-props :requesting-data? true)])
|
||||
(rerender-fn [quo.theme/provider {:theme :light}
|
||||
[network-routing/view (assoc default-props :requesting-data? true)]])
|
||||
;; Check number of networks rendered
|
||||
(->> (js->clj (h/query-all-by-label-text :network-routing-bar))
|
||||
(count)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]
|
||||
[utils.number]))
|
||||
|
||||
(def ^:private timeouts (atom {}))
|
||||
@@ -172,6 +173,22 @@
|
||||
[rn/view {:style (style/max-limit-bar-background network-name)}]
|
||||
[dashed-line network-name]])]))))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:networks {:optional true}
|
||||
[:maybe
|
||||
[:sequential
|
||||
[:map
|
||||
[:amount :int]
|
||||
[:max-amount :int]
|
||||
[:network-name [:or :string :keyword]]]]]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [networks container-style theme] :as params}]
|
||||
(reagent/with-let [total-width (reagent/atom nil)]
|
||||
@@ -186,4 +203,6 @@
|
||||
(doseq [[_ living-timeout] @timeouts]
|
||||
(js/clearTimeout living-timeout)))))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -2,7 +2,19 @@
|
||||
(:require
|
||||
[quo.components.wallet.progress-bar.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:theme :schema.common/theme]
|
||||
[:progressed-value {:optional true} [:maybe [:or :string :int]]]
|
||||
[:full-width? {:optional true} [:maybe :boolean]]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [full-width?] :as props}]
|
||||
@@ -12,4 +24,6 @@
|
||||
(when full-width?
|
||||
[rn/view {:style (style/progressed-bar props)}])])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
[:amount {:optional true} [:maybe [:or :string :int]]]
|
||||
[:token {:optional true} [:maybe :string]]
|
||||
[:token-img-src {:optional true} [:maybe :schema.common/image-source]]
|
||||
[:collectible-img-src {:optional true} :schema.common/image-source]
|
||||
[:collectible-img-src {:optional true} [:maybe :schema.common/image-source]]
|
||||
[:collectible-name {:optional true} [:maybe :string]]
|
||||
[:divider? {:optional true} [:maybe :boolean]]
|
||||
[:theme :schema.common/theme]
|
||||
|
||||
@@ -13,48 +13,49 @@
|
||||
|
||||
(h/describe "Wallet: Summary Info"
|
||||
(h/test "Type of `status-account` title renders"
|
||||
(h/render [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/render-with-theme-provider [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/is-truthy (h/get-by-text "Collectibles vault")))
|
||||
|
||||
(h/test "Type of `user` title renders"
|
||||
(h/render [summary-info/view
|
||||
{:type :user
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props {:full-name "M L"
|
||||
:status-indicator? false
|
||||
:size :small
|
||||
:customization-color :blue
|
||||
:name "Mark Libot"
|
||||
:address "0x0ah...78b"
|
||||
:status-account (merge status-account-props {:size 16})}}])
|
||||
(h/render-with-theme-provider [summary-info/view
|
||||
{:type :user
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props {:full-name "M L"
|
||||
:status-indicator? false
|
||||
:size :small
|
||||
:customization-color :blue
|
||||
:name "Mark Libot"
|
||||
:address "0x0ah...78b"
|
||||
:status-account (merge status-account-props
|
||||
{:size 16})}}])
|
||||
(h/is-truthy (h/get-by-text "Mark Libot"))
|
||||
(h/is-truthy (h/get-by-text "Collectibles vault")))
|
||||
|
||||
(h/test "Networks true render"
|
||||
(h/render [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/render-with-theme-provider [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? true
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/is-truthy (h/get-by-label-text :networks)))
|
||||
|
||||
(h/test "Networks false render"
|
||||
(h/render [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? false
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/render-with-theme-provider [summary-info/view
|
||||
{:type :status-account
|
||||
:networks? false
|
||||
:values {:ethereum 150
|
||||
:optimism 50
|
||||
:arbitrum 25}
|
||||
:account-props status-account-props}])
|
||||
(h/is-null (h/query-by-label-text :networks))))
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- network-amount
|
||||
[{:keys [network amount divider? theme]}]
|
||||
@@ -51,6 +52,18 @@
|
||||
:amount (str (:amount arbitrum) " " (or (:token-symbol arbitrum) "ARB"))
|
||||
:theme theme}])]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:theme :schema.common/theme]
|
||||
[:type [:enum :status-account :saved-account :account :user]]
|
||||
[:account-props {:optional true} [:maybe :map]]
|
||||
[:networks? {:optional true} [:maybe :boolean]]
|
||||
[:values {:optional true} [:maybe :map]]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [theme type account-props networks? values]}]
|
||||
[rn/view
|
||||
@@ -91,4 +104,6 @@
|
||||
{:style (style/line-divider theme)}]
|
||||
[networks values theme]])])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns quo.components.wallet.transaction-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- get-test-data
|
||||
@@ -8,193 +7,228 @@
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:title "Title"
|
||||
:tag-name "Doodle"
|
||||
:tag-number "120"
|
||||
:tag-number 120
|
||||
:network network
|
||||
:customization-color :blue
|
||||
:networks [{:network :mainnet
|
||||
:state state
|
||||
:counter (reagent/atom 0)
|
||||
:counter 0
|
||||
:total-box 85
|
||||
:progress 30
|
||||
:epoch-number "123"}
|
||||
{:network :optimism
|
||||
:state state
|
||||
:progress "50"
|
||||
:progress 50
|
||||
:epoch-number "123"}
|
||||
{:network :arbitrum
|
||||
:state state
|
||||
:progress "30"
|
||||
:progress 30
|
||||
:epoch-number "123"}]
|
||||
:on-press (fn []
|
||||
(js/alert "Transaction progress item pressed"))})
|
||||
|
||||
(h/describe "Transaction Progress"
|
||||
(h/test "component renders without props"
|
||||
(h/render [quo/transaction-progress])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :sending})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :confirmed})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalising})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalized})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :error})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "mainnet progress box is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "arbitrum-optimism progress box is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "arbitrum progress box is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "optimism progress box is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "title is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "context tag is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/render-with-theme-provider
|
||||
[quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag))))
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
quo.components.tabs.account-selector
|
||||
quo.components.tabs.segmented-tab
|
||||
quo.components.tabs.tabs.view
|
||||
quo.components.tags.collectible-tag.view
|
||||
quo.components.tags.context-tag.view
|
||||
quo.components.tags.network-tags.view
|
||||
quo.components.tags.number-tag.view
|
||||
@@ -156,6 +157,7 @@
|
||||
quo.components.wallet.account-overview.view
|
||||
quo.components.wallet.account-permissions.view
|
||||
quo.components.wallet.address-text.view
|
||||
quo.components.wallet.amount-input.view
|
||||
quo.components.wallet.confirmation-progress.view
|
||||
quo.components.wallet.keypair.view
|
||||
quo.components.wallet.network-amount.view
|
||||
@@ -387,6 +389,7 @@
|
||||
(def account-selector quo.components.tabs.account-selector/account-selector)
|
||||
|
||||
;;;; Tags
|
||||
(def collectible-tag quo.components.tags.collectible-tag.view/view)
|
||||
(def context-tag quo.components.tags.context-tag.view/view)
|
||||
(def network-tags quo.components.tags.network-tags.view/view)
|
||||
(def number-tag quo.components.tags.number-tag.view/view)
|
||||
@@ -414,6 +417,7 @@
|
||||
(def account-overview quo.components.wallet.account-overview.view/view)
|
||||
(def account-permissions quo.components.wallet.account-permissions.view/view)
|
||||
(def address-text quo.components.wallet.address-text.view/view)
|
||||
(def amount-input quo.components.wallet.amount-input.view/view)
|
||||
(def confirmation-propgress quo.components.wallet.confirmation-progress.view/view)
|
||||
(def keypair quo.components.wallet.keypair.view/view)
|
||||
(def network-amount quo.components.wallet.network-amount.view/view)
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
quo.components.wallet.account-origin.component-spec
|
||||
quo.components.wallet.account-overview.component-spec
|
||||
quo.components.wallet.account-permissions.component-spec
|
||||
quo.components.wallet.amount-input.component-spec
|
||||
quo.components.wallet.confirmation-progress.component-spec
|
||||
quo.components.wallet.keypair.component-spec
|
||||
quo.components.wallet.network-amount.component-spec
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
LinearTransition
|
||||
enableLayoutAnimations
|
||||
useAnimatedScrollHandler
|
||||
runOnJS)]
|
||||
runOnJS)
|
||||
:as reanimated*]
|
||||
["react-native-redash" :refer (withPause)]
|
||||
[oops.core :as oops]
|
||||
[react-native.flat-list :as rn-flat-list]
|
||||
@@ -113,6 +114,8 @@
|
||||
(when (and anim (some? v))
|
||||
(set! (.-value anim) v)))
|
||||
|
||||
(def interpolate* reanimated*/interpolate)
|
||||
|
||||
(defn interpolate
|
||||
([shared-value input-range output-range]
|
||||
(interpolate shared-value input-range output-range nil))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{:min 1}
|
||||
[:map
|
||||
{:closed true}
|
||||
[:method :string]
|
||||
[:method [:or :keyword :string]]
|
||||
[:params [:sequential :any]]
|
||||
[:js-response {:optional true} :any]
|
||||
[:on-success [:or fn? [:cat keyword? [:* :any]]]]
|
||||
|
||||
@@ -54,38 +54,43 @@
|
||||
|
||||
(defn share-qr-code
|
||||
"Receives the following properties:
|
||||
- type: :profile | :wallet-legacy | :wallet-multichain
|
||||
- qr-data: Text to encode in the QR code
|
||||
- qr-data-label-shown: Text to show below the QR code
|
||||
- on-text-press: Callback for the `qr-data-label-shown` text.
|
||||
- on-text-long-press: Callback for the `qr-data-label-shown` text.
|
||||
- on-share-press: Callback for the share button.
|
||||
- customization-color: Custom color for the QR code component.
|
||||
- unblur-on-android?: [Android only] disables blur for this component.
|
||||
|
||||
Depending on the `type`, different properties are accepted:
|
||||
`:profile`
|
||||
- full-name: User full name.
|
||||
- profile-picture: map ({:source image-source}) or any image source.
|
||||
`:wallet-legacy`
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-info-press: Callback for the info icon.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- on-multichain-press: Callback for the multichain tab.
|
||||
`:wallet-multichain`
|
||||
- networks: A vector of network names (`[:ethereum, :optimism, :my-net, ,,,]`)
|
||||
they will add network prefixes to the address in
|
||||
`qr-data-label-shown` and the QR code generated.
|
||||
- on-settings-press: Callback for the settings button.
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-info-press: Callback for the info icon.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- on-multichain-press: Callback for the multichain tab."
|
||||
[{:keys [qr-data qr-data-label-shown networks]
|
||||
- type: :profile | :wallet | :saved-address | :watched-address
|
||||
- qr-image-uri: Image source value.
|
||||
- qr-data: Text to show below the QR code.
|
||||
- on-text-press: Callback for the `qr-data` text.
|
||||
- on-text-long-press: Callback for the `qr-data` text.
|
||||
- on-share-press: Callback for the share button.
|
||||
- customization-color: Custom color for the QR code component.
|
||||
- unblur-on-android?: [Android only] disables blur for this component.
|
||||
- full-name: User full name.
|
||||
|
||||
Depending on the `type`, different properties are accepted:
|
||||
`:profile`
|
||||
- profile-picture: map ({:source image-source}) or any image source.
|
||||
`:wallet`
|
||||
- networks: A vector of network names as keywords (`[:ethereum, :my-net, ...]`).
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- on-multichain-press: Callback for the multichain tab.
|
||||
- address: :legacy | :multichain
|
||||
`:saved-address`
|
||||
- networks: A vector of network names as keywords (`[:ethereum, :my-net, ...]`).
|
||||
- on-settings-press: Callback for the settings button.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- address: :legacy | :multichain
|
||||
- on-multichain-press: Callback for the multichain tab.
|
||||
`:watched-address`
|
||||
- networks: A vector of network names as keywords (`[:ethereum, :my-net, ...]`).
|
||||
- on-settings-press: Callback for the settings button.
|
||||
- emoji: Emoji in a string to show in the QR code.
|
||||
- on-legacy-press: Callback for the legacy tab.
|
||||
- address: :legacy | :multichain
|
||||
- on-multichain-press: Callback for the multichain tab."
|
||||
[{:keys [qr-data qr-data-label-shown networks address]
|
||||
share-qr-type :type
|
||||
:as props}]
|
||||
(let [label (or qr-data-label-shown qr-data)
|
||||
string-to-encode (if (= share-qr-type :wallet-multichain)
|
||||
string-to-encode (if (and (= share-qr-type :wallet) (= address :multichain))
|
||||
(get-qr-data-for-wallet-multichain qr-data networks)
|
||||
qr-data)
|
||||
qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
(ns status-im.common.toasts.style)
|
||||
(ns status-im.common.toasts.style
|
||||
(:require [react-native.safe-area :as safe-area]))
|
||||
|
||||
(def outmost-transparent-container
|
||||
(defn outmost-transparent-container
|
||||
[]
|
||||
{:elevation 2
|
||||
:pointer-events :box-none
|
||||
:padding-top 52
|
||||
:padding-top (+ (safe-area/get-top) 6)
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
@@ -60,5 +60,5 @@
|
||||
[]
|
||||
(->> (rf/sub [:toasts])
|
||||
:ordered
|
||||
(into [rn/view {:style style/outmost-transparent-container}]
|
||||
(into [rn/view {:style (style/outmost-transparent-container)}]
|
||||
(map #(with-meta [:f> f-container %] {:key %})))))
|
||||
|
||||
@@ -169,8 +169,3 @@
|
||||
|
||||
(def community-accounts-selection-enabled? (enabled? (get-config :ACCOUNT_SELECTION_ENABLED "0")))
|
||||
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
|
||||
|
||||
(def wallet-feature-flags
|
||||
{:edit-default-keypair false
|
||||
:bridge-token false
|
||||
:remove-account false})
|
||||
|
||||
@@ -159,6 +159,9 @@
|
||||
community-token-permission-become-token-master
|
||||
community-token-permission-become-token-owner})
|
||||
|
||||
(def ^:const community-token-type-erc20 1)
|
||||
(def ^:const community-token-type-erc721 2)
|
||||
|
||||
;; Community rules for joining
|
||||
(def ^:const community-rule-ens-only "ens-only")
|
||||
|
||||
|
||||
@@ -153,19 +153,19 @@
|
||||
50)}]))
|
||||
:max-duration-ms constants/audio-max-duration-ms}]]))
|
||||
|
||||
(defn images-limit-toast
|
||||
(defn photo-limit-toast
|
||||
[]
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:type :negative
|
||||
:container-style {:top (when platform/ios? 20)}
|
||||
:text (i18n/label :t/only-6-images)}]))
|
||||
{:id :random-id
|
||||
:type :negative
|
||||
:text (i18n/label :t/hit-photos-limit
|
||||
{:max-photos constants/max-album-photos})}]))
|
||||
|
||||
|
||||
(defn go-to-camera
|
||||
[images-count]
|
||||
(device-permissions/camera #(if (>= images-count constants/max-album-photos)
|
||||
(images-limit-toast)
|
||||
(photo-limit-toast)
|
||||
(rf/dispatch [:navigate-to :camera-screen]))))
|
||||
|
||||
(defn camera-button
|
||||
|
||||
@@ -151,7 +151,6 @@
|
||||
:icon :i/pin
|
||||
:counter-value pins-count
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(rf/dispatch [:pin-message/show-pins-bottom-sheet
|
||||
chat-id]))}
|
||||
{:accessibility-label :action-button-mute
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
^js identity-images (.-identityImages response-js)
|
||||
^js accounts (.-accounts response-js)
|
||||
^js ens-username-details-js (.-ensUsernameDetails response-js)
|
||||
^js customization-color-js (.-customizationColor response-js)
|
||||
sync-handler (when-not process-async process-response)]
|
||||
(cond
|
||||
|
||||
@@ -204,7 +205,14 @@
|
||||
(js-delete response-js "ensUsernameDetails")
|
||||
(rf/merge cofx
|
||||
(process-next response-js sync-handler)
|
||||
(rf/dispatch [:ens/update-usernames ens-username-details-clj]))))))
|
||||
(rf/dispatch [:ens/update-usernames ens-username-details-clj])))
|
||||
|
||||
(seq customization-color-js)
|
||||
(let [customization-color (types/js->clj customization-color-js)]
|
||||
(js-delete response-js "customizationColor")
|
||||
(rf/merge cofx
|
||||
(process-next response-js sync-handler)
|
||||
(rf/dispatch [:profile/save-local-accent-color (keyword customization-color)]))))))
|
||||
|
||||
(defn group-by-and-update-unviewed-counts
|
||||
"group messages by current chat, profile updates, transactions and update unviewed counters in db for not curent chats"
|
||||
|
||||
@@ -75,3 +75,6 @@
|
||||
{:position :absolute
|
||||
:top 8
|
||||
:right 8})
|
||||
|
||||
(def photo-limit-toast-container
|
||||
{:top (if platform/ios? 6 16)})
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
@@ -17,13 +16,14 @@
|
||||
|
||||
(def min-scroll-to-blur 5)
|
||||
|
||||
(defn show-toast
|
||||
(defn show-photo-limit-toast
|
||||
[]
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:type :negative
|
||||
:container-style {:top (when platform/ios? 20)}
|
||||
:text (i18n/label :t/only-6-images)}]))
|
||||
:container-style style/photo-limit-toast-container
|
||||
:text (i18n/label :t/hit-photos-limit
|
||||
{:max-photos constants/max-album-photos})}]))
|
||||
|
||||
(defn on-press-confirm-selection
|
||||
[selected close]
|
||||
@@ -74,7 +74,7 @@
|
||||
(if item-selected?
|
||||
(swap! selected remove-selected item)
|
||||
(if (>= (count @selected) constants/max-album-photos)
|
||||
(show-toast)
|
||||
(show-photo-limit-toast)
|
||||
(swap! selected conj item))))
|
||||
:accessibility-label (str "image-" index)}
|
||||
[rn/image
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{:community-id id :password %}])}])
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn f-view-internal
|
||||
(defn view
|
||||
[]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name color images]} (rf/sub [:communities/community id])
|
||||
@@ -83,7 +83,3 @@
|
||||
:track-icon :i/face-id
|
||||
:customization-color color
|
||||
:on-complete #(join-community-and-navigate-back id)}]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:f> f-view-internal])
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
(ns status-im.contexts.communities.actions.addresses-for-permissions.events
|
||||
(:require
|
||||
[schema.core :as schema]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-permissioned-balances
|
||||
[{[event-id _] :original-event} [community-id]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method :wakuext_getCommunityPermissionedBalances
|
||||
:params [{:communityId community-id}]
|
||||
:on-success [:communities/get-permissioned-balances-success community-id]
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to get balances"
|
||||
{:community-id community-id
|
||||
:event event-id
|
||||
:error error}))}]]]})
|
||||
|
||||
(schema/=> get-permissioned-balances
|
||||
[:=>
|
||||
[:catn
|
||||
[:cofx :schema.re-frame/cofx]
|
||||
[:args [:schema [:catn [:community-id :string]]]]]
|
||||
[:map {:closed true}
|
||||
[:fx
|
||||
[:tuple
|
||||
[:tuple [:= :json-rpc/call] :schema.common/rpc-call]]]]])
|
||||
|
||||
(rf/reg-event-fx :communities/get-permissioned-balances get-permissioned-balances)
|
||||
|
||||
(defn get-permissioned-balances-success
|
||||
[{:keys [db]} [community-id response]]
|
||||
{:db (assoc-in db [:communities/permissioned-balances community-id] response)})
|
||||
|
||||
(def ^:private ?account-address keyword?)
|
||||
|
||||
(def ^:private ?permissioned-balances-response
|
||||
[:map-of
|
||||
?account-address
|
||||
[:sequential
|
||||
[:map
|
||||
[:type int?]
|
||||
[:symbol string?]
|
||||
[:decimals int?]
|
||||
[:amount string?]]]])
|
||||
|
||||
(schema/=> get-permissioned-balances-success
|
||||
[:=>
|
||||
[:catn
|
||||
[:cofx :schema.re-frame/cofx]
|
||||
[:args
|
||||
[:schema
|
||||
[:catn
|
||||
[:community-id string?]
|
||||
[:response ?permissioned-balances-response]]]]]
|
||||
map?])
|
||||
|
||||
(rf/reg-event-fx :communities/get-permissioned-balances-success get-permissioned-balances-success)
|
||||
@@ -0,0 +1,15 @@
|
||||
(ns status-im.contexts.communities.actions.addresses-for-permissions.events-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is]]
|
||||
[status-im.contexts.communities.actions.addresses-for-permissions.events :as sut]))
|
||||
|
||||
(def community-id "0x1")
|
||||
|
||||
(deftest get-permissioned-balances-test
|
||||
(let [cofx {:db {}}]
|
||||
(is (match? {:fx [[:json-rpc/call
|
||||
[{:method :wakuext_getCommunityPermissionedBalances
|
||||
:params [{:communityId community-id}]
|
||||
:on-success [:communities/get-permissioned-balances-success community-id]
|
||||
:on-error fn?}]]]}
|
||||
(sut/get-permissioned-balances cofx [community-id])))))
|
||||
@@ -8,12 +8,6 @@
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 12})
|
||||
|
||||
(def error-message
|
||||
{:flex-direction :row
|
||||
:gap 4
|
||||
:justify-content :center
|
||||
:margin-bottom 8})
|
||||
|
||||
(def highest-role
|
||||
{:flex-direction :row
|
||||
:gap 4
|
||||
|
||||
@@ -3,90 +3,111 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.communities.actions.addresses-for-permissions.style :as style]
|
||||
[status-im.contexts.communities.utils :as communities.utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- balances->components-props
|
||||
[balances]
|
||||
(for [{:keys [amount decimals type name] :as balance} balances]
|
||||
(cond-> balance
|
||||
true
|
||||
(assoc :type
|
||||
(condp = type
|
||||
constants/community-token-type-erc20 :token
|
||||
constants/community-token-type-erc721 :collectible
|
||||
:token))
|
||||
|
||||
(= type constants/community-token-type-erc721)
|
||||
(assoc :collectible-name name
|
||||
:collectible-img-src (resources/get-mock-image :collectible))
|
||||
|
||||
(= type constants/community-token-type-erc20)
|
||||
(assoc :amount (str (money/with-precision (money/token->unit amount decimals) 3))
|
||||
:token (:symbol balance)))))
|
||||
|
||||
(defn- account-item
|
||||
[item _ _ [selected-addresses community-id]]
|
||||
[quo/account-permissions
|
||||
{:account {:name (:name item)
|
||||
:address (:address item)
|
||||
:emoji (:emoji item)
|
||||
:customization-color (:customization-color item)}
|
||||
:token-details []
|
||||
:checked? (contains? selected-addresses (:address item))
|
||||
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
|
||||
(:address item) community-id])
|
||||
:container-style {:margin-bottom 8}}])
|
||||
[{:keys [customization-color address name emoji]} _ _ [selected-addresses community-id]]
|
||||
(let [balances (rf/sub [:communities/permissioned-balances-by-address community-id address])]
|
||||
[quo/account-permissions
|
||||
{:account {:name name
|
||||
:address address
|
||||
:emoji emoji
|
||||
:customization-color customization-color}
|
||||
:token-details (balances->components-props balances)
|
||||
:checked? (contains? selected-addresses address)
|
||||
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
|
||||
address community-id])
|
||||
:container-style {:margin-bottom 8}}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name color images]} (rf/sub [:communities/community id])
|
||||
{:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id])
|
||||
accounts (rf/sub [:wallet/accounts-with-customization-color])
|
||||
selected-addresses (rf/sub [:communities/selected-permission-addresses id])
|
||||
highest-role-text
|
||||
(i18n/label
|
||||
(communities.utils/role->translation-key highest-permission-role))]
|
||||
[rn/safe-area-view {:style style/container}
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:title (i18n/label :t/addresses-for-permissions)
|
||||
:context-tag-type :community
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:customization-color color}]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])]
|
||||
(rf/dispatch [:communities/get-permissioned-balances id])
|
||||
(fn []
|
||||
(let [{:keys [name color images]} (rf/sub [:communities/community id])
|
||||
{:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id])
|
||||
accounts (rf/sub [:wallet/accounts-with-customization-color])
|
||||
selected-addresses (rf/sub [:communities/selected-permission-addresses id])
|
||||
highest-role-text (when highest-permission-role
|
||||
(i18n/label (communities.utils/role->translation-key
|
||||
highest-permission-role)))]
|
||||
[rn/safe-area-view {:style style/container}
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:title (i18n/label :t/addresses-for-permissions)
|
||||
:context-tag-type :community
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:customization-color color}]
|
||||
|
||||
[rn/flat-list
|
||||
{:render-fn account-item
|
||||
:render-data [selected-addresses id]
|
||||
:content-container-style {:padding 20}
|
||||
:key-fn :address
|
||||
:data accounts}]
|
||||
[rn/flat-list
|
||||
{:render-fn account-item
|
||||
:render-data [selected-addresses id]
|
||||
:content-container-style {:padding 20}
|
||||
:key-fn :address
|
||||
:data accounts}]
|
||||
|
||||
(when (and highest-permission-role (seq selected-addresses))
|
||||
[rn/view
|
||||
{:style style/highest-role}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color colors/neutral-50}}
|
||||
(i18n/label :t/eligible-to-join-as {:role ""})]
|
||||
[quo/context-tag
|
||||
{:type :icon
|
||||
:icon :i/members
|
||||
:size 24
|
||||
:context highest-role-text}]])
|
||||
(if (and highest-permission-role (seq selected-addresses))
|
||||
[rn/view
|
||||
{:style style/highest-role}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color colors/neutral-50}}
|
||||
(i18n/label :t/eligible-to-join-as)]
|
||||
[quo/context-tag
|
||||
{:type :icon
|
||||
:icon :i/members
|
||||
:size 24
|
||||
:context highest-role-text}]]
|
||||
[quo/info-message
|
||||
{:type :error
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:style {:justify-content :center}}
|
||||
(if (empty? selected-addresses)
|
||||
(i18n/label :t/no-addresses-selected)
|
||||
(i18n/label :t/addresses-dont-contain-tokens-needed))])
|
||||
|
||||
(when (empty? selected-addresses)
|
||||
[rn/view
|
||||
{:style style/error-message}
|
||||
[quo/icon
|
||||
:i/info
|
||||
{:color colors/danger-50
|
||||
:size 16}]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color colors/danger-50}}
|
||||
(i18n/label :t/no-addresses-selected)]])
|
||||
|
||||
[rn/view {:style style/buttons}
|
||||
[quo/button
|
||||
{:type :grey
|
||||
:container-style {:flex 1}
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities/reset-selected-permission-addresses id])
|
||||
(rf/dispatch [:navigate-back]))}
|
||||
(i18n/label :t/cancel)]
|
||||
[quo/button
|
||||
{:container-style {:flex 1}
|
||||
:customization-color color
|
||||
:disabled? (empty? selected-addresses)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities/update-previous-permission-addresses id])
|
||||
[rn/view {:style style/buttons}
|
||||
[quo/button
|
||||
{:type :grey
|
||||
:container-style {:flex 1}
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities/reset-selected-permission-addresses id])
|
||||
(rf/dispatch [:navigate-back]))}
|
||||
(i18n/label :t/confirm-changes)]]]))
|
||||
(i18n/label :t/cancel)]
|
||||
[quo/button
|
||||
{:container-style {:flex 1}
|
||||
:customization-color color
|
||||
:disabled? (empty? selected-addresses)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities/update-previous-permission-addresses id])
|
||||
(rf/dispatch [:navigate-back]))}
|
||||
(i18n/label :t/confirm-changes)]]]))))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[schema.core :as schema]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
|
||||
status-im.contexts.communities.actions.addresses-for-permissions.events
|
||||
status-im.contexts.communities.actions.community-options.events
|
||||
status-im.contexts.communities.actions.leave.events
|
||||
[status-im.navigation.events :as navigation]
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns status-im.contexts.preview.feature-flags.style)
|
||||
|
||||
(def container
|
||||
{:flex 1
|
||||
:margin-left 20})
|
||||
@@ -0,0 +1,39 @@
|
||||
(ns status-im.contexts.preview.feature-flags.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as rf]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.preview.feature-flags.style :as style]
|
||||
[status-im.feature-flags :as ff]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/page-nav
|
||||
{:type :title
|
||||
:text-align :left
|
||||
:title "Features Flags"
|
||||
:icon-name :i/arrow-left
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
(doall
|
||||
(for [context-name ff/feature-flags-categories
|
||||
:let [context-flags (filter (fn [[k]]
|
||||
(string/includes? (str k) context-name))
|
||||
(ff/feature-flags))]]
|
||||
^{:key (str context-name)}
|
||||
[rn/view {:style style/container}
|
||||
[quo/text
|
||||
context-name]
|
||||
(doall
|
||||
(for [i (range (count context-flags))
|
||||
:let [[flag] (nth context-flags i)]]
|
||||
^{:key (str context-name flag i)}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/selectors
|
||||
{:type :toggle
|
||||
:checked? (ff/enabled? flag)
|
||||
:container-style {:margin-right 8}
|
||||
:on-change #(ff/toggle flag)}]
|
||||
[quo/text (second (string/split (name flag) "."))]]))]))])
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
(def descriptor
|
||||
[{:type :select
|
||||
:key :actions
|
||||
:options [{:key :1-action}
|
||||
{:key :2-actions}]}
|
||||
:options [{:key :one-action}
|
||||
{:key :two-actions}]}
|
||||
{:key :button-one-label
|
||||
:type :text}
|
||||
{:label "Button 1 type"
|
||||
:type :select
|
||||
:key :type
|
||||
@@ -30,6 +32,8 @@
|
||||
:type :boolean
|
||||
:key :disabled?
|
||||
:path [:button-one-props]}
|
||||
{:key :button-two-label
|
||||
:type :text}
|
||||
{:label "Button 2 type"
|
||||
:type :select
|
||||
:key :type
|
||||
@@ -39,32 +43,59 @@
|
||||
:type :boolean
|
||||
:key :disabled?
|
||||
:path [:button-two-props]}
|
||||
{:key :description
|
||||
:type :text}
|
||||
{:key :button-one-label
|
||||
:type :text}
|
||||
{:key :button-two-label
|
||||
:type :text}
|
||||
{:key :blur?
|
||||
:type :boolean}
|
||||
{:key :scroll?
|
||||
:type :boolean}])
|
||||
:type :boolean}
|
||||
{:key :description
|
||||
:type :select
|
||||
:options [{:key nil
|
||||
:value :none}
|
||||
{:key :top}
|
||||
{:key :bottom}
|
||||
{:key :top-error}]}])
|
||||
|
||||
(def role-descriptor
|
||||
{:key :role
|
||||
:type :select
|
||||
:options [{:key :owner}
|
||||
{:key :token-master}
|
||||
{:key :admin}
|
||||
{:key :member}]})
|
||||
|
||||
(def description-descriptor
|
||||
{:key :description-text
|
||||
:type :text})
|
||||
|
||||
(def error-descriptor
|
||||
{:key :error-message
|
||||
:type :text})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:actions :2-actions
|
||||
:description description
|
||||
(let [state (reagent/atom {:actions :two-actions
|
||||
:description :bottom
|
||||
:description-text description
|
||||
:error-message "Error message"
|
||||
:button-one-label button-one
|
||||
:button-two-label button-two
|
||||
:button-one-props {:on-press (button-press 1)
|
||||
:type :primary
|
||||
:icon-left :i/arrow-up}
|
||||
:button-one-props {:on-press (button-press 1)
|
||||
:type :primary}
|
||||
:button-two-props {:on-press (button-press 2)
|
||||
:type :grey}
|
||||
:blur? false
|
||||
:role :owner
|
||||
:scroll? false})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:blur? (:scroll? @state)
|
||||
:descriptor (merge descriptor
|
||||
(case (:description @state)
|
||||
:top role-descriptor
|
||||
:bottom description-descriptor
|
||||
:top-error error-descriptor
|
||||
nil))
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true
|
||||
:blur-dark-only? true
|
||||
:component-container-style {:margin-top 40
|
||||
|
||||
@@ -158,6 +158,7 @@
|
||||
[status-im.contexts.preview.quo.tabs.account-selector :as account-selector]
|
||||
[status-im.contexts.preview.quo.tabs.segmented-tab :as segmented]
|
||||
[status-im.contexts.preview.quo.tabs.tabs :as tabs]
|
||||
[status-im.contexts.preview.quo.tags.collectible-tag :as collectible-tag]
|
||||
[status-im.contexts.preview.quo.tags.context-tags :as context-tags]
|
||||
[status-im.contexts.preview.quo.tags.network-tags :as network-tags]
|
||||
[status-im.contexts.preview.quo.tags.number-tag :as number-tag]
|
||||
@@ -178,6 +179,7 @@
|
||||
[status-im.contexts.preview.quo.wallet.account-overview :as
|
||||
account-overview]
|
||||
[status-im.contexts.preview.quo.wallet.account-permissions :as account-permissions]
|
||||
[status-im.contexts.preview.quo.wallet.amount-input :as amount-input]
|
||||
[status-im.contexts.preview.quo.wallet.confirmation-progress :as
|
||||
confirmation-progress]
|
||||
[status-im.contexts.preview.quo.wallet.keypair :as keypair]
|
||||
@@ -457,7 +459,9 @@
|
||||
:component tabs/view}
|
||||
{:name :account-selector
|
||||
:component account-selector/view}]
|
||||
:tags [{:name :context-tags
|
||||
:tags [{:name :collectible-tag
|
||||
:component collectible-tag/view}
|
||||
{:name :context-tags
|
||||
:component context-tags/view}
|
||||
{:name :network-tags
|
||||
:component network-tags/view}
|
||||
@@ -493,6 +497,8 @@
|
||||
:component account-overview/view}
|
||||
{:name :account-permissions
|
||||
:component account-permissions/view}
|
||||
{:name :amount-input
|
||||
:component amount-input/view}
|
||||
{:name :confirmation-progress
|
||||
:component confirmation-progress/view}
|
||||
{:name :keypair :component keypair/view}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.preview.quo.share.share-qr-code
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.contexts.preview.quo.preview :as preview]
|
||||
@@ -15,8 +14,23 @@
|
||||
{:key :type
|
||||
:type :select
|
||||
:options [{:key :profile}
|
||||
{:key :wallet-legacy}
|
||||
{:key :wallet-multichain}]}])
|
||||
{:key :wallet}
|
||||
{:key :saved-address}
|
||||
{:key :watched-address}]}])
|
||||
|
||||
(def possible-networks [:ethereum :optimism :arbitrum :myNet])
|
||||
|
||||
(def networks-selector
|
||||
{:key :networks
|
||||
:type :select
|
||||
:options [{:key (take 1 possible-networks)
|
||||
:value "Ethereum"}
|
||||
{:key (take 2 possible-networks)
|
||||
:value "Ethereum and Optimism"}
|
||||
{:key (take 3 possible-networks)
|
||||
:value "Ethereum, Optimism and Arbitrum"}
|
||||
{:key (take 4 possible-networks)
|
||||
:value "Ethereum, Optimism, Arbitrum and unknown"}]})
|
||||
|
||||
(def profile-descriptor
|
||||
[{:key :profile-picture
|
||||
@@ -24,40 +38,44 @@
|
||||
:options [{:key (resources/get-mock-image :user-picture-female2)
|
||||
:value "User 1"}
|
||||
{:key (resources/get-mock-image :user-picture-male4)
|
||||
:value "User 2"}
|
||||
{:key nil
|
||||
:value "No picture"}]}
|
||||
:value "User 2"}]}
|
||||
{:key :full-name
|
||||
:type :text}
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(def wallet-legacy-descriptor
|
||||
[{:key :emoji
|
||||
(def wallet-descriptor
|
||||
[{:key :address
|
||||
:type :select
|
||||
:options [{:key :legacy}
|
||||
{:key :multichain}]}
|
||||
{:key :emoji
|
||||
:type :select
|
||||
:options [{:key "🐈"}
|
||||
{:key "👻"}
|
||||
{:key "🐧"}]}
|
||||
networks-selector
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(def possible-networks [:ethereum :optimism :arbitrum :myNet])
|
||||
(def saved-address-descriptor
|
||||
[{:key :address
|
||||
:type :select
|
||||
:options [{:key :legacy}
|
||||
{:key :multichain}]}
|
||||
networks-selector
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(def wallet-multichain-descriptor
|
||||
[{:key :emoji
|
||||
(def watched-address-descriptor
|
||||
[{:key :address
|
||||
:type :select
|
||||
:options [{:key :legacy}
|
||||
{:key :multichain}]}
|
||||
{:key :emoji
|
||||
:type :select
|
||||
:options [{:key "🐈"}
|
||||
{:key "👻"}
|
||||
{:key "🐧"}]}
|
||||
(preview/customization-color-option)
|
||||
{:key :networks
|
||||
:type :select
|
||||
:options [{:key (take 1 possible-networks)
|
||||
:value "Ethereum"}
|
||||
{:key (take 2 possible-networks)
|
||||
:value "Ethereum and Optimism"}
|
||||
{:key (take 3 possible-networks)
|
||||
:value "Ethereum, Optimism and Arbitrum"}
|
||||
{:key (take 4 possible-networks)
|
||||
:value "Ethereum, Optimism, Arbitrum and unknown"}]}])
|
||||
networks-selector
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(defn- get-network-short-name-url
|
||||
[network]
|
||||
@@ -84,22 +102,23 @@
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:type :profile
|
||||
:address :legacy
|
||||
:qr-data profile-link
|
||||
:on-share-press #(js/alert "share pressed")
|
||||
:on-text-press #(js/alert "text pressed")
|
||||
:on-text-long-press #(js/alert "text long press")
|
||||
:profile-picture nil
|
||||
:profile-picture (resources/get-mock-image :user-picture-female2)
|
||||
:full-name "My User"
|
||||
:customization-color :purple
|
||||
:emoji "🐈"
|
||||
:on-info-press #(js/alert "Info pressed")
|
||||
:on-legacy-press #(js/alert (str "Tab " % " pressed"))
|
||||
:on-multichain-press #(js/alert (str "Tab " % " pressed"))
|
||||
:networks (take 2 possible-networks)
|
||||
:on-settings-press #(js/alert "Settings pressed")})
|
||||
_ (add-watch state :change set-qr-data-based-on-type)]
|
||||
(fn []
|
||||
(let [qr-url (if (= (:type @state) :wallet-multichain)
|
||||
(let [qr-url (if (and (= (:address @state) :multichain)
|
||||
(not= (:type @state) :profile))
|
||||
(as-> (:networks @state) $
|
||||
(map get-network-short-name-url $)
|
||||
(apply str $)
|
||||
@@ -112,31 +131,20 @@
|
||||
:error-level :highest})
|
||||
typed-descriptor (concat descriptor
|
||||
(case (:type @state)
|
||||
:profile profile-descriptor
|
||||
:wallet-legacy wallet-legacy-descriptor
|
||||
:wallet-multichain wallet-multichain-descriptor
|
||||
:profile profile-descriptor
|
||||
:wallet wallet-descriptor
|
||||
:saved-address saved-address-descriptor
|
||||
:watched-address watched-address-descriptor
|
||||
nil))]
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor typed-descriptor
|
||||
:component-container-style {:padding-horizontal 0}}
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:justify-content :flex-end
|
||||
:align-items :center
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 30}}
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0}}
|
||||
[rn/image
|
||||
{:style {:flex 1
|
||||
:resize-mode :stretch}
|
||||
:source (resources/get-mock-image :dark-blur-bg)}]]
|
||||
[quo/share-qr-code
|
||||
(assoc @state
|
||||
:qr-image-uri qr-media-server-uri
|
||||
:qr-data qr-url)]]]))))
|
||||
:blur? true
|
||||
:blur-height 500
|
||||
:component-container-style {:padding-horizontal 0}
|
||||
:show-blur-background? true
|
||||
:blur-dark-only? true}
|
||||
[quo/share-qr-code
|
||||
(assoc @state
|
||||
:qr-image-uri qr-media-server-uri
|
||||
:qr-data qr-url)]]))))
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
(ns status-im.contexts.preview.quo.tags.collectible-tag
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :size
|
||||
:type :select
|
||||
:options [{:key :size-24
|
||||
:value "Size 24"}
|
||||
{:key :size-32
|
||||
:value "Size 32"}]}
|
||||
{:key :options
|
||||
:type :select
|
||||
:options [{:key false
|
||||
:value false}
|
||||
{:key :add
|
||||
:value :add}
|
||||
{:key :hold
|
||||
:value :hold}]}
|
||||
{:key :blur?
|
||||
:type :boolean}
|
||||
{:key :collectible-name
|
||||
:type :text}
|
||||
{:key :collectible-id
|
||||
:type :text}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:size :size-24
|
||||
:collectible-name "Collectible"
|
||||
:collectible-id "#123"
|
||||
:collectible-img-src (resources/mock-images :collectible)
|
||||
:options false
|
||||
:blur? false
|
||||
:container-width 0})
|
||||
on-layout #(swap! state assoc
|
||||
:container-width
|
||||
(oget % :nativeEvent :layout :width))]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true
|
||||
:descriptor descriptor}
|
||||
[rn/view {:style {:align-items :center}}
|
||||
[quo/collectible-tag (assoc @state :on-layout on-layout)]]])))
|
||||
@@ -0,0 +1,29 @@
|
||||
(ns status-im.contexts.preview.quo.wallet.amount-input
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :max-value
|
||||
:type :number}
|
||||
{:key :min-value
|
||||
:type :number}
|
||||
{:key :init-value
|
||||
:type :number}
|
||||
{:type :select
|
||||
:key :status
|
||||
:options [{:key :default}
|
||||
{:key :error}]}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:max-value 10000
|
||||
:min-value 0
|
||||
:init-value 1
|
||||
:status :default})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor}
|
||||
[quo/amount-input @state]])))
|
||||
@@ -6,7 +6,7 @@
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:type :text
|
||||
[{:type :number
|
||||
:key :progress-value}
|
||||
{:type :select
|
||||
:key :network
|
||||
@@ -78,7 +78,7 @@
|
||||
[]
|
||||
(let [state (reagent/atom
|
||||
{:total-box total-box
|
||||
:progress-value "10"
|
||||
:progress-value 10
|
||||
:network :mainnet
|
||||
:state :pending
|
||||
:customization-color :blue})]
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
:key :epoch-number-arbitrum}
|
||||
{:type :text
|
||||
:key :tag-number}
|
||||
{:type :text
|
||||
{:type :number
|
||||
:key :optimism-progress-percentage}
|
||||
{:type :text
|
||||
{:type :number
|
||||
:key :arbitrum-progress-percentage}
|
||||
{:type :select
|
||||
:key :network
|
||||
@@ -142,8 +142,8 @@
|
||||
:epoch-number-mainnet "181,329"
|
||||
:epoch-number-optimism "181,329"
|
||||
:epoch-number-arbitrum "181,329"
|
||||
:optimism-progress-percentage "10"
|
||||
:arbitrum-progress-percentage "10"
|
||||
:optimism-progress-percentage 10
|
||||
:arbitrum-progress-percentage 10
|
||||
:network :mainnet
|
||||
:state-mainnet :pending
|
||||
:state-arbitrum :pending
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(ns status-im.contexts.profile.edit.accent-colour.events
|
||||
(:require [taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :profile/edit-accent-colour-success
|
||||
(fn [_ [customization-color]]
|
||||
{:fx [[:dispatch [:profile/save-local-accent-color customization-color]]
|
||||
[:dispatch [:navigate-back]]
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:theme :dark
|
||||
:text (i18n/label :t/accent-colour-updated)}]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile/save-local-accent-color
|
||||
(fn [{:keys [db]} [customization-color]]
|
||||
{:db (assoc-in db [:profile/profile :customization-color] customization-color)}))
|
||||
|
||||
(defn edit-accent-colour
|
||||
[{:keys [db]} [customization-color]]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_setCustomizationColor"
|
||||
:params [{:customizationColor customization-color
|
||||
:keyUid key-uid}]
|
||||
:on-success [:profile/edit-accent-colour-success customization-color]
|
||||
:on-error #(log/error "failed to edit accent color." {:error %})}]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile/edit-accent-colour edit-accent-colour)
|
||||