Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0a3a97596 | ||
|
|
664048468b | ||
|
|
73e9f67dbd | ||
|
|
86c5505c94 | ||
|
|
c1dcd7a764 | ||
|
|
17ebedd6b8 | ||
|
|
2e2d15adfb | ||
|
|
1d1d586223 | ||
|
|
88dd5e04bb |
@@ -16,10 +16,18 @@
|
||||
:clj-kondo-config {:level :error}
|
||||
:cond-else {:level :error}
|
||||
:consistent-alias {:level :error
|
||||
:aliases {clojure.string string
|
||||
clojure.set set
|
||||
clojure.walk walk
|
||||
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
|
||||
taoensso.timbre log}}
|
||||
:deprecated-namespace {:level :warning}
|
||||
:docstring-blank {:level :error}
|
||||
:equals-true {:level :error}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
{:lint-as {malli.experimental/defn schema.core/defn}
|
||||
:linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}
|
||||
@@ -36,6 +36,7 @@
|
||||
"deftest-sub" :arg1-body
|
||||
"wait-for" :arg1-body
|
||||
"with-deps-check" :arg1-body
|
||||
"schema/=>" :arg1-body
|
||||
"->" [:noarg1-body
|
||||
{:list {:constant-pair? false :force-nl? false}
|
||||
:next-inner-restore [[:list :constant-pair?]]}]
|
||||
|
||||
@@ -45,11 +45,20 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "borkdude/edamame/1.1.17/edamame-1.1.17",
|
||||
"path": "borkdude/dynaload/0.3.5/dynaload-0.3.5",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "9087f7abf0104e0354d7db7fc4576608eac558f4",
|
||||
"sha256": "1n1872i240lakn4pzsag4grf7bv7lcsipmqllxd9m4k1zp3dgla1"
|
||||
"sha1": "accd696ba364b850b4d92e38f5a34d0e828a0ad1",
|
||||
"sha256": "0k62m1f29xfh3cp67w7kcvkp5aj35simi8kf95ycvkmgp76w11q8"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "borkdude/edamame/1.3.23/edamame-1.3.23",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "254d023e97ed438f0f44532b5a06d928d031ede4",
|
||||
"sha256": "0l7mxza2nimslhg0qh6jp7gmb8sd6l89fk5d1zvzq2xskscq2vly"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -81,20 +90,20 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cider/cider-nrepl/0.29.0/cider-nrepl-0.29.0",
|
||||
"path": "cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "45f6034b26a14138e74145b7a4059628c0fedcd1",
|
||||
"sha256": "1dy1l6y8cb8xiqq97a4lf8giyiicq4wfl4s2lxn5fb6614cjxqx2"
|
||||
"sha1": "5ae0efd9377a5e60c084bdaf4a2ce094f759ce23",
|
||||
"sha256": "0drxf9nm23i1pcgrkwbcr09msq37csilzww38709add0hz8spjhq"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cider/piggieback/0.5.2/piggieback-0.5.2",
|
||||
"path": "cider/piggieback/0.4.1/piggieback-0.4.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "ecfd5c286a85db3f059e75c37fca5722d9e26f79",
|
||||
"sha256": "1ps9yf3cxmlm447hqkidjb5xry90n0wl3jk0jn28fagq31lzylkl"
|
||||
"sha1": "0a02a3e2ecd7a126ab60d8a44793342f20ced79b",
|
||||
"sha256": "142vl5np33akcrnn6pksi0rjfsmmi528villxsj6cwcndvybiw4m"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -539,6 +548,24 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "metosin/malli/0.13.0/malli-0.13.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "286c52d26a3a9d613b5f692971bd19c581cdc4b0",
|
||||
"sha256": "0vaq9d6cln5j4ww302fwlgg7m647cf2j16gs2i1p1d4klbn4jddz"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "mvxcvi/arrangement/2.1.0/arrangement-2.1.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "1bc8f3bba7a28de85f319b7d464aa8d955f44918",
|
||||
"sha256": "1j1rkwrs4wm8zk9v7ilgpnyav5sipdd2bmb83sazh392blw52wpk"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "net/cgrand/macrovich/0.2.1/macrovich-0.2.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -728,6 +755,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/test.check/1.1.1/test.check-1.1.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"jar": {
|
||||
"sha1": "f33d988fd57bc9c11af1952db81c10f319c91416",
|
||||
"sha256": "0y2hpkj7zl4yrpsl35ifpdaja5c72b8fpjcnmdgmld9c7cb1hlcl"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -909,11 +945,11 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "refactor-nrepl/refactor-nrepl/3.6.0/refactor-nrepl-3.6.0",
|
||||
"path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "2b3bb82da53b5db9c2b2aa298417816b81d0ed97",
|
||||
"sha256": "1ysqabmlnghki6x0636zngxza2d83c85276wp9ma9wk183mkv52a"
|
||||
"sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207",
|
||||
"sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@ babashka/fs/0.2.16/fs-0.2.16.jar
|
||||
bidi/bidi/2.1.6/bidi-2.1.6.jar
|
||||
binaryage/env-config/0.2.2/env-config-0.2.2.jar
|
||||
binaryage/oops/0.7.2/oops-0.7.2.jar
|
||||
borkdude/edamame/1.1.17/edamame-1.1.17.jar
|
||||
borkdude/dynaload/0.3.5/dynaload-0.3.5.jar
|
||||
borkdude/edamame/1.3.23/edamame-1.3.23.jar
|
||||
borkdude/sci.impl.reflector/0.0.1/sci.impl.reflector-0.0.1.jar
|
||||
camel-snake-kebab/camel-snake-kebab/0.4.3/camel-snake-kebab-0.4.3.jar
|
||||
cheshire/cheshire/5.11.0/cheshire-5.11.0.jar
|
||||
cider/cider-nrepl/0.29.0/cider-nrepl-0.29.0.jar
|
||||
cider/piggieback/0.5.2/piggieback-0.5.2.jar
|
||||
cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3.jar
|
||||
cider/piggieback/0.4.1/piggieback-0.4.1.jar
|
||||
clj-kondo/clj-kondo/2023.09.07/clj-kondo-2023.09.07.jar
|
||||
cljs-bean/cljs-bean/1.9.0/cljs-bean-1.9.0.jar
|
||||
clout/clout/2.1.2/clout-2.1.2.jar
|
||||
@@ -58,6 +59,8 @@ javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar
|
||||
javax/servlet/servlet-api/2.5/servlet-api-2.5.jar
|
||||
javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar
|
||||
medley/medley/0.8.2/medley-0.8.2.jar
|
||||
metosin/malli/0.13.0/malli-0.13.0.jar
|
||||
mvxcvi/arrangement/2.1.0/arrangement-2.1.0.jar
|
||||
net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
|
||||
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
|
||||
nrepl/bencode/1.1.0/bencode-1.1.0.jar
|
||||
@@ -79,6 +82,7 @@ org/clojure/data.priority-map/1.1.0/data.priority-map-1.1.0.jar
|
||||
org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541.jar
|
||||
org/clojure/google-closure-library-third-party/0.0-20230227-c7c0a541/google-closure-library-third-party-0.0-20230227-c7c0a541.jar
|
||||
org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar
|
||||
org/clojure/test.check/1.1.1/test.check-1.1.1.jar
|
||||
org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0.jar
|
||||
org/clojure/tools.analyzer.jvm/1.2.2/tools.analyzer.jvm-1.2.2.jar
|
||||
org/clojure/tools.cli/1.0.206/tools.cli-1.0.206.jar
|
||||
@@ -99,7 +103,7 @@ org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final.jar
|
||||
prismatic/schema/1.1.7/schema-1.1.7.jar
|
||||
reagent/reagent/1.2.0/reagent-1.2.0.jar
|
||||
re-com/re-com/2.8.0/re-com-2.8.0.jar
|
||||
refactor-nrepl/refactor-nrepl/3.6.0/refactor-nrepl-3.6.0.jar
|
||||
refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
|
||||
re-frame/re-frame/1.3.0/re-frame-1.3.0.jar
|
||||
re-frisk-remote/re-frisk-remote/1.6.0/re-frisk-remote-1.6.0.jar
|
||||
re-frisk/sente/1.15.0/sente-1.15.0.jar
|
||||
|
||||
@@ -67,9 +67,12 @@ stdenv.mkDerivation {
|
||||
'';
|
||||
buildPhase = ''
|
||||
# Assemble CLASSPATH from available clojure dependencies.
|
||||
# We append 'src' so it can find the local sources.
|
||||
export CLASS_PATH="$(find ${deps.clojure} \
|
||||
-iname '*.jar' | tr '\n' ':')src"
|
||||
# We prepend 'src' so it can find the local sources and prioritize
|
||||
# our own namespaces over dependencies, given that indirect dependencies
|
||||
# can also cause naming conflicts (e.g. prismatic/schema already uses
|
||||
# namespace schema.core).
|
||||
export CLASS_PATH="src:$(find ${deps.clojure} \
|
||||
-iname '*.jar' | tr '\n' ':')"
|
||||
|
||||
# target must be one of the builds defined in shadow-cljs.edn
|
||||
java -cp "$CLASS_PATH" clojure.main \
|
||||
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 30 KiB |
@@ -9,6 +9,7 @@
|
||||
[cljs-bean "1.9.0"]
|
||||
[com.cognitect/transit-cljs "0.8.280"]
|
||||
[camel-snake-kebab "0.4.3"]
|
||||
[metosin/malli "0.13.0"]
|
||||
|
||||
;; Dev dependencies
|
||||
[refactor-nrepl "2.5.0"]
|
||||
@@ -50,6 +51,7 @@
|
||||
:after-load-async status-im2.setup.hot-reload/reload
|
||||
:build-notify status-im2.setup.hot-reload/build-notify
|
||||
:preloads [re-frisk-remote.preload
|
||||
status-im2.setup.schema-preload
|
||||
;; In order to use component test helpers in the REPL we
|
||||
;; need to preload namespaces that are not normally required
|
||||
;; by production code, such as
|
||||
@@ -71,6 +73,10 @@
|
||||
:warnings {:fn-deprecated false}
|
||||
:closure-defines {re-frame.trace/trace-enabled? true}
|
||||
:source-map false
|
||||
;; This seems to be necessary while using the REPL,
|
||||
;; otherwise sometimes you'll get weird errors when
|
||||
;; instrumenting functions.
|
||||
:static-fns false
|
||||
:infer-externs true}
|
||||
;; if you want to use a real device, set your local ip
|
||||
;; in the SHADOW_HOST env variable to make sure that
|
||||
@@ -104,13 +110,15 @@
|
||||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
:dev {:devtools {:preloads [status-im2.setup.schema-preload]}}
|
||||
;; Uncomment line below to `make test-watch` a specific file
|
||||
;; :ns-regexp "status-im2.subs.messages-test$"
|
||||
:main status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
:ui-driven true
|
||||
:closure-defines
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
{schema.core/throw-on-error? true
|
||||
status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
@@ -139,9 +147,17 @@
|
||||
:compiler-options {:optimizations :simple
|
||||
:source-map false}}
|
||||
:component-test {:target :npm-module
|
||||
:entries [quo.core-spec status-im2.core-spec]
|
||||
:entries [;; We need to tell shadow-cljs to compile
|
||||
;; the preloads namespace because it will
|
||||
;; be used directly by Jest in the option
|
||||
;; setupFilesAfterEnv.
|
||||
status-im2.setup.schema-preload
|
||||
|
||||
quo.core-spec
|
||||
status-im2.core-spec]
|
||||
:ns-regexp "component-spec$"
|
||||
:output-dir "component-spec"
|
||||
:closure-defines {schema.core/throw-on-error? true}
|
||||
:compiler-options {:warnings-as-errors false
|
||||
:static-fns false
|
||||
:infer-externs true}}}}
|
||||
|
||||
@@ -3,18 +3,22 @@
|
||||
[quo.components.counter.step.view :as step]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn render
|
||||
[component]
|
||||
(h/render-with-theme-provider component :dark))
|
||||
|
||||
(h/describe "step component"
|
||||
(h/test "default render of step component"
|
||||
(h/render [step/view {} nil])
|
||||
(render [step/view {} nil])
|
||||
(-> (h/expect (h/query-by-label-text :step-counter))
|
||||
(h/is-truthy)))
|
||||
|
||||
(h/test "renders step with a string value"
|
||||
(h/render [step/view {} "1"])
|
||||
(render [step/view {} "1"])
|
||||
(-> (h/expect (h/get-by-text "1"))
|
||||
(h/is-truthy)))
|
||||
|
||||
(h/test "renders step with an integer value"
|
||||
(h/render [step/view {} 1])
|
||||
(render [step/view {} 1])
|
||||
(-> (h/expect (h/get-by-text "1"))
|
||||
(h/is-truthy))))
|
||||
|
||||
@@ -2,10 +2,24 @@
|
||||
(:require
|
||||
[quo.components.counter.step.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.theme :as theme]
|
||||
quo.theme
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]
|
||||
[utils.number]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:accessibility-label {:optional true} [:maybe :keyword]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:in-blur-view? {:optional true} [:maybe :boolean]]
|
||||
[:theme :schema.common/theme]
|
||||
[:type {:optional true} [:enum :active :complete :neutral]]]]
|
||||
[:value [:maybe [:or :string :int]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type accessibility-label theme in-blur-view? customization-color]} value]
|
||||
(let [type (or type :neutral)
|
||||
@@ -23,6 +37,9 @@
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :label
|
||||
:style {:color (style/text-color type theme)}} label]]))
|
||||
:style {:color (style/text-color type theme)}}
|
||||
label]]))
|
||||
|
||||
(def view (theme/with-theme view-internal))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
|
||||
@@ -19,3 +19,7 @@
|
||||
:background-color colors/danger-50
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def empty-state
|
||||
{:width 375
|
||||
:height 116})
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
(:require
|
||||
[quo.components.graph.utils :as utils]
|
||||
[quo.components.graph.wallet-graph.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.charts :as charts]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
(defn- time-frame->max-data-points
|
||||
@@ -42,11 +43,10 @@
|
||||
gradient-colors [(colors/alpha line-color 0.1) (colors/alpha line-color 0)]
|
||||
fill-color (colors/theme-colors colors/white colors/neutral-95)]
|
||||
(if (= time-frame :empty)
|
||||
[rn/view
|
||||
{:accessibility-label :illustration
|
||||
:style style/illustration}
|
||||
[text/text {:style {:color colors/white}}
|
||||
"Illustration here"]]
|
||||
[fast-image/fast-image
|
||||
{:style style/empty-state
|
||||
:source (resources/get-themed-image :no-funds theme)
|
||||
:accessibility-label :illustration}]
|
||||
[rn/view
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors gradient-colors
|
||||
|
||||
@@ -3,22 +3,17 @@
|
||||
[quo.components.icon :as quo.icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as theme]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes
|
||||
{:light {:default colors/neutral-50
|
||||
:success colors/success-50
|
||||
:error colors/danger-50}
|
||||
:dark {:default colors/neutral-40
|
||||
:success colors/success-60
|
||||
:error colors/danger-60}})
|
||||
|
||||
(defn get-color
|
||||
[k]
|
||||
(get-in themes [(theme/get-theme) k]))
|
||||
[k theme]
|
||||
(case k
|
||||
:success (colors/resolve-color :success theme)
|
||||
:error (colors/resolve-color :danger theme)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
|
||||
|
||||
(defn info-message
|
||||
(defn view-internal
|
||||
"[info-message opts \"message\"]
|
||||
opts
|
||||
{:type :default/:success/:error
|
||||
@@ -27,11 +22,11 @@
|
||||
:text-color colors/white ;; text color override
|
||||
:icon-color colors/white ;; icon color override
|
||||
:no-icon-color? false ;; disable tint color for icon"
|
||||
[{:keys [type size icon text-color icon-color no-icon-color? style]} message]
|
||||
[{:keys [type size theme icon text-color icon-color no-icon-color? style accessibility-label]} message]
|
||||
(let [weight (if (= size :default) :regular :medium)
|
||||
icon-size (if (= size :default) 16 12)
|
||||
size (if (= size :default) :paragraph-2 :label)
|
||||
text-color (or text-color (get-color type))
|
||||
text-color (or text-color (get-color type theme))
|
||||
icon-color (or icon-color text-color)]
|
||||
[rn/view
|
||||
{:style (merge {:flex-direction :row
|
||||
@@ -42,7 +37,10 @@
|
||||
:no-color no-icon-color?
|
||||
:size icon-size}]
|
||||
[text/text
|
||||
{:size size
|
||||
:weight weight
|
||||
:style {:color text-color
|
||||
:margin-horizontal 4}} message]]))
|
||||
{:accessibility-label accessibility-label
|
||||
:size size
|
||||
:weight weight
|
||||
:style {:color text-color
|
||||
:margin-horizontal 4}} message]]))
|
||||
|
||||
(def info-message (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
(h/is-truthy (h/get-by-text "test description")))
|
||||
|
||||
(h/test "renders step component when step-number is valid and type is step"
|
||||
(h/render [list/view
|
||||
{:type :step
|
||||
:step-number 1}])
|
||||
(h/render-with-theme-provider [list/view
|
||||
{:type :step
|
||||
:step-number 1}]
|
||||
:dark)
|
||||
(h/is-truthy (h/get-by-label-text :step-counter)))
|
||||
|
||||
(h/test "renders decription with a context tag component and description after the tag"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
:blur? false
|
||||
:type :digit} 1])
|
||||
(h/is-truthy (h/query-by-label-text :text-label))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "Is not pressable when disabled is true"
|
||||
@@ -47,5 +47,5 @@
|
||||
:blur? false
|
||||
:type :digit} 1])
|
||||
(h/is-truthy (h/query-by-label-text :text-label))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
|
||||
(h/was-not-called on-press))))
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- label->accessibility-label
|
||||
[label]
|
||||
(let [label-name (if (keyword? label) (name label) label)]
|
||||
(keyword (str "keyboard-key-" label-name))))
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
@@ -14,9 +19,11 @@
|
||||
(let [label-color (style/get-label-color disabled? theme blur?)
|
||||
background-color (style/toggle-background-color @pressed? blur? theme)]
|
||||
[rn/pressable
|
||||
{:accessibility-label :keyboard-key
|
||||
{:accessibility-label (label->accessibility-label label)
|
||||
:disabled (or disabled? (not label))
|
||||
:on-press (fn [] (on-press label))
|
||||
:on-press (fn []
|
||||
(when on-press
|
||||
(on-press label)))
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)
|
||||
:style (style/container background-color)}
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press]}]
|
||||
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete]
|
||||
:or {left-action :none}}]
|
||||
[rn/view
|
||||
{:style style/container}
|
||||
(for [row-index (range 1 4)]
|
||||
^{:key row-index}
|
||||
[rn/view {:style style/row-container}
|
||||
(for [column-index (range 1 4)]
|
||||
^{:key (str row-index column-index)}
|
||||
[keyboard-item
|
||||
{:item (+ (* (dec row-index) 3) column-index)
|
||||
:type :digit
|
||||
@@ -58,10 +60,10 @@
|
||||
:theme theme}]
|
||||
(if delete-key?
|
||||
[keyboard-item
|
||||
{:item :i/delete
|
||||
{:item :i/travel
|
||||
:type :key
|
||||
:disabled? disabled?
|
||||
:on-press on-press
|
||||
:on-press on-delete
|
||||
:blur? blur?
|
||||
:theme theme}]
|
||||
[keyboard-item])]]))
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
:padding-bottom 4
|
||||
:height 36
|
||||
:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
:justify-content :space-between
|
||||
;;
|
||||
:background-color :pink
|
||||
})
|
||||
|
||||
(def token
|
||||
{:width 32
|
||||
@@ -22,14 +25,12 @@
|
||||
|
||||
(defn text-input
|
||||
[theme]
|
||||
(merge typography/heading-1
|
||||
{:font-weight "600"
|
||||
:margin-left 8
|
||||
:margin-right (if platform/ios? 6 4)
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:padding 0
|
||||
:text-align :center
|
||||
:height "100%"}))
|
||||
(assoc typography/heading-1
|
||||
:font-weight "600"
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:padding 0
|
||||
;; TODO: fix the padding
|
||||
:height "100%"))
|
||||
|
||||
(defn divider
|
||||
[width theme]
|
||||
|
||||
@@ -1,73 +1,107 @@
|
||||
(ns quo.components.wallet.token-input.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.dividers.divider-line.view :as divider-line]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.network-tags.view :as network-tag]
|
||||
[quo.components.wallet.token-input.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.common :as common]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
[clojure.string :as string]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.dividers.divider-line.view :as divider-line]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.network-tags.view :as network-tag]
|
||||
[quo.components.wallet.token-input.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.common :as common]
|
||||
[oops.core :as oops]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn calc-value
|
||||
[crypto? currency token value conversion]
|
||||
(if crypto?
|
||||
(str (get common/currency-label currency) (.toFixed (* value conversion) 2))
|
||||
(str (.toFixed (/ value conversion) 2) " " (string/upper-case (clj->js token)))))
|
||||
(let [num-value (if (string? value) (parse-double (or value "0")) value)]
|
||||
(if crypto?
|
||||
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2))
|
||||
(str (.toFixed (/ num-value conversion) 2) " " (string/upper-case (or (clj->js token) ""))))))
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [width (:width (rn/get-window))
|
||||
value (reagent/atom 0)
|
||||
value (reagent/atom nil)
|
||||
crypto? (reagent/atom true)
|
||||
input-ref (atom nil)]
|
||||
(fn [{:keys [theme token currency conversion networks title customization-color]}]
|
||||
[rn/view {:style (style/main-container width)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[rn/pressable
|
||||
{:on-press #(when @input-ref (.focus ^js @input-ref))
|
||||
:style {:flex-direction :row
|
||||
:flex-grow 1
|
||||
:align-items :flex-end}}
|
||||
[rn/image
|
||||
{:style style/token
|
||||
:source (resources/get-token token)}]
|
||||
[rn/text-input
|
||||
{:ref #(reset! input-ref %)
|
||||
:placeholder "0"
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)
|
||||
:keyboard-type :numeric
|
||||
:max-length 12
|
||||
:default-value @value
|
||||
:on-change-text #(reset! value %)
|
||||
:style (style/text-input theme)
|
||||
:selection-color customization-color}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:margin-right 8
|
||||
:padding-bottom 2}}
|
||||
(string/upper-case (clj->js (if @crypto? token currency)))]]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press #(swap! crypto? not)
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style {:margin-vertical 8}}]
|
||||
[rn/view {:style style/data-container}
|
||||
[network-tag/view {:networks networks :title title}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
(calc-value @crypto? currency token @value conversion)]]])))
|
||||
(fn [{:keys [theme token currency conversion networks title customization-color
|
||||
on-swap container-style show-keyboard?]
|
||||
:or {show-keyboard? true}
|
||||
external-value :value}]
|
||||
(let [number-of-chars (count (or external-value @value))
|
||||
text-unit-position (+ 23
|
||||
(* (if (<= number-of-chars 1)
|
||||
0
|
||||
(- number-of-chars 1))
|
||||
15.333))]
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/main-container width)
|
||||
container-style)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[rn/pressable
|
||||
{:on-press #(when @input-ref (.focus ^js @input-ref))
|
||||
:style {:flex 1
|
||||
:background-color :orange
|
||||
}}
|
||||
[rn/image
|
||||
{:style style/token
|
||||
:source (resources/get-token token)}]
|
||||
|
||||
|
||||
[rn/view {:style {:background-color :lightblue
|
||||
;;
|
||||
:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 40
|
||||
:right 0
|
||||
}}
|
||||
[rn/text-input
|
||||
{:ref #(reset! input-ref %)
|
||||
:auto-focus true
|
||||
:placeholder "0"
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-50
|
||||
theme)
|
||||
:default-value (or external-value @value)
|
||||
:keyboard-type :numeric
|
||||
:max-length 12
|
||||
:on-change-text #(reset! value %)
|
||||
:style (style/text-input theme)
|
||||
:selection-color customization-color
|
||||
:show-soft-input-on-focus show-keyboard?}]
|
||||
;;
|
||||
[rn/view {:style {:position :absolute
|
||||
:bottom 1
|
||||
:left text-unit-position}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
(string/upper-case (or (clj->js (if @crypto? token currency)) ""))]]]]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap
|
||||
(on-swap @crypto?)))
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style {:margin-vertical 8}}]
|
||||
[rn/view {:style style/data-container}
|
||||
[network-tag/view {:networks networks :title title}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
(calc-value @crypto? currency token (or external-value @value) conversion)]]]))))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
|
||||
;;;; Counter
|
||||
(def counter quo.components.counter.counter.view/view)
|
||||
(def step quo.components.counter.step.view/view)
|
||||
(def step #'quo.components.counter.step.view/view)
|
||||
|
||||
;;;; Dividers
|
||||
(def divider-label quo.components.dividers.divider-label.view/view)
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")
|
||||
:bored-ape (js/require "../resources/images/mock2/bored-ape.png")})
|
||||
|
||||
(def ui-themed
|
||||
{:no-funds
|
||||
{:light (js/require "../resources/images/ui2/no-funds-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-funds-dark.png")}})
|
||||
|
||||
(defn get-themed-image
|
||||
[k theme]
|
||||
(get-in ui-themed [k theme]))
|
||||
|
||||
(defn get-image
|
||||
[k]
|
||||
(get ui k))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Schemas
|
||||
|
||||
This document will grow to describe how we use Malli in the project and our
|
||||
conventions. It's still early days 🐪
|
||||
|
||||
## Guidelines
|
||||
### Use var quote `#'` when aliasing instrumented vars
|
||||
|
||||
It is common in this repository to have aliases to vars. For example, `view`
|
||||
referring to `var-internal`, or `quo.core/button` referring to
|
||||
`quo.components.buttons.button.view`.
|
||||
|
||||
If the original var being aliased is instrumented, the alias var MUST [var
|
||||
quote](https://clojure.org/guides/weird_characters#_var_quote) the original var.
|
||||
If you don't do this, the aliased var will not be instrumented.
|
||||
|
||||
```clojure
|
||||
;; bad, view-internal is instrumented, but both aliases don't use a var quote.
|
||||
(schema.core/=> view-internal ?schema)
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
(def button quo.components.buttons.button.view/button)
|
||||
|
||||
;; good
|
||||
(schema.core/=> view-internal ?schema)
|
||||
(def view (quo.theme/with-theme #'view-internal))
|
||||
(def button #'quo.components.buttons.button.view/button)
|
||||
```
|
||||
|
||||
### Prefix schema references with `?`
|
||||
|
||||
Prefix schema bindings and vars with a question mark `?`. This is the naming
|
||||
convention used by malli itself when functions receive instances of schemas and
|
||||
it's an unambiguous way to avoid naming clashes.
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
(def message-type [:enum ...])
|
||||
|
||||
(defn view
|
||||
[message-type] ; Shadows `message-type` schema
|
||||
(do-something message-type))
|
||||
|
||||
;; good
|
||||
(def ?message-type [:enum ...])
|
||||
|
||||
(defn view
|
||||
[message-type] ; Unambiguous naming strategy
|
||||
(do-something message-type))
|
||||
```
|
||||
|
||||
### Define schemas as functions when needed
|
||||
|
||||
Malli has many utility functions to manipulate schemas as data, and they will
|
||||
automatically check if the schemas were already defined in the registry.
|
||||
|
||||
For schemas we want to conveniently access from the global registry, like
|
||||
`:schema.common/theme`, they must be registered before Malli tries to use them.
|
||||
|
||||
```clojure
|
||||
;; bad, will fail if :schema.common/bar is not registered.
|
||||
(def ^:private ?foo
|
||||
(malli.util/select-keys :schema.common/bar [:id :name]))
|
||||
|
||||
;; good, execution will be delayed until the schema ?foo is correctly registered.
|
||||
(defn- ?foo
|
||||
[]
|
||||
(malli.util/select-keys :schema.common/bar [:id :name]))
|
||||
```
|
||||
@@ -0,0 +1,14 @@
|
||||
(ns schema.common
|
||||
(:require
|
||||
[schema.registry :as registry]))
|
||||
|
||||
(def ^:private ?theme
|
||||
[:enum :light :dark])
|
||||
|
||||
(def ^:private ?customization-color
|
||||
[:or :string :keyword])
|
||||
|
||||
(defn register-schemas
|
||||
[]
|
||||
(registry/register ::theme ?theme)
|
||||
(registry/register ::customization-color ?customization-color))
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns schema.core)
|
||||
|
||||
(defmacro =>
|
||||
"Similar to `malli.core/=>`, but instrumentation code will be completely removed
|
||||
in non-debug environments.
|
||||
|
||||
`value` is first transformed via `malli.core/schema` to make sure we fail fast
|
||||
and only register valid schemas."
|
||||
[sym value]
|
||||
`(if ^boolean js/goog.DEBUG
|
||||
(try
|
||||
(malli.core/=> ~sym (malli.core/schema ~value))
|
||||
(catch js/Error e#
|
||||
(taoensso.timbre/error "Failed to instrument function"
|
||||
{:symbol ~sym :error e#})
|
||||
~sym))
|
||||
~sym))
|
||||
@@ -0,0 +1,95 @@
|
||||
(ns schema.core
|
||||
(:require-macros schema.core)
|
||||
(:require
|
||||
[malli.core :as malli]
|
||||
[malli.dev.pretty :as malli.pretty]
|
||||
schema.state
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(goog-define throw-on-error? false)
|
||||
|
||||
(defn- ui-reporter
|
||||
"Prints to STDOUT and signals a schema error should be displayed on screen."
|
||||
[schema-id printer]
|
||||
(let [report (malli.pretty/reporter printer)]
|
||||
(fn [type data]
|
||||
(report type data)
|
||||
(swap! schema.state/errors conj schema-id))))
|
||||
|
||||
(defn- thrower
|
||||
"Similar to `malli.dev.pretty/thrower`, but this reporter uses js/Error instead
|
||||
of ex-info, otherwise invalid schema errors will be printed in one long and
|
||||
incomprehensible line in unit test failures."
|
||||
([] (thrower (malli.pretty/-printer)))
|
||||
([printer]
|
||||
(let [report (malli.pretty/reporter printer)]
|
||||
(fn [type data]
|
||||
(let [message (with-out-str (report type data))]
|
||||
(throw (js/Error. (str "\n" message))))))))
|
||||
|
||||
(defn reporter
|
||||
([]
|
||||
(reporter nil nil))
|
||||
([schema-id]
|
||||
(reporter schema-id nil))
|
||||
([schema-id opts]
|
||||
(let [printer (malli.pretty/-printer
|
||||
(merge {:width 60
|
||||
:print-length 6
|
||||
:print-level 3
|
||||
:print-meta false}
|
||||
opts))]
|
||||
(if throw-on-error?
|
||||
;; The thrower reporter should be used to short-circuit tests on schema errors.
|
||||
(thrower printer)
|
||||
(ui-reporter schema-id printer)))))
|
||||
|
||||
(defn- with-clear-schema-error
|
||||
"Clears current schema error on app if args passed to `f` are valid."
|
||||
[schema-id validate-input f]
|
||||
(fn [& args]
|
||||
(when (validate-input args)
|
||||
(swap! schema.state/errors disj schema-id))
|
||||
(apply f args)))
|
||||
|
||||
(defn instrument
|
||||
"Similar to `malli/-instrument`, but will automatically clear up visible schema
|
||||
errors if `f` is called with valid arguments.
|
||||
|
||||
We use a validator cached by `malli.core/validator`, so that validation is
|
||||
performed once.
|
||||
|
||||
If `?schema` is invalid, then behave like a nop, log the error and return `f`.
|
||||
|
||||
`schema-id` is optional, but should be passed when instrumenting anonymous
|
||||
functions. Consider using a namespaced keyword. For example:
|
||||
|
||||
(schema/instrument ::foo
|
||||
(fn [x] (inc x))
|
||||
[:=> [:cat :int] :int])
|
||||
"
|
||||
([f ?schema]
|
||||
(if ^boolean js/goog.DEBUG
|
||||
(let [schema-id (when (var? f) (symbol f))]
|
||||
(when-not schema-id
|
||||
(log/warn "Anonymous function instrumented without an explicit identifier."
|
||||
{:schema ?schema}))
|
||||
(instrument schema-id f ?schema))
|
||||
f))
|
||||
([schema-id f ?schema]
|
||||
(if ^boolean js/goog.DEBUG
|
||||
(try
|
||||
(let [?schema (malli/schema ?schema)
|
||||
{schema-input :input} (malli/-function-info ?schema)
|
||||
[validate-input _] (malli/-vmap malli/validator [schema-input])]
|
||||
(malli/-instrument {:schema ?schema
|
||||
:report (reporter schema-id
|
||||
{:title (str "Schema error at " schema-id)})}
|
||||
(with-clear-schema-error schema-id validate-input f)))
|
||||
(catch js/Error e
|
||||
(log/error "Failed to instrument function"
|
||||
{:schema-id schema-id
|
||||
:error e
|
||||
:function f})
|
||||
f))
|
||||
f)))
|
||||
@@ -0,0 +1,26 @@
|
||||
(ns schema.registry
|
||||
(:refer-clojure :exclude [merge])
|
||||
(:require
|
||||
[malli.core :as malli]
|
||||
malli.registry))
|
||||
|
||||
(defonce ^:private registry
|
||||
(atom (malli/default-schemas)))
|
||||
|
||||
(defn init-global-registry
|
||||
[]
|
||||
(malli.registry/set-default-registry! (malli.registry/mutable-registry registry)))
|
||||
|
||||
(defn register
|
||||
"Defines a new schema in mutable `registry`.
|
||||
|
||||
We normalize `?schema` by always registering it as a proper instance of
|
||||
`malli.core/Schema` to avoid inconsistencies down the road."
|
||||
[type ?schema]
|
||||
(swap! registry assoc type (malli/schema ?schema))
|
||||
?schema)
|
||||
|
||||
(defn merge
|
||||
[& schemas]
|
||||
(apply swap! registry cljs.core/merge schemas)
|
||||
schemas)
|
||||
@@ -0,0 +1,11 @@
|
||||
(ns schema.state
|
||||
(:require [reagent.core :as reagent]))
|
||||
|
||||
(def errors
|
||||
"Set of schema identifiers, usually namespaced keywords. When the set is empty,
|
||||
no schema errors will be displayed on the app. See `schema.view/view`."
|
||||
(reagent/atom #{}))
|
||||
|
||||
(defn clear-errors
|
||||
[]
|
||||
(reset! errors #{}))
|
||||
@@ -0,0 +1,28 @@
|
||||
(ns schema.style)
|
||||
|
||||
(defn container
|
||||
[{:keys [bottom-inset]}]
|
||||
{:align-items :center
|
||||
:flex-direction :row
|
||||
:background-color "#cc0000"
|
||||
:border-bottom-left-radius 8
|
||||
:border-top-left-radius 8
|
||||
:justify-content :center
|
||||
:padding-vertical 6
|
||||
:padding-right 16
|
||||
:position :absolute
|
||||
:bottom (+ 12 bottom-inset)
|
||||
:right 0
|
||||
:z-index 10000000})
|
||||
|
||||
(def icon
|
||||
{:margin-horizontal 8})
|
||||
|
||||
(def text
|
||||
{:font-family "Inter-SemiBold"
|
||||
:font-size 13
|
||||
:color "#ddd"})
|
||||
|
||||
(def text-suffix
|
||||
{:font-style :italic
|
||||
:font-size 9})
|
||||
@@ -0,0 +1,18 @@
|
||||
(ns schema.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
schema.state
|
||||
[schema.style :as style]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(when (seq @schema.state/errors)
|
||||
[rn/pressable
|
||||
{:on-press schema.state/clear-errors
|
||||
:style (style/container {:bottom-inset (safe-area/get-bottom)})}
|
||||
[quo/icon :i/close {:size 12 :color "#ddd" :container-style style/icon}]
|
||||
[rn/text {:style style/text}
|
||||
"Schema error(s)"
|
||||
[rn/text {:style (merge style/text style/text-suffix)} " check logs"]]]))
|
||||
@@ -8,6 +8,7 @@
|
||||
status-im.subs.root
|
||||
status-im2.setup.i18n-resources
|
||||
[status-im2.setup.interceptors :as interceptors]
|
||||
[status-im2.setup.schema :as schema]
|
||||
status-im2.subs.root
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -118,6 +119,7 @@
|
||||
[& args]
|
||||
(reset-test-data!)
|
||||
(interceptors/register-global-interceptors)
|
||||
(schema/setup!)
|
||||
(rf/set-mergeable-keys #{:filters/load-filters
|
||||
:pairing/set-installation-metadata
|
||||
:dispatch-n
|
||||
|
||||
@@ -131,6 +131,13 @@
|
||||
:accessibility-label :appearance-settings-button
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :quo-preview])}])
|
||||
(when config/quo-preview-enabled?
|
||||
[list.item/list-item
|
||||
{:icon :main-icons/appearance
|
||||
:title "Status IM Components"
|
||||
:accessibility-label :status-im-common-components
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :status-im-preview])}])
|
||||
[list.item/list-item
|
||||
{:icon :main-icons/appearance
|
||||
:title (i18n/label :t/appearance)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
(ns status-im2.common.floating-button-page.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[status-im2.common.floating-button-page.view :as floating-button-page]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "floating button page"
|
||||
(h/test "renders with a header and standard button"
|
||||
(h/render [floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :title-description
|
||||
:title "floating button page"
|
||||
:description "press right icon to swap button type"
|
||||
:text-align :left
|
||||
:background :blur
|
||||
:icon-name :i/close}]
|
||||
:footer [quo/button {} "continue"]}])
|
||||
(h/is-truthy (h/get-by-text "continue"))
|
||||
(h/is-truthy (h/get-by-text "floating button page")))
|
||||
|
||||
(h/test "renders with a header and a slide button"
|
||||
(h/render [floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :title-description
|
||||
:title "floating button page"
|
||||
:description "press right icon to swap button type"
|
||||
:text-align :left
|
||||
:background :blur
|
||||
:icon-name :i/close}]
|
||||
:footer [quo/slide-button
|
||||
{:track-text "We gotta slide"
|
||||
:track-icon :face-id}]}])
|
||||
(h/is-truthy (h/get-by-text "We gotta slide"))))
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns status-im2.common.floating-button-page.floating-container.style
|
||||
(:require [react-native.safe-area :as safe-area]))
|
||||
|
||||
(defn content-container
|
||||
[blur? keyboard-shown?]
|
||||
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
|
||||
(cond-> {:margin-top :auto
|
||||
:overflow :hidden
|
||||
:margin-bottom margin-bottom
|
||||
:padding-vertical 12
|
||||
:padding-horizontal 20}
|
||||
blur? (dissoc :padding-vertical :padding-horizontal))))
|
||||
|
||||
(def blur-inner-container
|
||||
{:background-color :transparent ; required, otherwise blur-view will shrink
|
||||
:padding-vertical 12
|
||||
:padding-horizontal 20})
|
||||
@@ -0,0 +1,25 @@
|
||||
(ns status-im2.common.floating-button-page.floating-container.view
|
||||
(:require [quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.common.floating-button-page.floating-container.style :as style]))
|
||||
|
||||
(defn- blur-container
|
||||
[child theme]
|
||||
[blur/view
|
||||
{:blur-amount 12
|
||||
:blur-radius 12
|
||||
:blur-type (quo.theme/theme-value :light :dark theme)}
|
||||
[rn/view {:style style/blur-inner-container}
|
||||
child]])
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [theme on-layout keyboard-shown? blur?]} child]
|
||||
[rn/view
|
||||
{:style (style/content-container blur? keyboard-shown?)
|
||||
:on-layout on-layout}
|
||||
(if blur?
|
||||
[blur-container child theme]
|
||||
child)])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,15 @@
|
||||
(ns status-im2.common.floating-button-page.style)
|
||||
|
||||
(def page-container
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def keyboard-avoiding-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
@@ -0,0 +1,102 @@
|
||||
(ns status-im2.common.floating-button-page.view
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.floating-button-page.floating-container.view :as floating-container]
|
||||
[status-im2.common.floating-button-page.style :as style]))
|
||||
|
||||
(defn- show-background
|
||||
[{:keys [window-height keyboard-height footer-container-height content-scroll-y
|
||||
content-container-height header-height keyboard-shown?]}]
|
||||
(let [available-space (- window-height
|
||||
(safe-area/get-top)
|
||||
header-height
|
||||
keyboard-height ; Already contains the bottom safe area value
|
||||
footer-container-height)
|
||||
scroll-view-height (- content-container-height content-scroll-y)
|
||||
overlap? (< available-space scroll-view-height)]
|
||||
(and keyboard-shown? overlap?)))
|
||||
|
||||
(defn- set-height-on-layout
|
||||
[ratom]
|
||||
(fn [event]
|
||||
(let [height (oops/oget event "nativeEvent.layout.height")]
|
||||
(reset! ratom height))))
|
||||
|
||||
(defn- init-keyboard-listeners
|
||||
[{:keys [on-did-show]}]
|
||||
(let [keyboard-will-show? (reagent/atom false)
|
||||
keyboard-did-show? (reagent/atom false)
|
||||
add-listener (fn [listener callback]
|
||||
(oops/ocall rn/keyboard "addListener" listener callback))
|
||||
will-show-listener (add-listener "keyboardWillShow"
|
||||
#(reset! keyboard-will-show? true))
|
||||
did-show-listener (add-listener "keyboardDidShow"
|
||||
(fn [e]
|
||||
(reset! keyboard-did-show? true)
|
||||
(when on-did-show (on-did-show e))))
|
||||
will-hide-listener (add-listener "keyboardWillHide"
|
||||
#(reset! keyboard-will-show? false))
|
||||
did-hide-listener (add-listener "keyboardDidHide"
|
||||
#(reset! keyboard-did-show? false))
|
||||
remove-listeners (fn []
|
||||
(doseq [listener [will-show-listener will-hide-listener
|
||||
did-show-listener did-hide-listener]]
|
||||
(oops/ocall listener "remove")))]
|
||||
{:keyboard-will-show? keyboard-will-show?
|
||||
:keyboard-did-show? keyboard-did-show?
|
||||
:remove-listeners remove-listeners}))
|
||||
|
||||
(defn view
|
||||
[{:keys [header footer]} & children]
|
||||
(reagent/with-let [window-height (:height (rn/get-window))
|
||||
footer-container-height (reagent/atom 0)
|
||||
header-height (reagent/atom 0)
|
||||
content-container-height (reagent/atom 0)
|
||||
content-scroll-y (reagent/atom 0)
|
||||
keyboard-height (reagent/atom 0)
|
||||
{:keys [keyboard-will-show?
|
||||
keyboard-did-show?
|
||||
remove-listeners]} (init-keyboard-listeners
|
||||
{:on-did-show
|
||||
(fn [e]
|
||||
(reset! keyboard-height
|
||||
(oops/oget e "endCoordinates.height")))})
|
||||
set-header-height (set-height-on-layout header-height)
|
||||
set-content-container-height (set-height-on-layout content-container-height)
|
||||
set-footer-container-height (set-height-on-layout footer-container-height)
|
||||
set-content-y-scroll (fn [event]
|
||||
(reset! content-scroll-y
|
||||
(oops/oget event "nativeEvent.contentOffset.y")))]
|
||||
(let [keyboard-shown? (if platform/ios? @keyboard-will-show? @keyboard-did-show?)
|
||||
show-background? (show-background {:window-height window-height
|
||||
:footer-container-height @footer-container-height
|
||||
:keyboard-height @keyboard-height
|
||||
:content-scroll-y @content-scroll-y
|
||||
:content-container-height @content-container-height
|
||||
:header-height @header-height
|
||||
:keyboard-shown? keyboard-shown?})]
|
||||
|
||||
[rn/view {:style style/page-container}
|
||||
[rn/view {:on-layout set-header-height}
|
||||
header]
|
||||
[rn/scroll-view
|
||||
{:on-scroll set-content-y-scroll
|
||||
:scroll-event-throttle 64
|
||||
:content-container-style {:flex-grow 1}}
|
||||
(into [rn/view {:on-layout set-content-container-height}]
|
||||
children)]
|
||||
[rn/keyboard-avoiding-view
|
||||
{:style style/keyboard-avoiding-view
|
||||
:keyboard-vertical-offset (if platform/ios? (safe-area/get-top) 0)
|
||||
:pointer-events :box-none}
|
||||
[floating-container/view
|
||||
{:on-layout set-footer-container-height
|
||||
:keyboard-shown? keyboard-shown?
|
||||
:blur? show-background?}
|
||||
footer]]])
|
||||
(finally
|
||||
(remove-listeners))))
|
||||
@@ -31,10 +31,10 @@
|
||||
:on-change-text #(reset! entered-password %)}]
|
||||
(when (not-empty error)
|
||||
[quo/info-message
|
||||
{:type :error
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:style {:margin-top 8}}
|
||||
{:type :error
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:containstyle {:margin-top 8}}
|
||||
(i18n/label :t/oops-wrong-password)])
|
||||
[quo/button
|
||||
{:container-style {:margin-bottom 12 :margin-top 40}
|
||||
|
||||
@@ -79,7 +79,19 @@
|
||||
:dark (js/require "../resources/images/ui2/no-contacts-to-invite-dark.png")}
|
||||
:no-notifications
|
||||
{:light (js/require "../resources/images/ui2/no-notifications-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-notifications-dark.png")}})
|
||||
:dark (js/require "../resources/images/ui2/no-notifications-dark.png")}
|
||||
:no-activity
|
||||
{:light (js/require "../resources/images/ui2/no-activity-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-activity-dark.png")}
|
||||
:no-collectibles
|
||||
{:light (js/require "../resources/images/ui2/no-collectibles-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-collectibles-dark.png")}
|
||||
:no-dapps
|
||||
{:light (js/require "../resources/images/ui2/no-dapps-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-dapps-dark.png")}
|
||||
:no-permissions
|
||||
{:light (js/require "../resources/images/ui2/no-permissions-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-permissions-dark.png")}})
|
||||
|
||||
(def mock-images
|
||||
{:bored-ape (js/require "../resources/images/mock2/bored-ape.png")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
(ns status-im2.common.standard-authentication.core
|
||||
(:require
|
||||
status-im2.common.standard-authentication.standard-auth.button.view
|
||||
status-im2.common.standard-authentication.standard-auth.slide-button.view))
|
||||
|
||||
(def button status-im2.common.standard-authentication.standard-auth.button.view/view)
|
||||
(def slide-button status-im2.common.standard-authentication.standard-auth.slide-button.view/view)
|
||||
@@ -1,10 +1,6 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.view
|
||||
(ns status-im2.common.standard-authentication.standard-auth.authorize
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.touch-id :as biometric]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.enter-password.view :as enter-password]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -46,39 +42,3 @@
|
||||
{:on-enter-password on-enter-password
|
||||
:button-icon-left auth-button-icon-left
|
||||
:button-label auth-button-label}])}]))))))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
track-text
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
size
|
||||
theme
|
||||
blur?
|
||||
container-style]}]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/slide-button
|
||||
{:size size
|
||||
:container-style container-style
|
||||
:customization-color customization-color
|
||||
:on-reset (when @reset-slider? #(reset! reset-slider? false))
|
||||
:on-complete #(authorize {:on-close on-close
|
||||
:auth-button-icon-left auth-button-icon-left
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? biometric-auth?
|
||||
:on-auth-success on-auth-success
|
||||
:on-auth-fail on-auth-fail
|
||||
:auth-button-label auth-button-label})
|
||||
:track-icon (if biometric-auth? :i/face-id :password)
|
||||
:track-text track-text}]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,44 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.button.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-press
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
size
|
||||
button-label
|
||||
theme
|
||||
blur?
|
||||
container-style
|
||||
icon-left]}]
|
||||
[quo/button
|
||||
{:size size
|
||||
:container-style container-style
|
||||
:customization-color customization-color
|
||||
:icon-left icon-left
|
||||
:on-press (if on-press
|
||||
on-press
|
||||
#(authorize/authorize {:on-close on-close
|
||||
:auth-button-icon-left auth-button-icon-left
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? biometric-auth?
|
||||
:on-auth-success on-auth-success
|
||||
:on-auth-fail on-auth-fail
|
||||
:auth-button-label auth-button-label}))}
|
||||
button-label])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,43 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.slide-button.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
track-text
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
size
|
||||
theme
|
||||
blur?
|
||||
container-style]}]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/slide-button
|
||||
{:size size
|
||||
:container-style container-style
|
||||
:customization-color customization-color
|
||||
:on-reset (when @reset-slider? #(reset! reset-slider? false))
|
||||
:on-complete #(authorize/authorize {:on-close on-close
|
||||
:auth-button-icon-left auth-button-icon-left
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? biometric-auth?
|
||||
:on-auth-success on-auth-success
|
||||
:on-auth-fail on-auth-fail
|
||||
:auth-button-label auth-button-label})
|
||||
:track-icon (if biometric-auth? :i/face-id :password)
|
||||
:track-text track-text}]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -1,15 +1,20 @@
|
||||
(ns status-im2.contexts.onboarding.enable-biometrics.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.common.biometric.events :as biometric]
|
||||
[status-im2.common.parallax.view :as parallax]
|
||||
[status-im2.common.parallax.whitelist :as whitelist]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.common.standard-authentication.core :as standard-auth]
|
||||
[status-im2.contexts.onboarding.enable-biometrics.style :as style]
|
||||
[status-im2.navigation.state :as state]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
|
||||
(defn page-title
|
||||
[]
|
||||
@@ -21,22 +26,39 @@
|
||||
:description-accessibility-label :enable-biometrics-sub-title}])
|
||||
|
||||
(defn enable-biometrics-buttons
|
||||
[insets]
|
||||
[insets theme]
|
||||
(let [supported-biometric-type (rf/sub [:biometric/supported-type])
|
||||
bio-type-label (biometric/get-label-by-type supported-biometric-type)
|
||||
profile-color (:color (rf/sub [:onboarding-2/profile]))]
|
||||
profile-color (or (:color (rf/sub [:onboarding-2/profile]))
|
||||
(rf/sub [:profile/customization-color]))
|
||||
syncing-results? (= :syncing-results @state/root-id)]
|
||||
[rn/view {:style (style/buttons insets)}
|
||||
[quo/button
|
||||
{:accessibility-label :enable-biometrics-button
|
||||
:on-press #(rf/dispatch [:onboarding-2/enable-biometrics])
|
||||
:icon-left :i/face-id
|
||||
:customization-color profile-color}
|
||||
(i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})]
|
||||
[standard-auth/button
|
||||
(merge
|
||||
{:size 40
|
||||
:accessibility-label :enable-biometrics-button
|
||||
:icon-left :i/face-id
|
||||
:customization-color profile-color
|
||||
:button-label (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})}
|
||||
(if syncing-results?
|
||||
{:theme theme
|
||||
:blur? true
|
||||
:on-enter-password (fn [entered-password]
|
||||
(rf/dispatch
|
||||
[:onboarding-2/authenticate-enable-biometrics
|
||||
(security/safe-unmask-data
|
||||
entered-password)])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
:auth-button-label (i18n/label :t/confirm)}
|
||||
{:on-press #(rf/dispatch [:onboarding-2/enable-biometrics])}))]
|
||||
[quo/button
|
||||
{:accessibility-label :maybe-later-button
|
||||
:background :blur
|
||||
:type :grey
|
||||
:on-press #(rf/dispatch [:onboarding-2/create-account-and-login])
|
||||
:on-press #(rf/dispatch (if syncing-results?
|
||||
[:navigate-to-within-stack
|
||||
[:enable-notifications :enable-biometrics]]
|
||||
[:onboarding-2/create-account-and-login]))
|
||||
:container-style {:margin-top 12}}
|
||||
(i18n/label :t/maybe-later)]]))
|
||||
|
||||
@@ -55,12 +77,19 @@
|
||||
:style (style/page-illustration width)
|
||||
:source (resources/get-image :biometrics)}]))
|
||||
|
||||
(defn enable-biometrics
|
||||
[]
|
||||
(defn f-enable-biometrics
|
||||
[{:keys [theme]}]
|
||||
(let [insets (safe-area/get-insets)]
|
||||
[rn/view {:style (style/page-container insets)}
|
||||
[page-title]
|
||||
(if whitelist/whitelisted?
|
||||
[enable-biometrics-parallax]
|
||||
[enable-biometrics-simple])
|
||||
[enable-biometrics-buttons insets]]))
|
||||
[enable-biometrics-buttons insets theme]]))
|
||||
|
||||
|
||||
(defn- internale-enable-biometrics
|
||||
[params]
|
||||
[:f> f-enable-biometrics params])
|
||||
|
||||
(def view (quo.theme/with-theme internale-enable-biometrics))
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
[quo/page-nav
|
||||
{:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press #(rf/dispatch [:navigate-back-within-stack :new-to-status])}]
|
||||
:on-press #(rf/dispatch [:navigate-back-within-stack :enable-biometrics])}]
|
||||
[page-title]
|
||||
[rn/view {:style style/page-illustration}
|
||||
[quo/text
|
||||
|
||||
@@ -35,11 +35,30 @@
|
||||
{:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done])
|
||||
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}})
|
||||
|
||||
(rf/defn authenticate-enable-biometrics
|
||||
{:events [:onboarding-2/authenticate-enable-biometrics]}
|
||||
[{:keys [db]} password]
|
||||
{:db (-> db
|
||||
(assoc-in [:onboarding-2/profile :password] password)
|
||||
(assoc-in [:onboarding-2/profile :syncing?] true))
|
||||
:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done])
|
||||
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}})
|
||||
|
||||
(rf/defn navigate-to-enable-notifications
|
||||
{:events [:onboarding-2/navigate-to-enable-notifications]}
|
||||
[{:keys [db]}]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:db (dissoc db :onboarding-2/profile)
|
||||
:dispatch [:navigate-to-within-stack [:enable-notifications :enable-biometrics]]}))
|
||||
|
||||
(rf/defn biometrics-done
|
||||
{:events [:onboarding-2/biometrics-done]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:onboarding-2/profile :auth-method] constants/auth-method-biometric)
|
||||
:dispatch [:onboarding-2/create-account-and-login]})
|
||||
(let [syncing? (get-in db [:onboarding-2/profile :syncing?])]
|
||||
{:db (assoc-in db [:onboarding-2/profile :auth-method] constants/auth-method-biometric)
|
||||
:dispatch (if syncing?
|
||||
[:onboarding-2/finalize-setup]
|
||||
[:onboarding-2/create-account-and-login])}))
|
||||
|
||||
(rf/defn biometrics-fail
|
||||
{:events [:onboarding-2/biometrics-fail]}
|
||||
@@ -83,6 +102,14 @@
|
||||
[:navigate-to-within-stack [:enable-biometrics :new-to-status]]
|
||||
[:onboarding-2/create-account-and-login])}))
|
||||
|
||||
(rf/defn navigate-to-enable-biometrics
|
||||
{:events [:onboarding-2/navigate-to-enable-biometrics]}
|
||||
[{:keys [db]}]
|
||||
(let [supported-type (:biometric/supported-type db)]
|
||||
{:dispatch (if supported-type
|
||||
[:open-modal :enable-biometrics]
|
||||
[:open-modal :enable-notifications])}))
|
||||
|
||||
(rf/defn seed-phrase-entered
|
||||
{:events [:onboarding-2/seed-phrase-entered]}
|
||||
[_ seed-phrase on-error]
|
||||
@@ -120,6 +147,7 @@
|
||||
[{:keys [db]}]
|
||||
(let [masked-password (get-in db [:onboarding-2/profile :password])
|
||||
key-uid (get-in db [:profile/profile :key-uid])
|
||||
syncing? (get-in db [:onboarding-2/profile :syncing?])
|
||||
biometric-enabled? (= (get-in db [:onboarding-2/profile :auth-method])
|
||||
constants/auth-method-biometric)]
|
||||
(cond-> {:db (assoc db :onboarding-2/generated-keys? true)}
|
||||
@@ -127,7 +155,10 @@
|
||||
(assoc :keychain/save-password-and-auth-method
|
||||
{:key-uid key-uid
|
||||
:masked-password masked-password
|
||||
:on-success #(log/debug "successfully saved biometric")
|
||||
:on-success (fn []
|
||||
(if syncing?
|
||||
(rf/dispatch [:onboarding-2/navigate-to-enable-notifications])
|
||||
(log/error "successfully saved biometrics")))
|
||||
:on-error #(log/error "failed to save biometrics"
|
||||
{:key-uid key-uid
|
||||
:error %})}))))
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
{:on-press (fn []
|
||||
(when on-press
|
||||
(on-press))
|
||||
(rf/dispatch [:open-modal :enable-notifications]))
|
||||
(rf/dispatch [:onboarding-2/navigate-to-enable-biometrics]))
|
||||
:accessibility-label :continue-button
|
||||
:customization-color profile-color
|
||||
:container-style style/continue-button}
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
[{:keys [theme title]}]
|
||||
(let [logged-in? (rf/sub [:multiaccount/logged-in?])
|
||||
has-profiles? (boolean (rf/sub [:profile/profiles-overview]))
|
||||
root (if has-profiles? :profiles :intro)
|
||||
light? (= theme :light)]
|
||||
[quo/page-nav
|
||||
{:type :title
|
||||
:title "quo components preview"
|
||||
:title title
|
||||
:text-align :left
|
||||
:icon-name :i/close
|
||||
:right-side [{:icon-name (if light? :i/dark :i/light)
|
||||
|
||||
@@ -26,4 +26,4 @@
|
||||
:descriptor descriptor
|
||||
:blur? (:in-blur-view? @state)
|
||||
:show-blur-background? (:in-blur-view? @state)}
|
||||
[quo/step @state (:value @state)]])))
|
||||
[quo/step (dissoc @state :value) (:value @state)]])))
|
||||
|
||||
@@ -487,7 +487,7 @@
|
||||
(defn- main-screen
|
||||
[]
|
||||
[:<>
|
||||
[common/navigation-bar]
|
||||
[common/navigation-bar {:title "Quo components preview"}]
|
||||
[rn/scroll-view {:style (style/main)}
|
||||
(for [category (sort screens-categories)]
|
||||
^{:key (first category)}
|
||||
|
||||
@@ -317,10 +317,10 @@
|
||||
children)])
|
||||
|
||||
(defn- f-preview-container
|
||||
[{:keys [state descriptor blur? blur-dark-only?
|
||||
[{:keys [title state descriptor blur? blur-dark-only?
|
||||
component-container-style
|
||||
blur-container-style blur-view-props blur-height show-blur-background?]
|
||||
:or {blur-height 200}}
|
||||
:or {blur-height 200 title "quo component"}}
|
||||
& children]
|
||||
(let [theme (quo.theme/use-theme-value)]
|
||||
(rn/use-effect (fn []
|
||||
@@ -332,7 +332,7 @@
|
||||
[rn/view
|
||||
{:style {:top (safe-area/get-top)
|
||||
:flex 1}}
|
||||
[common/navigation-bar]
|
||||
[common/navigation-bar {:title title}]
|
||||
[rn/scroll-view
|
||||
{:style (style/panel-basic)
|
||||
:shows-vertical-scroll-indicator false}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
(ns status-im2.contexts.status-im-preview.common.floating-button-page.style
|
||||
(:require [quo.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(defn container
|
||||
[]
|
||||
{:flex 1
|
||||
:margin-top (safe-area/get-top)})
|
||||
|
||||
(def background-image
|
||||
{:position :absolute
|
||||
:top (- (safe-area/get-top))
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 200})
|
||||
|
||||
(defn page-content
|
||||
[height]
|
||||
{:flex 1
|
||||
:height height
|
||||
:overflow :hidden
|
||||
:background-color (colors/resolve-color :army 30)})
|
||||
@@ -0,0 +1,55 @@
|
||||
(ns status-im2.contexts.status-im-preview.common.floating-button-page.view
|
||||
(:require [quo.core :as quo]
|
||||
[re-frame.core :as rf]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.status-im-preview.common.floating-button-page.style :as style]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [content-height (reagent/atom 450)
|
||||
slide? (reagent/atom false)]
|
||||
(fn []
|
||||
[rn/view {:style (style/container)}
|
||||
(when-not @slide?
|
||||
[rn/image
|
||||
{:style style/background-image
|
||||
:source (resources/get-mock-image :dark-blur-bg)}])
|
||||
[floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :title-description
|
||||
:title "floating button page"
|
||||
:description "press right icon to swap button type"
|
||||
:text-align :left
|
||||
:right-side [{:icon-name :i/swap
|
||||
:on-press #(swap! slide? not)}]
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
:footer (if @slide?
|
||||
[quo/slide-button
|
||||
{:track-text "We gotta slide"
|
||||
:track-icon :face-id
|
||||
:container-style {:z-index 2}
|
||||
:customization-color :blue
|
||||
:on-complete #(js/alert "button slid")}
|
||||
"Save address"]
|
||||
[quo/button
|
||||
{:container-style {:z-index 2}
|
||||
:on-press #(js/alert "button pressed")}
|
||||
"Save address"])}
|
||||
[rn/view {:style (style/page-content @content-height)}
|
||||
[quo/text {:size :heading-1} "Page Content"]
|
||||
[quo/input
|
||||
{:auto-focus true
|
||||
:value ""}]
|
||||
[quo/button
|
||||
{:type :outline
|
||||
:on-press #(swap! content-height (fn [v] (+ v 10)))}
|
||||
"increase height"]
|
||||
[quo/button
|
||||
{:type :outline
|
||||
:on-press #(swap! content-height (fn [v] (- v 10)))}
|
||||
"decrease height"]]]])))
|
||||
@@ -0,0 +1,59 @@
|
||||
(ns status-im2.contexts.status-im-preview.main
|
||||
(:refer-clojure :exclude [filter])
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.quo-preview.common :as common]
|
||||
[status-im2.contexts.status-im-preview.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im2.contexts.status-im-preview.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def screens-categories
|
||||
{:common [{:name :floating-button-page
|
||||
:component floating-button-page/view}]})
|
||||
|
||||
(defn- category-view
|
||||
[]
|
||||
(let [open? (reagent/atom false)
|
||||
on-press #(swap! open? not)]
|
||||
(fn [category]
|
||||
[rn/view {:style {:margin-vertical 8}}
|
||||
[quo/dropdown
|
||||
{:type :grey
|
||||
:state (if @open? :active :default)
|
||||
:on-press on-press}
|
||||
(name (key category))]
|
||||
(when @open?
|
||||
(for [{category-name :name} (val category)]
|
||||
^{:key category-name}
|
||||
[quo/button
|
||||
{:type :outline
|
||||
:container-style {:margin-vertical 8}
|
||||
:on-press #(rf/dispatch [:navigate-to category-name])}
|
||||
(name category-name)]))])))
|
||||
|
||||
(defn- main-screen
|
||||
[]
|
||||
[:<>
|
||||
[common/navigation-bar {:title "Status IM components"}]
|
||||
[rn/scroll-view {:style (style/main)}
|
||||
(for [category (sort screens-categories)]
|
||||
^{:key (first category)}
|
||||
[category-view category])]])
|
||||
|
||||
(def screens
|
||||
(->> screens-categories
|
||||
(map val)
|
||||
flatten
|
||||
(map (fn [subcategory]
|
||||
(update-in subcategory
|
||||
[:options :topBar]
|
||||
merge
|
||||
{:visible false})))))
|
||||
|
||||
(def main-screens
|
||||
[{:name :status-im-preview
|
||||
:options {:topBar {:visible false}
|
||||
:insets {:top? true}}
|
||||
:component main-screen}])
|
||||
@@ -0,0 +1,10 @@
|
||||
(ns status-im2.contexts.status-im-preview.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn main
|
||||
[]
|
||||
{:flex 1
|
||||
:padding-bottom 8
|
||||
:padding-horizontal 16
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-90)})
|
||||
@@ -8,7 +8,7 @@
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.qr-codes.view :as qr-codes]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.common.standard-authentication.standard-auth.view :as standard-auth]
|
||||
[status-im2.common.standard-authentication.core :as standard-auth]
|
||||
[status-im2.contexts.syncing.setup-syncing.style :as style]
|
||||
[status-im2.contexts.syncing.utils :as sync-utils]
|
||||
[utils.datetime :as datetime]
|
||||
@@ -119,7 +119,7 @@
|
||||
(i18n/label :t/copy-qr)]])
|
||||
(when-not (sync-utils/valid-connection-string? @code)
|
||||
[rn/view {:style style/standard-auth}
|
||||
[standard-auth/view
|
||||
[standard-auth/slide-button
|
||||
{:blur? true
|
||||
:size :size-40
|
||||
:track-text (i18n/label :t/slide-to-reveal-code)
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.wallet.account.tabs.dapps.style :as style]
|
||||
[status-im2.contexts.wallet.common.empty-tab.view :as empty-tab]
|
||||
[status-im2.contexts.wallet.common.temp :as temp]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn dapp-options
|
||||
[]
|
||||
@@ -23,13 +22,12 @@
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [dapps-list (temp/dapps-list {:on-press-icon #(rf/dispatch [:show-bottom-sheet
|
||||
{:content dapp-options}])})]
|
||||
(let [dapps-list []]
|
||||
(if (empty? dapps-list)
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-dapps)
|
||||
:description (i18n/label :t/no-collectibles-description)
|
||||
:placeholder? true}]
|
||||
{:title (i18n/label :t/no-dapps)
|
||||
:description (i18n/label :t/no-dapps-description)
|
||||
:image (resources/get-themed-image :no-dapps theme)}]
|
||||
[rn/view {:style style/dapps-container}
|
||||
[rn/flat-list
|
||||
{:data dapps-list
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
(ns status-im2.contexts.wallet.account.tabs.view
|
||||
(:require
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.wallet.account.tabs.about.view :as about]
|
||||
[status-im2.contexts.wallet.account.tabs.dapps.view :as dapps]
|
||||
[status-im2.contexts.wallet.common.activity-tab.view :as activity]
|
||||
@@ -10,8 +12,8 @@
|
||||
[status-im2.contexts.wallet.common.token-value.view :as token-value]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn view
|
||||
[{:keys [selected-tab]}]
|
||||
(defn- view-internal
|
||||
[{:keys [selected-tab theme]}]
|
||||
(case selected-tab
|
||||
:assets [rn/flat-list
|
||||
{:render-fn token-value/view
|
||||
@@ -20,8 +22,13 @@
|
||||
:collectibles [collectibles/view]
|
||||
:activity [activity/view]
|
||||
:permissions [empty-tab/view
|
||||
{:title (i18n/label :t/no-permissions)
|
||||
:description (i18n/label :t/no-collectibles-description)
|
||||
:placeholder? true}]
|
||||
{:title (i18n/label :t/no-permissions)
|
||||
:description (i18n/label :t/no-collectibles-description)
|
||||
:image (resources/get-image
|
||||
(quo.theme/theme-value :no-permissions-light
|
||||
:no-permissions-dark
|
||||
theme))}]
|
||||
:dapps [dapps/view]
|
||||
[about/view]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
[{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab}
|
||||
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
|
||||
{:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}
|
||||
{:id :permissions :label (i18n/label :t/permissions) :accessibility-label :permissions}
|
||||
{:id :dapps :label (i18n/label :t/dapps) :accessibility-label :dapps}
|
||||
{:id :about :label (i18n/label :t/about) :accessibility-label :about}])
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
(ns status-im2.contexts.wallet.add-address-to-watch.component-spec
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.contexts.wallet.add-address-to-watch.view :as add-address-to-watch]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn setup-subs
|
||||
[subscriptions]
|
||||
(doseq [keyval subscriptions]
|
||||
(re-frame/reg-sub
|
||||
(key keyval)
|
||||
(fn [_] (val keyval)))))
|
||||
|
||||
(h/describe "select address for watch only account"
|
||||
(h/test "validation messages show for already used addressed"
|
||||
(setup-subs {:wallet/scanned-address nil
|
||||
:wallet/addresses (set
|
||||
["0x12E838Ae1f769147b12956485dc56e57138f3AC8"
|
||||
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"])
|
||||
:profile/customization-color :blue})
|
||||
(h/render [add-address-to-watch/view])
|
||||
(h/is-falsy (h/query-by-label-text :error-message))
|
||||
(h/fire-event :change-text
|
||||
(h/get-by-label-text :add-address-to-watch)
|
||||
"0x12E838Ae1f769147b12956485dc56e57138f3AC8")
|
||||
(h/is-truthy (h/get-by-translation-text :address-already-in-use))))
|
||||
|
||||
(h/test "validation messages show for invalid address"
|
||||
(setup-subs {:wallet/scanned-address nil
|
||||
:wallet/addresses (set
|
||||
["0x12E838Ae1f769147b12956485dc56e57138f3AC8"
|
||||
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"])
|
||||
:profile/customization-color :blue})
|
||||
(h/render [add-address-to-watch/view])
|
||||
(h/is-falsy (h/query-by-label-text :error-message))
|
||||
(h/fire-event :change-text (h/get-by-label-text :add-address-to-watch) "0x12E838Ae1f769147b")
|
||||
(h/is-truthy (h/get-by-translation-text :invalid-address)))
|
||||
|
||||
@@ -3,18 +3,7 @@
|
||||
(def container
|
||||
{:flex 1})
|
||||
|
||||
(def input
|
||||
{:margin-right 12
|
||||
:flex 1})
|
||||
|
||||
(def data-item
|
||||
{:margin-horizontal 20
|
||||
:padding-vertical 8
|
||||
:padding-horizontal 12})
|
||||
|
||||
(defn button-container
|
||||
[bottom]
|
||||
{:position :absolute
|
||||
:bottom (+ bottom 12)
|
||||
:left 20
|
||||
:right 20})
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
@@ -14,13 +13,12 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- view-internal
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [address]} (rf/sub [:get-screen-params])
|
||||
number-of-accounts (count (rf/sub [:profile/wallet-accounts]))
|
||||
account-name (reagent/atom (i18n/label :t/default-account-name
|
||||
{:number (inc number-of-accounts)}))
|
||||
address-title (i18n/label :t/watch-address)
|
||||
account-color (reagent/atom (rand-nth colors/account-colors))
|
||||
account-emoji (reagent/atom (emoji-picker.utils/random-emoji))
|
||||
on-change-name #(reset! account-name %)
|
||||
@@ -40,8 +38,9 @@
|
||||
:on-change-name on-change-name
|
||||
:on-change-color on-change-color
|
||||
:on-change-emoji on-change-emoji
|
||||
:watch-only? true
|
||||
:bottom-action? true
|
||||
:bottom-action-label :t/create-account
|
||||
:bottom-action-label :t/add-watched-address
|
||||
:bottom-action-props {:customization-color @account-color
|
||||
:disabled? (string/blank? @account-name)
|
||||
:on-press #(re-frame/dispatch [:navigate-to
|
||||
@@ -51,11 +50,9 @@
|
||||
:right-icon :i/advanced
|
||||
:icon-right? true
|
||||
:emoji @account-emoji
|
||||
:title address-title
|
||||
:title (i18n/label :t/watched-address)
|
||||
:subtitle address
|
||||
:status :default
|
||||
:size :default
|
||||
:container-style style/data-item
|
||||
:on-press #(js/alert "To be implemented")}]]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -5,13 +5,24 @@
|
||||
:margin-top 12
|
||||
:margin-bottom 20})
|
||||
|
||||
(def input-container
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 20
|
||||
:align-items :flex-end})
|
||||
|
||||
(def button-container
|
||||
{:position :absolute
|
||||
:bottom 22
|
||||
:left 20
|
||||
:right 20})
|
||||
|
||||
(def scan
|
||||
{:align-self
|
||||
:flex-end})
|
||||
|
||||
(def input
|
||||
{:flex 1
|
||||
:margin-right 12})
|
||||
|
||||
(def input-container
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20})
|
||||
|
||||
(def info-message
|
||||
{:margin-top 8
|
||||
:margin-left 20})
|
||||
|
||||
@@ -2,51 +2,114 @@
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.wallet.add-address-to-watch.style :as style]
|
||||
[status-im2.contexts.wallet.common.validation :as validation]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view-internal
|
||||
(defn validate-message
|
||||
[addresses]
|
||||
(fn [s]
|
||||
(cond
|
||||
(or (= s nil) (= s "")) nil
|
||||
(contains? addresses s) (i18n/label :t/address-already-in-use)
|
||||
(not (or (validation/eth-address? s)
|
||||
(validation/ens-name? s))) (i18n/label :t/invalid-address)
|
||||
:else nil)))
|
||||
|
||||
(defn- address-input
|
||||
[{:keys [input-value validation-msg validate
|
||||
clear-input]}]
|
||||
(let [scanned-address (rf/sub [:wallet/scanned-address])
|
||||
empty-input? (and (string/blank? @input-value)
|
||||
(string/blank? scanned-address))
|
||||
|
||||
on-change-text (fn [new-text]
|
||||
(reset! validation-msg (validate new-text))
|
||||
(reset! input-value new-text)
|
||||
(when (and scanned-address (not= scanned-address new-text))
|
||||
(rf/dispatch [:wallet/clean-scanned-address])))
|
||||
paste-on-input #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
(on-change-text clipboard-text)))]
|
||||
(rn/use-effect (fn []
|
||||
(when-not (string/blank? scanned-address)
|
||||
(on-change-text scanned-address)))
|
||||
[scanned-address])
|
||||
[rn/view
|
||||
{:style style/input-container}
|
||||
[quo/input
|
||||
{:accessibility-label :add-address-to-watch
|
||||
:placeholder (i18n/label :t/address-placeholder)
|
||||
:container-style style/input
|
||||
:label (i18n/label :t/eth-or-ens)
|
||||
:auto-capitalize :none
|
||||
:multiline? true
|
||||
:on-clear clear-input
|
||||
:return-key-type :done
|
||||
:clearable? (not empty-input?)
|
||||
:on-change-text on-change-text
|
||||
:button (when empty-input?
|
||||
{:on-press paste-on-input
|
||||
:text (i18n/label :t/paste)})
|
||||
:value @input-value}]
|
||||
[quo/button
|
||||
{:type :outline
|
||||
:on-press (fn []
|
||||
(rn/dismiss-keyboard!)
|
||||
(rf/dispatch [:open-modal :scan-address]))
|
||||
:container-style style/scan
|
||||
:size 40
|
||||
:icon-only? true}
|
||||
:i/scan]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [input-value (reagent/atom "")
|
||||
(let [addresses (rf/sub [:wallet/addresses])
|
||||
input-value (reagent/atom nil)
|
||||
validate (validate-message (set addresses))
|
||||
validation-msg (reagent/atom (validate
|
||||
@input-value))
|
||||
clear-input (fn []
|
||||
(reset! input-value nil)
|
||||
(reset! validation-msg nil)
|
||||
(rf/dispatch [:wallet/clean-scanned-address]))
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(fn []
|
||||
[rn/view
|
||||
{:style {:flex 1}}
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:navigate-back]))}]
|
||||
[quo/text-combinations
|
||||
{:container-style style/header-container
|
||||
:title (i18n/label :t/add-address)
|
||||
:description (i18n/label :t/enter-eth)}]
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/input
|
||||
{:label (i18n/label :t/eth-or-ens)
|
||||
:button {:on-press (fn [] (clipboard/get-string #(reset! input-value %)))
|
||||
:text (i18n/label :t/paste)}
|
||||
:placeholder (str "0x123abc... " (string/lower-case (i18n/label :t/or)) " bob.eth")
|
||||
:container-style {:margin-right 12
|
||||
:flex 1}
|
||||
:weight :monospace
|
||||
:on-change-text #(reset! input-value %)
|
||||
:default-value @input-value}]
|
||||
[quo/button
|
||||
{:icon-only? true
|
||||
:type :outline} :i/scan]]
|
||||
[:f> address-input
|
||||
{:input-value input-value
|
||||
:validate validate
|
||||
:validation-msg validation-msg
|
||||
:clear-input clear-input}]
|
||||
(when @validation-msg
|
||||
[quo/info-message
|
||||
{:accessibility-label :error-message
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:type :error
|
||||
:style style/info-message}
|
||||
@validation-msg])
|
||||
[quo/button
|
||||
{:customization-color customization-color
|
||||
:disabled? (clojure.string/blank? @input-value)
|
||||
:on-press #(re-frame/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address @input-value}])
|
||||
:disabled? (string/blank? @input-value)
|
||||
:on-press #(rf/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address @input-value}])
|
||||
:container-style style/button-container}
|
||||
(i18n/label :t/continue)]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
(ns status-im2.contexts.wallet.common.activity-tab.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.wallet.common.empty-tab.view :as empty-tab]
|
||||
[status-im2.contexts.wallet.common.temp :as temp]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn activity-item
|
||||
@@ -14,15 +15,17 @@
|
||||
(merge {:on-press #(js/alert "Item pressed")}
|
||||
item)]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [activity-list temp/activity-list]
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [activity-list []]
|
||||
(if (empty? activity-list)
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-activity)
|
||||
:description (i18n/label :t/empty-tab-description)
|
||||
:placeholder? true}]
|
||||
{:title (i18n/label :t/no-activity)
|
||||
:description (i18n/label :t/empty-tab-description)
|
||||
:image (resources/get-themed-image :no-activity theme)}]
|
||||
[rn/flat-list
|
||||
{:data activity-list
|
||||
:style {:flex 1}
|
||||
:render-fn activity-item}])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
(ns status-im2.contexts.wallet.common.collectibles-tab.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.wallet.common.empty-tab.view :as empty-tab]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [collectible-list (rf/sub [:wallet/collectibles])]
|
||||
(if (empty? collectible-list)
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-collectibles)
|
||||
:description (i18n/label :t/no-collectibles-description)
|
||||
:placeholder? true}]
|
||||
{:title (i18n/label :t/no-collectibles)
|
||||
:description (i18n/label :t/no-collectibles-description)
|
||||
:image (resources/get-themed-image :no-collectibles theme)}]
|
||||
[rn/flat-list
|
||||
{:data collectible-list
|
||||
:style {:flex 1}
|
||||
@@ -25,3 +27,5 @@
|
||||
:on-press #(rf/dispatch
|
||||
[:navigate-to
|
||||
:wallet-collectible])}])}])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im2.contexts.wallet.common.screen-base.create-or-edit-account.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.constants :as constants]
|
||||
@@ -8,12 +7,12 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- view-internal
|
||||
(defn view
|
||||
[{:keys [margin-top? page-nav-right-side account-name account-color account-emoji on-change-name
|
||||
on-change-color
|
||||
on-change-emoji on-focus on-blur section-label bottom-action?
|
||||
bottom-action-label bottom-action-props
|
||||
custom-bottom-action]} & children]
|
||||
custom-bottom-action watch-only?]} & children]
|
||||
(let [{:keys [top bottom]} (safe-area/get-insets)
|
||||
margin-top (if (false? margin-top?) 0 top)
|
||||
{window-width :width} (rn/get-window)]
|
||||
@@ -36,7 +35,7 @@
|
||||
{:customization-color account-color
|
||||
:size 80
|
||||
:emoji account-emoji
|
||||
:type :default}]
|
||||
:type (if watch-only? :watch-only :default)}]
|
||||
[quo/button
|
||||
{:size 32
|
||||
:type :grey
|
||||
@@ -81,5 +80,3 @@
|
||||
:type :primary}
|
||||
bottom-action-props)
|
||||
(i18n/label bottom-action-label)])])]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
(ns status-im2.contexts.wallet.common.sheets.account-options.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
quo.theme
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.wallet.common.sheets.account-options.style :as style]
|
||||
[status-im2.contexts.wallet.common.temp :as temp]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [{:keys [name color emoji address]} (rf/sub [:wallet/current-viewing-account])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
@@ -26,7 +29,13 @@
|
||||
:on-press #(rf/dispatch [:navigate-to :wallet-edit-account])}
|
||||
{:icon :i/copy
|
||||
:accessibility-label :copy-address
|
||||
:label (i18n/label :t/copy-address)}
|
||||
:label (i18n/label :t/copy-address)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:icon :i/correct
|
||||
:icon-color (colors/resolve-color :success theme)
|
||||
:text (i18n/label :t/address-copied)}])
|
||||
(clipboard/set-string address))}
|
||||
{:icon :i/share
|
||||
:accessibility-label :share-account
|
||||
:label (i18n/label :t/share-account)}
|
||||
@@ -42,3 +51,5 @@
|
||||
{:data temp/other-accounts
|
||||
:render-fn (fn [account] [quo/account-item {:account-props account}])
|
||||
:style {:margin-horizontal 8}}]]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-create-account])}
|
||||
"Create Account"]
|
||||
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-saved-addresses])}
|
||||
"Saved Addresses"]])
|
||||
"Saved Addresses"]
|
||||
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-send-input-amount])}
|
||||
"Send: input amount"]])
|
||||
|
||||
(defn wallet-overview-state
|
||||
[networks]
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns status-im2.contexts.wallet.common.validation
|
||||
(:require [status-im2.constants :as constants]))
|
||||
|
||||
(defn ens-name? [s] (re-find constants/regx-ens s))
|
||||
(defn eth-address? [s] (re-find constants/regx-address s))
|
||||
@@ -7,7 +7,7 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.view :as standard-auth]
|
||||
[status-im2.common.standard-authentication.core :as standard-auth]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.emoji-picker.utils :as emoji-picker.utils]
|
||||
[status-im2.contexts.wallet.common.utils :as utils]
|
||||
@@ -114,7 +114,7 @@
|
||||
{:list-type :settings
|
||||
:label (i18n/label :t/origin)
|
||||
:data (get-keypair-data primary-name @derivation-path @account-color)}]
|
||||
[standard-auth/view
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-create-account)
|
||||
:customization-color @account-color
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
(defn- new-account-card-data
|
||||
[]
|
||||
{:customization-color (rf/sub [:profile/customization-color])
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet {:content new-account}])
|
||||
:on-press #(rf/dispatch [:navigate-to :wallet-send-input-amount
|
||||
] ;[:show-bottom-sheet {:content new-account}]
|
||||
)
|
||||
:type :add-account})
|
||||
|
||||
(def tabs-data
|
||||
@@ -53,10 +55,7 @@
|
||||
[common.top-nav/view]
|
||||
[rn/view {:style style/overview-container}
|
||||
[quo/wallet-overview (temp/wallet-overview-state networks)]]
|
||||
[rn/pressable
|
||||
{:on-long-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content temp/wallet-temporary-navigation}])}
|
||||
[quo/wallet-graph {:time-frame :empty}]]
|
||||
[quo/wallet-graph {:time-frame :empty}]
|
||||
[rn/flat-list
|
||||
{:style style/accounts-list
|
||||
:content-container-style style/accounts-list-container
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
(ns status-im2.contexts.wallet.send.input-amount.component-spec
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.contexts.wallet.send.input-amount.view :as input-amount]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn setup-subs
|
||||
[subscriptions]
|
||||
(doseq [keyval subscriptions]
|
||||
(re-frame/reg-sub
|
||||
(key keyval)
|
||||
(fn [_] (val keyval)))))
|
||||
|
||||
(def sub-mocks
|
||||
{:profile/profile {:currency :usd}
|
||||
:wallet/network-details [{:source 525
|
||||
:short-name "eth"
|
||||
:network-name :ethereum
|
||||
:chain-id 1
|
||||
:related-chain-id 5}]})
|
||||
|
||||
(h/describe "Send > input amount screen"
|
||||
(h/test "Default render"
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view {}])
|
||||
(h/is-truthy (h/get-by-text "0"))
|
||||
(h/is-truthy (h/get-by-text "ETH"))
|
||||
(h/is-truthy (h/get-by-text "$0.00"))
|
||||
(h/is-disabled (h/get-by-label-text :button-one)))
|
||||
|
||||
(h/test "Fill token input and confirm"
|
||||
(setup-subs sub-mocks)
|
||||
(let [on-confirm (h/mock-fn)]
|
||||
(h/render [input-amount/view {:on-confirm on-confirm}])
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-3))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-.))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-4))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "$1234.50")))
|
||||
|
||||
(h/is-truthy (h/get-by-label-text :button-one))
|
||||
|
||||
(h/fire-event :press (h/get-by-label-text :button-one))
|
||||
(h/was-called on-confirm)))
|
||||
|
||||
(h/test "Try to fill more than limit"
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view {}])
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "$290.00")))
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-backspace))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-8))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "$2850.00"))))
|
||||
|
||||
(h/test "Switch from crypto to fiat and check limit"
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view {}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-0))
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "$200.00")))
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :reorder))
|
||||
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "2.00 ETH")))
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH")))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH")))))
|
||||
@@ -0,0 +1,8 @@
|
||||
(ns status-im2.contexts.wallet.send.input-amount.style)
|
||||
|
||||
(def screen
|
||||
{:flex 1})
|
||||
|
||||
(def input-container
|
||||
{:padding-top 12
|
||||
:padding-bottom 0})
|
||||
@@ -0,0 +1,93 @@
|
||||
(ns status-im2.contexts.wallet.send.input-amount.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.wallet.send.input-amount.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- make-limit-label
|
||||
[{:keys [amount currency]}]
|
||||
(str amount " " (string/upper-case (name currency))))
|
||||
|
||||
(defn- make-new-input
|
||||
[current v]
|
||||
(let [dot "."
|
||||
max-length 12
|
||||
length-owerflow? (>= (count current) max-length)
|
||||
ignore-extra-dot? (and (= v dot) (string/includes? current dot))
|
||||
ignore-value? (or
|
||||
ignore-extra-dot?
|
||||
length-owerflow?)]
|
||||
(if ignore-value?
|
||||
current
|
||||
(str current v))))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [token :eth
|
||||
{:keys [currency]} (rf/sub [:profile/profile])
|
||||
networks (rf/sub [:wallet/network-details])
|
||||
conversion-rate 10
|
||||
limit-crypto 100000000
|
||||
limit-fiat (* limit-crypto conversion-rate)
|
||||
input-value (reagent/atom "")
|
||||
current-limit (reagent/atom {:amount limit-crypto
|
||||
:currency token})
|
||||
handle-swap (fn [crypto?]
|
||||
(let [num-value (parse-double @input-value)]
|
||||
(reset! current-limit (if crypto?
|
||||
{:amount limit-crypto
|
||||
:currency token}
|
||||
{:amount limit-fiat
|
||||
:currency currency}))
|
||||
(when (> num-value (:amount @current-limit))
|
||||
(reset! input-value ""))))
|
||||
handle-keyboard-press (fn [v]
|
||||
(let [current-value @input-value
|
||||
new-value (make-new-input current-value v)
|
||||
num-value (parse-double new-value)]
|
||||
(when (<= num-value (:amount @current-limit))
|
||||
(reset! input-value new-value))))
|
||||
handle-delete (fn [_]
|
||||
(swap! input-value #(subs % 0 (dec (count %)))))]
|
||||
(fn [{:keys [on-confirm]
|
||||
:or {on-confirm #(js/alert "Confirmed")}}]
|
||||
(let [limit-label (make-limit-label @current-limit)]
|
||||
[rn/view
|
||||
{:style style/screen}
|
||||
[quo/page-nav
|
||||
{:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:right-side :account-switcher
|
||||
:account-switcher {:customization-color :yellow
|
||||
:emoji "🎮"
|
||||
:on-press #(js/alert "Switch account")}}]
|
||||
[quo/token-input
|
||||
{:container-style style/input-container
|
||||
:token token
|
||||
:currency currency
|
||||
:networks networks
|
||||
:title (i18n/label :t/send-limit {:limit limit-label})
|
||||
:conversion conversion-rate
|
||||
:show-keyboard? false
|
||||
:value @input-value
|
||||
:on-swap handle-swap}]
|
||||
;; Network routing content to be added
|
||||
[rn/scroll-view]
|
||||
[quo/bottom-actions
|
||||
{:actions :1-action
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
:button-one-props {:disabled? (empty? @input-value)
|
||||
:on-press on-confirm}}]
|
||||
[quo/numbered-keyboard
|
||||
{:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press handle-keyboard-press
|
||||
:on-delete handle-delete}]]))))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -48,7 +48,7 @@
|
||||
(fn []
|
||||
(let [scanned-address (rf/sub [:wallet/scanned-address])
|
||||
send-address (rf/sub [:wallet/send-address])
|
||||
valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))]
|
||||
valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])]
|
||||
[quo/address-input
|
||||
{:on-focus #(reset! input-focused? true)
|
||||
:on-blur #(reset! input-focused? false)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
(ns status-im2.core-spec
|
||||
(:require
|
||||
[status-im2.common.floating-button-page.component-spec]
|
||||
[status-im2.contexts.chat.messages.content.audio.component-spec]
|
||||
[status-im2.contexts.communities.actions.community-options.component-spec]
|
||||
[status-im2.contexts.wallet.create-account.edit-derivation-path.component-spec]))
|
||||
[status-im2.contexts.wallet.add-address-to-watch.component-spec]
|
||||
[status-im2.contexts.wallet.create-account.edit-derivation-path.component-spec]
|
||||
[status-im2.contexts.wallet.send.input-amount.component-spec]))
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
[status-im2.contexts.shell.activity-center.view :as activity-center]
|
||||
[status-im2.contexts.shell.jump-to.view :as shell]
|
||||
[status-im2.contexts.shell.share.view :as share]
|
||||
[status-im2.contexts.status-im-preview.main :as status-im-preview]
|
||||
[status-im2.contexts.syncing.find-sync-code.view :as find-sync-code]
|
||||
[status-im2.contexts.syncing.how-to-pair.view :as how-to-pair]
|
||||
[status-im2.contexts.syncing.scan-sync-code-page.view :as scan-sync-code-page]
|
||||
@@ -46,8 +47,9 @@
|
||||
[status-im2.contexts.wallet.create-account.select-keypair.view :as wallet-select-keypair]
|
||||
[status-im2.contexts.wallet.create-account.view :as wallet-create-account]
|
||||
[status-im2.contexts.wallet.edit-account.view :as wallet-edit-account]
|
||||
[status-im2.contexts.wallet.saved-address.view :as wallet-saved-address]
|
||||
[status-im2.contexts.wallet.saved-addresses.view :as wallet-saved-addresses]
|
||||
[status-im2.contexts.wallet.scan-account.view :as scan-address]
|
||||
[status-im2.contexts.wallet.send.input-amount.view :as wallet-send-input-amount]
|
||||
[status-im2.contexts.wallet.send.select-address.view :as wallet-select-address]
|
||||
[status-im2.navigation.options :as options]
|
||||
[status-im2.navigation.transitions :as transitions]))
|
||||
@@ -161,11 +163,15 @@
|
||||
:component create-password/create-password}
|
||||
|
||||
{:name :enable-biometrics
|
||||
:options {:theme :dark
|
||||
:layout options/onboarding-transparent-layout
|
||||
:animations transitions/push-animations-for-transparent-background
|
||||
:popGesture false}
|
||||
:component enable-biometrics/enable-biometrics}
|
||||
:options {:theme :dark
|
||||
:layout options/onboarding-transparent-layout
|
||||
:animations (merge transitions/new-to-status-modal-animations
|
||||
transitions/push-animations-for-transparent-background)
|
||||
:popGesture false
|
||||
:modalPresentationStyle :overCurrentContext
|
||||
:hardwareBackButton {:dismissModalOnPress false
|
||||
:popStackOnPress false}}
|
||||
:component enable-biometrics/view}
|
||||
|
||||
{:name :generating-keys
|
||||
:options {:theme :dark
|
||||
@@ -279,8 +285,13 @@
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-create-account/view}
|
||||
|
||||
{:name :wallet-saved-address
|
||||
:component wallet-saved-address/view}
|
||||
{:name :wallet-saved-addresses
|
||||
:component wallet-saved-addresses/view}
|
||||
|
||||
{:name :wallet-send-input-amount
|
||||
:options {:modalPresentationStyle :overCurrentContext
|
||||
:insets {:top? true}}
|
||||
:component wallet-send-input-amount/view}
|
||||
|
||||
{:name :wallet-select-address
|
||||
:options {:modalPresentationStyle :overCurrentContext}
|
||||
@@ -301,4 +312,11 @@
|
||||
quo.preview/screens)
|
||||
|
||||
(when config/quo-preview-enabled?
|
||||
quo.preview/main-screens)))
|
||||
quo.preview/main-screens)
|
||||
|
||||
(when config/quo-preview-enabled?
|
||||
status-im-preview/screens)
|
||||
|
||||
(when config/quo-preview-enabled?
|
||||
status-im-preview/main-screens)))
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
schema.view
|
||||
[status-im.bottom-sheet.sheets :as bottom-sheets-old]
|
||||
[status-im.ui.screens.popover.views :as popover]
|
||||
[status-im.ui.screens.profile.visibility-status.views :as visibility-status-views]
|
||||
@@ -71,7 +72,9 @@
|
||||
[bottom-sheet-screen/view {:content component}]
|
||||
[component])]
|
||||
(when js/goog.DEBUG
|
||||
[reloader/reload-view])]))))
|
||||
[:<>
|
||||
[reloader/reload-view]
|
||||
[schema.view/view]])]))))
|
||||
|
||||
(def bottom-sheet
|
||||
(reagent/reactify-component
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require
|
||||
["react-native" :refer (DevSettings LogBox)]
|
||||
[react-native.platform :as platform]
|
||||
[status-im2.setup.schema :as schema]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; Ignore all logs, because there are lots of temporary warnings when developing and hot reloading
|
||||
@@ -45,10 +46,11 @@
|
||||
:group-chats/extract-membership-signature
|
||||
:utils/dispatch-later
|
||||
:json-rpc/call})
|
||||
|
||||
(when (and js/goog.DEBUG platform/ios? DevSettings)
|
||||
;;on Android this method doesn't work
|
||||
(when-let [nm (.-_nativeModule DevSettings)]
|
||||
;;there is a bug in RN, so we have to enable it first and then disable
|
||||
(.setHotLoadingEnabled ^js nm true)
|
||||
(js/setTimeout #(.setHotLoadingEnabled ^js nm false) 1000))))
|
||||
(when ^:boolean js/goog.DEBUG
|
||||
(schema/setup!)
|
||||
(when (and platform/ios? DevSettings)
|
||||
;;on Android this method doesn't work
|
||||
(when-let [nm (.-_nativeModule DevSettings)]
|
||||
;;there is a bug in RN, so we have to enable it first and then disable
|
||||
(.setHotLoadingEnabled ^js nm true)
|
||||
(js/setTimeout #(.setHotLoadingEnabled ^js nm false) 1000)))))
|
||||
|
||||