Compare commits

..
2 Commits
Author SHA1 Message Date
Ibrahem Khalil ae03891d2f Merge branch 'develop' into 17827 2023-11-13 16:58:28 +02:00
Ibrkhalil 01efd56d6f Fix text content when editing and reentering chat 2023-11-11 10:53:03 +02:00
145 changed files with 773 additions and 2441 deletions
+4 -12
View File
@@ -16,18 +16,10 @@
:clj-kondo-config {:level :error}
:cond-else {:level :error}
:consistent-alias {:level :error
:aliases {clojure.set set
clojure.string string
clojure.walk walk
malli.core malli
malli.dev.pretty malli.pretty
malli.dev.virhe malli.virhe
malli.error malli.error
malli.generator malli.generator
malli.transform malli.transform
malli.util malli.util
schema.core schema
taoensso.timbre log}}
:aliases {clojure.string string
clojure.set set
clojure.walk walk
taoensso.timbre log}}
:deprecated-namespace {:level :warning}
:docstring-blank {:level :error}
:equals-true {:level :error}
-2
View File
@@ -1,2 +0,0 @@
{:lint-as {malli.experimental/defn schema.core/defn}
:linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}
-1
View File
@@ -36,7 +36,6 @@
"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?]]}]
+5 -6
View File
@@ -311,14 +311,13 @@ endef
lint: export TARGET := clojure
lint: export CLJ_LINTER_PRINT_WARNINGS ?= false
lint: ##@test Run code style checks
@sh scripts/lint/re-frame-in-quo-components.sh && \
sh scripts/lint/direct-require-component-outside-quo.sh && \
sh scripts/lint/require-i18n-resource-first.sh && \
@sh scripts/lint-re-frame-in-quo-components.sh && \
sh scripts/lint-direct-require-component-outside-quo.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
scripts/lint/translations.clj && \
scripts/lint_translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \
sh scripts/lint-trailing-newline.sh && \
node_modules/.bin/prettier --write .
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
@@ -328,7 +327,7 @@ lint-fix: ##@test Run code style checks and fix issues
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
clojure-lsp --ns-exclude-regex ".*/src/status_im2/core\.cljs$$" clean-ns && \
sh scripts/lint/trailing-newline.sh --fix && \
sh scripts/lint-trailing-newline.sh --fix && \
node_modules/.bin/prettier --write .
shadow-server: export TARGET := clojure
+12 -48
View File
@@ -45,20 +45,11 @@
},
{
"path": "borkdude/dynaload/0.3.5/dynaload-0.3.5",
"path": "borkdude/edamame/1.1.17/edamame-1.1.17",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "accd696ba364b850b4d92e38f5a34d0e828a0ad1",
"sha256": "0k62m1f29xfh3cp67w7kcvkp5aj35simi8kf95ycvkmgp76w11q8"
}
},
{
"path": "borkdude/edamame/1.3.23/edamame-1.3.23",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "254d023e97ed438f0f44532b5a06d928d031ede4",
"sha256": "0l7mxza2nimslhg0qh6jp7gmb8sd6l89fk5d1zvzq2xskscq2vly"
"sha1": "9087f7abf0104e0354d7db7fc4576608eac558f4",
"sha256": "1n1872i240lakn4pzsag4grf7bv7lcsipmqllxd9m4k1zp3dgla1"
}
},
@@ -90,20 +81,20 @@
},
{
"path": "cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3",
"path": "cider/cider-nrepl/0.29.0/cider-nrepl-0.29.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "5ae0efd9377a5e60c084bdaf4a2ce094f759ce23",
"sha256": "0drxf9nm23i1pcgrkwbcr09msq37csilzww38709add0hz8spjhq"
"sha1": "45f6034b26a14138e74145b7a4059628c0fedcd1",
"sha256": "1dy1l6y8cb8xiqq97a4lf8giyiicq4wfl4s2lxn5fb6614cjxqx2"
}
},
{
"path": "cider/piggieback/0.4.1/piggieback-0.4.1",
"path": "cider/piggieback/0.5.2/piggieback-0.5.2",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "0a02a3e2ecd7a126ab60d8a44793342f20ced79b",
"sha256": "142vl5np33akcrnn6pksi0rjfsmmi528villxsj6cwcndvybiw4m"
"sha1": "ecfd5c286a85db3f059e75c37fca5722d9e26f79",
"sha256": "1ps9yf3cxmlm447hqkidjb5xry90n0wl3jk0jn28fagq31lzylkl"
}
},
@@ -548,24 +539,6 @@
}
},
{
"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",
@@ -755,15 +728,6 @@
}
},
{
"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",
@@ -945,11 +909,11 @@
},
{
"path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0",
"path": "refactor-nrepl/refactor-nrepl/3.6.0/refactor-nrepl-3.6.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207",
"sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i"
"sha1": "2b3bb82da53b5db9c2b2aa298417816b81d0ed97",
"sha256": "1ysqabmlnghki6x0636zngxza2d83c85276wp9ma9wk183mkv52a"
}
},
+4 -8
View File
@@ -3,13 +3,12 @@ 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/dynaload/0.3.5/dynaload-0.3.5.jar
borkdude/edamame/1.3.23/edamame-1.3.23.jar
borkdude/edamame/1.1.17/edamame-1.1.17.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.25.3/cider-nrepl-0.25.3.jar
cider/piggieback/0.4.1/piggieback-0.4.1.jar
cider/cider-nrepl/0.29.0/cider-nrepl-0.29.0.jar
cider/piggieback/0.5.2/piggieback-0.5.2.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
@@ -59,8 +58,6 @@ 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
@@ -82,7 +79,6 @@ 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
@@ -103,7 +99,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/2.5.0/refactor-nrepl-2.5.0.jar
refactor-nrepl/refactor-nrepl/3.6.0/refactor-nrepl-3.6.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
+3 -6
View File
@@ -67,12 +67,9 @@ stdenv.mkDerivation {
'';
buildPhase = ''
# Assemble CLASSPATH from available clojure dependencies.
# 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' ':')"
# We append 'src' so it can find the local sources.
export CLASS_PATH="$(find ${deps.clojure} \
-iname '*.jar' | tr '\n' ':')src"
# target must be one of the builds defined in shadow-cljs.edn
java -cp "$CLASS_PATH" clojure.main \
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

@@ -1,10 +0,0 @@
#!/usr/bin/env sh
if rg --quiet --multiline '^\(ns.*\n^\s*\(:require\n(^\s*(;|#_).*\n)*(^\s*\[status-im2\.setup\.i18n-resources\W)' src/status_im2/core.cljs; then
exit 0
elif [ $? -eq 1 ]; then
echo "status-im2.setup.i18n-resources must be loaded first (be the first one in ns :require form) in status-im2.core"
echo "For more info, check the comment here https://github.com/status-im/status-mobile/pull/17618#discussion_r1361275489"
else
exit $?
fi
+2 -18
View File
@@ -9,7 +9,6 @@
[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"]
@@ -51,7 +50,6 @@
: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
@@ -73,10 +71,6 @@
: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
@@ -110,15 +104,13 @@
: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
{schema.core/throw-on-error? true
status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
{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"
@@ -147,17 +139,9 @@
:compiler-options {:optimizations :simple
:source-map false}}
:component-test {:target :npm-module
: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]
:entries [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,22 +3,18 @@
[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"
(render [step/view {} nil])
(h/render [step/view {} nil])
(-> (h/expect (h/query-by-label-text :step-counter))
(h/is-truthy)))
(h/test "renders step with a string value"
(render [step/view {} "1"])
(h/render [step/view {} "1"])
(-> (h/expect (h/get-by-text "1"))
(h/is-truthy)))
(h/test "renders step with an integer value"
(render [step/view {} 1])
(h/render [step/view {} 1])
(-> (h/expect (h/get-by-text "1"))
(h/is-truthy))))
+3 -20
View File
@@ -2,24 +2,10 @@
(:require
[quo.components.counter.step.style :as style]
[quo.components.markdown.text :as text]
quo.theme
[quo.theme :as 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)
@@ -37,9 +23,6 @@
[text/text
{:weight :medium
:size :label
:style {:color (style/text-color type theme)}}
label]]))
:style {:color (style/text-color type theme)}} label]]))
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal ?schema)))
(def view (theme/with-theme view-internal))
@@ -19,7 +19,3 @@
:background-color colors/danger-50
:align-items :center
:justify-content :center})
(def empty-state
{:width 375
:height 116})
@@ -2,12 +2,11 @@
(: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
@@ -43,10 +42,11 @@
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)
[fast-image/fast-image
{:style style/empty-state
:source (resources/get-themed-image :no-funds theme)
:accessibility-label :illustration}]
[rn/view
{:accessibility-label :illustration
:style style/illustration}
[text/text {:style {:color colors/white}}
"Illustration here"]]
[rn/view
[linear-gradient/linear-gradient
{:colors gradient-colors
+19 -17
View File
@@ -3,17 +3,22 @@
[quo.components.icon :as quo.icons]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[quo.theme :as theme]
[react-native.core :as rn]))
(defn get-color
[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)))
(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 view-internal
(defn get-color
[k]
(get-in themes [(theme/get-theme) k]))
(defn info-message
"[info-message opts \"message\"]
opts
{:type :default/:success/:error
@@ -22,11 +27,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 theme icon text-color icon-color no-icon-color? style accessibility-label]} message]
[{:keys [type size icon text-color icon-color no-icon-color? style]} 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 theme))
text-color (or text-color (get-color type))
icon-color (or icon-color text-color)]
[rn/view
{:style (merge {:flex-direction :row
@@ -37,10 +42,7 @@
:no-color no-icon-color?
:size icon-size}]
[text/text
{: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))
{:size size
:weight weight
:style {:color text-color
:margin-horizontal 4}} message]]))
@@ -22,10 +22,9 @@
(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-with-theme-provider [list/view
{:type :step
:step-number 1}]
:dark)
(h/render [list/view
{:type :step
:step-number 1}])
(h/is-truthy (h/get-by-label-text :step-counter)))
(h/test "renders decription with a context tag component and description after the tag"
@@ -7,11 +7,6 @@
[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)]
@@ -19,11 +14,9 @@
(let [label-color (style/get-label-color disabled? theme blur?)
background-color (style/toggle-background-color @pressed? blur? theme)]
[rn/pressable
{:accessibility-label (label->accessibility-label label)
{:accessibility-label :keyboard-key
:disabled (or disabled? (not label))
:on-press (fn []
(when on-press
(on-press label)))
:on-press (fn [] (on-press label))
:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? false)
:style (style/container background-color)}
@@ -17,15 +17,13 @@
(defn- view-internal
[]
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete]
:or {left-action :none}}]
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press]}]
[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
@@ -63,7 +61,7 @@
{:item :i/delete
:type :key
:disabled? disabled?
:on-press on-delete
:on-press on-press
:blur? blur?
:theme theme}]
[keyboard-item])]]))
@@ -1,53 +0,0 @@
(ns quo.components.tags.summary-tag.component-spec
(:require
[quo.components.tags.summary-tag.view :as summary-tag]
[test-helpers.component :as h]))
(h/describe "Summary tag component tests"
(h/test "Basic render"
(h/render [summary-tag/view])
(h/is-truthy (h/query-by-label-text :container)))
(h/test "Account view render"
(h/render [summary-tag/view
{:type :account
:label "Alice's Account"
:customization-color "#ff0000"
:emoji "🎉"}])
(h/is-truthy (h/get-by-text "Alice's Account")))
(h/test "Network view render"
(h/render [summary-tag/view
{:type :network
:label "Ethereum Network"
:image-source "path/to/ethereum-logo.png"}])
(h/is-truthy (h/get-by-text "Ethereum Network")))
(h/test "Saved address view render"
(h/render [summary-tag/view
{:type :saved-address
:label "Charlie's Wallet"
:customization-color "#00ff00"}])
(h/is-truthy (h/get-by-text "Charlie's Wallet")))
(h/test "Collectible view render"
(h/render [summary-tag/view
{:type :collectible
:label "Rare Artifact"
:image-source "path/to/artifact-image.png"}])
(h/is-truthy (h/get-by-text "Rare Artifact")))
(h/test "User view render"
(h/render [summary-tag/view
{:type :user
:label "Bob Smith"
:image-source "path/to/profile-pic.png"
:customization-color "#0000ff"}])
(h/is-truthy (h/get-by-text "Bob Smith")))
(h/test "Token view render"
(h/render [summary-tag/view
{:type :token
:label "1,000 SNT"
:image-source "path/to/token-image.png"}])
(h/is-truthy (h/get-by-text "1,000 SNT"))))
@@ -1,29 +0,0 @@
(ns quo.components.tags.summary-tag.style
(:require
[quo.foundations.colors :as colors]))
(defn main
[{:keys [type theme customization-color]}]
{:justify-content :center
:align-items :center
:height 32
:padding-left 4
:padding-right 10
:flex-direction :row
:border-radius (if (#{:account :collectible} type) 10 16)
:background-color (colors/resolve-color customization-color theme 10)})
(defn label
[type theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
:margin-left (if (= type :address) 6 4)})
(def collectible-image
{:width 24
:height 24
:border-radius 10})
(def token-image
{:width 24
:height 24
:border-radius 12})
@@ -1,67 +0,0 @@
(ns quo.components.tags.summary-tag.view
(:require
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
[quo.components.markdown.text :as text]
[quo.components.tags.summary-tag.style :as style]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn- left-view
[{:keys [label type customization-color emoji image-source]}]
(case type
:account
[account-avatar/view
{:customization-color customization-color
:size 24
:emoji emoji
:type :default}]
:network
[rn/image
{:source image-source
:style style/token-image}]
:saved-address
[wallet-user-avatar/wallet-user-avatar
{:full-name label
:size :size-24
:customization-color customization-color}]
:collectible
[rn/image
{:source image-source
:style style/collectible-image}]
:user
[user-avatar/user-avatar
{:full-name label
:size :xs
:profile-picture image-source
:customization-color customization-color}]
:token
[rn/image
{:source image-source
:style style/token-image}]
nil))
(defn- view-internal
"Options:
- :label - string - tag label
- :customization-color - color - It will be passed down to components that
should vary based on a custom color.
- :type - :token / :user / :collectible / :saved-address / :network / :account
- :emoji - string - emoji used for displaying account avatar
- :image-source - resource - image to display on :network, :collectible :user and :token
- :theme - :light / :dark"
[{:keys [label customization-color type theme]
:as props
:or {customization-color colors/neutral-80-opa-5}}]
[rn/view
{:accessibility-label :container
:style (style/main (assoc props :customization-color customization-color))}
[left-view props]
[text/text
{:style (style/label type theme)
:weight :semi-bold
:size :heading-1} label]])
(def view (quo.theme/with-theme view-internal))
+43 -58
View File
@@ -1,39 +1,32 @@
(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]
[quo.foundations.resources :as resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
(defn calc-value
[crypto? currency token value conversion]
(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) ""))))))
(if crypto?
(str (get common/currency-label currency) (.toFixed (* value conversion) 2))
(str (.toFixed (/ value conversion) 2) " " (string/upper-case (clj->js token)))))
(defn- view-internal
[]
(let [width (:width (rn/get-window))
value (reagent/atom nil)
value (reagent/atom 0)
crypto? (reagent/atom true)
input-ref (atom nil)]
(fn [{:keys [theme token currency conversion networks title customization-color
on-swap container-style show-keyboard?]
:or {show-keyboard? true}
external-value :value}]
[rn/view
{:style (merge
(style/main-container width)
container-style)}
(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))
@@ -44,38 +37,30 @@
{:style style/token
:source (resources/get-token token)}]
[rn/text-input
{:ref #(do (reset! input-ref %)
(when %
(.focus ^js %)))
: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?}]]
[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 (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]
{: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}]
@@ -83,6 +68,6 @@
{: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)]]])))
(calc-value @crypto? currency token @value conversion)]]])))
(def view (quo.theme/with-theme view-internal))
+1 -3
View File
@@ -131,7 +131,6 @@
quo.components.tags.number-tag.view
quo.components.tags.permission-tag
quo.components.tags.status-tags
quo.components.tags.summary-tag.view
quo.components.tags.tag
quo.components.tags.tags
quo.components.tags.tiny-tag.view
@@ -212,7 +211,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)
@@ -361,7 +360,6 @@
(def number-tag quo.components.tags.number-tag.view/view)
(def permission-tag quo.components.tags.permission-tag/tag)
(def status-tag quo.components.tags.status-tags/status-tag)
(def summary-tag quo.components.tags.summary-tag.view/view)
(def tag quo.components.tags.tag/tag)
(def tags quo.components.tags.tags/tags)
(def tiny-tag quo.components.tags.tiny-tag.view/view)
-1
View File
@@ -73,7 +73,6 @@
[quo.components.switchers.group-messaging-card.component-spec]
[quo.components.tags.network-tags.component-spec]
[quo.components.tags.status-tags-component-spec]
[quo.components.tags.summary-tag.component-spec]
[quo.components.tags.tiny-tag.component-spec]
[quo.components.wallet.account-card.component-spec]
[quo.components.wallet.account-origin.component-spec]
-9
View File
@@ -7,15 +7,6 @@
: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))
-68
View File
@@ -1,68 +0,0 @@
# 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]))
```
-14
View File
@@ -1,14 +0,0 @@
(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))
-17
View File
@@ -1,17 +0,0 @@
(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))
-95
View File
@@ -1,95 +0,0 @@
(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)))
-26
View File
@@ -1,26 +0,0 @@
(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)
-11
View File
@@ -1,11 +0,0 @@
(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 #{}))
-28
View File
@@ -1,28 +0,0 @@
(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})
-18
View File
@@ -1,18 +0,0 @@
(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"]]]))
-2
View File
@@ -8,7 +8,6 @@
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]))
@@ -119,7 +118,6 @@
[& args]
(reset-test-data!)
(interceptors/register-global-interceptors)
(schema/setup!)
(rf/set-mergeable-keys #{:filters/load-filters
:pairing/set-installation-metadata
:dispatch-n
+1 -3
View File
@@ -225,9 +225,7 @@
(.. ^js % -nativeEvent -data)])
:on-load #(re-frame/dispatch [:browser/loading-started])
:on-error #(re-frame/dispatch [:browser/error-occured])
:injected-java-script-before-content-loaded (js-res/ethereum-provider (str network-id))
;; https://github.com/status-im/status-mobile/issues/17854
:allows-inline-media-playback true}])]
:injected-java-script-before-content-loaded (js-res/ethereum-provider (str network-id))}])]
[navigation
{:url url-original
:name name
@@ -131,13 +131,6 @@
: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)
+4 -8
View File
@@ -15,8 +15,6 @@
(def test-dir (.mkdtempSync fs test-dir-prefix))
(def initialized? (atom false))
(defn signal-received-callback
[a]
(re-frame/dispatch [:signals/signal-received a]))
@@ -24,12 +22,10 @@
;; We poll for signals, could not get callback working
(defn init!
[]
(when-not @initialized?
(.setSignalEventCallback native-status)
(reset! initialized? true)
(js/setInterval (fn []
(.pollSignal native-status signal-received-callback)
100))))
(.setSignalEventCallback native-status)
(js/setInterval (fn []
(.pollSignal native-status signal-received-callback)
100)))
(def status
(clj->js
@@ -1,32 +0,0 @@
(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"))))
@@ -1,17 +0,0 @@
(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})
@@ -1,25 +0,0 @@
(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))
@@ -1,15 +0,0 @@
(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})
@@ -1,102 +0,0 @@
(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
:containstyle {:margin-top 8}}
{:type :error
:size :default
:icon :i/info
:style {:margin-top 8}}
(i18n/label :t/oops-wrong-password)])
[quo/button
{:container-style {:margin-bottom 12 :margin-top 40}
+1 -13
View File
@@ -79,19 +79,7 @@
: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")}
: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")}})
:dark (js/require "../resources/images/ui2/no-notifications-dark.png")}})
(def mock-images
{:bored-ape (js/require "../resources/images/mock2/bored-ape.png")
@@ -1,7 +0,0 @@
(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,44 +0,0 @@
(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))
@@ -1,43 +0,0 @@
(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,6 +1,10 @@
(ns status-im2.common.standard-authentication.standard-auth.authorize
(ns status-im2.common.standard-authentication.standard-auth.view
(: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]
@@ -42,3 +46,39 @@
{: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))
@@ -11,7 +11,7 @@
[utils.re-frame :as rf]))
(defn edit-message
[{:keys [text-value input-ref]}]
[state]
[rn/view
{:style style/container
:accessibility-label :edit-message}
@@ -30,18 +30,20 @@
{:size 24
:icon-only? true
:accessibility-label :edit-cancel-button
:on-press #(utils/cancel-edit-message text-value input-ref)
:on-press (fn []
(utils/cancel-edit-message state)
(rf/dispatch [:chat.ui/cancel-message-edit]))
:type :outline}
:i/close]])
(defn- f-view
[props]
[state]
(let [edit (rf/sub [:chats/edit-message])
height (reanimated/use-shared-value (if edit constants/edit-container-height 0))]
(rn/use-effect #(reanimated/animate height (if edit constants/edit-container-height 0)) [edit])
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
(when edit [edit-message props])]))
(when edit [edit-message state])]))
(defn view
[props]
[:f> f-view props])
[state]
[:f> f-view state])
@@ -6,7 +6,6 @@
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.keyboard :as kb]
[status-im2.contexts.chat.composer.utils :as utils]
@@ -106,62 +105,50 @@
(defn use-edit
[{:keys [input-ref]}
{:keys [text-value saved-cursor-position cursor-position]}
{:keys [edit input-with-mentions]}
messages-list-on-layout-finished?]
(let [mention? (some #(= :mention (first %)) (seq input-with-mentions))
composer-just-opened? (not @messages-list-on-layout-finished?)]
(rn/use-effect
(fn []
(let [mention-text (reduce (fn [acc item]
(str acc (second item)))
""
input-with-mentions)
edit-text (cond
mention? mention-text
;; NOTE: using text-value for cases when the user
;; leaves the app with an unfinished edit and re-opens
;; the chat.
(and (seq @text-value) composer-just-opened?)
@text-value
:else (get-in edit [:content :text]))
selection-pos (count edit-text)
inject-edit-text (fn []
(reset! text-value edit-text)
(reset! cursor-position selection-pos)
(reset! saved-cursor-position selection-pos)
(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:text edit-text}))))]
(when (and edit @input-ref)
;; NOTE: A small setTimeout is necessary to ensure the focus is enqueued and is executed
;; ASAP. Check https://github.com/software-mansion/react-native-screens/issues/472
;;
;; The nested setTimeout is necessary to avoid both `on-focus` and
;; `on-content-size-change` handlers triggering the height animation simultaneously, as
;; this causes a jump in the
;; UI. This way, `on-focus` will trigger first without changing the height, after which
;; `on-content-size-change` will animate the height of the input based on the injected
;; text.
(js/setTimeout #(do (when @messages-list-on-layout-finished? (.focus ^js @input-ref))
(reagent/next-tick inject-edit-text))
600))))
[(:message-id edit)])))
{:keys [text-value saved-cursor-position]}
{:keys [edit]}]
(rn/use-effect
(fn []
(let [edit-text (get-in edit [:content :text])]
(when (and edit @input-ref)
;; A small setTimeout is necessary to ensure the statement is enqueued and will get executed
;; ASAP.
;; https://github.com/software-mansion/react-native-screens/issues/472
(js/setTimeout #(.focus ^js @input-ref) 250)
(.setNativeProps ^js @input-ref (clj->js {:text edit-text}))
(reset! text-value edit-text)
(reset! saved-cursor-position (count edit-text)))))
[(:message-id edit)]))
(defn use-reply
[{:keys [input-ref]}
{:keys [container-opacity]}
{:keys [reply]}
messages-list-on-layout-finished?]
{:keys [reply]}]
(rn/use-effect
(fn []
(when reply
(reanimated/animate container-opacity 1))
(when (and reply @input-ref @messages-list-on-layout-finished?)
(js/setTimeout #(.focus ^js @input-ref) 600)))
(when (and reply @input-ref)
(js/setTimeout #(.focus ^js @input-ref) 250)))
[(:message-id reply)]))
(defn edit-mentions
[{:keys [input-ref]} {:keys [text-value cursor-position]} {:keys [input-with-mentions]}]
(rn/use-effect (fn []
(let [input-text (reduce (fn [acc item]
(str acc (second item)))
""
input-with-mentions)]
(reset! text-value input-text)
(reset! cursor-position (count input-text))
(js/setTimeout #(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:selection {:start (count input-text)
:end (count
input-text)}})))
300)))
[(some #(= :mention (first %)) (seq input-with-mentions))]))
(defn update-input-mention
[{:keys [input-ref]}
{:keys [text-value]}
@@ -43,7 +43,8 @@
(reset! emoji-kb-extra-height nil))
(reset! maximized? false)
(rf/dispatch [:chat.ui/set-input-maximized false])
(utils/blur-input input-ref))
(when @input-ref
(.blur ^js @input-ref)))
(defn bounce-back
[{:keys [height saved-height opacity background-y]}
@@ -95,13 +96,13 @@
max-height
bounded-height
saved-height))
; sheet at min-height, collapse keyboard
(utils/blur-input input-ref))))))
(when @input-ref ; sheet at min-height, collapse keyboard
(.blur ^js @input-ref)))))))
(gesture/on-end (fn []
(let [diff (- (reanimated/get-shared-value height)
(reanimated/get-shared-value saved-height))]
(if @gesture-enabled?
(if (and @expanding? (>= diff 0))
(if (>= diff 0)
(if (> diff constants/drag-threshold)
(maximize state animations dimensions)
(bounce-back animations dimensions starting-opacity))
@@ -23,14 +23,12 @@
show-floating-scroll-down-button?]
(reset! focused? true)
(rf/dispatch [:chat.ui/set-input-focused true])
(let [last-height-value (reanimated/get-shared-value last-height)]
(reanimated/animate height last-height-value)
(reanimated/set-shared-value saved-height last-height-value)
(reanimated/animate container-opacity 1)
(when (> last-height-value (* constants/background-threshold max-height))
(reanimated/animate opacity 1)
(reanimated/set-shared-value background-y 0)))
(reanimated/animate height (reanimated/get-shared-value last-height))
(reanimated/set-shared-value saved-height (reanimated/get-shared-value last-height))
(reanimated/animate container-opacity 1)
(when (> (reanimated/get-shared-value last-height) (* constants/background-threshold max-height))
(reanimated/animate opacity 1)
(reanimated/set-shared-value background-y 0))
(js/setTimeout #(reset! lock-selection? false) 300)
(when (and (not-empty @text-value) @input-ref)
(.setNativeProps ^js @input-ref
@@ -74,7 +72,7 @@
"Save new text height, expand composer if possible, show background overlay if needed"
[event
{:keys [maximized? lock-layout? text-value]}
{:keys [height saved-height last-height opacity background-y]}
{:keys [height saved-height opacity background-y]}
{:keys [content-height window-height max-height]}
keyboard-shown]
(when keyboard-shown
@@ -89,9 +87,8 @@
max-height)
new-height (min new-height max-height)]
(reset! content-height content-size)
(when (utils/update-height? content-size height max-height)
(when (utils/update-height? content-size height max-height maximized?)
(reanimated/animate height new-height)
(reanimated/set-shared-value last-height new-height)
(reanimated/set-shared-value saved-height new-height))
(when (= new-height max-height)
(reset! maximized? true)
@@ -4,8 +4,7 @@
[react-native.async-storage :as async-storage]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.composer.utils :as utils]))
[react-native.reanimated :as reanimated]))
(defn get-kb-height
[curr-height default-height]
@@ -21,24 +20,18 @@
(async-storage/set-item! :kb-default-height (str height)))))
(defn handle-emoji-kb-ios
"Opening emoji KB on iOS will cause a flicker up and down due to height differences.
This method handles that by adding the extra difference between the keyboards. When the input is
expanded to a point where the added difference will make the composer go beyond the screen causing a flicker,
we're subtracting the difference so it only reaches the allowed max-height. We're not animating these
changes to make it appear seamless during transitions between keyboard types when maximized."
"Opening emoji KB on iOS while maximized will cause a flicker up and down. This method handles that."
[event
{:keys [emoji-kb-extra-height]}
{:keys [text-value kb-height]}
{:keys [text-value]}
{:keys [height saved-height]}
{:keys [max-height]}]
(let [start-h (oops/oget event "startCoordinates.height")
end-h (oops/oget event "endCoordinates.height")
diff (- end-h start-h)
max-height-diff (- max-height diff)
curr-text @text-value
bigger-than-default-kb? (> end-h @kb-height)
almost-expanded? (> (reanimated/get-shared-value height) max-height-diff)]
(if (and almost-expanded? bigger-than-default-kb? (pos? diff))
(let [start-h (oops/oget event "startCoordinates.height")
end-h (oops/oget event "endCoordinates.height")
diff (- end-h start-h)
max-height-diff (- max-height diff)
curr-text @text-value]
(if (> (reanimated/get-shared-value height) max-height-diff)
(do
(reanimated/set-shared-value height (- (reanimated/get-shared-value height) diff))
(reanimated/set-shared-value saved-height (- (reanimated/get-shared-value saved-height) diff))
@@ -65,8 +58,8 @@
#(handle-emoji-kb-ios % props state animations dimensions)))
(reset! keyboard-hide-listener (.addListener rn/keyboard
"keyboardDidHide"
#(when platform/android?
(utils/blur-input input-ref)))))
#(when (and platform/android? @input-ref)
(.blur ^js @input-ref)))))
(defn handle-refocus-emoji-kb-ios
[{:keys [saved-emoji-kb-extra-height]}
@@ -9,7 +9,6 @@
[status-im2.constants :as constant]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.reply.style :as style]
[status-im2.contexts.chat.composer.utils :as utils]
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -86,7 +85,7 @@
(defn quoted-message
[{:keys [from content-type contentType parsed-text content deleted? deleted-for-me?
album-images-count]}
in-chat-input? pin? recording-audio? input-ref]
in-chat-input? pin? recording-audio?]
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])
current-public-key (rf/sub [:multiaccount/public-key])
content-type (or content-type contentType)
@@ -137,7 +136,7 @@
{:icon-only? true
:size 24
:accessibility-label :reply-cancel-button
:on-press #(utils/cancel-reply-message input-ref)
:on-press #(rf/dispatch [:chat.ui/cancel-message-reply])
:type :outline}
:i/close])
(when (and in-chat-input? recording-audio?)
@@ -149,13 +148,13 @@
:style style/gradient}])]))
(defn- f-view
[recording? input-ref]
[recording?]
(let [reply (rf/sub [:chats/reply-message])
height (reanimated/use-shared-value (if reply constants/reply-container-height 0))]
(rn/use-effect #(reanimated/animate height (if reply constants/reply-container-height 0)) [reply])
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
(when reply [quoted-message reply true false recording? input-ref])]))
(when reply [quoted-message reply true false recording?])]))
(defn view
[{:keys [recording?]} input-ref]
[:f> f-view @recording? input-ref])
[{:keys [recording?]}]
[:f> f-view @recording?])
@@ -16,10 +16,11 @@
(max min-v (min v max-v)))
(defn update-height?
[content-size height max-height]
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff constants/content-change-threshold))))
[content-size height max-height maximized?]
(when-not @maximized?
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff constants/content-change-threshold)))))
(defn show-top-gradient?
[y lines max-lines gradient-opacity focused?]
@@ -99,28 +100,10 @@
(not reply?)
(not audio?)))
(defn blur-input
[input-ref]
(when @input-ref
(rf/dispatch [:chat.ui/set-input-focused false])
(.blur ^js @input-ref)))
(defn cancel-reply-message
[input-ref]
(js/setTimeout #(blur-input input-ref) 100)
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height])
(rf/dispatch [:chat.ui/cancel-message-reply]))
(defn cancel-edit-message
[text-value input-ref]
[{:keys [text-value]}]
(reset! text-value "")
;; NOTE: adding a timeout to assure the input is blurred on the next tick
;; after the `text-value` was cleared. Otherwise the height will be calculated
;; with the old `text-value`, leading to wrong composer height after blur.
(js/setTimeout #(blur-input input-ref) 100)
(.setNativeProps ^js @input-ref (clj->js {:text ""}))
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height])
(rf/dispatch [:chat.ui/cancel-message-edit]))
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height]))
(defn count-lines
[s]
@@ -33,8 +33,7 @@
blur-height
opacity
background-y
theme
messages-list-on-layout-finished?]} props state]
theme]} props state]
(let [{:keys [chat-screen-loaded?]
:as subscriptions} (utils/init-subs)
content-height (reagent/atom (or (:input-content-height ; Actual text height
@@ -74,9 +73,10 @@
animations
dimensions
subscriptions)
(effects/use-edit props state subscriptions messages-list-on-layout-finished?)
(effects/use-reply props animations subscriptions messages-list-on-layout-finished?)
(effects/use-edit props state subscriptions)
(effects/use-reply props animations subscriptions)
(effects/update-input-mention props state subscriptions)
(effects/edit-mentions props state subscriptions)
(effects/link-previews props state animations subscriptions)
(effects/use-images props state animations subscriptions)
[:<>
@@ -98,10 +98,8 @@
[sub-view/bar]
(when chat-screen-loaded?
[:<>
[reply/view state (:input-ref props)]
[edit/view
{:text-value (:text-value state)
:input-ref (:input-ref props)}]])
[reply/view state]
[edit/view state]])
[reanimated/touchable-opacity
{:active-opacity 1
:on-press (fn []
@@ -149,13 +147,11 @@
subscriptions]]]]]))
(defn composer
[{:keys [insets scroll-to-bottom-fn show-floating-scroll-down-button?
messages-list-on-layout-finished?]}]
[{:keys [insets scroll-to-bottom-fn show-floating-scroll-down-button?]}]
(let [window-height (:height (rn/get-window))
theme (quo.theme/use-theme-value)
opacity (reanimated/use-shared-value 0)
background-y (reanimated/use-shared-value (- window-height)) ; Y position of background
; overlay
background-y (reanimated/use-shared-value (- window-height)) ; Y position of background overlay
blur-height (reanimated/use-shared-value (+ constants/composer-default-height
(:bottom insets)))
extra-params {:insets insets
@@ -165,8 +161,7 @@
:blur-height blur-height
:opacity opacity
:background-y background-y
:theme theme
:messages-list-on-layout-finished? messages-list-on-layout-finished?}
:theme theme}
props (utils/init-non-reactive-state)
state (utils/init-reactive-state)]
[rn/view (when platform/ios? {:style {:z-index 1}})
@@ -298,7 +298,7 @@
(defn f-messages-list-content
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms
big-name-visible? animate-topbar-opacity? composer-active? messages-list-on-layout-finished?
big-name-visible? animate-topbar-opacity? composer-active?
on-end-reached? animate-topbar-name?]}]
(rn/use-effect (fn []
(if (and (not @on-end-reached?)
@@ -412,15 +412,6 @@
;;TODO(rasom) https://github.com/facebook/react-native/issues/30034
:inverted (when platform/ios? true)
:on-layout (fn [e]
;; FIXME: the 1s timeout is to assure all effects with
;; timeouts that depend on the value are considered.
;; Hacky, but we're heavily relying on timeouts in the
;; composer and need to react to differently (e.g.
;; inside effects/use-edit) when the chat has just
;; opened and the subsequent times.
(js/setTimeout #(reset! messages-list-on-layout-finished?
true)
1000)
(let [layout-height (oops/oget e
"nativeEvent.layout.height")]
(reset! messages-view-height layout-height)))
+15 -18
View File
@@ -15,7 +15,7 @@
(defn f-chat
[{:keys [show-floating-scroll-down-button? animate-topbar-name?
big-name-visible? animate-topbar-opacity? on-end-reached? messages-list-on-layout-finished?]
big-name-visible? animate-topbar-opacity? on-end-reached?]
:as inner-state-atoms}]
(let [insets (safe-area/get-insets)
scroll-y (reanimated/use-shared-value 0)
@@ -53,19 +53,18 @@
:keyboard-vertical-offset (- (:bottom insets))}
[list.view/message-list-content-view
{:chat chat
:insets insets
:scroll-y scroll-y
:content-height content-height
:cover-bg-color :turquoise
:keyboard-shown? keyboard-shown
:inner-state-atoms inner-state-atoms
:animate-topbar-name? animate-topbar-name?
:big-name-visible? big-name-visible?
:animate-topbar-opacity? animate-topbar-opacity?
:composer-active? focused?
:on-end-reached? on-end-reached?
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]
{:chat chat
:insets insets
:scroll-y scroll-y
:content-height content-height
:cover-bg-color :turquoise
:keyboard-shown? keyboard-shown
:inner-state-atoms inner-state-atoms
:animate-topbar-name? animate-topbar-name?
:big-name-visible? big-name-visible?
:animate-topbar-opacity? animate-topbar-opacity?
:composer-active? focused?
:on-end-reached? on-end-reached?}]
[messages.navigation/navigation-view
{:scroll-y scroll-y
@@ -87,8 +86,7 @@
[:f> composer.view/composer
{:insets insets
:scroll-to-bottom-fn list.view/scroll-to-bottom
:show-floating-scroll-down-button? show-floating-scroll-down-button?
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]
:show-floating-scroll-down-button? show-floating-scroll-down-button?}]
[contact-requests.bottom-drawer/view chat-id contact-request-state group-chat]))]))
(defn chat
@@ -101,6 +99,5 @@
:animate-topbar-name? (reagent/atom false)
:big-name-visible? (reagent/atom :initial-render)
:animate-topbar-opacity? (reagent/atom false)
:on-end-reached? (reagent/atom false)
:messages-list-on-layout-finished? (reagent/atom false)}]
:on-end-reached? (reagent/atom false)}]
[:f> f-chat inner-state-atoms]))
@@ -42,31 +42,26 @@
community-id %])
:on-error #(log/error "failed to request to join community" community-id %)}]})
(defn request-to-join
[{:keys [db]} [{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal []]
{:fx [[:json-rpc/call
[{:method "wakuext_generateJoiningCommunityRequestsForSigning"
:params [pub-key community-id addresses-to-reveal]
:on-success [:communities/sign-data community-id password]
:on-error [:communities/requested-to-join-error community-id]}]]]}))
;; Event to be called to request to join a community.
;; This event will generate the data to be signed and then call the sign-data event.
;; This is the only event that should be called from the UI.
(rf/reg-event-fx :communities/request-to-join request-to-join)
(rf/reg-event-fx :communities/request-to-join
(fn [{:keys [db]} [{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal []]
{:fx [[:json-rpc/call
[{:method "wakuext_generateJoiningCommunityRequestsForSigning"
:params [pub-key community-id addresses-to-reveal]
:on-success [:communities/sign-data community-id password]
:on-error [:communities/requested-to-join-error community-id]}]]]})))
(defn sign-data
[_ [community-id password sign-params]]
(let [addresses-to-reveal (map :account sign-params)]
{:fx [[:json-rpc/call
[{:method "wakuext_signData"
:params [(map #(assoc % :password password) sign-params)]
:on-success [:communities/request-to-join-with-signatures community-id addresses-to-reveal]
:on-error [:communities/requested-to-join-error community-id]}]]]}))
(rf/reg-event-fx :communities/sign-data sign-data)
(rf/reg-event-fx :communities/sign-data
(fn [_ [community-id password sign-params]]
{:fx [[:json-rpc/call
[{:method "wakuext_signData"
:params [(map #(assoc % :password password) sign-params)]
:on-success [:communities/request-to-join-with-signatures community-id]
:on-error [:communities/requested-to-join-error community-id]}]]]}))
(rf/reg-event-fx :communities/requested-to-join-error
(fn [{:keys [db]} [community-id error]]
@@ -76,19 +71,11 @@
:event :communities/requested-to-join-error})
{:db (assoc-in db [:password-authentication :error] error)}))
(defn request-to-join-with-signatures
[_ [community-id addresses-to-reveal signatures]]
{:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
;; NOTE: At least one airdrop address is required.
;; This is a temporary solution while the address
;; selection feature is not implemented in mobile.
:airdropAddress (first addresses-to-reveal)}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]]})
(rf/reg-event-fx :communities/request-to-join-with-signatures request-to-join-with-signatures)
(rf/reg-event-fx :communities/request-to-join-with-signatures
(fn [_ [community-id signatures]]
{:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id :signatures signatures}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]]}))
@@ -1,53 +0,0 @@
(ns status-im2.contexts.communities.overview.events-test
(:require [cljs.test :refer [deftest is]]
[native-module.core :as native-module]
[status-im2.contexts.communities.overview.events :as sut]))
(def password (native-module/sha3 "password123"))
(def community-id "0x99")
(def account-pub-key "0x1")
(deftest request-to-join-test
(let [cofx {:db {:profile/profile {:public-key account-pub-key}}}
expected {:fx [[:json-rpc/call
[{:method "wakuext_generateJoiningCommunityRequestsForSigning"
:params [account-pub-key community-id []]
:on-success [:communities/sign-data community-id password]
:on-error [:communities/requested-to-join-error community-id]}]]]}]
(is (= expected
(sut/request-to-join cofx
[{:community-id community-id
:password password}])))))
(deftest sign-data-test
(let [cofx {:db {}}
sign-params [{:data "123" :account account-pub-key}
{:data "456" :account "0x2"}]
addresses-to-reveal [account-pub-key "0x2"]
expected {:fx
[[:json-rpc/call
[{:method "wakuext_signData"
:params [[{:data "123" :account account-pub-key :password password}
{:data "456" :account "0x2" :password password}]]
:on-success [:communities/request-to-join-with-signatures
community-id addresses-to-reveal]
:on-error [:communities/requested-to-join-error community-id]}]]]}]
(is (= expected
(sut/sign-data cofx [community-id password sign-params])))))
(deftest request-to-join-with-signatures-test
(let [cofx {:db {}}
addresses-to-reveal [account-pub-key "0x2"]
signatures ["11111" "222222"]
expected {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress "0x1"}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error
community-id]}]]]}]
(is (= expected
(sut/request-to-join-with-signatures cofx [community-id addresses-to-reveal signatures])))))
@@ -255,7 +255,7 @@
(defn community-content
[community]
(rf/dispatch [:communities/check-all-community-channels-permissions (:id community)])
(fn [{:keys [name description joined images tags color id token-permissions] :as community}
(fn [{:keys [name description joined images tags color id] :as community}
pending?
{:keys [on-category-layout
collapsed?
@@ -273,14 +273,12 @@
:last-item-style style/last-community-tag
:container-style style/community-tag-container}])
[join-community community pending?]]
(when (or (and (seq token-permissions) joined)
(empty? token-permissions))
[channel-list-component
{:on-category-layout on-category-layout
:community-id id
:community-color color
:on-first-channel-height-changed on-first-channel-height-changed}
(add-handlers-to-categorized-chats id chats-by-category joined)])])))
[channel-list-component
{:on-category-layout on-category-layout
:community-id id
:community-color color
:on-first-channel-height-changed on-first-channel-height-changed}
(add-handlers-to-categorized-chats id chats-by-category joined)]])))
(defn sticky-category-header
[_]
@@ -1,20 +1,15 @@
(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.security.core :as security]))
[utils.re-frame :as rf]))
(defn page-title
[]
@@ -26,39 +21,22 @@
:description-accessibility-label :enable-biometrics-sub-title}])
(defn enable-biometrics-buttons
[insets theme]
[insets]
(let [supported-biometric-type (rf/sub [:biometric/supported-type])
bio-type-label (biometric/get-label-by-type supported-biometric-type)
profile-color (or (:color (rf/sub [:onboarding-2/profile]))
(rf/sub [:profile/customization-color]))
syncing-results? (= :syncing-results @state/root-id)]
profile-color (:color (rf/sub [:onboarding-2/profile]))]
[rn/view {:style (style/buttons insets)}
[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 :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})]
[quo/button
{:accessibility-label :maybe-later-button
:background :blur
:type :grey
:on-press #(rf/dispatch (if syncing-results?
[:navigate-to-within-stack
[:enable-notifications :enable-biometrics]]
[:onboarding-2/create-account-and-login]))
:on-press #(rf/dispatch [:onboarding-2/create-account-and-login])
:container-style {:margin-top 12}}
(i18n/label :t/maybe-later)]]))
@@ -77,19 +55,12 @@
:style (style/page-illustration width)
:source (resources/get-image :biometrics)}]))
(defn f-enable-biometrics
[{:keys [theme]}]
(defn enable-biometrics
[]
(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 theme]]))
(defn- internale-enable-biometrics
[params]
[:f> f-enable-biometrics params])
(def view (quo.theme/with-theme internale-enable-biometrics))
[enable-biometrics-buttons insets]]))
@@ -51,7 +51,7 @@
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back-within-stack :enable-biometrics])}]
:on-press #(rf/dispatch [:navigate-back-within-stack :new-to-status])}]
[page-title]
[rn/view {:style style/page-illustration}
[quo/text
+3 -34
View File
@@ -35,30 +35,11 @@
{: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]}]
(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])}))
{:db (assoc-in db [:onboarding-2/profile :auth-method] constants/auth-method-biometric)
:dispatch [:onboarding-2/create-account-and-login]})
(rf/defn biometrics-fail
{:events [:onboarding-2/biometrics-fail]}
@@ -102,14 +83,6 @@
[: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]
@@ -147,7 +120,6 @@
[{: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)}
@@ -155,10 +127,7 @@
(assoc :keychain/save-password-and-auth-method
{:key-uid key-uid
:masked-password masked-password
:on-success (fn []
(if syncing?
(rf/dispatch [:onboarding-2/navigate-to-enable-notifications])
(log/error "successfully saved biometrics")))
:on-success #(log/debug "successfully saved biometric")
: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 [:onboarding-2/navigate-to-enable-biometrics]))
(rf/dispatch [:open-modal :enable-notifications]))
:accessibility-label :continue-button
:customization-color profile-color
:container-style style/continue-button}
@@ -73,12 +73,12 @@
(data-store.settings/rpc->settings settings)
profile-overview (profile.rpc/rpc->profiles-overview account)]
(rf/merge cofx
{:db (-> db
(assoc :chats/loading? true
:networks/current-network current-network
:networks/networks (merge networks config/default-networks-by-id)
:profile/profile (merge profile-overview settings))
(assoc-in [:wallet :ui :tokens-loading?] true))}
{:db (assoc db
:chats/loading? true
:networks/current-network current-network
:wallet/tokens-loading? true
:networks/networks (merge networks config/default-networks-by-id)
:profile/profile (merge profile-overview settings))}
(notifications/load-preferences)
(data-store.chats/fetch-chats-preview
{:on-success
@@ -6,14 +6,14 @@
(defn- view-internal
[{:keys [theme title]}]
[{:keys [theme]}]
(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 title
:title "quo components preview"
: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 (dissoc @state :value) (:value @state)]])))
[quo/step @state (:value @state)]])))
@@ -153,7 +153,6 @@
[status-im2.contexts.quo-preview.tags.number-tag :as number-tag]
[status-im2.contexts.quo-preview.tags.permission-tag :as permission-tag]
[status-im2.contexts.quo-preview.tags.status-tags :as status-tags]
[status-im2.contexts.quo-preview.tags.summary-tag :as summary-tag]
[status-im2.contexts.quo-preview.tags.tag :as tag]
[status-im2.contexts.quo-preview.tags.tags :as tags]
[status-im2.contexts.quo-preview.tags.tiny-tag :as tiny-tag]
@@ -434,8 +433,6 @@
:component permission-tag/view}
{:name :status-tags
:component status-tags/view}
{:name :summary-tag
:component summary-tag/view}
{:name :tag
:component tag/view}
{:name :tags
@@ -487,7 +484,7 @@
(defn- main-screen
[]
[:<>
[common/navigation-bar {:title "Quo components preview"}]
[common/navigation-bar]
[rn/scroll-view {:style (style/main)}
(for [category (sort screens-categories)]
^{:key (first category)}
@@ -317,10 +317,10 @@
children)])
(defn- f-preview-container
[{:keys [title state descriptor blur? blur-dark-only?
[{:keys [state descriptor blur? blur-dark-only?
component-container-style
blur-container-style blur-view-props blur-height show-blur-background?]
:or {blur-height 200 title "quo component"}}
:or {blur-height 200}}
& 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 {:title title}]
[common/navigation-bar]
[rn/scroll-view
{:style (style/panel-basic)
:shows-vertical-scroll-indicator false}
@@ -1,66 +0,0 @@
(ns status-im2.contexts.quo-preview.tags.summary-tag
(:require
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(defn data
[type]
(case type
:token
{:customization-color "#9999991A"
:label "150 ETH"
:image-source (quo.resources/get-token :eth)}
:address
{:label "0x39c...Bd2"}
:user
{:image-source (resources/mock-images :user-picture-male4)
:customization-color :blue
:label "Mark Libot"}
:collectible
{:label "Isekai #1"
:image-source (resources/mock-images :collectible2)
:customization-color :yellow}
:network
{:image-source (quo.resources/get-network :ethereum)
:label "Mainnet"}
:saved-address
{:customization-color :flamingo
:label "Peter Lambo"}
:account
{:label "Account"
:emoji "🍿"
:customization-color :purple}))
(def descriptor
[{:key :type
:type :select
:options [{:value "Token"
:key :token}
{:value "Address"
:key :address}
{:value "User"
:key :user}
{:value "Collectible"
:key :collectible}
{:value "Network"
:key :network}
{:value "Saved address"
:key :saved-address}
{:value "Account"
:key :account}]}])
(defn view
[]
(let [state (reagent/atom
(merge {:type :token}
(data :token)))]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor}
[rn/view {:style {:align-items :center}}
[quo/summary-tag (merge @state (data (:type @state)))]]])))
@@ -1,22 +0,0 @@
(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)})
@@ -1,55 +0,0 @@
(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"]]]])))
@@ -1,59 +0,0 @@
(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}])
@@ -1,10 +0,0 @@
(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.core :as standard-auth]
[status-im2.common.standard-authentication.standard-auth.view :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/slide-button
[standard-auth/view
{:blur? true
:size :size-40
:track-text (i18n/label :t/slide-to-reveal-code)
@@ -3,10 +3,11 @@
[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]
[utils.i18n :as i18n]))
[status-im2.contexts.wallet.common.temp :as temp]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn dapp-options
[]
@@ -22,12 +23,13 @@
(defn- view-internal
[{:keys [theme]}]
(let [dapps-list []]
(let [dapps-list (temp/dapps-list {:on-press-icon #(rf/dispatch [:show-bottom-sheet
{:content dapp-options}])})]
(if (empty? dapps-list)
[empty-tab/view
{:title (i18n/label :t/no-dapps)
:description (i18n/label :t/no-dapps-description)
:image (resources/get-themed-image :no-dapps theme)}]
{:title (i18n/label :t/no-dapps)
:description (i18n/label :t/no-collectibles-description)
:placeholder? true}]
[rn/view {:style style/dapps-container}
[rn/flat-list
{:data dapps-list

Some files were not shown because too many files have changed in this diff Show More